简介
日常开发中经常要用到圆角矩形或者圆形来显示头像或图片,因此对于它的使用方式我们还是比较关注的。下面我们就自定义一个View
来进行圆角矩形或圆形图片的展示,同时也支持自定义设置边框大小、边框颜色、按下状态蒙层颜色等属性。
使用
1、在attrs.xml
中自定义属性
<declare-styleable name="RoundImageView">
<!-- 显示类型 -->
<attr name="imageType" format="enum">
<enum name="circle" value="0" />
<enum name="round" value="1" />
</attr>
<!-- 边框大小 -->
<attr name="borderWidth" format="dimension" />
<!-- 边框颜色 -->
<attr name="borderColor" format="color" />
<!-- 圆角大小 -->
<attr name="roundRadius" format="dimension" />
<!-- 按下状态蒙层颜色 -->
<attr name="coverColor" format="color" />
<!-- 是否可被按下 -->
<attr name="isPressed" format="boolean" />
</declare-styleable>
2、布局引用
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<com.wiggins.roundpicture.widget.RoundImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/pic_one" />
<com.wiggins.roundpicture.widget.RoundImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginBottom="@dimen/margin_large"
android:layout_marginTop="@dimen/margin_large"
android:src="@drawable/pic_three"
app:borderColor="@color/red"
app:borderWidth="1.5dp"
app:imageType="circle" />
<com.wiggins.roundpicture.widget.RoundImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/pic_two"
app:borderColor="@color/colorAccent"
app:borderWidth="1.5dp"
app:imageType="round" />
</LinearLayout>
3、自定义RoundImageView
初始化属性
private void initAttributes() {
// 设置缩放
setScaleType(ScaleType.CENTER_CROP);
// 初始化画笔等属性
mShaderMatrix = new Matrix();
mRcBitmap = new RectF();
mRcBorder = new RectF();
mBitmapPaint = new Paint();
mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setDither(true);
mBorderPaint = new Paint();
mBorderPaint.setAntiAlias(true);
mBorderPaint.setDither(true);
mBorderPaint.setStyle(Paint.Style.FILL);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStrokeWidth(mBorderWidth);
}
渲染器及大小
private void setShader() {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
Bitmap bitmap = getBitmapFromDrawable(drawable);
mBitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);
mBitmapPaint.setShader(mBitmapShader);
mRcBorder.set(0, 0, getWidth(), getHeight());
mBorderRadius = Math.min((mRcBorder.height() - mBorderWidth) / 2, (mRcBorder.width() - mBorderWidth) / 2);
if (mImageType == TYPE_CIRCLE) {
mRcBitmap.set(mBorderWidth, mBorderWidth, mRcBorder.width() - mBorderWidth, mRcBorder.height() - mBorderWidth);
} else if (mImageType == TYPE_ROUND) {
mRcBitmap.set(mBorderWidth / 2, mBorderWidth / 2, mRcBorder.width() - mBorderWidth / 2, mRcBorder.height() - mBorderWidth / 2);
}
mBitmapRadius = Math.min(mRcBitmap.height() / 2, mRcBitmap.width() / 2);
updateShaderMatrix(bitmap);
invalidate();
}
矩阵变换
private void updateShaderMatrix(Bitmap mBitmap) {
float scale;
float dx = 0;
float dy = 0;
mShaderMatrix.set(null);
if (mBitmap.getWidth() * mRcBitmap.height() > mRcBitmap.width() * mBitmap.getHeight()) {
scale = mRcBitmap.height() / (float) mBitmap.getHeight();
dx = (mRcBitmap.width() - mBitmap.getWidth() * scale) * 0.5f;
} else {
scale = mRcBitmap.width() / (float) mBitmap.getWidth();
dy = (mRcBitmap.height() - mBitmap.getHeight() * scale) * 0.5f;
}
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth);
mBitmapShader.setLocalMatrix(mShaderMatrix);
}
视图绘制
@Override
protected void onDraw(Canvas canvas) {
if (getDrawable() == null) {
return;
}
setShader();
if (mImageType == TYPE_ROUND) {
canvas.drawRoundRect(mRcBorder, mRoundRadius, mRoundRadius, mBorderPaint);
canvas.drawRoundRect(mRcBitmap, mRoundRadius, mRoundRadius, mBitmapPaint);
} else {
canvas.drawCircle(mCenterCoordinates, mCenterCoordinates, mBorderRadius, mBorderPaint);
canvas.drawCircle(mCenterCoordinates, mCenterCoordinates, mBitmapRadius, mBitmapPaint);
}
}
触屏事件
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
setPressed(true);
break;
case MotionEvent.ACTION_MOVE:
if (!mRcBitmap.contains(event.getX(), event.getY())) {
setPressed(false);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
setPressed(false);
break;
}
return true;
}
按下状态蒙层颜色
@Override
public void setPressed(boolean pressed) {
super.setPressed(pressed);
if (!mIsPressed) {
return;
}
if (pressed) {
mBitmapPaint.setColorFilter(new PorterDuffColorFilter(mCoverColor, PorterDuff.Mode.SRC_ATOP));
} else {
mBitmapPaint.setColorFilter(null);
}
invalidate();
}
项目地址 ☞ 传送门