Android自定义View之图形图像(模仿360的刷新球自定义一个SeekBar)

概述:

360安全卫士的那个刷新球(姑且叫它刷新球,因为真的不知道叫什么好,不是dota里的刷新球!!),里面像住了水一样,生动可爱,看似简单,写起来不太简单,本例程只是实现了它的部分功能而已,说实话,跟360的刷新球比起来差距还是很大,我这个长得有点挫。
本历程需要用到的知识包括:android的自定义View,自定义canvas、path、Bitmap、Handler

先结果演示:

Damo

1 class="language-java" hljs="">public class MyPathView extends View {
2     private int width;
3     private int height;
4     private int progress;
5     private int maxProgress = 100;
6  
7     private Path mPath;
8     private Paint mPaintCircle;
9     private Paint mPaintWave;
10     private Paint mPaintText;
11     private Bitmap mBitmapBubble;
12     private Canvas mCanvasBitmap;
13  
14     private int size = 0;//水波动幅度
15     private int count;//水流动距离
16     private boolean isAdd = true;
17     private static final int START_WAVE = 0x21;
18  
19     public int getProgress() {
20         return progress;
21     }
22  
23     public void setProgress(int progress) {
24         this.progress = progress;
25         invalidate();
26     }
27  
28     public int getMaxProgress() {
29         return maxProgress;
30     }
31  
32     public void setMaxProgress(int maxProgress) {
33         this.maxProgress = maxProgress;
34     }
35  
36     private Handler handler = new Handler() {
37         @Override
38         public void handleMessage(Message msg) {
39             super.handleMessage(msg);
40             switch (msg.what) {
41                 case START_WAVE:
42                     count += 30;
43                     if (count >= 180) {
44                         count = 0;
45                     }
46                     if (isAdd) {
47                         size += 7;
48                         if (size > 41) {
49                             isAdd = false;
50                         }
51                     else {
52                         size -= 7;
53                         if (size <= -41) {
54                             isAdd = true;
55                         }
56                     }
57                     invalidate();
58                     sendEmptyMessageDelayed(START_WAVE, 100);
59                     break;
60             }
61         }
62     };
63  
64     public MyPathView(Context context) {
65         super(context);
66     }
67  
68     public MyPathView(Context context, AttributeSet attrs) {
69         super(context, attrs);
70  
71         mPaintCircle = new Paint();
72         mPaintCircle.setStyle(Paint.Style.FILL_AND_STROKE);
73         mPaintCircle.setColor(Color.argb(0X4f0x4d0x4d0xff));
74  
75         mPaintText = new Paint();
76         mPaintText.setColor(Color.WHITE);
77         mPaintText.setTextSize(50);
78         mPaintText.setTextAlign(Paint.Align.CENTER);
79  
80         mPaintWave = new Paint();
81         mPaintWave.setColor(Color.argb(0xaa0xff0x7c0x00));
82         mPaintWave.setStyle(Paint.Style.FILL);
83         //不显示非重叠部分,并且重叠部分显示自己
84         PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP);
85         mPaintWave.setXfermode(mode);
86  
87         mPath = new Path();
88         handler.sendEmptyMessageDelayed(START_WAVE, 1000);
89     }
90  
91     @Override
92     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
93         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
94         width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
95         height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
96         setMeasuredDimension(width, height);
97  
98         mBitmapBubble = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
99         mCanvasBitmap = new Canvas(mBitmapBubble);
100  
101     }
102  
103     @Override
104     protected void onDraw(Canvas canvas) {
105         super.onDraw(canvas);
106  
107         mPath.reset();
108         //canvas.drawColor(Color.argb(0xaa, 0x88, 0x7e, 0x7f));//自定义颜色
109         mCanvasBitmap.drawCircle(width / 2, height / 2200, mPaintCircle);
110         mPath.reset();
111         //用path圈出一个矩形,把水波和球的包含进去
112         mPath.moveTo(width / 2 200, height / 2 200 - progress / maxProgress * 400);
113         mPath.lineTo(width / 2 200, height / 2 200);
114         mPath.lineTo(0, height / 2 200);
115         mPath.lineTo(0, height / 2 200 - progress / maxProgress * 400);
116         /*
117         画一条个模拟流动的波浪
118          */
119         //当count增大时,重绘会显示向前流动效果,count的值不能大于width/2-200
120         mPath.lineTo(count, height / 2 + 200 -(float) progress / maxProgress * 400);
121 //        mPath.moveTo(count,200);
122         //size的从大到小从小到大变化,重绘时会产生波浪起伏效果
123         for (int i = 0; i < 20; i++) {
124             /*
125             rQuadTo()方法每次都会自动移动到下一位置,参数依次为水平幅度,
126             垂直幅度,水平位移,处置位移
127             */
128             mPath.rQuadTo(20, size, 900);
129             mPath.rQuadTo(20, -size, 900);
130         }
131         mPath.close();
132         mCanvasBitmap.drawPath(mPath, mPaintWave);
133         canvas.drawBitmap(mBitmapBubble, 00null);
134         //绘制文本,当前进度
135         canvas.drawText(progress*100/maxProgress+%,width/2,height/2,mPaintText);
136  
137     }
138 }

主活动调用自定义View:

查看源代码
打印 帮助
1 class="language-java" hljs="">public class MainActivity extends Activity {
2     private int progress;
3     private Button mButtonStart;
4     private MyPathView myPathView;
5  
6     private static final int DOWNLOAD_UPDATE = 0x99;
7     //模拟下载
8     private Handler mHandler = new Handler() {
9         @Override
10         public void handleMessage(Message msg) {
11             super.handleMessage(msg);
12             //处理msg
13             switch (msg.what) {
14                 case DOWNLOAD_UPDATE:
15                     progress += 1;
16                     //当progress大于maxProgress时,不再调用一下方法
17                     if (progress<=myPathView.getMaxProgress()){
18                         myPathView.setProgress(progress);//设置新的进度
19                         sendEmptyMessageDelayed(DOWNLOAD_UPDATE, 100);//每隔100毫秒发送一次handler
20                     }
21                     break;
22             }
23         }
24     };
25  

你可能感兴趣的:(Android自定义View之图形图像(模仿360的刷新球自定义一个SeekBar))