PorterDuff masking leaves opaque black background - android

I'm trying to mask a FrameLayout with a mask defined as a nine patch. However, although it works fine on 5.0+ on older versions (such as 4.4.4), the patch leaves an opaque black background. Is there anything that can be done to avoid this other than drawing to an off screen bitmap before rendering to the screen or reverting to software layers?
public class MaskedLayout extends FrameLayout {
private final static PorterDuffXfermode DST_IN = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private NinePatchDrawable mMask;
private boolean mShowTail = true;
private boolean mReverseLayout;
public ChatBubbleLayout(Context context) {
this(context, null);
}
public ChatBubbleLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ChatBubbleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWillNotDraw(false);
setLayerType(LAYER_TYPE_HARDWARE, mPaint);
mMask = createMask(R.drawable.mask);
}
private NinePatchDrawable createMask(#DrawableRes int res) {
final Bitmap maskBitmap = BitmapFactory.decodeResource(getResources(), res);
final NinePatch patch = new NinePatch(maskBitmap, maskBitmap.getNinePatchChunk(), "Mask");
return new NinePatchDrawable(getResources(), patch);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w != oldw || h != oldh) {
mMask.setBounds(0, 0, w, h);
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
mMask.getPaint().setXfermode(DST_IN);
mMask.draw(canvas);
}
}

try this:
public class MaskedLayout extends FrameLayout {
private NinePatchDrawable mMask;
public MaskedLayout(Context context) {
this(context, null);
}
public MaskedLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MaskedLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mMask = (NinePatchDrawable) getResources().getDrawable(R.drawable.mask);
mMask.getPaint().setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mMask.setBounds(0, 0, w, h);
}
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);
super.dispatchDraw(canvas);
mMask.draw(canvas);
canvas.restore();
}
}

Related

How to make color filter round on an Android ImageView?

I'm using a custom class (extension of ImageView) to have an XML round image view. The problem is when I call .setColorFilter() it doesn't adhere to the same circular/round bounds.
How can I make the color filter only affect the image and not the entire rectangle of the view?
Here is my custom class for reference:
public class RoundedCornerImageFilterView extends ImageFilterView {
public RoundedCornerImageFilterView(Context context) {
super(context);
}
public RoundedCornerImageFilterView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundedCornerImageFilterView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setImageFilter(int color) {
this.setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
#Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth();
int h = getHeight();
Bitmap roundedCornerBitmap = getRoundedCornerBitmap(bitmap, h, w);
canvas.drawBitmap(roundedCornerBitmap, 0, 0, null);
}
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int height, int width) {
Bitmap sbmp;
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0,
(width), (height));
final RectF rectF = new RectF(rect);
final float roundPx = 28;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}
My xml implementation:
<MY_PATH.RoundedCornerImageFilterView
android:id="#+id/MY_IMAGE_VIEW"
android:layout_width="match_parent"
android:layout_height="150dp"
/>
Me trying to set the color filter:
MY_IMAGE_VIEW.setColorFilter(Color.parseColor(color), PorterDuff.Mode.OVERLAY)
Before the filter (looking like it's supposed to):
After setting the filter (you can see the square edges now):
Although the image (bitmap) has been given rounded corners, the canvas that it is written to has not. Since the color filter is being applied to the canvas, the tint spills out into the corners.
I suggest that you apply a rounded rectangle to a path then clip the path to the canvas. Something like this:
public class RoundedImageView extends AppCompatImageView {
private final Path mPath = new Path();
public RoundedImageView(Context context) {
super(context);
init();
}
public RoundedImageView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedImageView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setColorFilter(Color.RED, PorterDuff.Mode.OVERLAY);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mPath.reset();
mPath.addRoundRect(new RectF(0, 0, w, h), 128, 128, Path.Direction.CW);
}
#Override
public void draw(Canvas canvas) {
canvas.save();
canvas.clipPath(mPath);
super.draw(canvas);
canvas.restore();
}
}
I am using ImageView here, but the concept remains the same.
If you do this type of clipping, then rounding the bitmap becomes superfluous since it will also be clipped to the path.

Android extend EditText draw on canvas out of bounds

Im trying to draw text on EditText below by extending it and overriding onDraw function:
As you can see, the word gets cut off, from what am I seeing online, they don't do anything on the canvas aside from drawing on it. From what I've observed, I think because the canvas of the EditText is limited, that's why it is being cut off. I know there's a better solution rather than overriding onDraw, but I want to know the reason why this is happening. Can anybody explain or give a hint? Thank you very much.
CustomEditText.java:
public class CustomEditText extends AppCompatEditText {
private Rect mTitleRect;
private Rect mErrorTextRect;
private Paint mTitlePaint;
private Paint mErrorTextPaint;
private String mTitle = "";
private String mErrorText = "";
private int mEditTextHeight;
public CustomEditText(Context context) {
super(context);
}
public CustomEditText(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.customEditTextStyle);
init();
init(context, attrs);
}
public CustomEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
init(context, attrs);
}
private void init() {
mTitleRect = new Rect();
mErrorTextRect = new Rect();
mTitlePaint = new Paint();
mErrorTextPaint = new Paint();
mTitlePaint.setColor(Color.BLACK);
mTitlePaint.setTextSize(getResources().getDimension(R.dimen.text_small));
mErrorTextPaint.setColor(Color.parseColor("#FF4336"));
mErrorTextPaint.setTextSize(getResources().getDimension(R.dimen.text_small));
}
private void init(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomEditText);
try {
mTitle = a.getString(R.styleable.CustomEditText_headerTitle);
mErrorText = a.getString(R.styleable.CustomEditText_errorText);
} finally {
a.recycle();
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mEditTextHeight = h;
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mTitle != null && !mTitle.isEmpty()) {
mTitlePaint.getTextBounds(mTitle, 0, mTitle.length(), mTitleRect);
canvas.drawText(mTitle, getPaddingLeft(), getPaddingTop() - mTitleRect.height(), mTitlePaint);
}
if (mErrorText != null && !mErrorText.isEmpty()) {
mErrorTextPaint.getTextBounds(mErrorText, 0, mErrorText.length(), mErrorTextRect);
canvas.drawText(mErrorText, getPaddingLeft(), mEditTextHeight + mErrorTextRect.height() / 2, mErrorTextPaint);
}
}
}
attrs.xml
<declare-styleable name="CustomEditText">
<attr name="errorText" format="string|reference" />
<attr name="headerTitle" format="string|reference" />
</declare-styleable>
XML:
<com.mypackage.CustomEditText
android:id="#+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Username"
app:errorText="errorrrr"
app:headerTitle="testing title" />
I think you are misinterpreting android canvas coordinate. Origin coordinate (0, 0) of a canvas is at the very left top x-coordinate is increasing as you go to the right and y-coordinate is increasing as you go to the bottom.
You need to pass left top coordinate of the text that you want to draw.
https://developer.android.com/reference/android/graphics/Canvas#drawText(java.lang.String,%20float,%20float,%20android.graphics.Paint)
I could not understand where do you want to draw the the text so assuming that you want to draw at the top left of the view have to call draw text like this
canvas.drawText(mTitle, getPaddingLeft(), getPaddingTop(), mTitlePaint);
public class CustomEditText extends AppCompatEditText {
private Rect mTitleRect;
private Rect mErrorTextRect;
private Paint mTitlePaint;
private Paint mErrorTextPaint;
private String mTitle = "";
private String mErrorText = "";
private int mEditTextHeight;
public CustomEditText(Context context) {
this(context, null);
}
public CustomEditText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
init(attrs);
}
private void init() {
mTitleRect = new Rect();
mErrorTextRect = new Rect();
mTitlePaint = new Paint();
mErrorTextPaint = new Paint();
mTitlePaint.setColor(Color.BLACK);
mTitlePaint.setTextSize(getResources().getDimension(R.dimen.text_small));
mErrorTextPaint.setColor(Color.parseColor("#FF4336"));
mErrorTextPaint.setTextSize(getResources().getDimension(R.dimen.text_small));
}
private void init(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomEditText);
try {
mTitle = a.getString(R.styleable.CustomEditText_headerTitle);
mErrorText = a.getString(R.styleable.CustomEditText_errorText);
} finally {
a.recycle();
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mEditTextHeight = h;
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
setPadding(0, 0, 0, (int) getResources().getDimension(R.dimen.text_small));
if (mTitle != null && !mTitle.isEmpty()) {
mTitlePaint.getTextBounds(mTitle, 0, mTitle.length(), mTitleRect);
canvas.drawText(mTitle, getPaddingLeft(), getPaddingTop() - mTitleRect.height(), mTitlePaint);
}
if (mErrorText != null && !mErrorText.isEmpty()) {
mErrorTextPaint.getTextBounds(mErrorText, 0, mErrorText.length(), mErrorTextRect);
canvas.drawText(mErrorText, getPaddingLeft(), getHeight(), mErrorTextPaint);
}
}

