一、如何自定义控件
不同的需求,使用不同的方法自定义控件。
(1)在原生的控件的基本功能上进行扩展,这时只要extends并对控件进行扩展,通过重写它的整件,onDraw,但是始终保持父类方法的调用。
(2)要用几个控件的功能的和,可以将几个控件组合起来。
(3)完全自定义一个新的控件,也就是直接从View,ViewGroup开始绘制控件。
Android的UI界面都是从View和ViewGroup和其派生类组合而成了。其中View中所有UI的基类,ViewGroup是容纳这些组件的容器,本身也是从View派生过来的。
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. |
Called after a view and all of its children has been inflated from XML. |
||
Layout |
Called to determine the size requirements for this view and all of its children. |
|
Called when this view should assign a size and position to all of its children. |
||
Called when the size of this view has changed. |
||
Drawing |
Called when the view should render its content. |
|
Event processing |
Called when a new hardware key event occurs. |
|
Called when a hardware key up event occurs. |
||
Called when a trackball motion event occurs. |
||
Called when a touch screen motion event occurs. |
||
Focus |
Called when the view gains or loses focus. |
|
Called when the window containing the view gains or loses focus. |
||
Attaching |
Called when the view is attached to a window. |
|
Called when the view is detached from its window. |
||
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方法。