效果:
用到图片下载:
自定义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>