波形自定义控件(二):原理解析之初始化

上一篇向我们展示了WaveLoadingView的效果,本篇及后续几篇来讲解它的实现原理,先从控件的初始化开始。

创建自定义控件的java文件

首先我们为自定义控件创建一个java文件,并让它继承某个自定义控件,以WaveLoadingView为例,此外还需要继承控件的构造函数,默认有四个,都继承下来。

public class WaveLoadingView extends View {
	//1
	public WaveLoadingView(Context context) {
        super(context);
    }

	//2
    public WaveLoadingView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context,attrs);
    }

	//3
    public WaveLoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context,attrs);
    }

	//4
    public WaveLoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        ...
    }
	...
}

其实1~3构造函数最终都调用了4构造函数,在构造函数里我们需要获取到布局文件的参数并完成初始化,下面会讲解。

自定义参数

<com.pyjtlk.waveloadview.WaveLoadingView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:text="Loading"
        app:textSize="20sp"
        app:waveLength="3"
        app:waveHeight="normal"/>

以上是WaveLoadingView的基本参数设置,以app:开头的参数都是WaveLoadingView自定义的。

要想自定义控件参数类型,首先需要在res/values文件夹下新建一个xml文件,命名格式为attr_xxx.xml,命名其实没有硬性要求,但推荐以这样的格式命名。

创建完毕后会得到标签,里面什么也没有,我们需要自己写一些东西。

<resources>
    <declare-styleable name="WaveLoadingView">
        <attr format="string" name="text"/>
        <attr format="dimension" name="textSize"/>
        <attr format="integer" name="length"/>
        <attr format="color" name="color"/>
        <attr format="reference" name="customImage"/>
        <attr format="enum" name="waveHeight">
            <enum name="slight" value="1"/>
            <enum name="normal" value="2"/>
            <enum name="big" value="3"/>
            <enum name="large" value="4"/>
        </attr>
        ...
    </declare-styleable>
</resources>

首先是declare-styleable标签的name,这个是用来和刚刚的java文件绑定的,也就是自定义控件java文件的名字。

attr标签就是自定义参数,format是参数类型,name是参数的名字。

比如text是字符串类型的参数,使用的时候只能输入字符串。

textSize是尺寸类型的参数,使用的时候能输入sp、px、dp等尺寸参数

length是整型参数,使用的时候可以输入整型数据

color是颜色类型的参数,使用的时候只能输入#AABBCCDD
其中AA BB CC DD分别指A(透明度)R(红)G(绿)B(蓝)的十六进制数
透明度可以省略不写,但前面的#不能省略,如#E142D3

customImage是引用类型的参数,使用的时候可以输入引用的资源文件
举个例子,ImageView的src参数就是引用类型的

waveHeight是枚举类型的参数,枚举值必须写整数且不能重复。

获取参数

定义好了参数,就需要在java文件上获取它们了。

//4
public WaveLoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context,attrs);
    }

private void init(Context context, @Nullable AttributeSet attrs){
        //1
        TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.WaveLoadingView);
		...
		//2
		typedArray.recycle();
}

我们通过TypedArray这个类来获取布局文件的数据(代码1),获取完后要记得回收它。而中间的部分就是获取xml数据的,看看下面的例子。

	//1
	mText = typedArray.getString(R.styleable.WaveLoadingView_text);
	
	//2
	mColor = typedArray.getColor(R.styleable.WaveLoadingView_color, Color.BLUE);

	//3
	mImageSize = typedArray.getDimensionPixelSize(R.styleable.WaveLoadingView_imageSize,dp2px(DEFAULT_IMAGE_SIZE_DP));

	//4.1
	mWaveHeight = typedArray.getInt(R.styleable.WaveLoadingView_waveHeight,WAVE_HEIGHT_NORMAL);

	//4.2
	mWaveLength = typedArray.getInt(R.styleable.WaveLoadingView_waveLength,1);

	//5
	mCustomWaveDrawable = typedArray.getDrawable(R.styleable.WaveLoadingView_customImage);

代码1 getString方法可以获取到xml文件的字符串类型数据。
R.styleable.WaveLoadingView_text这个值是自动生成的。

代码2getColor可以获取到颜色值,注意getColor返回值的是整型。

代码3 getDimensionPixelSize可以获取尺寸的像素值,如果xml文件上使用的是sp或dp返回的像素值会有所不同。比如xml上写了10dp,px与dp是3:1的关系,则getDimensionPixelSize返回的是10 * 3。

代码4.1和 代码4.2 getInt获取的都是整型值 ,也就是说枚举值也是通过getInt来获取的。

代码5 getDrawable可以获取到图片的drawable

最后

限于文章篇幅,文章只贴了关键代码,想深入了解此控件测量流程的朋友可以到Github项目上阅读完整代码。

下一篇讲解控件的测量,感兴趣的朋友可以看看。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值