谈到 Android自定义控件 ,这是一个令人渴望又害怕的领域,是作为一个Android开发人员的必经之路。
鄙人也是一名初学者,怀着一颗分享的心,将自己所理解的知识点与君分享,不足之处望纠正
哈哈哈,说的有点多了,下面直入正题吧!
一、自定义控件预备知识点①构造方法
package com.example.mytextview;
//import javax.swing.text.View; 这里别到错了包,这个包是错误的
import android.content.Context;
import android.util.AttributeSet;
import android.view.View; //这个是正确的包
import androidx.annotation.Nullable;
ppublic class TextView extends View {
// 构造函数会在代码里面new的时候调用 : TextView tv = new TextView(this);
// 用 this 的好处就是 不管你从哪个构造函数 进入, 都会走到第三个里面 进行统一处理
public TextView(Context context) {
this(context,null);
}
// 在布局 layout 中使用(调用) :
// <com.example.view_day01.TextView
// android:layout_width="wrap_content"
// android:layout_height="wrap_content"
// android:text="Hello World!" />
public TextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
// 在布局 layout 中使用(调用) 但是会有style:
// <com.example.view_day01.TextView
// style="@style/myStyle"
// android:text="Hello World!" />
public TextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
系统为我们提供了 四种构造方法 但是,第四种几乎用不到,所有,为列出。
对于以上三种构造方法,我们需要掌握的就是:①这几个构造方法在什么时候被调用,和Activity生命周期检测一样,可以通过打印Log来分辨,(调用时期已注解在旁边,望知)
②我们通常将前两个构造方法的 super 修改为 this,方便在第三个构造方法里进行统一处理。
②常用方法
/**
*自定义View的测量方法
*@Author yiqi
*@created 2021/2/22 14:04
*@param widthMeasureSpec || heightMeasureSpec 32位的值 前两位是 model :MeasureSpec.AT_MOST
* 后三十位是 Integer.MAX_VALUE
*@return
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//这个可以解决 ScrollView 嵌套 ListView 显示不全的问题(面试常被问及)
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2 , MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//布局的宽高都是由这个方法指定
//指定控件的宽高,需要测量
//获取宽高的模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec); //获取前两位
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//获取宽高的值
int widthSize = MeasureSpec.getSize(widthMeasureSpec); //获取后面30位
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// MeasureSpec.AT_MOST : 在布局中指定了wrap_content
// MeasureSpec.EXACTLY : 在布局中指定了确切的值 100dp match_parent fill_parent
// MeasureSpec.UNSPECIFIED : 尽可能的大 , 很少能用到 ListView ScrollView 在测量子布局的时候会用到 UNSPECIFIED
if (widthMode == MeasureSpec.UNSPECIFIED){
}
}
对于onMeasure()这个方法,我们需要弄清楚一下几点:
第一点:widthMeasureSpec, heightMeasureSpec 都是 32位二进制值,前两位代表模式 可以通过 MeasureSpec.getMode 获取,后30位代表最大宽高 可以通过 MeasureSpec.getSize 获取
第二点:MeasureSpec.makeMeasureSpec() 这个方法可以用来设置 测量模式,(这个地方会牵扯一个面试问题=》S从rollView里嵌套ListView ListView显示不全问题,后面章节进行讲解)
第三点:setMeasuredDimension() 这个方法可以用来设置自定义控件的宽高
/**
*用于绘制
*@Author yiqi
*@created 2021/2/22 18:00
*@param
*@return
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画文本
canvas.drawText();
//画弧
canvas.drawArc();
//画圆
canvas.drawCircle();
}
对于 onDraw() 方法 主要是掌握以上就差不多了,后面用到时会详细讲解
/**
*处理跟用户交互的 手指触摸等等
*@Author yiqi
*@created 2021/2/22 18:05
*@param
*@return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
}
return super.onTouchEvent(event);
}
对于 onTouchEvent() 方法,并非一言两语就能说尽的,它也是得在实战中体现其价值。
看到这里,就说明你掌握基础了,是不是觉得很简单呢!!!,哈哈哈。可是别轻敌,前面轻松代表后面很苦哦
本文摘自 :https://blog.51cto.com/u