一、如何自定义控件

不同的需求,使用不同的方法自定义控件。

(1)在原生的控件的基本功能上进行扩展,这时只要extends并对控件进行扩展,通过重写它的整件,onDraw,但是始终保持父类方法的调用。

(2)要用几个控件的功能的和,可以将几个控件组合起来。

(3)完全自定义一个新的控件,也就是直接从View,ViewGroup开始绘制控件。

Android的UI界面都是从View和ViewGroup和其派生类组合而成了。其中View中所有UI的基类,ViewGroup是容纳这些组件的容器,本身也是从View派生过来的。

android 自定义 Dialog Android 自定义控件_android 自定义 Dialog

ViewGroup可以通过重写onMeasure,onLayout为加入其中的View进行布局和处理。下面我们先学习View类派生自定义组件。

二、android自定义View

方法:

extends View --->重写构造函数---->重写onDraw()等函数。

如果自定义的View要有自定义的属性,则要在values下建立attrs.xml。在其中定义属性,使用到的自定义的xml布局文件中要加入

xmlns:前缀="http://schemas.android.com/apk/res/自定义的View所在的包路径".

在使用自定义的属性时候,使用

前缀:属性名

如   myTextview:textColor=" "

  • View类的方法

Creation

Constructors

There is a form of the constructor that are called when the view is created from code and a form that is called when the view is inflated from a layout file. The second form should parse and apply any attributes defined in the layout file.

 

onFinishInflate()

Called after a view and all of its children has been inflated from XML.

Layout

onMeasure(int, int)

Called to determine the size requirements for this view and all of its children.

onLayout(boolean, int, int, int, int)

Called when this view should assign a size and position to all of its children.

onSizeChanged(int, int, int, int)

Called when the size of this view has changed.

Drawing

onDraw(android.graphics.Canvas)

Called when the view should render its content.

Event processing

onKeyDown(int, KeyEvent)

Called when a new hardware key event occurs.

onKeyUp(int, KeyEvent)

Called when a hardware key up event occurs.

onTrackballEvent(MotionEvent)

Called when a trackball motion event occurs.

onTouchEvent(MotionEvent)

Called when a touch screen motion event occurs.

Focus

onFocusChanged(boolean, int, android.graphics.Rect)

Called when the view gains or loses focus.

onWindowFocusChanged(boolean)

Called when the window containing the view gains or loses focus.

Attaching

onAttachedToWindow()

Called when the view is attached to a window.

onDetachedFromWindow()

Called when the view is detached from its window.

onWindowVisibilityChanged(int)

Called when the visibility of the window containing the view has changed.

  • 一般情况下,我们要重写下面的方法

1.构造器

至少用来得到Context.

2.onFinishInflate()

这是一个回调方法,当应用从xml布局文件加载组件并利用它来构建界面后,这个方法就会调用。

3.onMeasure(int ,int )

调用这个方法来检测 View组件及它所包含的所有子组件的大小、

4.onLayout(boolean ,int ,int ,int ,int )

当组件要分配其子组件的位置,大小时,这个方法就会被调用,View类中布局发生变化时会调用,这个方法是所有的View,ViewGroup及其派生类都具有的方法,重载这个方法,可以在布局发生改变时作定制处理,这在实现一些特效时很有用。

5.onSizeChanged(int,int ,int ,int)

当这个组件的大小改变时调用。

6.onDraw(Canvas)

当组件将要绘制它的内容时回调这个方法并进行绘制。这个方法是所有的View,ViewGroup及其派生类都具有的方法,也是android UI绘制最重要的方法。重载这个方法,并在重载的方法里基于canvas绘制自己的各种图形。

7.onKeyDown(in ,KeyEvent)/onKeyUp(int ,KeyEvent)

按下和松开一个按键时触发。

8.onTouchEvent(MotionEvent)

当发生触摸屏事件时触发。

9.onWindowFocusChanged(boolean)

包含组件的窗口得到或者失去焦点时触发的方法。

10.onFocusChanged(boolean,int ,Rect)

组件得到或者失去焦点时触发的方法。

11.onWindowVisibilityChanged(int )

当包含这个组件的窗口可见性发生变化时触发。

  • 补充两个ViewGroup常常重写的方法

1.protected void dispatchDraw(Canvas canvas)

ViewGroup类及其派生类具有的方法,用于控制子View绘制的分发,重载这个类可以改变子View的绘制,从而实现一些复杂的效果。

2.protected boolean drawChild(Canvas canvas, View child,long drawingTime)

ViewGroup及其派生的类具有的方法,可以直接绘制具体的子 View,重载这个类可以控制某个具体的子View.

三、示例

我们做一个ball,让其跟随手指运行,在程序中,先得到MotionEvent的位置,再在这个位置重绘就可以了。

代码如下

package chuiyuan.lsj.androidjava.utils;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by lsj on 2015/9/26.
 */
public class BallView extends View{
    private float x = 40;
    private float y =50;
    private float r =15 ;

    public BallView(Context context, AttributeSet attr){
        super(context, attr);
    }

    @Override
    public void onDraw(Canvas canvas){
        super.onDraw(canvas);
        //创建画笔
        Paint paint= new Paint();
        //设置画笔颜色
        paint.setColor(Color.RED);
        //画circle
        canvas.drawCircle(x, y, r, paint);
    }
    //注释时使用的 是CustumViewActivity中的监听
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        setX(event.getX());
        setY(event.getY());
        invalidate(); //刷新
        return true; //一定要返回true,说明成功了
    }

    @Override
    public float getX() {
        return x;
    }

    @Override
    public void setX(float x) {
        this.x = x;
    }

    @Override
    public float getY() {
        return y;
    }

    @Override
    public void setY(float y) {
        this.y = y;
    }

    public float getR() {
        return r;
    }

    public void setR(float r) {
        this.r = r;
    }
}

 在测试类中

package chuiyuan.lsj.androidjava.view;

import android.view.MotionEvent;
import android.view.View;

import chuiyuan.lsj.androidjava.R;
import chuiyuan.lsj.androidjava.base.BaseActivity;
import chuiyuan.lsj.androidjava.utils.BallView;

/**
 * Created by lsj on 2015/9/26.
 */
public class CustumViewActivity  extends BaseActivity{
    BallView ballView ;
    @Override
    protected void findView() {
        setContentView(R.layout.activity_cumstomview);
    }

    @Override
    protected void initView() {
        ballView = (BallView)findViewById(R.id.ballview);
        //下面的换成了BallView中的onTouchEvent
        ballView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                //得到坐标并设置小球
                ballView.setX(event.getX());
                ballView.setY(event.getY());
                //通知ball重绘,会调用onDraw(),一定要在UI线程中
                ballView.invalidate();
                //表示执行成功
                return true;
            }
        });
    }

    @Override
    protected void setOnClickListener() {

    }

    @Override
    public void onClick(View v) {

    }
}

我们可以看到,为了实现跟随的效果,我们还要实现对它的监听,实际上正如注释中那样,可以通过经常要重载的方法来实现 :onTouchEvent方法。