Android 从 0 开始学习自定义 View(一)基本流程

1.概述

一开始也很害怕自定义 View,机缘之下看了辉哥-红橙Darren的视频,跟着视频开始学习自定义 View,之后一系列的文章也是记录自定义 View 的学习过程。

2.自定义 View 的基本流程

  • 创建 View Class
  • 创建 attr 属性文件,确定属性
  • View Class 绑定 attr 属性
  • onMeasure 测量
  • onDraw 绘制
2.1 创建 View Class ( 以 CustomTextView 为例子 )
public class CustomTextView extends View {
    //在初始化时调用
    public CustomTextView(Context context) {
        this(context, null);
    }

    //在 Layout 中调用
    public CustomTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    //在 Layout 中设置 style 调用
    public CustomTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}
2.2 创建 Attr 属性文件
Android 从 0 开始学习自定义 View(一)基本流程_第1张图片
Attr

res -> values -> New Values Resource File

attr.xml
 

    
        
        
        
        
        
        
    

2.3 View Class 绑定属性
定义属性
private void initAttr(Context context, AttributeSet attrs) {
    //第一步获取 TypedArray
    TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView);
    //第二步获取属性
    mText = array.getString(R.styleable.CustomTextView_cusText);
    mTextColor = array.getColor(R.styleable.CustomTextView_cusTextColor, mTextColor);
    //默认是 px,将 sp 转换成 px
     mTextSize = array.getDimensionPixelSize(R.styleable.CustomTextView_cusTextSize, sp2px(mTextSize));
    //回收
    array.recycle();
}


private int sp2px(int sp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
}
2.4 onMeasure 测量
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    //第一步获取测量模式
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    //第二步获取数值
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    //第三步判断模式,如果是 wrap_content 就需要计算宽高
    //通过画笔 Paint 测量文本的宽高
    Rect rect = new Rect();
    mPaint.getTextBounds(mText, 0, mText.length(), rect);
    if (widthMode == MeasureSpec.AT_MOST) {
        widthSize = rect.width() + getPaddingLeft() + getPaddingRight();
    }
    if (heightMode == MeasureSpec.AT_MOST) {
        heightSize = rect.height() + getPaddingTop() + getPaddingBottom();
    }
    //第四部设置宽高
    setMeasuredDimension(widthSize, heightSize);
}
2.5 onDraw 绘制
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int x = getPaddingLeft();
    //需要计算基线 baseline 位置
    //获取
    Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt();
    //两种计算方式
    //(fontMetricsInt.bottom - fontMetricsInt.top)/2 - fontMetricsInt.bottom
    //(fontMetricsInt.top - fontMetricsInt.bottom) / 2 - fontMetricsInt.top
    int y = (fontMetricsInt.bottom - fontMetricsInt.top)/2 - fontMetricsInt.bottom;
    int baseline = getHeight() / 2 + y;
    canvas.drawText(mText, x, baseline, mPaint);
}
给大家大致讲一下基线计算方式
Android 从 0 开始学习自定义 View(一)基本流程_第2张图片
基线.jpg
发现在原有的图上操作太麻烦,画了一张草图
Android 从 0 开始学习自定义 View(一)基本流程_第3张图片
计算方式.jpg
最简单的自定义 View 流程大概就是这么多,总结一下需要常用的方法。
  1. onMeasure
  • MeasureSpec.getMode
  • MeasureSpec.getSize
  • setMeasuredDimension
  1. onDraw
  • Paint.FontMetricsInt 计算 BaseLine 基线
  • drawText|drawCircle|drawArc ......

GitHub 源码链接

你可能感兴趣的:(Android 从 0 开始学习自定义 View(一)基本流程)