自定义View

Android自定义View实现很简单

继承View,重写构造函数、onDraw,(onMeasure)等函数。

如果自定义的View需要有自定义的属性,需要在values下建立attrs.xml。在其中定义你的属性。

在使用到自定义View的xml布局文件中需要加入xmlns:前缀=”http://schemas.android.com/apk/res/你的自定义View所在的包路径”.
这里写图片描述

1、制作简易手表

先写一个类继承View,重写onMeasure(),onDraw()

public class MyView extends View {
    private int width;
    private int height;
    private  Paint mPaintDuan;
    private Paint mPaintLine;
    private  Paint mPaintSecond;
    private Paint mPaintCircle;
    private Paint mPaintText;
    private Calendar mCalendar;
    public static  final  int NEED_INVALIDATE=0X23;
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case NEED_INVALIDATE:
                    mCalendar = Calendar.getInstance();//每次要刷新时间
                    invalidate();//告诉主线程重新绘制
                    handler.sendEmptyMessageDelayed(NEED_INVALIDATE, 1000);
                    break;
            }
        }
    };

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

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mCalendar =Calendar.getInstance();

        mPaintDuan = new Paint();//设置直线的参数
        mPaintDuan.setColor(Color.RED);
        mPaintDuan.setStrokeWidth(8);

        mPaintLine = new Paint();//设置直线的参数
        mPaintLine.setColor(Color.GREEN);
        mPaintLine.setStrokeWidth(10);

        mPaintSecond= new Paint();//设置秒针线的参数
        mPaintSecond.setColor(Color.GREEN);
        mPaintSecond.setStrokeWidth(5);

        mPaintCircle = new Paint();//设置圆的参数
        mPaintCircle.setColor(Color.LTGRAY);
        mPaintCircle.setStrokeWidth(10);
        mPaintCircle.setStyle(Paint.Style.STROKE);

        mPaintText = new Paint();
        mPaintText.setColor(Color.BLACK);
        mPaintText.setTextSize(30);
        mPaintText.setTextAlign(Paint.Align.CENTER);

        handler.sendEmptyMessage(NEED_INVALIDATE);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //是由UI主线程自动调用,只需要在此绘制即可
        //       canvas.drawLine(0,0,300,300,mPaintLine);//画直线
        //    canvas.drawCircle(350,350,100,mPaintCircle);//画圆
        canvas.drawCircle(width / 2, height / 2, 300, mPaintCircle);
        canvas.drawCircle(width / 2, height / 2, 10, mPaintCircle);
        for (int i = 1; i <= 12; i++) {//用FOR循环画12条短线
            canvas.save();//保存画布当前的状态
            canvas.rotate(360 / 12 * i, width / 2, height / 2);//旋转画布,每次转30度
            canvas.drawLine(width / 2, height / 2 - 300, width / 2, height / 2 - 280, mPaintDuan);
            canvas.drawText("" + i, width / 2, height / 2 - 250, mPaintText);
            canvas.restore();
        }

        //获得分钟数,小时数
        int minute = mCalendar.get(Calendar.MINUTE);
        int hour = mCalendar.get(Calendar.HOUR);
        float minuteDegree = minute / 60f * 360;//获得分针的旋转度
        canvas.save();
        canvas.rotate(minuteDegree, width / 2, height / 2);
        canvas.drawLine(width / 2, height / 2, width / 2, height / 2 - 200, mPaintLine);
        canvas.restore();
        float hourDegree = (hour*60+minute)/12f/60*360;//计算时针所占表盘的度数
        canvas.save();
        canvas.rotate(hourDegree, width / 2, height / 2);
        canvas.drawLine(width / 2, height / 2, width / 2, height / 2 - 150, mPaintLine);
        canvas.restore();

        int second = mCalendar.get(Calendar.SECOND);
        float secondDegree = second/60f*360;//计算秒针此刻的位置
        canvas.save();
        canvas.rotate(secondDegree, width / 2, height / 2);
        canvas.drawLine(width / 2, height / 2, width / 2, height / 2 - 230, mPaintSecond);
        canvas.restore();

    }
}

然后再布局文件下添加这个view

<LinearLayout 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:orientation="vertical"
    tools:context=".MainActivity">

    <com.my.administrator.zdyview.MyView//这里的MyView要和上面写的类名一致
        android:id="@+id/tiaoxingview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


</LinearLayout>

