Last active
August 18, 2016 10:26
-
-
Save vudunguit/50715590ca141f8b1c2060a79dde8588 to your computer and use it in GitHub Desktop.
ImageView support set badge drawable(gift...). I just extracted the widgets from Plaid app developed by Nick Butcher(https://github.com/nickbutcher).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<declare-styleable name="ForegroundView"> | |
<attr name="android:foreground" /> | |
<attr name="android:foregroundInsidePadding" /> | |
<attr name="android:foregroundGravity" /> | |
</declare-styleable> | |
<declare-styleable name="BadgedImageView"> | |
<attr name="badgeGravity"> | |
<!-- Push object to the top of its container, not changing its size. --> | |
<flag name="top" value="0x30" /> | |
<!-- Push object to the bottom of its container, not changing its size. --> | |
<flag name="bottom" value="0x50" /> | |
<!-- Push object to the left of its container, not changing its size. --> | |
<flag name="left" value="0x03" /> | |
<!-- Push object to the right of its container, not changing its size. --> | |
<flag name="right" value="0x05" /> | |
<!-- Push object to the beginning of its container, not changing its size. --> | |
<flag name="start" value="0x00800003" /> | |
<!-- Push object to the end of its container, not changing its size. --> | |
<flag name="end" value="0x00800005" /> | |
</attr> | |
<attr name="badgePadding" format="dimension|reference"/> | |
</declare-styleable> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.content.res.TypedArray; | |
import android.graphics.Bitmap; | |
import android.graphics.Canvas; | |
import android.graphics.Color; | |
import android.graphics.ColorFilter; | |
import android.graphics.Paint; | |
import android.graphics.PorterDuff; | |
import android.graphics.PorterDuffXfermode; | |
import android.graphics.Rect; | |
import android.graphics.Typeface; | |
import android.graphics.drawable.Drawable; | |
import android.support.annotation.ColorInt; | |
import android.text.TextPaint; | |
import android.util.AttributeSet; | |
import android.util.DisplayMetrics; | |
import android.view.Gravity; | |
import io.plaidapp.R; | |
/** | |
* A view group that draws a badge drawable on top of it's contents. | |
*/ | |
public class BadgedFourThreeImageView extends FourThreeImageView { | |
private Drawable badge; | |
private boolean drawBadge; | |
private boolean badgeBoundsSet = false; | |
private int badgeGravity; | |
private int badgePadding; | |
public BadgedFourThreeImageView(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
badge = new GifBadge(context); | |
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BadgedImageView, 0, 0); | |
badgeGravity = a.getInt(R.styleable.BadgedImageView_badgeGravity, Gravity.END | Gravity | |
.BOTTOM); | |
badgePadding = a.getDimensionPixelSize(R.styleable.BadgedImageView_badgePadding, 0); | |
a.recycle(); | |
} | |
public void showBadge(boolean show) { | |
drawBadge = show; | |
} | |
public void setBadgeColor(@ColorInt int color) { | |
badge.setColorFilter(color, PorterDuff.Mode.SRC_IN); | |
} | |
@Override | |
public void draw(Canvas canvas) { | |
super.draw(canvas); | |
if (drawBadge) { | |
if (!badgeBoundsSet) { | |
layoutBadge(); | |
} | |
badge.draw(canvas); | |
} | |
} | |
@Override | |
protected void onSizeChanged(int w, int h, int oldw, int oldh) { | |
super.onSizeChanged(w, h, oldw, oldh); | |
layoutBadge(); | |
} | |
private void layoutBadge() { | |
Rect badgeBounds = badge.getBounds(); | |
Gravity.apply(badgeGravity, | |
badge.getIntrinsicWidth(), | |
badge.getIntrinsicHeight(), | |
new Rect(0, 0, getWidth(), getHeight()), | |
badgePadding, | |
badgePadding, | |
badgeBounds); | |
badge.setBounds(badgeBounds); | |
badgeBoundsSet = true; | |
} | |
/** | |
* A drawable for indicating that an image is animated | |
*/ | |
private static class GifBadge extends Drawable { | |
private static final String GIF = "GIF"; | |
private static final int TEXT_SIZE = 12; // sp | |
private static final int PADDING = 4; // dp | |
private static final int CORNER_RADIUS = 2; // dp | |
private static final int BACKGROUND_COLOR = Color.WHITE; | |
private static final String TYPEFACE = "sans-serif-black"; | |
private static final int TYPEFACE_STYLE = Typeface.NORMAL; | |
private static Bitmap bitmap; | |
private static int width; | |
private static int height; | |
private final Paint paint; | |
GifBadge(Context context) { | |
if (bitmap == null) { | |
final DisplayMetrics dm = context.getResources().getDisplayMetrics(); | |
final float density = dm.density; | |
final float scaledDensity = dm.scaledDensity; | |
final TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint | |
.SUBPIXEL_TEXT_FLAG); | |
textPaint.setTypeface(Typeface.create(TYPEFACE, TYPEFACE_STYLE)); | |
textPaint.setTextSize(TEXT_SIZE * scaledDensity); | |
final float padding = PADDING * density; | |
final float cornerRadius = CORNER_RADIUS * density; | |
final Rect textBounds = new Rect(); | |
textPaint.getTextBounds(GIF, 0, GIF.length(), textBounds); | |
height = (int) (padding + textBounds.height() + padding); | |
width = (int) (padding + textBounds.width() + padding); | |
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); | |
bitmap.setHasAlpha(true); | |
final Canvas canvas = new Canvas(bitmap); | |
final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); | |
backgroundPaint.setColor(BACKGROUND_COLOR); | |
canvas.drawRoundRect(0, 0, width, height, cornerRadius, cornerRadius, | |
backgroundPaint); | |
// punch out the word 'GIF', leaving transparency | |
textPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); | |
canvas.drawText(GIF, padding, height - padding, textPaint); | |
} | |
paint = new Paint(); | |
} | |
@Override | |
public int getIntrinsicWidth() { | |
return width; | |
} | |
@Override | |
public int getIntrinsicHeight() { | |
return height; | |
} | |
@Override | |
public void draw(Canvas canvas) { | |
canvas.drawBitmap(bitmap, getBounds().left, getBounds().top, paint); | |
} | |
@Override | |
public void setAlpha(int alpha) { | |
// ignored | |
} | |
@Override | |
public void setColorFilter(ColorFilter cf) { | |
paint.setColorFilter(cf); | |
} | |
@Override | |
public int getOpacity() { | |
return 0; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.content.res.TypedArray; | |
import android.graphics.Canvas; | |
import android.graphics.drawable.Drawable; | |
import android.util.AttributeSet; | |
import android.view.ViewOutlineProvider; | |
import android.widget.ImageView; | |
import io.plaidapp.R; | |
/** | |
* An extension to {@link ImageView} which has a foreground drawable. | |
*/ | |
public class ForegroundImageView extends ImageView { | |
private Drawable foreground; | |
public ForegroundImageView(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ForegroundView); | |
final Drawable d = a.getDrawable(R.styleable.ForegroundView_android_foreground); | |
if (d != null) { | |
setForeground(d); | |
} | |
a.recycle(); | |
setOutlineProvider(ViewOutlineProvider.BOUNDS); | |
} | |
@Override | |
protected void onSizeChanged(int w, int h, int oldw, int oldh) { | |
super.onSizeChanged(w, h, oldw, oldh); | |
if (foreground != null) { | |
foreground.setBounds(0, 0, w, h); | |
} | |
} | |
@Override | |
public boolean hasOverlappingRendering() { | |
return false; | |
} | |
@Override | |
protected boolean verifyDrawable(Drawable who) { | |
return super.verifyDrawable(who) || (who == foreground); | |
} | |
@Override | |
public void jumpDrawablesToCurrentState() { | |
super.jumpDrawablesToCurrentState(); | |
if (foreground != null) foreground.jumpToCurrentState(); | |
} | |
@Override | |
protected void drawableStateChanged() { | |
super.drawableStateChanged(); | |
if (foreground != null && foreground.isStateful()) { | |
foreground.setState(getDrawableState()); | |
} | |
} | |
/** | |
* Returns the drawable used as the foreground of this view. The | |
* foreground drawable, if non-null, is always drawn on top of the children. | |
* | |
* @return A Drawable or null if no foreground was set. | |
*/ | |
public Drawable getForeground() { | |
return foreground; | |
} | |
/** | |
* Supply a Drawable that is to be rendered on top of the contents of this ImageView | |
* | |
* @param drawable The Drawable to be drawn on top of the ImageView | |
*/ | |
public void setForeground(Drawable drawable) { | |
if (foreground != drawable) { | |
if (foreground != null) { | |
foreground.setCallback(null); | |
unscheduleDrawable(foreground); | |
} | |
foreground = drawable; | |
if (foreground != null) { | |
foreground.setBounds(0, 0, getWidth(), getHeight()); | |
setWillNotDraw(false); | |
foreground.setCallback(this); | |
if (foreground.isStateful()) { | |
foreground.setState(getDrawableState()); | |
} | |
} else { | |
setWillNotDraw(true); | |
} | |
invalidate(); | |
} | |
} | |
@Override | |
public void draw(Canvas canvas) { | |
super.draw(canvas); | |
if (foreground != null) { | |
foreground.draw(canvas); | |
} | |
} | |
@Override | |
public void drawableHotspotChanged(float x, float y) { | |
super.drawableHotspotChanged(x, y); | |
if (foreground != null) { | |
foreground.setHotspot(x, y); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.util.AttributeSet; | |
/** | |
* A extension of ForegroundImageView that is always 4:3 aspect ratio. | |
*/ | |
public class FourThreeImageView extends ForegroundImageView { | |
public FourThreeImageView(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
} | |
@Override | |
protected void onMeasure(int widthSpec, int heightSpec) { | |
int fourThreeHeight = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthSpec) * 3 / 4, | |
MeasureSpec.EXACTLY); | |
super.onMeasure(widthSpec, fourThreeHeight); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment