Android 自定义View的原理与基础

Android自定义View

Android的显示控件都是继承自View,当我们开发的时候Android官方的View达不到我们想要的效果时就可以选择自定义Viwe,这也是Java的面向对象给我们带来的便利。


View的自定义其实就是继承Android SDK中官方的View控件,再加入自己编写的逻辑、显示元素最终达到想要的显示效果。在日常的开发中一般的需求都可以使用Android SDK官方的显示View达到。但是一些特殊的显示需求官方的View无法到达所需求的效果时就可以考虑自定义View或使用第三方自定义View的插件


创建一个自定义的View首先我们要先创建一个继承系统View的Java类

package com.arvin.customview

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

public class customView extends View{
    // 自定义View需要添加构造方法
    // 主要在代码中使用的
    public customView (Context context) {
        super(context);
    }

    // 在xml布局中使用的
    public customView (Context context, AttributeSet attr) {
        super(context, attr);
    }
}

在定义的View中可以通过View的 onDraw() 方法绘制文字、图片等我们想要的信息

protected void onDraw(Canvas canvas) {
    Paint paint = new Patint();
    paint.setTextSize(30);
    // 绘制文字通过paint指定的大小
    canvas.drawText("this is onDraw", 0, 30, paint);
    // 绘制直线
    canvas.drawLine(0, 60, 100, 60, paint);

    // 通过坐标绘制矩形
    canvas.drawRect(0, 90, 100, 190, paint);

    // 通过Rect对象绘制矩形
    Rect rect = new Rect(0, 90, 100, 190);
    canvas.drawRect(rect, paint);

    // 通过RectF绘制矩形
    RectF rectf = new RectF(0, 90, 100, 190);
    canvas.drawRect(rectf, paint);

    // 绘制圆角矩形
    canvas.drawRoundRect(rect, 10, 10, paint);

    // 绘制圆形
    canvas.drawCircle(50, 270, 50, paint);

    // 绘制Bitmap
    Bitmap bitmap = BiatmapFactory.decodeResource(getResource(),
        R.drawable.ic_launcher);
    canvas.drawBitmap(bitmap, 0, 350, paint);
}

加入逻辑处理进行绘图操作:

@Override
    protected void onDraw(Canvas canvas) {
        paint.setTextSize(30);
        paint.setColor(0xfff91121);
        canvas.drawText("自定义View", rx, 30, paint);
        rectF = new RectF(left, 60, right, 160);
        if (left < 90) {
            canvas.drawCircle(110, 110, 10, paint);
        }
        canvas.drawArc(rectF, startAngle, sweepAngle, true, paint);
        if (myThread == null) {
            myThread = new MyThread();
            myThread.start();
        }
    }

    class MyThread extends Thread {

        @Override
        public void run() {
            while (true) {
                rx += 3;
                if (rx > getWidth()) {
                    rx = 0 - paint.measureText("自定义View");
                }
                if (flag) {
                    startAngle = 0;
                    sweepAngle = 360;
                    flag = false;
                } else {
                    startAngle = 30;
                    sweepAngle = 300;
                    flag = true;
                }
                left += 3;
                right += 3;
                if (left > getWidth()) {
                    left = -100;
                    right = 0;
                }
                postInvalidate();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

    }

对自定义View的封装与代码简化:
将自定义的View做成抽象类,在抽象类中只关心线程与对外提供可供外部实现的抽象方法

package com.arvin.customview.v2;

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

public abstract class BaseView extends View {

    private MyThread myThread;

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

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

    protected abstract void darwSub(Canvas canvas);

    protected abstract void Logic();

    @Override
    protected final void onDraw(Canvas canvas) {
        if (myThread == null) {
            myThread = new MyThread();
            myThread.start();
        } else {
            darwSub(canvas);
        }
    }

    class MyThread extends Thread {

        @Override
        public void run() {
            while (true) {
                Logic();
                postInvalidate();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

自定义View的逻辑处理:
在逻辑处理的类中只关心绘制与逻辑功能处理,而不用去关心线程的启动等

package com.arvin.customview.v2;

import com.arvin.customview.v2.BaseView.MyThread;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;

public class LogicView extends BaseView{

    private float rx = 0;
    private Paint paint = new Paint();
    private float startAngle = 0;
    private float sweepAngle = 0;
    private boolean flag = false;
    private float right = 100, left = 0;
    private RectF rectF;

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

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

    @Override
    public void darwSub(Canvas canvas) {
        paint.setTextSize(30);
        paint.setColor(0xfff91121);
        canvas.drawText("自定义View", rx, 30, paint);
        rectF = new RectF(left, 60, right, 160);
        if (left < 90) {
            canvas.drawCircle(110, 110, 10, paint);
        }
        canvas.drawArc(rectF, startAngle, sweepAngle, true, paint);
    }

    @Override
    public void Logic() {
        rx += 3;
        if (rx > getWidth()) {
            rx = 0 - paint.measureText("自定义View");
        }
        if (flag) {
            startAngle = 0;
            sweepAngle = 360;
            flag = false;
        } else {
            startAngle = 30;
            sweepAngle = 300;
            flag = true;
        }
        left += 3;
        right += 3;
        if (left > getWidth()) {
            left = -100;
            right = 0;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值