Clear a views canvas with a TextView

I'm trying to achieve a visual effect, that if I could make would look awesome! The login of the app that I'm doing looks like this:
Keep in mind that the image on the background is an animation, that makes a slightly transition from that image to another.
What I want is make the title of the app "Akrasia" be transparent, but transparent meaning that you can see the image in background through the title letters, this means that in some way I must override the onDraw method of the RelativeLayout that contains this form. I tried to do that, but the only thing that I got was errors. Maybe I'm wrong trying to override the onDraw method in boths, the TextView and the RelativeLayout, maybe there's an easiest way to do it. What do you think? Or maybe is impossible to achive this effect?
UPDATE:
This is how it should look like.
Also I tried to make a custom view extending from TextView wich has a method setBackgroundView wich stores a view instance into a field. Later on the onDraw method and I managed to get the bitmap from the background image. But I don't know how draw it using canvas.
UPDATE:
I make it work! Now I only need change that blue-like background by the drawable of the background.
The view:
final public class SeeThroughTextView extends TextView
{
Bitmap mMaskBitmap;
Canvas mMaskCanvas;
Paint mPaint;
Drawable mBackground;
Bitmap mBackgroundBitmap;
Canvas mBackgroundCanvas;
boolean mSetBoundsOnSizeAvailable = false;
public SeeThroughTextView(Context context)
{
super(context);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
public SeeThroughTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SeeThroughTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#Override
#Deprecated
public void setBackgroundDrawable(Drawable bg)
{
mBackground = bg;
int w = bg.getIntrinsicWidth();
int h = bg.getIntrinsicHeight();
// Drawable has no dimensions, retrieve View's dimensions
if (w == -1 || h == -1)
{
w = getWidth();
h = getHeight();
}
// Layout has not run
if (w == 0 || h == 0)
{
mSetBoundsOnSizeAvailable = true;
return;
}
mBackground.setBounds(0, 0, w, h);
invalidate();
}
#Override
public void setBackgroundColor(int color)
{
setBackgroundDrawable(new ColorDrawable(color));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mBackgroundBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mBackgroundCanvas = new Canvas(mBackgroundBitmap);
mMaskBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mMaskCanvas = new Canvas(mMaskBitmap);
if (mSetBoundsOnSizeAvailable)
{
mBackground.setBounds(0, 0, w, h);
mSetBoundsOnSizeAvailable = false;
}
}
#Override
protected void onDraw(Canvas canvas)
{
// Draw background
mBackground.draw(mBackgroundCanvas);
// Draw mask
mMaskCanvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
super.onDraw(mMaskCanvas);
mBackgroundCanvas.drawBitmap(mMaskBitmap, 0.f, 0.f, mPaint);
canvas.drawBitmap(mBackgroundBitmap, 0.f, 0.f, null);
}
}
And in my fragment I have this because the animation in the background:
vBackground.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
vTitle.setBackgroundDrawable(new BitmapDrawable(vBackground.getDrawingCache()));
vTitle.invalidate();
}
});
Nailed!
The view:
final public class SeeThroughTextView extends TextView
{
Bitmap mMaskBitmap;
Canvas mMaskCanvas;
Paint mPaint;
Drawable mBackground;
Bitmap mBackgroundBitmap;
Canvas mBackgroundCanvas;
boolean mSetBoundsOnSizeAvailable = false;
public SeeThroughTextView(Context context)
{
super(context);
init();
}
private void init() {
Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/gillsans.ttf");
setTypeface(myTypeface);
mPaint = new Paint();
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
public SeeThroughTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SeeThroughTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#Override
#Deprecated
public void setBackgroundDrawable(Drawable bg)
{
mBackground = bg;
int w = bg.getIntrinsicWidth();
int h = bg.getIntrinsicHeight();
// Drawable has no dimensions, retrieve View's dimensions
if (w == -1 || h == -1)
{
w = getWidth();
h = getHeight();
}
// Layout has not run
if (w == 0 || h == 0)
{
mSetBoundsOnSizeAvailable = true;
return;
}
mBackground.setBounds(0, 0, w, h);
invalidate();
}
#Override
public void setBackgroundColor(int color)
{
setBackgroundDrawable(new ColorDrawable(color));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mBackgroundBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mBackgroundCanvas = new Canvas(mBackgroundBitmap);
mMaskBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mMaskCanvas = new Canvas(mMaskBitmap);
if (mSetBoundsOnSizeAvailable)
{
mBackground.setBounds(0, 0, w, h);
mSetBoundsOnSizeAvailable = false;
}
}
#Override
protected void onDraw(Canvas canvas)
{
// Draw background
mBackground.draw(mBackgroundCanvas);
// Draw mask
mMaskCanvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
super.onDraw(mMaskCanvas);
mBackgroundCanvas.drawBitmap(mMaskBitmap, 0.f, 0.f, mPaint);
canvas.drawBitmap(mBackgroundBitmap, 0.f, 0.f, null);
}
}
In my fragment:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
vLoginBtn = (Button) view.findViewById(R.id.btn_login);
vRegistrationBtn = (Button) view.findViewById(R.id.btn_registration);
vForgotBtn = (Button) view.findViewById(R.id.btn_forgot);
vBackground = (KenBurnsView) view.findViewById(R.id.login_background);
vTitle = (SeeThroughTextView) view.findViewById(R.id.txt_view_login_title);
vBackground.setResourceUrls(
"http://www.youwall.com/papel/peaceful_place_wallpaper_4f3f3.jpg",
"http://www.fwallpaper.net/wallpapers/P/E/Peaceful-Scenary_1920x1200.jpg",
"http://p1.pichost.me/i/39/1620902.jpg"
);
vBackground.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
vTitle.setBackgroundDrawable(getResources().getDrawable(R.drawable.drawable_background_login_top));
vTitle.invalidate();
vBackground.removeOnLayoutChangeListener(this);
}
});
}
The drawables are just two shapes, one with the top-left corner and top-right corner with radius 10dp and the another one with the radius in the bottoms.
The custom TextView with the top drawable shape is alligned above the RelativeLayout wich contains the EditTexts.
No much rocket science. Thanks a lot to #Klotor for suggesting the idea!
Specify a new color in your res/values/colors.xml file (create one if it doesn't exist), the file might look like:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ltGray">#33999999</color>
</resources>
where the first two numbers are transparency (00 - fully transparent, FF - fully opaque).
Then simply set the text color of desired TextView to #color/ltGray in the xml of that layout, or go
tvTitle.setTextColor(getResources().getColor(R.color.ltGray))
after instatiating the TextView.

Display a grid using Canvas in Android

I'm trying to display a grid in my Android application. I'm using the "onDraw" method of a custom view I created for this purpose.
The problem is that the result is very strange, not all lines are drawn and some artifacts are visible. May I have your help to solve this?
Here's the code I use:
public class GridView extends View {
private int cellHeight;
private int cellWidth;
private int cellRows = 16;
private int cellColumns = 16;
private Paint lines = new Paint();
public GridView(Context context) {
super(context);
init();
}
public GridView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public GridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
lines.setStyle(Paint.Style.FILL_AND_STROKE);
lines.setColor(Color.BLACK);
cellWidth = getWidth() / cellColumns;
cellHeight = getHeight() / cellRows;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
cellWidth = getWidth() / cellColumns;
cellHeight = getHeight() / cellRows;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
for (int i = 0; i < cellRows; i++)
{
canvas.drawLine(0, i * cellHeight, getWidth(), i * cellHeight,
lines);
}
for (int i = 0; i < cellColumns; i++)
{
canvas.drawLine(i * cellWidth, 0, i * cellWidth, getHeight(),
lines);
}
}
}
This is what I get in EMULATOR:
http://hpics.li/ca14cd1
Moreover, in Android preview (when designing activity), I can see the result expected:
http://hpics.li/7b97afb
The problem occurs when the application is really started.

