android,自定义View 基本概念

相关链接:自定义View详解

基本概念

View类是android提供的控件基类,其常用的子类有Button、TextView...

View的绘制包含三个方面:宽高、位置、样式(形状、颜色...),分别对应measure()、layout()、draw()三个函数,在View中实现了这三方面的基本功能,和基本的属性

xml布局的控件属性,基本都是围绕这三方面的

当android提供的控件,不能满足需要时。我们可以自定义View,即创建View的子类,主要考虑宽高、样式(形状、颜色...)两个方面(一般自定义ViewGroup时要考虑到位置)

体现在代码上就是重写onMeasure()和onDraw()

有时候还需要自定义View的属性,需要在构造方法中获取属性值

Android中,自定义View是一个大的技术点,可深、可广

基本实现步骤,如下

继承View

package com.clc.diyview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

public class View1 extends View {
    //自定义属性,对应 R.styleable.view1(xml),记得getter/setter
    private String attributeStr;
    private int attributeInteger;

    //必须有一个构造方法
    public View1(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        //获取属性集资源(自定义属性时才需要)
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.view1);

        //获取xml布局中View1相应的属性值
        attributeStr = typedArray.getString(R.styleable.view1_attribute_str);
        attributeInteger = typedArray.getInteger(R.styleable.view1_attribute_integer, -1);

        //最后,回收typedArray
        typedArray.recycle();
    }

    //重写onMeasure(),设置控件宽高;不重写,则表示采用父类View默认的宽高处理逻辑
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //调用父类View基本的宽高处理功能
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        /*
        xxxMeasureSpec是xml布局中View1宽高属性的int值,这个int值(32bit)包含两部分,前2bit为尺寸模式(UNSPECIFIED/EXACTLY/AT_MOST),剩余30bit为尺寸值
        宽高值对应模式:match_parent-->EXACTLY
                    固定尺寸(如10dp)-->EXACTLY
                    warp_content--> AT_MOST
         */
        //获取width的尺寸模式
        int wmode = MeasureSpec.getMode(widthMeasureSpec);
        //获取width的尺寸值
        int width = MeasureSpec.getSize(widthMeasureSpec);

        int hmode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        //处理宽高...

        //设置最终宽高
        setMeasuredDimension(width,height);
    }

    //重写onDraw(),绘制控件;不重写,则表示采用父类View默认的绘制功能
    @Override
    protected void onDraw(Canvas canvas) {
        //调用父类View基本的绘制功能
        super.onDraw(canvas);

        //...

        //canvas.xxx();//绘制
    }

}

在xml布局中应用

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

    <com.clc.diyview.View1
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="#F44336"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:attribute_str="sssss"
        app:attribute_integer="11111"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

自定义属性

新建 res/values/attrs.xml,自定义属性详细介绍

<resources>

    <!--声明属性集合,name为“属性集合”的资源名-->
    <declare-styleable name="view1">
        <!--声明单个属性,name为属性名,format指定属性值类型-->
        <attr name="attribute_str" format="string" />
        <attr name="attribute_integer" format="integer" />
    </declare-styleable>

</resources>

把自定义属性绑定到自定义View中

public class View1 extends View {
    //自定义属性,对应 R.styleable.view1(xml),记得getter/setter
    private String attributeStr;
    private int attributeInteger;

    //必须有一个构造方法
    public View1(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        //获取属性集资源
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.view1);

        //获取xml布局中View1相应的属性值,getXxx(index) index为属性id:属性集资源id_属性名
        attributeStr = typedArray.getString(R.styleable.view1_attribute_str);
        attributeInteger = typedArray.getInteger(R.styleable.view1_attribute_integer, -1);

        //最后,回收typedArray
        typedArray.recycle();
    }
    
    //......

xml布局中使用自定义属性

<com.clc.diyview.View1
    ...
    app:attribute_str="sssss"
    app:attribute_integer="11111"
    ...
    />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值