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

it2023-05-23  77

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

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

 

 

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(); } }

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

 

 

 

最新回复(0)