Android: Draw seekbar progress from center

Hey guys I am currently working on my own Android SeekBar and I want to make the progress color to be drawn from the center of the bar to the thumb. Currently, my SeekBar class looks like this:
public class VerticalSeekBar extends SeekBar {
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
setThumb(getResources().getDrawable(R.drawable.slidera));
setProgressDrawable(getResources().getDrawable(R.drawable.sl_bg));
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
[...]
My Problem now is that I don't know what method I need to override in order to change the behaviour of the drawing of the ProgressDrawable, I am sure there must be some way.
Thanks in advance
So this is now the whole class. The getRekt methods get the size of the SeekBar and the other stuff you see in the onDraw method is pretty much self-explaining. The background drawable is a drawable consisting of the color value 0x00000000 so it doesn't cover the "new" progress background.
public class VerticalSeekBar extends SeekBar {
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
setThumb(getResources().getDrawable(R.drawable.slidera));
setThumbOffset(0);
setProgressDrawable(getResources().getDrawable(R.drawable.sl_bg));
setPadding(0,0,0,0);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
Paint paint = new Paint();
paint.setColor(0xffff7700);
paint.setStrokeWidth(11);
BlurMaskFilter blurMaskFilter=new BlurMaskFilter(15.0f,BlurMaskFilter.Blur.OUTER);
c.drawLine(
getRectX()+(getProgress()-50)*getRHeight()/100, getRectY(),getRectX(), getRectY(), paint);
paint.setMaskFilter(blurMaskFilter);
c.drawLine(
getRectX()+(getProgress()-50)*getRHeight()/100, getRectY(),getRectX(), getRectY(), paint);
drawMeter(c);
super.onDraw(c);
}
public int getRectX(){
Rect MLG= getProgressDrawable().getBounds();
return MLG.centerX();
}
public int getRectY(){
Rect MLG= getProgressDrawable().getBounds();
return MLG.centerY();
}
public int getRHeight(){
Rect MLG= getProgressDrawable().getBounds();
return MLG.width();
}
public void drawMeter(Canvas c){
Paint paint = new Paint();
paint.setColor(0xffff7700);
paint.setStrokeWidth(2);
c.drawLine(
0,100,0, 0, paint);
c.drawLine(
getRHeight()/2,100,getRHeight()/2, 0, paint);
c.drawLine(
getRHeight(),100,getRHeight(), 0, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
setProgress(getMax() - (int) (getMax() * event.getY() / getHeight()));
onSizeChanged(getWidth(), getHeight(), 0, 0);
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
}
This should then look like this:

Categories

Resources