android自定义view实现原理,android随笔之自定义View基本原理

本文详细介绍了Android自定义控件的基础,包括要求、工作原理、绘制步骤,以及通过继承View和ViewGroup的方式实现的实例。学习如何创建一个百分比圆形视图,了解onMeasure、onLayout和onDraw的运用。
摘要由CSDN通过智能技术生成

前言:

在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理。

自定义控件要求:

1. 应当遵守Android标准的规范(命名,可配置,事件处理等)。

2. 在XML布局中可配置控件的属性。

3. 对交互应当有合适的反馈,比如按下,点击等。

4. 具有兼容性, Android版本很多,应该具有广泛的适用性。

自定义控件学习步骤:

1 .View的工作原理

2 .编写View类

3.为View类增加属性

4 .绘制屏幕

5. 响应用户消息

6 .自定义回调函数

自定义控件两种方式:

1. 继承ViewGroup

例如:ViewGroup、LinearLayout、FrameLayout、RelativeLayout等。

2. 继承View

例如:View、TextView、ImageView、Button等。

自定义控件基本绘制原理:

View的绘制基本上由measure()、layout()、draw()这个三个函数完成

1.)测量-Measure过程是计算视图大小,View measure过程相关方法主要有三个:

protected final void setMeasuredDimension(int measuredWidth, int measuredHeight)

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

measure调用onMeasure,onMeasure测量宽度、高度然后调用setMeasureDimension保存测量结果,measure,setMeasureDimension是final类型,view的子类不需要重写,onMeasure在view的子类中重写。

关于MeasureSpec:

(1) UPSPECIFIED :父容器对于子容器没有任何限制,子容器想要多大就多大.

(2) EXACTLY父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间.

(3) AT_MOST子容器可以是声明大小内的任意大小.

2.)布局-Layout过程用于设置视图在屏幕中显示的位置,View layout过程相关方法主要要三个:

protected boolean setFrame(int left, int top, int right, int bottom)

protected void onLayout(boolean changed, int left, int top, int right, int bottom)

layout通过调用setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,onLayout一般只会在自定义ViewGroup中才会使用

3.)绘制-draw过程主要用于利用前两步得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。

protected void onDraw(Canvas canvas)

通过调用draw函数进行视图绘制,在View类中onDraw函数是个空函数,最终的绘制需求需要在自定义的onDraw函数中进行实现,比如ImageView完成图片的绘制,如果自定义ViewGroup这个函数则不需要重载。

自定义控件示例:

这里先介绍继承View的方式为例,其实ViewGroup最终的继承的也是View。这里 模拟一个需求场景,需要一个圆形显示百分比。

private final static String TAG = PercentView.class.getSimpleName();

private Paint mPaint;

private RectF oval;

public PercentView(Context context) {

super(context);

init();

}

public PercentView(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

public PercentView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();

}

private void init(){

mPaint = new Paint();

mPaint.setAntiAlias(true);

oval=new RectF();

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int widthSize = MeasureSpec.getSize(widthMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);

Log.e(TAG, "onMeasure--widthMode-->" + widthMode);

switch (widthMode) {

case MeasureSpec.EXACTLY:

break;

case MeasureSpec.AT_MOST:

break;

case MeasureSpec.UNSPECIFIED:

break;

}

Log.e(TAG, "onMeasure--widthSize-->" + widthSize);

Log.e(TAG, "onMeasure--heightMode-->" + heightMode);

Log.e(TAG, "onMeasure--heightSize-->" + heightSize);

}

@Override

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

super.onLayout(changed, left, top, right, bottom);

Log.e(TAG, "onLayout");

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

mPaint.setColor(Color.GRAY);

// FILL填充, STROKE描边,FILL_AND_STROKE填充和描边

mPaint.setStyle(Paint.Style.FILL_AND_STROKE);

int with = getWidth();

int height = getHeight();

Log.e(TAG, "onDraw---->" + with + "*" + height);

float radius = with / 4;

canvas.drawCircle(with / 2, with / 2, radius, mPaint);

mPaint.setColor(Color.BLUE);

oval.set(with / 2 - radius, with / 2 - radius, with / 2

+ radius, with / 2 + radius);//用于定义的圆弧的形状和大小的界限

canvas.drawArc(oval, 270, 120, true, mPaint); //根据进度画圆弧

}

}

在布局中如何使用

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:layout_width="150dp"

android:layout_height="150dp"

android:layout_margin="10dp" />

总结:

本篇主要介绍Android自定义控件的基本绘制原理,后面会介绍如何自定义属性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值