Canvas绘制水波进度加载
效果:
用到图片下载:
自定义View:
1 package com.czm.mysinkingview;
2
3 import android.content.Context;
4 import android.graphics.Bitmap;
5 import android.graphics.BitmapFactory;
6 import android.graphics.Canvas;
7 import android.graphics.Color;
8 import android.graphics.Paint;
9 import android.graphics.Paint.Style;
10 import android.graphics.Path;
11 import android.graphics.Path.Direction;
12 import android.graphics.Region.Op;
13 import android.util.AttributeSet;
14 import android.widget.FrameLayout;
15 /**
16 * 水波浪球形进度View
17 * @author caizhiming
18 *
19 */
20 public class SinkingView extends FrameLayout {
21 private static final int DEFAULT_TEXTCOLOT = 0xFFFF0000;
22
23 private static final int DEFAULT_TEXTSIZE =40;
24
25 private float mPercent;
26
27 private Paint mPaint = new Paint();
28
29 private Bitmap mBitmap;
30
31 private Bitmap mScaledBitmap;
32
33 private float mLeft;
34
35 private int mSpeed = 15;
36
37 private int mRepeatCount = 0;
38
39 private Status mFlag = Status.NONE;
40
41 private int mTextColor = DEFAULT_TEXTCOLOT;
42
43 private int mTextSize = DEFAULT_TEXTSIZE;
44
45 public SinkingView(Context context, AttributeSet attrs) {
46 super(context, attrs);
47 }
48
49 public void setTextColor(int color) {
50 mTextColor = color;
51 }
52
53 public void setTextSize(int size) {
54 mTextSize = size;
55 }
56
57 public void setPercent(float percent) {
58 mFlag = Status.RUNNING;
59 mPercent = percent;
60 postInvalidate();
61
62 }
63
64 public void setStatus(Status status) {
65 mFlag = status;
66 }
67
68 public void clear() {
69 mFlag = Status.NONE;
70 if (mScaledBitmap != null) {
71 mScaledBitmap.recycle();
72 mScaledBitmap = null;
73 }
74
75 if (mBitmap != null) {
76 mBitmap.recycle();
77 mBitmap = null;
78 }
79 }
80
81 @Override
82 protected void dispatchDraw(Canvas canvas) {
83 super.dispatchDraw(canvas);
84 int width = getWidth();
85 int height = getHeight();
86
87 //裁剪成圆区域
88 Path path = new Path();
89 canvas.save();
90 path.reset();
91 canvas.clipPath(path);
92 path.addCircle(width / 2, height / 2, width / 2, Direction.CCW);
93 canvas.clipPath(path, Op.REPLACE);
94
95 if (mFlag == Status.RUNNING) {
96 if (mScaledBitmap == null) {
97 mBitmap = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.wave2);
98 mScaledBitmap = Bitmap.createScaledBitmap(mBitmap, mBitmap.getWidth(), getHeight(), false);
99 mBitmap.recycle();
100 mBitmap = null;
101 mRepeatCount = (int) Math.ceil(getWidth() / mScaledBitmap.getWidth() + 0.5) + 1;
102 }
103 for (int idx = 0; idx < mRepeatCount; idx++) {
104 canvas.drawBitmap(mScaledBitmap, mLeft + (idx - 1) * mScaledBitmap.getWidth(), (1-mPercent) * getHeight(), null);
105 }
106 String str = (int) (mPercent * 100) + "%";
107 mPaint.setColor(mTextColor);
108 mPaint.setTextSize(mTextSize);
109 mPaint.setStyle(Style.FILL);
110 canvas.drawText(str, (getWidth() - mPaint.measureText(str)) / 2, getHeight() / 2 + mTextSize / 2, mPaint);
111
112 mLeft += mSpeed;
113 if (mLeft >= mScaledBitmap.getWidth())
114 mLeft = 0;
115 // 绘制外圆环
116 mPaint.setStyle(Paint.Style.STROKE);
117 mPaint.setStrokeWidth(4);
118 mPaint.setAntiAlias(true);
119 mPaint.setColor(Color.rgb(33, 211, 39));
120 canvas.drawCircle(width / 2, height / 2, width / 2 - 2, mPaint);
121
122 postInvalidateDelayed(20);
123 }
124 canvas.restore();
125
126 }
127
128 public enum Status {
129 RUNNING, NONE
130 }
131
132 }
调用:
1 package com.czm.mysinkingview;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.View;
6 import android.view.View.OnClickListener;
7
8 /**
9 * 测试用例页
10 *
11 * @author caizhiming
12 */
13 public class MainActivity extends Activity {
14 private SinkingView mSinkingView;
15
16 private float percent = 0;
17
18 @Override
19 protected void onCreate(Bundle savedInstanceState) {
20 super.onCreate(savedInstanceState);
21 setContentView(R.layout.activity_main);
22 mSinkingView = (SinkingView) findViewById(R.id.sinking);
23
24 findViewById(R.id.btn_test).setOnClickListener(new OnClickListener() {
25
26 @Override
27 public void onClick(View v) {
28 // TODO Auto-generated method stub
29 updateProgress();
30 }
31 });
32
33 percent = 0.3f;
34 mSinkingView.setPercent(percent);
35 }
36
37
38 private void updateProgress() {
39 Thread thread = new Thread(new Runnable() {
40
41 @Override
42 public void run() {
43
44 percent = 0;
45 while (percent <= 1) {
46 mSinkingView.setPercent(percent);
47 percent += 0.01f;
48 try {
49 Thread.sleep(40);
50 } catch (InterruptedException e) {
51 e.printStackTrace();
52 }
53 }
54 percent = 0.78f;
55 if(percent>0.7&&percent<1){
56 mSinkingView.setTextColor(0xFFFFFFFF);
57 }
58 mSinkingView.setPercent(percent);
59 // mSinkingView.clear();
60 }
61 });
62 thread.start();
63 }
64
65 }
调用布局:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5
6 tools:context=".MainActivity" >
7
8 <com.czm.mysinkingview.SinkingView
9 android:id="@+id/sinking"
10 android:layout_width="wrap_content"
11 android:layout_height="wrap_content"
12 android:layout_centerInParent="true" >
13
14 <ImageView
15 android:id="@+id/image"
16 android:layout_width="120dp"
17 android:layout_height="120dp"
18 android:src="@drawable/charming2" />
19 </com.czm.mysinkingview.SinkingView>
20
21 <LinearLayout
22 android:layout_width="match_parent"
23 android:layout_height="wrap_content"
24 android:layout_alignParentBottom="true"
25 android:layout_centerHorizontal="true"
26 android:orientation="horizontal" >
27
28 <Button
29 android:id="@+id/btn_test"
30 android:textColor="#ffffff"
31 android:background="#0000ff"
32 android:textSize="18sp"
33 android:layout_width="match_parent"
34 android:layout_height="50dp"
35 android:layout_margin="10dp"
36 android:text="更新" />
37
38 </LinearLayout>
39
40 </RelativeLayout>
清单文件配置:
1 <activity
2 android:name="com.czm.mysinkingview.MainActivity"
3 android:label="@string/app_name"
4 android:hardwareAccelerated="false"
5 >
6 <intent-filter>
7 <action android:name="android.intent.action.MAIN" />
8
9 <category android:name="android.intent.category.LAUNCHER" />
10 </intent-filter>
11 </activity>