<ShapedImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
app:radius="3dp"
app:strokeColor="#4D000000"
app:strokeWidth="1px"
app:widthWeight="1"
app:heightWeight="1"
app:base="heightBased"
/>
Last active
March 5, 2018 03:45
-
-
Save s1ntoneli/37b1233170555dc76ded696edf1ab80b to your computer and use it in GitHub Desktop.
指定比例的 ImageView
This file contains hidden or 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
| <?xml version="1.0" encoding="utf-8"?> | |
| <resources> | |
| <declare-styleable name="ShapedImageView"> | |
| <attr name="widthWeight" format="integer"/> | |
| <attr name="heightWeight" format="integer"/> | |
| <attr name="radius" format="dimension"/> | |
| <attr name="strokeColor"/> | |
| <attr name="strokeWidth" format="dimension"/> | |
| <attr name="base"> | |
| <enum name="heightBased" value="0" /> | |
| <enum name="widthBased" value="1" /> | |
| </attr> | |
| </declare-styleable> | |
| </resources> |
This file contains hidden or 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.Paint; | |
| import android.graphics.Path; | |
| import android.graphics.Rect; | |
| import android.graphics.RectF; | |
| import android.support.annotation.Nullable; | |
| import android.util.AttributeSet; | |
| import android.widget.ImageView; | |
| /** | |
| * Round ImageView | |
| * support equal-ratio scale | |
| */ | |
| public class ShapedImageView extends ImageView { | |
| private int widthWeight; | |
| private int heightWeight; | |
| private int base; | |
| private int radius; | |
| private int strokeColor; | |
| private int strokeWidth; | |
| public final static int HEIGHT_BASED = 0; | |
| public final static int WIDTH_BASED = 1; | |
| private final Path mRoundPath = new Path(); | |
| private final Paint mPaint = new Paint(); | |
| private final RectF mRect = new RectF(); | |
| private boolean mIsDirty = true; | |
| public ShapedImageView(Context context) { | |
| this(context, null); | |
| } | |
| public ShapedImageView(Context context, @Nullable AttributeSet attrs) { | |
| this(context, attrs, 0); | |
| } | |
| public ShapedImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { | |
| super(context, attrs, defStyleAttr); | |
| init(attrs, defStyleAttr); | |
| } | |
| private void init(AttributeSet attrs, int defStyleAttr) { | |
| final TypedArray attr = getContext().obtainStyledAttributes(attrs, R.styleable.ShapedImageView); | |
| widthWeight = attr.getInteger(R.styleable.ShapedImageView_widthWeight, 0); | |
| heightWeight = attr.getInteger(R.styleable.ShapedImageView_heightWeight, 0); | |
| base = attr.getInteger(R.styleable.ShapedImageView_base, 0); | |
| radius = attr.getDimensionPixelSize(R.styleable.ShapedImageView_radius, 0); | |
| strokeWidth = attr.getDimensionPixelSize(R.styleable.ShapedImageView_strokeWidth, 0); | |
| strokeColor = attr.getColor(R.styleable.ShapedImageView_strokeColor, 0x00000000); | |
| attr.recycle(); | |
| mPaint.setAntiAlias(true); | |
| mPaint.setStyle(Paint.Style.STROKE); | |
| mPaint.setStrokeWidth(strokeWidth); | |
| mPaint.setColor(strokeColor); | |
| } | |
| public void setCornerRadius(int px) { | |
| radius = px; | |
| mIsDirty = true; | |
| } | |
| public void setWidthWeight(int widthWeight) { | |
| this.widthWeight = widthWeight; | |
| mIsDirty = true; | |
| } | |
| public void setHeightWeight(int heightWeight) { | |
| this.heightWeight = heightWeight; | |
| mIsDirty = true; | |
| } | |
| public void setBase(int base) { | |
| this.base = base; | |
| mIsDirty = true; | |
| } | |
| @Override | |
| protected void onDraw(Canvas canvas) { | |
| if (!ensureValidRect()) { | |
| return; | |
| } | |
| canvas.save(); | |
| canvas.clipPath(mRoundPath); | |
| super.onDraw(canvas); | |
| canvas.restore(); | |
| canvas.drawRoundRect(mRect, radius, radius, mPaint); | |
| } | |
| @Override | |
| protected void onSizeChanged(int w, int h, int oldw, int oldh) { | |
| super.onSizeChanged(w, h, oldw, oldh); | |
| mIsDirty = true; | |
| } | |
| private boolean ensureValidRect() { | |
| if (mIsDirty) { | |
| mIsDirty = false; | |
| Rect bounds = new Rect(); | |
| float inset = mPaint.getStrokeWidth() * 0.5f; | |
| getDrawingRect(bounds); | |
| mRect.set(bounds.left + inset, bounds.top + inset, | |
| bounds.right - inset, bounds.bottom - inset); | |
| mRoundPath.addRoundRect(mRect, radius, radius, Path.Direction.CCW); | |
| } | |
| return !mRect.isEmpty(); | |
| } | |
| @Override | |
| protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
| if (widthWeight != 0 && heightWeight != 0) { | |
| if (base == HEIGHT_BASED) { | |
| int height = MeasureSpec.getSize(heightMeasureSpec); | |
| widthMeasureSpec = MeasureSpec.makeMeasureSpec(height * widthWeight / heightWeight, MeasureSpec.EXACTLY); | |
| } else { | |
| int width = MeasureSpec.getSize(widthMeasureSpec); | |
| heightMeasureSpec = MeasureSpec.makeMeasureSpec(width * heightWeight / widthWeight, MeasureSpec.EXACTLY); | |
| } | |
| } | |
| super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment