概述:
360安全卫士的那个刷新球(姑且叫它刷新球,因为真的不知道叫什么好,不是dota里的刷新球!!),里面像住了水一样,生动可爱,看似简单,写起来不太简单,本例程只是实现了它的部分功能而已,说实话,跟360的刷新球比起来差距还是很大,我这个长得有点挫。
本历程需要用到的知识包括:android的自定义View,自定义canvas、path、Bitmap、Handler
先结果演示:
Android自定义View之图形图像(模仿360的刷新球自定Damopublic class MyPathView extends View { private int width; private int height; private int progress; private int maxProgress = 100; private Path mPath; private Paint mPaintCircle; private Paint mPaintWave; private Paint mPaintText; private Bitmap mBitmapBubble; private Canvas mCanvasBitmap; private int size = 0;//水波动幅度 private int count;//水流动距离 private boolean isAdd = true; private static final int START_WAVE = 0x21; public int getProgress() { return progress; } public void setProgress(int progress) { this.progress = progress; invalidate(); } public int getMaxProgress() { return maxProgress; } public void setMaxProgress(int maxProgress) { this.maxProgress = maxProgress; } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case START_WAVE: count += 30; if (count >= 180) { count = 0; } if (isAdd) { size += 7; if (size > 41) { isAdd = false; } } else { size -= 7; if (size <= -41) { isAdd = true; } } invalidate(); sendEmptyMessageDelayed(START_WAVE, 100); break; } } }; public MyPathView(Context context) { super(context); } public MyPathView(Context context, AttributeSet attrs) { super(context, attrs); mPaintCircle = new Paint(); mPaintCircle.setStyle(Paint.Style.FILL_AND_STROKE); mPaintCircle.setColor(Color.argb(0X4f, 0x4d, 0x4d, 0xff)); mPaintText = new Paint(); mPaintText.setColor(Color.WHITE); mPaintText.setTextSize(50); mPaintText.setTextAlign(Paint.Align.CENTER); mPaintWave = new Paint(); mPaintWave.setColor(Color.argb(0xaa, 0xff, 0x7c, 0x00)); mPaintWave.setStyle(Paint.Style.FILL); //不显示非重叠部分,并且重叠部分显示自己 PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP); mPaintWave.setXfermode(mode); mPath = new Path(); handler.sendEmptyMessageDelayed(START_WAVE, 1000); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); setMeasuredDimension(width, height); mBitmapBubble = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvasBitmap = new Canvas(mBitmapBubble); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPath.reset(); //canvas.drawColor(Color.argb(0xaa, 0x88, 0x7e, 0x7f));//自定义颜色 mCanvasBitmap.drawCircle(width / 2, height / 2, 200, mPaintCircle); mPath.reset(); //用path圈出一个矩形,把水波和球的包含进去 mPath.moveTo(width / 2 + 200, height / 2 + 200 - progress / maxProgress * 400); mPath.lineTo(width / 2 + 200, height / 2 + 200); mPath.lineTo(0, height / 2 + 200); mPath.lineTo(0, height / 2 + 200 - progress / maxProgress * 400); /* 画一条个模拟流动的波浪 */ //当count增大时,重绘会显示向前流动效果,count的值不能大于width/2-200 mPath.lineTo(count, height / 2 + 200 -(float) progress / maxProgress * 400);// mPath.moveTo(count,200); //size的从大到小从小到大变化,重绘时会产生波浪起伏效果 for (int i = 0; i < 20; i++) { /* rQuadTo()方法每次都会自动移动到下一位置,参数依次为水平幅度, 垂直幅度,水平位移,处置位移 */ mPath.rQuadTo(20, size, 90, 0); mPath.rQuadTo(20, -size, 90, 0); } mPath.close(); mCanvasBitmap.drawPath(mPath, mPaintWave); canvas.drawBitmap(mBitmapBubble, 0, 0, null); //绘制文本,当前进度 canvas.drawText(progress*100/maxProgress+%,width/2,height/2,mPaintText); }}
主活动调用自定义View:public class MainActivity extends Activity { private int progress; private Button mButtonStart; private MyPathView myPathView; private static final int DOWNLOAD_UPDATE = 0x99; //模拟下载 private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); //处理msg switch (msg.what) { case DOWNLOAD_UPDATE: progress += 1; //当progress大于maxProgress时,不再调用一下方法 if (progress<=myPathView.getMaxProgress()){ myPathView.setProgress(progress);//设置新的进度 sendEmptyMessageDelayed(DOWNLOAD_UPDATE, 100);//每隔100毫秒发送一次handler } break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButtonStart = (Button) findViewById(R.id.button_start); myPathView = (MyPathView) findViewById(R.id.progress_view_first); mButtonStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //向handler发送一个延时空消息,1000毫秒后发送 mHandler.sendEmptyMessageDelayed(DOWNLOAD_UPDATE, 1000); } }); }}
内容由用户发布,不代表本站观点。如发现有害或侵权内容。请点击这里