Android学习记录,第三周

自定义控件

1、如何实现自定义控件

自定义控件顾名思义,主要用于开发系统没有提供的控件类型。要自定义控件,首先要创建一个类继承View或View的子类,也可以将各种控件组合起来以实现自定义的目的。

(1)自定义控件创建方法如下(此处自定义控件为继承View的子类,完全实现自定义绘制效果):

  1. 创建一个类,继承View,并进行初始化工作。
public class TimerView extends View{

    private Paint mPaint;
    private Rect mRect;


    public TimerView(Context context) {
        this(context, null);
    }

    public TimerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TimerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context,attrs);
    }
    private void init(Context context ,AttributeSet attrs){
        mPaint = new Paint();
        mRect = new Rect();
    }
}
  1. 重写onDraw方法。
  2. 完成后需使用invalidate()方法刷新界面。每当View的invalidate方法被调用时,系统会自动调用onDraw()方法进行界面更新。从此处可以看出,因onDraw()方法调用频繁,不要将声明变量等工作放在onDraw()方法中,否则多次调用onDraw()方法将会浪费大量内存。
  3. 自定义控件的属性,在attrs中declare-styleable声明变量名,并定义每一条属性及其类型。
    <declare-styleable name="TimerView" >
        <attr name="ProgressColor" format="color"/>
        <attr name="ProgressWidth" format="dimension"/>
        <attr name="TextSize" format="dimension"/>
        <attr name="TextColor" format="color"/>
    </declare-styleable>

(2)onDraw(Canvas canvas)方法的重写

onDraw方法中传入的参数Canvas是一个类似于画板的类,于它常常配合使用的类Paint,它作用类似于画笔,将画板Canvas和画笔Paint配合使用,就能绘制出一个View视图。
canvas常用方法:
canvas.drawCircle(…..); 绘制圆形
canvas.drawArc(RectF rectf,float startAngle,float sweepAngle,boolean useCenter,Paint paint);
绘制圆弧,参数特别说明下:
1、RectF作用类似于Rect,RectF的构造方法提供了四个参数,分别为左,上,右,下,如
RectF rectf = new RectF(0,0,100,100),则RectF是一个以(0,0)点为左上坐标,(100,100)为右下坐标的一个矩形范围,将这个参数传入drawArc()方法中,即可将圆弧的范围确定下来。
2、starAngle为起始角度,sweepAngle为扫过的角度(不是最终的角度)。而useCenter的作用为是否与圆心进行连线,若连线则画出类似于扇形的图案。

canvas.drawText (String text,float x, float y, Paint paint)
第一个参数为字符串,第二、三个参数定义了一个坐标(X,Y)作为起始坐标绘制,而paint中可以用
Paint.getTextBounds (String text, int start, int end, Rect bounds)来获取字符的范围,其值保存在Rect中。

(3)自定义属性的获得和设置

在自定义控件中,我们可以通过declare-styleable在attrs.xml中声明我们的控件,然后在代码中以R.styleable.XXX来获取。然后通过TypeArray类来获取特定的属性,如在attrs中以定义如下属性

    <declare-styleable name="TimerView" >
        <attr name="ProgressColor" format="color"/>
        <attr name="ProgressWidth" format="dimension"/>
        <attr name="TextSize" format="dimension"/>
        <attr name="TextColor" format="color"/>
    </declare-styleable>

在代码中可以用如下方法获得:

TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.TimerView);
float mTextSize = typedArray.getDimension(R.styleable.TimerView_TextSize, 50);
int mProgressColor = typedArray.getColor(R.styleable.TimerView_ProgressColor, Color.RED);
float mProgressWidth = typedArray.getDimension(R.styleable.TimerView_ProgressWidth, 3);   

在Xml文件中若要引用这些这些属性,需添加命名空间:

xmlns:timer="http://schemas.android.com/apk/res-auto"

这里的res-auto为自动适配。

2、handler的使用

handler常用方法

handler一个重要的作用为保证各个线程之间的同步运行。在android中,如网络请求等费时操作需要新建立线程进行以防止UI线程阻塞,而handler则作为线程之间的桥梁存在。Handler的声明及初始化如下:

public static class MyHanler extends Handler{

        public void handleMessage(Message msg) {
            super.handleMessage(msg);        
        }
    }

Handler中的抽象方法handlerMessage必须进行重写,每当程序接受到一个Message,则进入handlerMessage进行处理。
handler常用方法:
public final boolean sendMessage (Message msg);
传递一个Message对象
public final boolean sendMessageDelayed (Message msg, long delayMillis);
延迟一定时间发送信息,以毫秒为单位。
public boolean sendMessageAtTime (Message msg, long uptimeMillis);
在规定时间发送信息。
public final boolean sendEmptyMessage (int what);
在不需要传送message时,可以使用此方法,此方法主要功能为通知UI线程,本线程内工作以完毕且不需要返回数据。

Message的常用属性

Message类的声明及初始化代码如下:

Message message = hanler.obtainMessage();
//不要使用Message message = new Message();

使用handler.obtainMessage();能够更好的管理内存,当handler销毁时,Message也会释放,不会浪费内存空间。
Message的属性一共有如下几个
- obj obj类型,可以传递所有对象。
- args1 int类型
- args2 int类型
- what int类型,主要用于分辨不同的Message。

你可能感兴趣的:(Android学习记录,第三周)