Skip to content

Commit

Permalink
添加Drawable填充方式
Browse files Browse the repository at this point in the history
  • Loading branch information
YiiGuxing committed May 2, 2017
1 parent 27dc02e commit a620d79
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 13 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"/>
<!-- 默认fitType为CENTER -->
<!-- 默认gap为0.25 -->
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,23 @@ public class CompositionAvatarView extends View {
private final List<DrawableInfo> 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);
Expand All @@ -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();
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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() {
Expand All @@ -561,7 +649,6 @@ void reset() {
mGapCenterX = 0;
mGapCenterY = 0;
mHasGap = false;
mBounds.setEmpty();
mMaskPath.reset();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<resources>
<declare-styleable name="CompositionAvatarView">
<attr name="gap" format="float"/>
<attr name="fitType" format="enum">
<enum name="FIT" value="0"/>
<enum name="CENTER" value="1"/>
<enum name="START" value="2"/>
<enum name="END" value="3"/>
</attr>
</declare-styleable>
</resources>
4 changes: 0 additions & 4 deletions sample/src/main/java/cn/yiiguxing/sample/BindingUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -121,9 +120,6 @@ private void setDrawable(Drawable drawable) {
@Override
public void onResourceReady(GlideDrawable resource,
GlideAnimation<? super GlideDrawable> glideAnimation) {
if (!resource.isAnimated()) {
resource = new SquaringDrawable(resource, mView.getDrawableSize());
}
this.mResource = resource;
setDrawable(resource);
resource.setLoopCount(GlideDrawable.LOOP_FOREVER);
Expand Down

0 comments on commit a620d79

Please sign in to comment.