自定义view 很牛逼,实现起来超级简单!!!跟着个人套路走。android
下面代码实现了什么功能也没有的自定义view。重写了onLayout,onMeasure,onSizeChanged。canvas
public class MyView extends View{
private String TAG = "MyView";
public MyView(Context context) {
super(context);
initView();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
public void initView(){
Log.d(TAG, "onCreat");
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Log.d(TAG, "onLayout");
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d(TAG, "onMeasure");
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Log.d(TAG, "onSizeChanged");
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
Log.d(TAG, "onDraw");
super.onDraw(canvas);
}
}
将MyView添加到布局文件中:ide
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:id="@+id/activity_main" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="jaelyn.eventbus.MainActivity"> <jaelyn.eventbus.MyView android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
运行后打印的结果为:布局
在不一样的手机运行的打印结果不尽相同,可是大致的顺序是:动画
onCreat -> onMeasure -> onSizeChange -> onLayout-> onMeasure->onLayout -> onDrawspa
能够在这里面初始化常量如:paint;code
也能够获取布局文件中设置的属性。(经过AttributeSet attrs, int defStyleAttr);xml
计算view的宽高,咱们能够在这里根据须要修改view的宽高。blog
view放置的位置。view相对于父控件的位置。如传入的值是(8 ,9 ,100, 100),则view距离父控件的左上角位置(8,9),右下角(100, 100)的范围内显示。(我通常在自定义容器view 的时候会重写这个方法来计算自定义view的子view的位置)。utf-8
view大小改变的时候会掉用这个方法。我都是用这个方法来获取view的长宽、以及初始化一些位置常量。
经过这个方法的canvas,你就能够向屏幕画任何的东西了。
其中对于onMeasure、onLayout 在网上有不少详细的解析,这里就很少讲了。这两个方法比较难理解,你能够先放一放。
去掉这两个方法onMeasure、onLayout,自定义的套路就简化为
1.onCreate(initView):初始化常量
2.onSizeChange:计算位置
3.onDraw: 绘制
接下咱们使用这个套路像屏幕写字
public class MyView extends View{
private String TAG = "MyView";
private Paint paint;
float x, y;
private String text = "简单的自定义View";
public MyView(Context context) {
super(context);
initView();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
public void initView(){
Log.d(TAG, "onCreat");
paint = new Paint();
paint.setColor(Color.RED);
paint.setTextSize(40);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Log.d(TAG, "onSizeChanged");
super.onSizeChanged(w, h, oldw, oldh);
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
x = w / 2 - bounds.width() / 2;
y = h / 2 - bounds.height() / 2;
}
@Override
protected void onDraw(Canvas canvas) {
Log.d(TAG, "onDraw");
super.onDraw(canvas);
canvas.drawText("简单的自定义View", x, y , paint);
}
}
效果:
这就是我实现自定义view的基本套路。
在这个基础上能够加入 手机监听、计时器 来实现各类动画效果。