在Activity中只需要 setContentView(R.layout.activity_main);即可。
简易手表如下:
这里写图片描述

2、往容器中倒满水案例

public class TiaoxingView extends View {
    private int width;
    private int height;
    private Paint lineLeft;
    private Paint lineRight;
    private Paint lineButtom;
    private Paint lineNewRight;
    private  Paint mPaintText;
    private int progress=100;
    private int progressCurrent;

    public int getProgress() {
        return progress;
    }

    public void setProgress(int progress) {
        this.progress = progress;
    }

    public int getProgressCurrent() {
        return progressCurrent;
    }

    public void setProgressCurrent(int progressCurrent) {
        this.progressCurrent = progressCurrent;
        invalidate();//告诉主线程重新绘制
    }

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

    public TiaoxingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        lineLeft=new Paint();
        lineLeft.setColor(Color.BLACK);
        lineLeft.setStrokeWidth(5);
        lineRight=new Paint();
        lineRight.setColor(Color.BLACK);
        lineRight.setStrokeWidth(5);
        lineButtom=new Paint();
        lineButtom.setColor(Color.BLACK);
        lineButtom.setStrokeWidth(5);

        lineNewRight=new Paint();
        lineNewRight.setColor(Color.GREEN);
        lineNewRight.setStrokeWidth(300);

        mPaintText = new Paint();
        mPaintText.setColor(Color.BLUE);
        mPaintText.setTextSize(60);
        mPaintText.setTextAlign(Paint.Align.CENTER);//设置文本在给定坐标中间

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制如下图的容器
        canvas.drawLine(50, 100, 50, 500, lineLeft);
        canvas.drawLine(50,500,350,500,lineButtom);
        canvas.drawLine(350,500,350,100,lineRight);
        canvas.drawLine(200,500,200,500-progressCurrent*400f/progress,lineNewRight);//progressCurrent*400f/progress是此时应该画的长度,progressCurrent从activity中获得
        canvas.drawText(progressCurrent*100f/progress+"%",200,300,mPaintText);//给定文本坐标,写入文本
    }
}

这里写图片描述

布局问价:

<LinearLayout 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:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="开始" />

    <com.my.administrator.zdyview.TiaoxingView
        android:id="@+id/tiaoxingview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


</LinearLayout>

Activity

public class MainActivity extends AppCompatActivity {
    private TiaoxingView view;
    private Button mButton;
    private int progress;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 0x21:
                    progress++;
                    if (progress <= 100) {
                        view.setProgressCurrent(progress);//设置当前的进度
                        handler.sendEmptyMessageDelayed(0x21, 200);
                    }
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        view = (TiaoxingView) findViewById(R.id.tiaoxingview);
        mButton = (Button) findViewById(R.id.button);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.sendEmptyMessage(0x21);
            }
        });
    }
}

运行如下:
这里写图片描述

弧形进度条案例

其他代码和上面相同,view类如下:

public class ArcView extends View {
    private int width;
    private int height;
    private int progress=100;
    private int progressCurrent;
    private  Paint mCircle;
    private Paint mArc;
    private RectF mRectf;
    private Paint mText;

    public int getProgress() {
        return progress;
    }

    public void setProgress(int progress) {
        this.progress = progress;
    }

    public int getProgressCurrent() {
        return progressCurrent;
    }

    public void setProgressCurrent(int progressCurrent) {
        this.progressCurrent = progressCurrent;
        invalidate();
    }

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

    public ArcView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mArc = new Paint();
        mArc.setColor(Color.GREEN);
        mArc.setStrokeWidth(50);
        mArc.setStyle(Paint.Style.STROKE);

        mCircle = new Paint();
        mCircle.setColor(Color.GRAY);
        mCircle.setStyle(Paint.Style.STROKE);
        mCircle.setStrokeWidth(10);

        mText = new Paint();
        mText.setColor(Color.BLUE);
        mText.setTextSize(60);
        mText.setTextAlign(Paint.Align.CENTER);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(width / 2, height / 2, 300, mCircle);
        canvas.drawCircle(width / 2, height / 2, 250, mCircle);
        mRectf = new RectF(width/2-275,height/2-275,width/2+275,height/2+275);//设置画弧度的矩形框
        canvas.drawArc(mRectf,0,progressCurrent*360f/progress,false,mArc);
        canvas.drawText(progressCurrent * 100f / progress + "%", width / 2, height / 2, mText);
    }
}

运行如下;
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值