Android 简单的自定义View

在下面的例子中,我将讲解:

  • 如何实现一个基本的自定义View(继承VIew)
  • 如何自身支持wrap_content & padding属性
  • 如何为自定义View提供自定义属性(如颜色等等)
  • 实例说明:画一个实心圆

具体步骤

  • 创建自定义View类(继承View类)
  • 布局文件添加自定义View组件
  • 注意点设置(支持wrap_content & padding属性自定义属性等等)

创建自定义View类(继承View类)

// 用于绘制自定义View的具体内容
// 具体绘制是在复写的onDraw()内实现

public class CircleView extends View {

    // 设置画笔变量
    Paint mPaint1;

    // 自定义View有三个构造函数
    // 如果View是在Java代码里面new的,则调用第一个构造函数
    public CircleView(Context context){
        super(context);
        // 在构造函数里初始化画笔的操作
        init();
    }

// 如果View是在.xml里声明的,则调用第二个构造函数
// 自定义属性是从AttributeSet参数传进来的
    public CircleView(Context context,AttributeSet attrs){
        super(context, attrs);
        init();
    }

// 不会自动调用
// 一般是在第二个构造函数里主动调用
// 如View有style属性时
    public CircleView(Context context,AttributeSet attrs,int defStyleAttr ){
        super(context, attrs,defStyleAttr);
        init();
    }

    // 画笔初始化
    private void init() {
        // 创建画笔
        mPaint1 = new Paint ();
        // 设置画笔颜色为蓝色
        mPaint1.setColor(Color.BLUE);
        // 设置画笔宽度为5px
        mPaint1.setStrokeWidth(5f);
        //设置画笔模式为填充
        mPaint1.setStyle(Paint.Style.FILL);
    }

    // 复写onDraw()进行绘制  
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

       // 获取控件的高度和宽度
        int width = getWidth();
        int height = getHeight();

        // 设置圆的半径 = 宽,高最小值的2分之1
        int r = Math.min(width, height)/2;

        // 画出圆(蓝色)
        // 圆心 = 控件的中央,半径 = 宽,高最小值的2分之1
        canvas.drawCircle(width/2,height/2,r,mPaint1);
    }

}

在布局文件中添加自定义View类的组件 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 注意添加自定义View组件的标签名:包名 + 自定义View类名-->
    <!--  控件背景设置为黑色-->
    <com.example.learnview.CircleView
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:background="#000000" />
    
</RelativeLayout>

 

好了,至此,一个基本的自定义View已经实现了。接下来继续看自定义View所有应该注意的点:

  • 如何手动支持wrap_content属性
  • 如何手动支持padding属性
  • 如何为自定义View提供自定义属性(如颜色等等)

先来看wrap_content & match_parent属性的区别

// 视图的宽和高刚好适应视图内容的最小尺寸
android:layout_width="wrap_content"

// 视图的宽和高充满整个父布局
android:layout_width="match_parent"
// 在Android API 8之前叫作"fill_parent"
  • 但有些时候需要一些系统所没有的属性,称为自定义属性
  • 使用步骤有如下:
    1 在values目录下创建自定义属性的xml文件
    2 在自定义View的构造方法中解析自定义属性的值
    3 在布局文件中使用自定义属性

在values目录下创建自定义属性的xml文件

attrs_circle_view.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--自定义属性集合:CircleView-->
    <!--在该集合下,设置不同的自定义属性-->
    <declare-styleable name="CircleView">
        <!--在attr标签下设置需要的自定义属性-->
        <!--此处定义了一个设置图形的颜色:circle_color属性,格式是color,代表颜色-->
        <!--格式有很多种,如资源id(reference)等等-->
        <attr name="circle_color" format="color"/>

    </declare-styleable>
</resources>

在自定义View的构造方法中解析自定义属性的值

 // 不会自动调用
// 一般是在第二个构造函数里主动调用
// 如View有style属性时
    public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // 加载自定义属性集合CircleView
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.CircleView);

        // 解析集合中的属性circle_color属性
        // 该属性的id为:R.styleable.CircleView_circle_color
        // 将解析的属性传入到画圆的画笔颜色变量当中(本质上是自定义画圆画笔的颜色)
        // 第二个参数是默认设置颜色(即无指定circle_color情况下使用)
        mColor = a.getColor(R.styleable.CircleView_circle_color,Color.RED);

        // 解析后释放资源
        a.recycle();

        init();
    }

// 画笔初始化
    private void init() {
        // 创建画笔
        mPaint1 = new Paint();
        // 设置画笔颜色为蓝色
        mPaint1.setColor(mColor);
        // 设置画笔宽度为5px
        mPaint1.setStrokeWidth(5f);
        //设置画笔模式为填充
        mPaint1.setStyle(Paint.Style.FILL);
    }
 

 

在布局文件中使用自定义属性

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- 注意添加自定义View组件的标签名:包名 + 自定义View类名-->
    <!--  控件背景设置为黑色-->
    <com.example.learnview.CircleView
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:padding="20dp"
        app:circle_color="#FF4081"
        android:background="#000000" />

</RelativeLayout>


参考:https://www.jianshu.com/p/36dbd814dca3
posted @ 2025-03-25 15:07  春天又来了  阅读(82)  评论(0)    收藏  举报