From dad7194582d1dd3a17885d7eb77e4f6c11925b86 Mon Sep 17 00:00:00 2001 From: Toshihiro Yagi Date: Tue, 26 Sep 2017 13:11:35 +0900 Subject: [PATCH 1/3] Use Drawable instead of Bitmap. --- .../segmentedbutton/SegmentedButton.java | 89 +++++++++++-------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/library/src/main/java/co/ceryle/segmentedbutton/SegmentedButton.java b/library/src/main/java/co/ceryle/segmentedbutton/SegmentedButton.java index bf3bab7..2c617e9 100644 --- a/library/src/main/java/co/ceryle/segmentedbutton/SegmentedButton.java +++ b/library/src/main/java/co/ceryle/segmentedbutton/SegmentedButton.java @@ -28,10 +28,14 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.support.v4.content.ContextCompat; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.util.AttributeSet; +import android.util.Log; import android.view.View; public class SegmentedButton extends View { @@ -56,8 +60,6 @@ public SegmentedButton(Context context, AttributeSet attrs, int defStyleAttr) { private float mClipAmount; private boolean clipLeftToRight; - private Paint mBitmapPaint; - private TextPaint mTextPaint; private StaticLayout mStaticLayout, mStaticLayoutOverlay; private Rect mTextBounds = new Rect(); @@ -123,42 +125,23 @@ else if (null != textTypeface) { } private void initBitmap() { - if (!hasDrawable) - return; - - mBitmap = BitmapFactory.decodeResource(context.getResources(), drawable); - if (hasDrawableWidth || hasDrawableHeight) - mBitmap = getResizedBitmap(mBitmap, drawableWidth, drawableHeight); - - mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + if (hasDrawable) { + mDrawable = ContextCompat.getDrawable(context, drawable); + } if (hasDrawableTint) { mBitmapNormalColor = new PorterDuffColorFilter(drawableTint, PorterDuff.Mode.SRC_IN); - mBitmapPaint.setColorFilter(mBitmapNormalColor); } if (hasDrawableTintOnSelection) mBitmapClipColor = new PorterDuffColorFilter(drawableTintOnSelection, PorterDuff.Mode.SRC_IN); } - - public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) { - int width = bm.getWidth(); - int height = bm.getHeight(); - - float scaleWidth = hasDrawableWidth ? ((float) newWidth) / width : 1; - float scaleHeight = hasDrawableHeight ? ((float) newHeight) / height : 1; - - Matrix matrix = new Matrix(); - matrix.postScale(scaleWidth, scaleHeight); - - return Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false); - } - + private void measureTextWidth(int width) { if (!hasText) return; - int bitmapWidth = hasDrawable && drawableGravity.isHorizontal() ? mBitmap.getWidth() : 0; + int bitmapWidth = hasDrawable && drawableGravity.isHorizontal() ? mDrawable.getIntrinsicWidth() : 0; int textWidth = width - (bitmapWidth + getPaddingLeft() + getPaddingRight()); @@ -177,11 +160,11 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int heightRequirement = MeasureSpec.getSize(heightMeasureSpec); int width = 0; - int bitmapWidth = hasDrawable ? mBitmap.getWidth() : 0; + int bitmapWidth = hasDrawable ? mDrawable.getIntrinsicWidth() : 0; int textWidth = hasText ? mStaticLayout.getWidth() : 0; int height = getPaddingTop() + getPaddingBottom(); - int bitmapHeight = hasDrawable ? mBitmap.getHeight() : 0; + int bitmapHeight = hasDrawable ? mDrawable.getIntrinsicHeight() : 0; int textHeight = hasText ? mStaticLayout.getHeight() : 0; switch (widthMode) { @@ -265,8 +248,8 @@ private void calculate(int width, int height) { float bitmapHeight = 0, bitmapWidth = 0; if (hasDrawable) { - bitmapHeight = mBitmap.getHeight(); - bitmapWidth = mBitmap.getWidth(); + bitmapHeight = mDrawable.getIntrinsicHeight(); + bitmapWidth = mDrawable.getIntrinsicWidth(); } @@ -336,7 +319,7 @@ private void calculate(int width, int height) { private PorterDuffColorFilter mBitmapNormalColor, mBitmapClipColor; - private Bitmap mBitmap; + private Drawable mDrawable; @Override protected void onDraw(Canvas canvas) { @@ -372,8 +355,19 @@ protected void onDraw(Canvas canvas) { // Bitmap normal if (hasDrawable) { - mBitmapPaint.setColorFilter(mBitmapNormalColor); - canvas.drawBitmap(mBitmap, bitmap_X, bitmap_Y, mBitmapPaint); + int drawableX = (int)bitmap_X; + int drawableY = (int)bitmap_Y; + int drawableWidth = mDrawable.getIntrinsicWidth(); + if (hasDrawableWidth) { + drawableWidth = this.drawableWidth; + } + int drawableHeight = mDrawable.getIntrinsicHeight(); + if (hasDrawableHeight) { + drawableHeight = this.drawableHeight; + } + mDrawable.setColorFilter(mBitmapNormalColor); + mDrawable.setBounds(drawableX, drawableY, drawableX + drawableWidth, drawableY + drawableHeight); + mDrawable.draw(canvas); } // NORMAL -end @@ -399,9 +393,20 @@ protected void onDraw(Canvas canvas) { // Bitmap clip if (hasDrawable) { + int drawableX = (int)bitmap_X; + int drawableY = (int)bitmap_Y; + int drawableWidth = mDrawable.getIntrinsicWidth(); + if (hasDrawableWidth) { + drawableWidth = this.drawableWidth; + } + int drawableHeight = mDrawable.getIntrinsicHeight(); + if (hasDrawableHeight) { + drawableHeight = this.drawableHeight; + } if (hasDrawableTintOnSelection) - mBitmapPaint.setColorFilter(mBitmapClipColor); - canvas.drawBitmap(mBitmap, bitmap_X, bitmap_Y, mBitmapPaint); + mDrawable.setColorFilter(mBitmapClipColor); + mDrawable.setBounds(drawableX, drawableY, drawableX + drawableWidth, drawableY + drawableHeight); + mDrawable.draw(canvas); } // CLIP -end @@ -557,8 +562,18 @@ public boolean isHorizontal() { * @param resId is your drawable's resource id */ public void setDrawable(int resId) { - drawable = resId; - mBitmap = BitmapFactory.decodeResource(context.getResources(), resId); + setDrawable(ContextCompat.getDrawable(context, resId)); + } + + /** + * Sets button's drawable by given drawable object and its position + * + * @param drawable is your drawable object + */ + public void setDrawable(Drawable drawable){ + mDrawable = drawable; + hasDrawable = true; + requestLayout(); } /** From 718d2c2ee5ba89f3cbff1aedf68ed2329ea5552f Mon Sep 17 00:00:00 2001 From: Toshihiro Yagi Date: Tue, 26 Sep 2017 13:14:53 +0900 Subject: [PATCH 2/3] Add a sample code that dynamically sets drawable to SegmentedButton. --- .../segmentedbutton/sample/MainActivity.java | 27 ++++- .../sample/drawable/BadgeDrawable.java | 101 ++++++++++++++++++ sample/src/main/res/layout/activity_main.xml | 46 +++++++- 3 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 sample/src/main/java/co/ceryle/segmentedbutton/sample/drawable/BadgeDrawable.java diff --git a/sample/src/main/java/co/ceryle/segmentedbutton/sample/MainActivity.java b/sample/src/main/java/co/ceryle/segmentedbutton/sample/MainActivity.java index 15e859e..ed0e6a0 100644 --- a/sample/src/main/java/co/ceryle/segmentedbutton/sample/MainActivity.java +++ b/sample/src/main/java/co/ceryle/segmentedbutton/sample/MainActivity.java @@ -1,12 +1,15 @@ package co.ceryle.segmentedbutton.sample; +import android.graphics.Color; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; +import co.ceryle.segmentedbutton.SegmentedButton; import co.ceryle.segmentedbutton.SegmentedButtonGroup; +import co.ceryle.segmentedbutton.sample.drawable.BadgeDrawable; public class MainActivity extends AppCompatActivity { @@ -51,9 +54,31 @@ public void run() { } }; handler.postDelayed(runnable, 5000); + + setupDynamicDrawables(); + } + + private void setupDynamicDrawables() { + final BadgeDrawable drawable = new BadgeDrawable(Color.RED, 80, 50, 3, 3); + final SegmentedButton leftButton = (SegmentedButton) findViewById(R.id.left_button); + leftButton.setDrawable(drawable); + + SegmentedButtonGroup group = (SegmentedButtonGroup)findViewById(R.id.dynamic_drawable_group); + group.setOnClickedButtonListener(new SegmentedButtonGroup.OnClickedButtonListener() { + @Override + public void onClickedButton(int position) { + if(position == 0){ + drawable.setCount(drawable.getCount() + 1); + leftButton.requestLayout(); + } + } + }); + + final SegmentedButton rightButton = (SegmentedButton) findViewById(R.id.right_button); + rightButton.setDrawable(R.drawable.ic_b1); } private void updateButton(int position) { button.setText("Position: " + position); } -} \ No newline at end of file +} diff --git a/sample/src/main/java/co/ceryle/segmentedbutton/sample/drawable/BadgeDrawable.java b/sample/src/main/java/co/ceryle/segmentedbutton/sample/drawable/BadgeDrawable.java new file mode 100644 index 0000000..e1546ba --- /dev/null +++ b/sample/src/main/java/co/ceryle/segmentedbutton/sample/drawable/BadgeDrawable.java @@ -0,0 +1,101 @@ +package co.ceryle.segmentedbutton.sample.drawable; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; + +public class BadgeDrawable extends Drawable { + + private Paint paint; + private int color; + private int width; + private int height; + private int borderWidth; + private int borderRadius; + + private RectF rect; + private Path path; + private int count = 10; + + public BadgeDrawable(int color, int width, int height, int borderWidth, int borderRadius) { + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setStyle(Paint.Style.FILL); + paint.setTextSize(32); + + path = new Path(); + path.setFillType(Path.FillType.EVEN_ODD); + + rect = new RectF(); + + this.color = color; + this.width = width; + this.height = height; + this.borderWidth = borderWidth; + this.borderRadius = borderRadius; + } + + @Override + public int getIntrinsicWidth() { + return width; + } + + @Override + public int getIntrinsicHeight() { + return height; + } + + @Override + protected void onBoundsChange(Rect bounds) { + path.reset(); + + path.addRect(bounds.left, bounds.top, bounds.right, bounds.bottom, Path.Direction.CW); + rect.set(bounds.left + borderWidth, bounds.top + borderWidth, + bounds.right - borderWidth, bounds.bottom - borderWidth); + path.addRoundRect(rect, borderRadius, borderRadius, Path.Direction.CW); + } + + @Override + public void draw(@NonNull Canvas canvas) { + paint.setColor(color); + canvas.drawPath(path, paint); + + Rect textBounds = new Rect(); + String countString = String.valueOf(count); + paint.getTextBounds(countString, 0, countString.length(), textBounds); + canvas.drawText( + countString, + rect.right - (rect.right - rect.left) / 2 - textBounds.width() / 2, + rect.top + textBounds.height() / 2 + (rect.bottom - rect.top) / 2, + paint + ); + } + + @Override + public void setAlpha(int alpha) { + paint.setAlpha(alpha); + } + + @Override + public void setColorFilter(ColorFilter cf) { + paint.setColorFilter(cf); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } +} diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml index d16bf5a..07b022b 100644 --- a/sample/src/main/res/layout/activity_main.xml +++ b/sample/src/main/res/layout/activity_main.xml @@ -393,5 +393,49 @@ + - \ No newline at end of file + + + + + + + + From e0e4a77818dab92e22b7dac58179fac1201bba7d Mon Sep 17 00:00:00 2001 From: Toshihiro Yagi Date: Tue, 26 Sep 2017 13:21:43 +0900 Subject: [PATCH 3/3] Commonized draw function for Drawable. --- .../segmentedbutton/SegmentedButton.java | 46 ++++++++----------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/library/src/main/java/co/ceryle/segmentedbutton/SegmentedButton.java b/library/src/main/java/co/ceryle/segmentedbutton/SegmentedButton.java index 2c617e9..2022f2d 100644 --- a/library/src/main/java/co/ceryle/segmentedbutton/SegmentedButton.java +++ b/library/src/main/java/co/ceryle/segmentedbutton/SegmentedButton.java @@ -21,6 +21,7 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; @@ -355,19 +356,7 @@ protected void onDraw(Canvas canvas) { // Bitmap normal if (hasDrawable) { - int drawableX = (int)bitmap_X; - int drawableY = (int)bitmap_Y; - int drawableWidth = mDrawable.getIntrinsicWidth(); - if (hasDrawableWidth) { - drawableWidth = this.drawableWidth; - } - int drawableHeight = mDrawable.getIntrinsicHeight(); - if (hasDrawableHeight) { - drawableHeight = this.drawableHeight; - } - mDrawable.setColorFilter(mBitmapNormalColor); - mDrawable.setBounds(drawableX, drawableY, drawableX + drawableWidth, drawableY + drawableHeight); - mDrawable.draw(canvas); + drawDrawableWithColorFilter(canvas, mBitmapNormalColor); } // NORMAL -end @@ -393,26 +382,29 @@ protected void onDraw(Canvas canvas) { // Bitmap clip if (hasDrawable) { - int drawableX = (int)bitmap_X; - int drawableY = (int)bitmap_Y; - int drawableWidth = mDrawable.getIntrinsicWidth(); - if (hasDrawableWidth) { - drawableWidth = this.drawableWidth; - } - int drawableHeight = mDrawable.getIntrinsicHeight(); - if (hasDrawableHeight) { - drawableHeight = this.drawableHeight; - } - if (hasDrawableTintOnSelection) - mDrawable.setColorFilter(mBitmapClipColor); - mDrawable.setBounds(drawableX, drawableY, drawableX + drawableWidth, drawableY + drawableHeight); - mDrawable.draw(canvas); + drawDrawableWithColorFilter(canvas, mBitmapClipColor); } // CLIP -end canvas.restore(); } + private void drawDrawableWithColorFilter(Canvas canvas, ColorFilter colorFilter){ + int drawableX = (int)bitmap_X; + int drawableY = (int)bitmap_Y; + int drawableWidth = mDrawable.getIntrinsicWidth(); + if (hasDrawableWidth) { + drawableWidth = this.drawableWidth; + } + int drawableHeight = mDrawable.getIntrinsicHeight(); + if (hasDrawableHeight) { + drawableHeight = this.drawableHeight; + } + mDrawable.setColorFilter(colorFilter); + mDrawable.setBounds(drawableX, drawableY, drawableX + drawableWidth, drawableY + drawableHeight); + mDrawable.draw(canvas); + } + public void clipToLeft(float clip) { clipLeftToRight = false; mClipAmount = 1.0f - clip;