您的位置:

Android自定义View详解

一、自定义View基础

1、View的绘制流程

在了解自定义View之前,我们需要了解Android中View的绘制流程。View的绘制流程主要包括:

(1)测量(onMeasure):测量一个View的宽高,系统会根据这个宽高来确定View的布局位置。

(2)布局(onLayout):ViewGroup需要布局每个子View的位置,布局完成之后子View才可以被绘制。

(3)绘制(onDraw):如果这个View需要被绘制,那么系统就会调用onDraw方法,进行绘制。在绘制之前,系统会调用onMeasure和onLayout等方法来确定View的位置和大小。

2、继承View的自定义View

在使用自定义View之前,我们需要了解如何继承View类。以下是一个自定义View继承View类的示例代码:

public class MyView extends View {

    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
}

二、自定义View的属性

1、自定义View属性的定义

Android中使用自定义属性可以在XML文件中设置一些属性值,可以让我们的View更加灵活。以下是一个自定义属性值的示例:

<declare-styleable name="MyView">
    <attr name="my_text" format="string"/>
</declare-styleable>

2、在XML文件中使用自定义属性

以下是一个在XML文件中使用自定义属性的示例:

  

3、在自定义View中获取属性值

在自定义View中获取自定义属性的值可以通过context.getTheme().obtainStyledAttributes方法获取。以下是一个在自定义View中获取属性值的示例:

public class MyView extends View {

    private String mMyText;

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.MyView,
                0, 0);

        try {
            mMyText = a.getString(R.styleable.MyView_my_text);
        } finally {
            a.recycle();
        }
    }
}

三、自定义View的绘制

1、绘制基本图形

在自定义View中,我们可以使用Canvas对象绘制基本的图形,如:线条、矩形、圆形等。以下是一个绘制圆形的示例代码:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    Paint paint = new Paint();
    paint.setColor(Color.RED);
    canvas.drawCircle(100, 100, 50, paint);
}

2、使用Path绘制复杂图形

如果需要绘制复杂的图形,除了基本形状外,我们可以使用Path对象进行绘制。Path的常用方法有:moveTo、lineTo、quadTo、cubicTo等,可以绘制出各种形状。以下是一个使用Path绘制心形的示例代码:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    Paint paint = new Paint();
    paint.setColor(Color.RED);

    Path path = new Path();
    path.moveTo(150, 150);
    path.quadTo(200, 100, 250, 150);
    path.quadTo(200, 200, 150, 250);
    path.quadTo(100, 200, 150, 150);
    canvas.drawPath(path, paint);
}

四、自定义View的动画

在自定义View中,我们可以使用属性动画进行动画效果的实现。以下是一个使用属性动画实现位移效果的示例代码:

public class MyView extends View {

    private int mTranslationX = 0;

    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void startAnimate() {
        ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 1000);
        valueAnimator.setDuration(1000);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mTranslationX = (int) animation.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimator.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Paint paint = new Paint();
        paint.setColor(Color.RED);

        canvas.drawRect(mTranslationX, 0, mTranslationX + getWidth(), getHeight(), paint);
    }
}

五、自定义View的触摸事件

在自定义View中,我们可以使用触摸事件来实现交互效果。以下是一个处理触摸事件的示例代码:

public class MyView extends View {

    private Paint mPaint;
    private float mX, mY;

    public MyView(Context context) {
        super(context);
        init();
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(5);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.RED);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mX = event.getX();
                mY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                float x = event.getX();
                float y = event.getY();
                Path path = new Path();
                path.moveTo(mX, mY);
                path.lineTo(x, y);
                mX = x;
                mY = y;
                Canvas canvas = new Canvas();
                canvas.drawPath(path, mPaint);
                break;
        }
        return true;
    }
}