Created
July 19, 2017 07:51
-
-
Save wyon/c6262108e266dbc70e73a3c2fa97dfd5 to your computer and use it in GitHub Desktop.
RoundCornerImageView 带圆角的ImageView
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
public class RoundCornerImageView extends ImageView { | |
private final RectF mTmpRectF = new RectF(); | |
private int topLeftRadius; | |
private int topRightRadius; | |
private int bottomLeftRadius; | |
private int bottomRightRadius; | |
// todo canvas.clipPath(Round Rect)? | |
private Path topLeftPath; | |
private Path topRightPath; | |
private Path bottomLeftPath; | |
private Path bottomRightPath; | |
private boolean hasRound; | |
private Paint roundPaint; | |
private Paint defaultPaint; | |
private Bitmap mTmpBitmap; | |
private Canvas mCanvasOrigin; | |
public RoundCornerImageView(Context context) { | |
super(context); | |
init(context, null); | |
} | |
public RoundCornerImageView(Context context, @Nullable AttributeSet attrs) { | |
super(context, attrs); | |
init(context, attrs); | |
} | |
public RoundCornerImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { | |
super(context, attrs, defStyleAttr); | |
init(context, attrs); | |
} | |
@TargetApi(Build.VERSION_CODES.LOLLIPOP) | |
public RoundCornerImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { | |
super(context, attrs, defStyleAttr, defStyleRes); | |
init(context, attrs); | |
} | |
private void init(Context context, AttributeSet attrs) { | |
if (attrs != null) { | |
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundCornerImageView); | |
if (a != null) { | |
final int radius = a.getDimensionPixelSize(R.styleable.RoundCornerImageView_radius, 0); | |
topLeftRadius = a.getDimensionPixelSize(R.styleable.RoundCornerImageView_topLeftRadius, radius); | |
topRightRadius = a.getDimensionPixelSize(R.styleable.RoundCornerImageView_topRightRadius, radius); | |
bottomLeftRadius = a.getDimensionPixelSize(R.styleable.RoundCornerImageView_bottomLeftRadius, radius); | |
bottomRightRadius = a.getDimensionPixelSize(R.styleable.RoundCornerImageView_bottomRightRadius, radius); | |
a.recycle(); | |
} | |
} | |
setHasRound(); | |
} | |
private void setHasRound() { | |
hasRound = topLeftRadius > 0 | |
|| topRightRadius > 0 | |
|| bottomLeftRadius > 0 | |
|| bottomRightRadius > 0; | |
if (hasRound && roundPaint == null) { | |
roundPaint = new Paint(); | |
roundPaint.setColor(Color.WHITE); | |
roundPaint.setAntiAlias(true); | |
roundPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); | |
defaultPaint = new Paint(); | |
defaultPaint.setXfermode(null); | |
} | |
} | |
private void resetRoundPath() { | |
topLeftPath = topRightPath = bottomLeftPath = bottomRightPath = null; | |
} | |
private void initTopLeftPath() { | |
if (topLeftRadius > 0) { | |
if (topLeftPath == null) { | |
final Path path = new Path(); | |
path.moveTo(0, topLeftRadius); | |
path.lineTo(0, 0); | |
path.lineTo(topLeftRadius, 0); | |
mTmpRectF.setEmpty(); | |
mTmpRectF.set(0, 0, topLeftRadius * 2, topLeftRadius * 2); | |
path.arcTo(mTmpRectF, -90, -90); | |
path.close(); | |
topLeftPath = path; | |
} | |
} else { | |
topLeftPath = null; | |
} | |
} | |
private void initTopRightPath() { | |
if (topRightRadius > 0) { | |
if (topRightPath == null) { | |
final Path path = new Path(); | |
final int width = getWidth(); | |
path.moveTo(width, topRightRadius); | |
path.lineTo(width, 0); | |
path.lineTo(width - topRightRadius, 0); | |
mTmpRectF.setEmpty(); | |
mTmpRectF.set(width - topRightRadius * 2, 0, width, topRightRadius * 2); | |
path.arcTo(mTmpRectF, -90, 90); | |
path.close(); | |
topRightPath = path; | |
} | |
} else { | |
topRightPath = null; | |
} | |
} | |
private void initBottomLeftPath() { | |
if (bottomLeftRadius > 0) { | |
if (bottomLeftPath == null) { | |
final Path path = new Path(); | |
final int height = getHeight(); | |
path.moveTo(0, height - bottomLeftRadius); | |
path.lineTo(0, height); | |
path.lineTo(bottomLeftRadius, height); | |
mTmpRectF.setEmpty(); | |
mTmpRectF.set(0, height - bottomLeftRadius * 2, bottomLeftRadius * 2, height); | |
path.arcTo(mTmpRectF, 90, 90); | |
path.close(); | |
bottomLeftPath = path; | |
} | |
} else { | |
bottomLeftPath = null; | |
} | |
} | |
private void initBottomRightPath() { | |
if (bottomRightRadius > 0) { | |
if (bottomRightPath == null) { | |
final Path path = new Path(); | |
final int width = getWidth(); | |
final int height = getHeight(); | |
path.moveTo(width - bottomRightRadius, height); | |
path.lineTo(width, height); | |
path.lineTo(width, height - bottomRightRadius); | |
mTmpRectF.setEmpty(); | |
mTmpRectF.set(width - bottomRightRadius * 2, height - bottomRightRadius * 2, width, height); | |
path.arcTo(mTmpRectF, 0, 90); | |
path.close(); | |
bottomRightPath = path; | |
} | |
} else { | |
bottomRightPath = null; | |
} | |
} | |
private boolean canDrawRound() { | |
return hasRound && getWidth() != 0 && getHeight() != 0; | |
} | |
@Override | |
protected void onSizeChanged(int w, int h, int oldw, int oldh) { | |
super.onSizeChanged(w, h, oldw, oldh); | |
resetRoundPath(); | |
if (!canDrawRound()) { | |
return; | |
} | |
initTopLeftPath(); | |
initTopRightPath(); | |
initBottomLeftPath(); | |
initBottomRightPath(); | |
if (mTmpBitmap != null) { | |
mTmpBitmap.recycle(); | |
mTmpBitmap = null; | |
mCanvasOrigin = null; | |
} | |
} | |
@Override | |
public void draw(Canvas canvas) { | |
if (!canDrawRound()) { | |
super.draw(canvas); | |
return; | |
} | |
initCanvasOrigin(); | |
mCanvasOrigin.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); | |
super.draw(mCanvasOrigin); | |
// draw top left | |
if (topLeftPath != null) { | |
mCanvasOrigin.drawPath(topLeftPath, roundPaint); | |
} | |
// draw top right | |
if (topRightPath != null) { | |
mCanvasOrigin.drawPath(topRightPath, roundPaint); | |
} | |
// draw bottom left | |
if (bottomLeftPath != null) { | |
mCanvasOrigin.drawPath(bottomLeftPath, roundPaint); | |
} | |
// draw bottom right | |
if (bottomRightPath != null) { | |
mCanvasOrigin.drawPath(bottomRightPath, roundPaint); | |
} | |
canvas.drawBitmap(mTmpBitmap, 0, 0, defaultPaint); | |
} | |
private void initCanvasOrigin() { | |
if (mTmpBitmap == null) { | |
mTmpBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); | |
mCanvasOrigin = new Canvas(mTmpBitmap); | |
} | |
} | |
} | |
<declare-styleable name="RoundCornerImageView"> | |
<attr name="topLeftRadius" format="dimension"/> | |
<attr name="topRightRadius" format="dimension"/> | |
<attr name="bottomLeftRadius" format="dimension"/> | |
<attr name="bottomRightRadius" format="dimension"/> | |
<attr name="radius" format="dimension"/> | |
</declare-styleable> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment