自定义View在开发中是经常遇到的,例如一个×××灯的效果、或者自定义一个转盘来显示下载进度的百分百比。今天把实现方式写下来,下面是源码部分:
MainActivity:没变动
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
主布局:只增加了一个自定义View
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.myview.MineView
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</com.example.myview.MineView>
</RelativeLayout>
自定义View:
import java.util.Random;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.View;
public class MineView extends View {
/**
* 字体移动的X坐标
*/
private int rx = 0;
/**
* 画笔工具
*/
private Paint paint;
/**
* 创建线程对象,用于循环延迟执行命令
*/
private MyThread t;
/**
* 0表示圆的left,60表示圆的top,100表示圆的right,160表示圆的bottom
*/
private RectF rectF = new RectF(0, 60, 100, 160);
/**
* 表示区间角度
*/
private float sweepAngle;
/**
* 创建随机数对象
*/
private Random random;
/**
* isdestroy表示该Activity是否已经结束
*/
private boolean isdestroy = false;
public MineView(Context context, AttributeSet attrs) {
super(context, attrs);
System.out.println("构造器");
paint = new Paint();
random = new Random();
//抗锯齿,否则图像会很难看
paint.setAntiAlias(true);
if (t == null) {
t = new MyThread();
t.start();
}
}
public MineView(Context context) {
super(context);
System.out.println("构造器");
paint = new Paint();
paint.setAntiAlias(true);
if (t == null) {
t = new MyThread();
t.start();
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setTextSize(30);
// rx表示移动字体的x坐标
canvas.drawText("移动字体", rx, 30, paint);
// rectF表示圆的对象,0表示起始角度,sweepAngle表示区间角度,true和false表示绘制过程的方式,paint表示画笔对象
canvas.drawArc(rectF, 0, sweepAngle, true, paint);
}
class MyThread extends Thread {
@Override
public void run() {
super.run();
while (true) {
rx += 5;
// 如果字体移动出屏幕以外,就让字体从头开始
if (rx > getWidth()) {
rx = (int) (0 - paint.measureText("移动字体"));
}
sweepAngle += 5;
// 如果角度大于360就让圆从0度开始重新绘制
if (sweepAngle > 360) {
sweepAngle = 0;
}
// 让颜色从0-255随机选择
int r = random.nextInt(256);
int g = random.nextInt(256);
int b = random.nextInt(256);
// 分别表示:透明度(0~255)、红、绿、蓝
paint.setARGB(255, r, g, b);
/**
* 判断Activity是否已经退出,如果退出则isdestroy为true,那么立刻让线程对象与画笔对象为空,并且break,
* 否则会造成内存溢出,此办法必须在此处使用,否则会造成空指针的BUG。
*/
if (isdestroy) {
if (t != null) {
t = null;
}
if (paint != null) {
paint = null;
}
break;
}
// 睡眠
SystemClock.sleep(50);
// 可以让ondraw方法重新执行
postInvalidate();
// invalidate();分线程无效,要在主线程使用
}
}
}
/**
* 当窗口销毁的时候会调用此方法,用于关闭资源
*/
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
isdestroy = true;
System.out.println("onDetachedFromWindow");
}
}
运行效果:运行起来是动态的,我不会上传动态效果,想看效果的自己跑起来就可以了。
注意:这里的×××灯效果只是一种非常笨的方式,有更简单的办法,我以后会介绍!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。