在写android的时候使用到了自定控件,下面借着自定义圆形图片控件来记录一下控件的自定义方法。
自定义控件第1步:创建java文件
CircleImageView.java
public class CircleImageView extends AppCompatImageView {
private Paint paint = null;//画笔
private int radius;//圆形半径
private float scale;//图片缩放比例
private int borderWidth = 0;
private int borderColor = 0;
BitmapShader bitmapShader = null;
private Bitmap bitmap = null;//即将被绘制的图形
private Matrix matrix = null;//缩放的计算工具
public CircleImageView(@NonNull Context context) {
super(context);
}
public CircleImageView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView);
borderWidth = (int)typedArray.getDimension(R.styleable.CircleImageView_CircleImageView_borderWidth, 0);
borderColor = typedArray.getColor(R.styleable.CircleImageView_CircleImageView_color, 0);
typedArray.recycle();
}
public CircleImageView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取最短边用于圆形直径
//计算圆形半径
radius = Math.min(getMeasuredHeight(),getMeasuredWidth()) / 2;//Math.float(size/2.0)向下取整,绝对不要四舍五入
setMeasuredDimension(2 * radius,2 * radius);
Log.e("getMeasuredWidth()", "getMeasuredWidth(): " + getMeasuredWidth() );
Log.e("getMeasuredHeight()", "getMeasuredHeight(): " + getMeasuredHeight() );
Log.e("borderWidth", "borderWidth: " + borderWidth );
}
/**
* 用于绘制图形
* @param canvas 画板,需要用画笔在画板上绘画
*/
@Override
protected void onDraw(Canvas canvas) {
Log.e("onDraw", "onDraw: " );
paint = new Paint();//创建画笔 因为绘制可能会频繁被调用 与在循环操作限制一样 尽量避免在内部声明变量
paint.setAntiAlias(true);
//获取需要被绘制的图片
createBitmap(getDrawable());
//TitleMode.CLAMP 图片的渲染方式 边缘拉伸
bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//创建Bitmap的时候直接缩放图片
scale =((radius - borderWidth)*2.0f)/Math.min(bitmap.getHeight(), bitmap.getWidth());
matrix = new Matrix();
matrix.setScale(scale, scale, borderWidth, borderWidth);
bitmapShader.setLocalMatrix(matrix);
if (borderWidth > 0){
paint.setColor(borderColor);
canvas.drawCircle(radius, radius, radius, paint);
paint.reset();
paint.setAntiAlias(true);
}
//告知画笔绘制的内容
paint.setShader(bitmapShader);
//绘制圆形
canvas.drawCircle(radius, radius, radius - borderWidth, paint);
paint = null;
bitmapShader = null;
bitmap = null;
matrix = null;
}
private void createBitmap(Drawable drawable){
if (drawable instanceof BitmapDrawable){
bitmap = ((BitmapDrawable)drawable).getBitmap();
}else{
//首先创建一张空白图片
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
//在当前图片上创建画板
Canvas canvas = new Canvas(bitmap);
//将 drawable绘制到画板中
drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
drawable.draw(canvas);
canvas = null;
}
}
}
自定义控件第2步:如果自定义文件中含有自定义属性,想要调用的话,需要在values文件夹中创建自定义属性xml文件(本实例中创建了attrs.xml),之后在上方代码的构造器重载中进行引用,运用到TypedArray类
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleImageView">
<attr name="CircleImageView_color" format="color"/>
<attr name="CircleImageView_borderWidth" format="dimension"/>
</declare-styleable>
</resources>
CircleImageView.java中的构造器
public CircleImageView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView);
borderWidth = (int)typedArray.getDimension(R.styleable.CircleImageView_CircleImageView_borderWidth, 0);
borderColor = typedArray.getColor(R.styleable.CircleImageView_CircleImageView_color, 0);
typedArray.recycle();
}
自定义控件第3步:在layout布局文件中引用
<com.example.practicaltraining_musicplayer_xj.ui.custom.CircleImageView
android:id="@+id/img_manager_cover"
android:layout_width="@dimen/home_nav_img"
android:layout_height="@dimen/home_nav_img"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:CircleImageView_color="@color/black" <!-此行为自定义属性 -->
app:CircleImageView_borderWidth="5dp"/> <!--此行为自定义属性 -->