1、前言

最近发现自己如同并不是很会自界说View这一块捏,像个癌症晚期患者上不去,下不来,就卡那儿了,所以特发此篇文章学习和共享一下自界说View。

2、概述

我将自界说View分为三个过程:

  1. 自界说View特点以及获取
  2. 重写View的onDraw办法
  3. 重写View的onMeasure办法

本篇将说明自界说View特点以及获取

3、自界说View特点以及获取

自界说View特点

首要在选中项目目录中的values文件夹并新建attrs资源文件。如下图:

从0开始学会自定义View(一)

Ok,创立完成后咱们会看到这样的内容:

<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

之后就需求咱们在里面声明咱们需求的自界说特点了。 特点的声明格式如下:

<attr name="xxxx" format="xxxx"/>
  • name:便是你想要声明特点的姓名,到时候获取对应特点依托的便是这个name。

  • format:声明特点的格式,表明你这个特点它详细是什么,像色彩、字符串或者是其他的类型,可是这个format并不是随意给值的,一下是format的详细可取值的范围:

    format format类型
    color 表明色彩
    string 表明字符串
    boolean 表明布尔值
    reference 表明引证(如drawable
    dimension 表明尺寸
    float 表明浮点类型
    integer 表明整形
    fraction 表明百分数
    enum 表明枚举
    flags 表明位运算

声明特点的办法有多种,这儿给出最常用的两种办法:

  • 普通写法

    <!--布景色彩-->
    <attr name="solid_color" format="color"/>
    <!--文字-->
    <attr name="text" format="string"/>
    <!--文字色彩-->
    <attr name="text_color" format="color"/>
    <!--文字大小-->
    <attr name="text_size" format="dimension"/>
    
  • declare-styleable 标签封装 attr

    <declare-styleable name="MyCustomView">
      <!--布景色彩-->
      <attr name="solid_color" format="color"/>
      <!--文字-->
      <attr name="text" format="string"/>
      <!--文字色彩-->
      <attr name="text_color" format="color"/>
      <!--文字大小-->
      <attr name="text_size" format="dimension"/>
    </declare-styleable>
    

完成之后,咱们去创立一个自界说的View,本文类名为MyCustomView承继View,之后补全结构办法即可。

获取自界说特点

首要依据第一步中咱们创立的特点在MyCustomView中创立对应的目标:

private int mSolidColor; //布景色彩
private String mText; //文字
private int mTextColor; //文字色彩
private float mTextSize; //文字大小
private Paint mPaint; //画笔
private Rect mTextBound; //接受文字鸿沟

然后写一个获取自界说特点的办法给结构办法调用:

private void obtainAttrs(Context context, AttributeSet attrs) {
}

接着便是最重要的过程——运用创立TypedArray目标并用其获取到咱们创立的特点然后应用到画笔中:

  • 普通写法获取特点:

      int[] attrsKey = new int[]{R.attr.solid_color, R.attr.text, R.attr.text_color, R.attr.text_size};
      TypedArray a = context.obtainStyledAttributes(attrs, attrsKey);
      mSolidColor = a.getColor(0, 0xFF000000);
      mText = a.getString(1);
      mTextColor = a.getColor(2, 0xFFFFFFFF);
      mTextSize = a.getDimension(3, 14F);
      a.recycle();
    

    其间attrsKey代表自界说特点的调集,在context的obtainStyledAttributes办法中依托这个调集的索引来获取详细的特点

  • 带有declare-styleable标签获取特点:

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);
    mSolidColor = a.getColor(R.styleable.MyCustomView_solid_color, 0);
    mText = a.getString(R.styleable.MyCustomView_text);
    mTextColor = a.getColor(R.styleable.MyCustomView_text_color,0xFFFFFFFF);
    mTextSize = a.getDimension(R.styleable.MyCustomView_text_size,sp2px(14));
    a.recycle();
    

    其间MyCustomView是自界说特点中你声明的标签姓名,在后续获取详细的特点时传入的参数格式就为“声明的styleable名称_自界说特点名“ 应用到画笔中:

mPaint = new Paint();
mPaint.setTextSize(mTextSize); //设置文字大小
mTextBound = new Rect();
mPaint.getTextBounds(mText, 0, mText.length(), mTextBound);//丈量文字鸿沟

获取到TypedArray目标之后就能够运用它的办法来获取对应的特点,这些办法一般都需求索引(index以及一个默认值,最终最重要的一点便是在用完TypedArray目标之后必定必定要记住收回

a.recycle();//收回

最终重写onDraw,画一个简单的带布景的文字图形:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    mPaint.setColor(mSolidColor);//布景色彩
    canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);//制作布景
    mPaint.setColor(mTextColor);//文字色彩
    canvas.drawText(mText, getWidth() / 2 - mTextBound.width() / 2, getHeight() / 2 + mTextBound.height() / 2, mPaint);//制作文字
}

在布局文件引入咱们的自界说View:

<?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"
    android:background="@color/white"
    tools:context=".MainActivity">
    <com.my.mycustomview.MyCustomView
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:solid_color="@color/black"
        app:text="AAA"
        app:text_color="@color/white"
        app:text_size="25sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

效果图如下:

从0开始学会自定义View(一)

4、更多

复用自界说特点

当咱们一个自界说View有许多承继的子类,这些字类有共用的特点时能够选择复用自界说特点(以本文中的MyCustomView举例:

<!--布景色彩-->
<attr name="solid_color" format="color"/>
<!--文字-->
<attr name="text" format="string"/>
<!--文字色彩-->
<attr name="text_color" format="color"/>
<!--文字大小-->
<attr name="text_size" format="dimension"/>
<declare-styleable name="MyCustomView">
    <attr name="solid_color"/>
    <attr name="text"/>
    <attr name="text_color"/>
    <attr name="text_size"/>
</declare-styleable>
<!--另一个View-->
<declare-styleable name="XXXView">
    <attr name="solid_color"/>
    <attr name="text"/>
    <attr name="text_color"/>
    <attr name="text_size"/>
    <!--特有特点-->
    <attr name="xxxx" format="xxxx"/>
</declare-styleable>

这样共用的特点不必重复界说,在取值的时候只需求改变你声明的styleable姓名即可:

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.XXXView);

关于attrs

以第3点中的attrs为例子,attr 标签特点会在R类下的attr类中生成16进制地址静态常量

从0开始学会自定义View(一)
从0开始学会自定义View(一)

而运用declare-styleable封装的attr会在R类下的styleable类封装attr类下的16进制地址生成int[]数组,并生成下标索引:

从0开始学会自定义View(一)

完毕

那么到这儿这篇内容就完毕了,在这篇文章中讲述了自界说View的根本过程,以及如何自界说特点和如何获取这些特点,关于重写onDraw办法会放到下一章节说明,时间不定,作者懒狗一条,拜拜捏!