关于自定义View的学习与使用(一)

这篇博客介绍了如何在Android中创建自定义View,包括直接继承View、重写已有的View子类以及组合控件的方法。重点讲述了自绘控件的步骤,如继承View、实现onDraw方法、使用Paint和Canvas进行绘制,并以创建一个动态显示时间的时钟控件为例,详细解释了实现过程和需要注意的细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、View的大家族

大枝分类
这里写图片描述
详细分类
这里写图片描述

二、使用自定义View的方法

  • 通过直接继承View 例如 ABC extends View
  • 重写View子类实现逻辑的View 例如 ABC extends TextView 然后实现方法

注意点:方法二相比较与方法一更简单


三、使用自定义View的步骤

  1. 自绘控件:直接继承View类的方式自绘控件
  2. 重写控件:间接继承View子类的方式重写控件
  3. 组合控件:间接继承View子类,将需要用到的原生控件组合到一起

四、自绘控件的步骤

  1. 继承View
  2. 实现Listener接口
  3. 实现构造方法
  4. 重写onDraw方法

注意点:在自绘控件中,绘制的逻辑基本都写在此方法中
需调好Paint画笔,将Paint画在Canvas上,输出到屏幕上


5 Paint画笔

方法名解释
setAntiAlias设置画笔的锯齿效果
setColor设置画笔颜色
setARGB()设置画笔A,R,G,B的值
setAlpha设置画笔的Alpha值
setStyle设置画笔的风格(空心或实心)
setStrokeWidth设置空心边框的宽度
getColor获取画笔的颜色

6. Canvas绘制

方法名解释
drawLine()绘制直线
drawCircle()绘制圆形
drawBitmap()绘制图形
drawRect()绘制矩形
drawText()绘制字符

7. invalidate方法刷新
8. 在布局文件中引用

五、使用自绘控件的示例(以时钟为例)

要达到的效果是和我们日常看到的时钟一样
效果图
这里写图片描述
1.首先新建一个类继承View,实现他自带的方法,定义出画笔

public class MyView2 extends View {

    private Paint paint=new Paint();

    public MyView2(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

2.实现onDraw方法,在里面用画笔对象开始绘制时钟

 protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setColor(Color.BLUE);
        paint.setStyle(Paint.Style.STROKE);//空心圆
        paint.setAntiAlias(true);//减弱锯齿效果
        paint.setStrokeWidth(10);

        canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/3,paint);
        canvas.drawCircle(getWidth()/2,getHeight()/2,5,paint);

        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(2);
        paint.setTextSize(20);

3.我们知道时钟的一圈是1-12的数字,所以我们要用for循环来写这12个数字,注意要写在onDraw方法里

 for(int i=1;i<=12;i++){
            canvas.save();//保存画布当前的状态
            canvas.rotate(30*i,getWidth()/2,getHeight()/2);
            canvas.drawLine(getWidth()/2,getHeight()/2-getWidth()/3,getWidth()/2,getHeight()/2-getWidth()/3+20,paint);
            canvas.drawText(i+"",getWidth()/2-10,getHeight()/2-getHeight()/3+190,paint);

            canvas.restore();//画布复原
        }

4.涉及到旋转就势必要牵扯到角度问题,所以我们自定义一个角度,并设置其初始化

 public int sec=0;//设置初始化角度

5.用Calendar来获取模拟器也就是现在的时间

//获取当前时间
        Calendar calendar=Calendar.getInstance();
        int hour=calendar.get(Calendar.HOUR);
        int minute=calendar.get(Calendar.MINUTE);
        int second=calendar.get(Calendar.SECOND);

6.接下来就是绘制时针,分针,秒针了

  //绘制秒钟
        canvas.save();
        canvas.rotate(second*6,getWidth()/2,getHeight()/2);
        paint.setColor(Color.RED);
        canvas.drawLine(getWidth()/2,getHeight()/2,getWidth()/2,getHeight()/2-getHeight()/3+200,paint);
        canvas.restore();

        //绘制分钟
        canvas.save();
        canvas.rotate(minute*6,getWidth()/2,getHeight()/2);
        paint.setColor(Color.BLACK);
        canvas.drawLine(getWidth()/2,getHeight()/2,getWidth()/2,getHeight()/2-getHeight()/3+250,paint);
        canvas.restore();

        //绘制时钟
        canvas.save();
        canvas.rotate(hour*30+minute*30/60,getWidth()/2,getHeight()/2);
        paint.setColor(Color.GREEN);
        canvas.drawLine(getWidth()/2,getHeight()/2,getWidth()/2,getHeight()/2-getHeight()/3+300,paint);
        canvas.restore();

        invalidate();
    }

7.由于要运行一次就刷新页面来制造出在旋转的效果,所以要用到onTouchEvent方法。并且在里面开一个子线程

 public boolean onTouchEvent(MotionEvent event) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    handler.sendEmptyMessage(sec);
                    sec++;
                }
            }
        }).start();
        return super.onTouchEvent(event);
    }

8.在上面写Handler来接受子线程传来的消息(因为子线程不能更新UI)

private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            invalidate();
        }
    };

9.最后回到layout布局文件里把你定义的这个类写进去,主要要导你自己的包。不然会报错

 <com.example.view.MyView2
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

笔芯!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值