From a620d791108ee5cc57b3012ab05498e93cfba578 Mon Sep 17 00:00:00 2001 From: "Yii.Guxing" Date: Tue, 2 May 2017 23:39:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0Drawable=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + .../CompositionAvatarView.java | 105 ++++++++++++++++-- .../values/attrs_composition_avatar_view.xml | 6 + .../java/cn/yiiguxing/sample/BindingUtil.java | 4 - 4 files changed, 104 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 6b9004d..9322508 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,9 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="100dp" android:layout_height="wrap_content" + app:fitType="CENTER" app:gap="0.25"/> + ``` diff --git a/composition-avatar/src/main/java/cn/yiiguxing/compositionavatar/CompositionAvatarView.java b/composition-avatar/src/main/java/cn/yiiguxing/compositionavatar/CompositionAvatarView.java index e7d206e..c1513cc 100644 --- a/composition-avatar/src/main/java/cn/yiiguxing/compositionavatar/CompositionAvatarView.java +++ b/composition-avatar/src/main/java/cn/yiiguxing/compositionavatar/CompositionAvatarView.java @@ -35,14 +35,23 @@ public class CompositionAvatarView extends View { private final List mDrawables = new ArrayList<>(MAX_DRAWABLE_COUNT); private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private final Matrix mLayoutMatrix = new Matrix(); + private final RectF mTempBounds = new RectF(); private final float[] mPointsTemp = new float[2]; private int mContentSize; private float mSteinerCircleRadius; private float mOffsetY; + private FitType mFitType = FitType.CENTER; private float mGap = DEFAULT_GAP; + private static final FitType[] sFitTypeArray = { + FitType.FIT, + FitType.CENTER, + FitType.START, + FitType.END, + }; + public CompositionAvatarView(Context context) { super(context); init(null, 0); @@ -61,6 +70,12 @@ public CompositionAvatarView(Context context, AttributeSet attrs, int defStyle) private void init(AttributeSet attrs, int defStyle) { final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CompositionAvatarView, defStyle, 0); + + int index = a.getInt(R.styleable.CompositionAvatarView_fitType, -1); + if (index >= 0) { + setDrawableFitType(sFitTypeArray[index]); + } + float gap = a.getFloat(R.styleable.CompositionAvatarView_gap, DEFAULT_GAP); mGap = Math.max(0f, Math.min(gap, 1f)); a.recycle(); @@ -138,6 +153,44 @@ public int getDrawableSize() { return Math.round(mSteinerCircleRadius * 2); } + /** + * Drawable填充类型 + */ + public enum FitType { + FIT, + CENTER, + START, + END + } + + /** + * 设置Drawable填充类型 + * + * @param fitType Drawable填充类型 + * @see FitType + */ + public void setDrawableFitType(@NonNull FitType fitType) { + //noinspection ConstantConditions + if (fitType == null) { + throw new NullPointerException(); + } + if (mFitType != fitType) { + mFitType = fitType; + for (DrawableInfo drawableInfo : mDrawables) { + updateDrawableBounds(drawableInfo); + } + invalidate(); + } + } + + /** + * @return Drawable填充类型 + */ + @NonNull + public FitType getFitType() { + return mFitType; + } + /** * 通过ID获取对应的drawable. * @@ -216,6 +269,7 @@ public boolean addDrawable(int id, @NonNull Drawable drawable) { if (!hasSameDrawable(d)) { cleanDrawable(d); } + updateDrawableBounds(old); } else { if (getNumberOfDrawables() >= MAX_DRAWABLE_COUNT) { return false; @@ -350,6 +404,8 @@ private void layoutDrawables() { ((mContentSize - R - r * (1 + 1 / Math.tan(Math.PI / N))) / 2f); } + mSteinerCircleRadius = r; + final float startX, startY; if (N % 2 == 0) { startX = startY = r; @@ -384,8 +440,7 @@ private void layoutDrawables() { drawable.mCenterX = pointsTemp[0]; drawable.mCenterY = pointsTemp[1]; - drawable.mBounds.inset(-r, -r); - drawable.mBounds.offset(drawable.mCenterX, drawable.mCenterY); + updateDrawableBounds(drawable); drawable.mMaskPath.addCircle(drawable.mCenterX, drawable.mCenterY, r, Path.Direction.CW); @@ -399,13 +454,50 @@ private void layoutDrawables() { first.mGapCenterX = last.mCenterX; first.mGapCenterY = last.mCenterY; } - - mSteinerCircleRadius = r; } invalidate(); } + private void updateDrawableBounds(DrawableInfo drawableInfo) { + final Drawable drawable = drawableInfo.mDrawable; + + final float radius = mSteinerCircleRadius; + if (radius <= 0) { + drawable.setBounds(0, 0, 0, 0); + return; + } + + + final int dWidth = drawable.getIntrinsicWidth(); + final int dHeight = drawable.getIntrinsicHeight(); + + final RectF bounds = mTempBounds; + bounds.setEmpty(); + + if (dWidth <= 0 || dHeight <= 0 || dWidth == dHeight || FitType.FIT == mFitType) { + bounds.inset(-radius, -radius); + } else { + float scale; + if (dWidth > dHeight) { + scale = radius / (float) dHeight; + } else { + scale = radius / (float) dWidth; + } + bounds.inset(-dWidth * scale, -dHeight * scale); + + if (FitType.START == mFitType || FitType.END == mFitType) { + int dir = FitType.START == mFitType ? 1 : -1; + bounds.offset((bounds.width() * 0.5f - radius) * dir, + (bounds.height() * 0.5f - radius) * dir); + } + } + + bounds.offset(drawableInfo.mCenterX, drawableInfo.mCenterY); + drawable.setBounds((int) bounds.left, (int) bounds.top, + Math.round(bounds.right), Math.round(bounds.bottom)); + } + @Override protected void onSizeChanged(int w, int h, int oldW, int oldH) { super.onSizeChanged(w, h, oldW, oldH); @@ -444,12 +536,9 @@ protected void onDraw(Canvas canvas) { final float gapRadius = mSteinerCircleRadius * (mGap + 1f); for (int i = 0; i < drawables.size(); i++) { DrawableInfo drawable = drawables.get(i); - RectF bounds = drawable.mBounds; final int savedLayer = canvas.saveLayer(0, 0, mContentSize, mContentSize, null, Canvas.ALL_SAVE_FLAG); - drawable.mDrawable.setBounds((int) bounds.left, (int) bounds.top, - Math.round(bounds.right), Math.round(bounds.bottom)); drawable.mDrawable.draw(canvas); canvas.drawPath(drawable.mMaskPath, paint); @@ -552,7 +641,6 @@ private static class DrawableInfo { float mGapCenterX; float mGapCenterY; boolean mHasGap; - final RectF mBounds = new RectF(); final Path mMaskPath = new Path(); void reset() { @@ -561,7 +649,6 @@ void reset() { mGapCenterX = 0; mGapCenterY = 0; mHasGap = false; - mBounds.setEmpty(); mMaskPath.reset(); } } diff --git a/composition-avatar/src/main/res/values/attrs_composition_avatar_view.xml b/composition-avatar/src/main/res/values/attrs_composition_avatar_view.xml index eeadae6..54dd108 100644 --- a/composition-avatar/src/main/res/values/attrs_composition_avatar_view.xml +++ b/composition-avatar/src/main/res/values/attrs_composition_avatar_view.xml @@ -1,5 +1,11 @@ + + + + + + diff --git a/sample/src/main/java/cn/yiiguxing/sample/BindingUtil.java b/sample/src/main/java/cn/yiiguxing/sample/BindingUtil.java index 63e708d..772017d 100644 --- a/sample/src/main/java/cn/yiiguxing/sample/BindingUtil.java +++ b/sample/src/main/java/cn/yiiguxing/sample/BindingUtil.java @@ -10,7 +10,6 @@ import com.bumptech.glide.request.animation.GlideAnimation; import com.bumptech.glide.request.target.BaseTarget; import com.bumptech.glide.request.target.SizeReadyCallback; -import com.bumptech.glide.request.target.SquaringDrawable; import com.bumptech.glide.request.target.Target; import cn.yiiguxing.compositionavatar.CompositionAvatarView; @@ -121,9 +120,6 @@ private void setDrawable(Drawable drawable) { @Override public void onResourceReady(GlideDrawable resource, GlideAnimation glideAnimation) { - if (!resource.isAnimated()) { - resource = new SquaringDrawable(resource, mView.getDrawableSize()); - } this.mResource = resource; setDrawable(resource); resource.setLoopCount(GlideDrawable.LOOP_FOREVER);