IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 自定义View浅析 -> 正文阅读

[移动开发]自定义View浅析

自定义View过程

自定义View关键点:onMeasure()、onDraw()

onMeasure

该函数目的是测量View宽高属性,虽然在xml中制定了View宽高,但当设置为wrap_contentmatch_parent时,此处获取宽高就需要由onMeasure()处理。

举例:
实现一个宽采用match_parent,而高为100dp的正方形。
在不重写方法情况下,上述长宽通常是不同的,所以就需要在测量函数中调整长宽长度。

 private int getMySize(int defaultSize, int measureSpec) {
        int mySize = defaultSize;

        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);

        switch (mode) {
            case MeasureSpec.UNSPECIFIED: {//如果没有指定大小,就设置为默认大小
                mySize = defaultSize;
                break;
            }
            case MeasureSpec.AT_MOST: {//如果测量模式是最大取值为size
                //我们将大小取最大值,你也可以取其他值
                mySize = size;
                break;
            }
            case MeasureSpec.EXACTLY: {//如果是固定的大小,那就不要去改变它
                mySize = size;
                break;
            }
        }
        return mySize;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = getMySize(100, widthMeasureSpec);
        int height = getMySize(100, heightMeasureSpec);

		//进行正方形长宽判断设置
        if (width < height) {
            height = width;
        } else {
            width = height;
        }

        setMeasuredDimension(width, height);
}

布局:

  <com.hc.studyview.MyView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#ff0000" />

方法内部分参数名词解析:

onMeasure(int widthMeasureSpec, int heightMeasureSpec)
其中两个参数分别包含了宽度+测量模式,高度+测量模式
存放方式:一个int数据占32bit,前两个bit用于存放测量模式(只有三个模式,2bit足够存放),后30bit存放尺寸数据
其内容用内置类MeasureSpec可以直接获取:

int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);

测量模式:
match_parent对应EXACTLY:当前尺寸即View应该用的尺寸(即父View剩余空间尺寸)
wrap_content对应AT_MOST:当前尺寸是View可以取的最大尺寸
用户定的尺寸对应EXACTLY:指定大小,不用再干涉
还有一个测量模式UNSPECIFIED:对当前View没有限制

注意事项

上述控件需要放在LinearLayout中,不然setMeasuredDimension(width, height);将无效,而此句是确定长宽的重要部分

onDraw

在上述正方形View绘画一个圆形:

	@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int r = getMeasuredWidth() / 2;
        int x = r;
        int y = r;

        Paint paint = new Paint();
        paint.setColor(Color.BLUE);
        canvas.drawCircle(x, y, r, paint);
    }

注:canvas.drawCircle(x, y, r, paint);这一步前两个x,y是相对于当前View的位置,有文章内采用int centerX = getLeft() + r;这样获取出来的圆心位置是相对于父View的布局,即当View在左上角,显示正常(起始点就在父View0,0处),而换位置后,球就会消失,即小球不会跟着View移动

自定义布局属性

可以通过自定义布局属性去在布局里给控件xml文件添加字段。
styles.xml
该文件定义具体字段
res下values下建立该文件

<resources>

    <!--name为声明的"属性集合"名,可以随便取,但是最好是设置为跟我们的View一样的名称-->
    <declare-styleable name="MyView">
        <!--声明我们的属性,名称为default_size,取值类型为尺寸类型(dp,px等)-->
        <attr name="default_size" format="dimension" />
    </declare-styleable>
</resources>

此时在布局文件中,控件就可以添加对应default_size属性:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:proper="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.example.view.MyView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#ff0000"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        proper:default_size="100dp"/>


</LinearLayout>

注意头段xmlns:proper用于将自定义属性与其余自带分别出来,即在控件中直接proper:default_size="100dp"即可

通过上述设置,就可以在View中依据添加的字段获取其值:

public class MyView extends View {
    private int defaultSize;

    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);

        defaultSize = a.getDimensionPixelSize(R.styleable.MyView_default_size, 100);

        a.recycle();
    }

解析:
context.obtainStyledAttributes(attrs, R.styleable.MyView);这里第二个参数就是在styles.xml里设置的属性集合名
defaultSize = a.getDimensionPixelSize(R.styleable.MyView_default_size, 100);经过上述获得TypedArray后,即可通过字段获取在布局文件中设置好的值(第二个参数是获取失败后的默认值)

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-11 16:33:45  更:2022-05-11 16:34:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:42:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码