我套路的自定义View 基础篇 (一)

自定义view 很牛逼,实现起来超级简单!!!跟着我的套路走。

 

下面代码实现了什么功能也没有的自定义view。重写了onLayout,onMeasure,onSizeChanged。



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添加到布局文件中:

<?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 -> onDraw

onCreate

  可以在这里面初始化常量如:paint;

  也可以获取布局文件中设置的属性。(通过AttributeSet attrs, int defStyleAttr);

onMeasure

  计算view的宽高,我们可以在这里根据需要修改view的宽高。

onLayout

  view放置的位置。view相对于父控件的位置。如传入的值是(8 ,9 ,100, 100),则view距离父控件的左上角位置(8,9),右下角(100, 100)的范围内显示。(我一般在自定义容器view 的时候会重写这个方法来计算自定义view的子view的位置)。

 

onSizeChanged

  view大小改变的时候会掉用这个方法。我都是用这个方法来获取view的长宽、以及初始化一些位置常量。

onDraw

  通过这个方法的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的基本套路。

在这个基础上可以加入 手机监听、计时器 来实现各种动画效果。

 

 

  

 

posted @ 2017-03-30 09:24  Jaelyn静  阅读(953)  评论(0编辑  收藏  举报