安卓开发:1、自定义控件(自定义View)(自定义圆形图片控件ImageView)

在写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"/> <!--此行为自定义属性 --> 
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

倚肆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值