画一个 自定义控件 房子动态吹风

最近有需求需要画一个房子,要求能表达通风 ,显示温度和时间,借此机会,搞一个自定义控件

先看效果图,废话少说进入正题

 

 

1 先继承View 创建一个自定义控件 





public class House extends View {
   

    public House(Context context) {
        super(context);
        init(context, null, 0);
    }

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

    public House(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }


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




    public void init(Context context, AttributeSet attrs, int defStyle){
      

    }


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


    }

}

 1View的三个构造函数   2 onMeasure 3 onDraw 运行顺序依次123 

基础做好了,然后准备一个画笔,放在init里

Paint paint;
paint =  new Paint();
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);//抗锯齿
paint.setTextSize(16);

然后准备三张图,可以构成动态图,放在init里,顺便把它们放在数组中

 bitmap1= BitmapFactory.decodeResource(getResources(), R.drawable.house1);
 bitmap2= BitmapFactory.decodeResource(getResources(), R.drawable.house2);
 bitmap3= BitmapFactory.decodeResource(getResources(), R.drawable.house3);


 data[0] = bitmap1; // 第一个元素
 data[1] = bitmap2; // 第二个元素
 data[2] = bitmap3;

计算控件大小 ,在onMeasure 方法中执行,单位是像素,可以自己打印出来增加印象

height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

我们要求把动态图片摆放在控件的正中央这时候就要计算了。我们用的画图方法是

canvas.drawBitmap(Bitmap bitmap, float left, float top, @RecentlyNullable Paint paint);

第一个参数很简单,就是图片,第二个参数表示距离父布局左边多长, 第三个显然就是距离父布局上边沿多远 ,第四个参数为画笔

那么,我们需要把图片放在整个view中间,就需要知道图片的长宽多少,我们用到这个方法

bitmap1.getWidth(),
bitmap1.getHeight()

我们的View 大小为 

width 和 height 

知道了两者的大小,根据canvas.drawBitmap 的参数说明可以计算得到 当

left = width / 2-(bitmap1.getWidth()/2)

top = height / 2-(bitmap1.getHeight()/2),时 图片会居中显示 

所以我们在

onDraw 这个方法里画上bitmap 
canvas.drawBitmap(data[position], width / 2-(bitmap1.getWidth()/2),  height / 2-(bitmap1.getHeight()/2), paint);

然后我们还需要时间和温度 

这时候需要用到  canvas.drawText ( String text, float x, float y,  Paint paint)这个方法

参数和上面差不多,就不多解释了 看代码

  paint.setTextSize(width/15);
  paint.setStyle(Paint.Style.STROKE);
        
 canvas.drawBitmap(data[position], width / 2-(bitmap1.getWidth()/2),  height / 2-(bitmap1.getHeight()/2), paint);
        
 canvas.drawText(Temp, width/2-paint.getTextSize(), height/2-paint.getTextSize(), paint);
        
 paint.setTextSize(width/20);
 canvas.drawText(TimeDate, width/2-( 3*paint.getTextSize()), height/2, paint);

上面代码可以看出文字在View居中。 值得注意的是下面这个乘以3 的,因为我们知道时间是  这个格式 

11:59 星期三

前面的11:59  大概有三个字的大小,所以要乘3 。这样我们就得到一开始的效果图了

还剩最后一个问题,怎么让图片动起来,像帧动画一样一帧一帧播放

这时候我们需要用到定时器Timer ,有个方法是

schedule(TimerTask task, long delay, long period)
//第一个参数代表 执行任务事件
//第二个参数代表 延时几秒开始操作 单位毫秒
//第三个参数代表 每间隔几秒开始就执行一次 单位毫秒

 

创建一个任务事件类

 private class InputCheckTimerTask extends TimerTask {
        @Override
        public void run() {
            position++;
            if (position>2){
                position=0;
            }
            invalidate();
        }
    }

然后再创建一个设置设置图片的方法 

 public   void  setPosition(){

        if (mTimer == null)
            mTimer = new Timer();
        //第一个参数代表 执行任务事件
        //第二个参数代表 延时几秒开始操作 单位毫秒
        //第三个参数代表 每间隔几秒开始就执行一次 单位毫秒
        mTimer.schedule(mTask, 0, 1000);

    }

顺便再创建两个方法,让时间和日期可以更改

 public   void  setTemp(String string){
        Temp = string;
        invalidate();
    }


    public   void  setTimeDate(String string){
        TimeDate = string;
        invalidate();
    }

这样就做完了一个简单的动态吹风的房间了,我们来看一下最终代码

package com.davell.ventilationSystem.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.davell.ventilationSystem.R;

import java.util.Timer;
import java.util.TimerTask;

public class House extends View {
     int height;
     int width;
     Paint paint;
    Bitmap bitmap1,bitmap2,bitmap3;

    Bitmap data[] = new Bitmap[3];
    /**
     * 输入检查任务,即 要重复的事件
     */
    InputCheckTimerTask mTask= new InputCheckTimerTask();
    /**
     * 定时器
     */
    Timer mTimer = null;

    int position = 0;

    String Temp = "88°C";

    String TimeDate = "11:59 星期三";

    public House(Context context) {
        super(context);
        init(context, null, 0);
    }

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

    public House(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.e("House","onMeasure" );
          height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
          width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

    }




    public void init(Context context, AttributeSet attrs, int defStyle){
        Log.e("House","init" );


        paint =  new Paint();
        paint.setColor(Color.WHITE);
        paint.setAntiAlias(true);
        paint.setTextSize(16);


        bitmap1= BitmapFactory.decodeResource(getResources(), R.drawable.house1);
        bitmap2= BitmapFactory.decodeResource(getResources(), R.drawable.house2);
        bitmap3= BitmapFactory.decodeResource(getResources(), R.drawable.house3);


//        bitmap1.setHeight();

        data[0] = bitmap1; // 第一个元素
        data[1] = bitmap2; // 第二个元素
        data[2] = bitmap3;
        setPosition();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.e("House","onDraw" );

        paint.setTextSize(width/15);
        paint.setStyle(Paint.Style.STROKE);

        canvas.drawBitmap(data[position], width / 2-(bitmap1.getWidth()/2),  height / 2-(bitmap1.getHeight()/2), paint);

        canvas.drawText(Temp, width/2-paint.getTextSize(), height/2-paint.getTextSize(), paint);

        paint.setTextSize(width/20);
        canvas.drawText(TimeDate, width/2-( 3*paint.getTextSize()), height/2, paint);
    }


    public   void  setPosition(){

        if (mTimer == null)
            mTimer = new Timer();
        //第一个参数代表 执行任务事件
        //第二个参数代表 延时几秒开始操作 单位毫秒
        //第三个参数代表 每间隔几秒开始就执行一次 单位毫秒
        mTimer.schedule(mTask, 0, 1000);

    }


    public   int  getPosition(){
       return position;

    }

    private class InputCheckTimerTask extends TimerTask {
        @Override
        public void run() {
            position++;
            if (position>2){
                position=0;
            }
            invalidate();
        }
    }
    public   void  setTemp(String string){
        Temp = string;
        invalidate();
    }


    public   void  setTimeDate(String string){
        TimeDate = string;
        invalidate();
    }


}

有需要的小伙伴可以直接复制代码拿去用就行了

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值