自定义圆形、圆角矩形View

时间:2021-06-18 20:38:14

简介

日常开发中经常要用到圆角矩形或者圆形来显示头像或图片,因此对于它的使用方式我们还是比较关注的。下面我们就自定义一个View来进行圆角矩形或圆形图片的展示,同时也支持自定义设置边框大小、边框颜色、按下状态蒙层颜色等属性。

自定义圆形、圆角矩形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();
}

项目地址 ☞ 传送门