自定义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"); } }
运行效果:运行起来是动态的,我不会上传动态效果,想看效果的自己跑起来就可以了。
注意:这里的跑马灯效果只是一种非常笨的方式,有更简单的办法,我以后会介绍!
时间: 2024-11-03 05:29:50