目录
2.使用自绘View,写一个简单的交通灯程序(斑马线上的那种)
1.简单实现
自绘View实现其实很简单,可以简单总结为三步:
1.继承View;
2.创建Paint;
3.在onDraw()里面画。
例子:
public class DrawView extends View
{
private Paint paint;
public DrawView(Context context, @Nullable AttributeSet attrs)
{
super(context, attrs);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.GREEN);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2, paint);
}
}
将paint的flage设置为Paint.ANTI_ALIAS_FLAG,意思是设置成抗锯齿模式。什么是抗锯齿?我在网上看到的答案:
当然你设置成别的flag也完全OK
设置paint的颜色设置为Color.GREEN
最后在onDraw里面用canvas.drawCircle()绘制圆,前两个参数为圆心的x,y坐标,第三个参数为半径,最后一个为绘制这个圆所使用的颜料就是指paint
使用:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.view.customview.DrawView
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"></com.view.customview.DrawView>
</RelativeLayout>
运行效果:
还有一点就是invalidate()方法会让View重新绘制一次,也就是会重新回调一次onDraw()
例子:
我们将这个View设置为点击一下,更换颜色成蓝色
public class DrawView extends View implements View.OnClickListener
{
private Paint paint;
public DrawView(Context context, @Nullable AttributeSet attrs)
{
super(context, attrs);
setOnClickListener(this);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.GREEN);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2, paint);
}
@Override
public void onClick(View v)
{
paint.setColor(Color.BLUE);
invalidate();
}
}
点击事件触发将paint改成蓝色,再调用invalidate(),回调onDraw重绘此View
2.使用自绘View,写一个简单的交通灯程序(斑马线上的那种)
我的需求:
1.红灯先常亮10s,之后黄灯常亮3s,之后绿灯常亮10s,最后黄灯常亮3s,以此循环;
2.灯的熄灭状态设置为亮灰色;
3.他们倒计时的时间需要显示的灯上。
自定义交通灯LightView
public class LightView extends View
{
private Paint paint;
private Rect bounds; //用于获取文字的高度
private int count = 0; //倒计时的时间
private int color = Color.LTGRAY;
private boolean isShowCount = false;
private CountDownTimer countDownTimer; //计时器
public LightView(Context context, @Nullable AttributeSet attrs)
{
super(context, attrs);
bounds = new Rect();
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
/**
* 绘制代码写在onDraw()
*
* @param canvas 靠他来画
*/
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
paint.setColor(color);
//绘制圆
canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2, paint);
if (isShowCount)
{
paint.setColor(Color.BLACK);
paint.setTextSize(100);
String showText = String.valueOf(count);
//这里获取showText文字的宽度和高度
paint.getTextBounds(showText, 0, showText.length(), bounds);
float textWidth = bounds.width();
float textHeight = bounds.height();
//绘制倒计时文字
canvas.drawText(showText, getWidth() / 2 - textWidth / 2, getHeight() / 2 + textHeight / 2, paint);
}
}
/**
* 设置开关灯
*
* @param isOpen 是否打开
* @param color 打开什么颜色
* @param isShowCount 是否显示倒计时
* @param count 显示时间的长度
*/
public void setSwitchLight(boolean isOpen, int color, boolean isShowCount, int count)
{
if (isOpen)
{
this.color = color;
this.isShowCount = isShowCount;
this.count = count;
countDownTimer = new CountDownTimer(count * 1000, 1000)
{
@Override
public void onTick(long millisUntilFinished)
{
invalidate();
LightView.this.count--;
}
@Override
public void onFinish()
{
}
};
countDownTimer.start();
} else
{
this.color = Color.LTGRAY;
this.isShowCount = false;
}
invalidate();
}
}
这里我们使用CountDownTimer来计时,从而刷新灯上的数字。
activity_light.xml的编写
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.view.customview.LightView
android:id="@+id/dv_red_light"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_above="@+id/dv_yellow_light"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:visibility="visible" />
<com.view.customview.LightView
android:id="@+id/dv_yellow_light"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:visibility="visible" />
<com.view.customview.LightView
android:id="@+id/dv_green_light"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_below="@+id/dv_yellow_light"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:visibility="visible" />
</RelativeLayout>
LightActivity.java
public class LightActivity extends AppCompatActivity
{
private LightView redLight;
private LightView yellowLight;
private LightView greenLight;
private static final int RED = 0;
private static final int YELLOW = 1;
private static final int GREEN = 2;
private Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case RED:
redLight.setSwitchLight(true, Color.RED, true, 10);
yellowLight.setSwitchLight(false, Color.LTGRAY, false, 0);
greenLight.setSwitchLight(false, Color.LTGRAY, false, 0);
break;
case YELLOW:
yellowLight.setSwitchLight(true, Color.YELLOW, true, 3);
redLight.setSwitchLight(false, Color.LTGRAY, false, 0);
greenLight.setSwitchLight(false, Color.LTGRAY, false, 0);
break;
case GREEN:
greenLight.setSwitchLight(true, Color.GREEN, true, 10);
redLight.setSwitchLight(false, Color.LTGRAY, false, 0);
yellowLight.setSwitchLight(false, Color.LTGRAY, false, 0);
break;
default:
break;
}
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_light);
initData();
initView();
setListener();
}
private void initData()
{
}
private void initView()
{
redLight = findViewById(R.id.dv_red_light);
yellowLight = findViewById(R.id.dv_yellow_light);
greenLight = findViewById(R.id.dv_green_light);
}
private void setListener()
{
/**
* step1.先亮红灯3s
* step2.再亮黄灯1s
* step3.最后亮绿灯3s
* step4.循环1-3
* */
new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
handler.sendEmptyMessage(RED);
Thread.sleep(10 * 1000);
handler.sendEmptyMessage(YELLOW);
Thread.sleep(3 * 1000);
handler.sendEmptyMessage(GREEN);
Thread.sleep(10 * 1000);
handler.sendEmptyMessage(YELLOW);
Thread.sleep(3 * 1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}).start();
}
}
编译运行: