效果:
用到图片下载:
自定义View:
package com.czm.mysinkingview; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Region.Op;
import android.util.AttributeSet;
import android.widget.FrameLayout;
/**
* 水波浪球形进度View
* @author caizhiming
*
*/
public class SinkingView extends FrameLayout {
private static final int DEFAULT_TEXTCOLOT = 0xFFFF0000; private static final int DEFAULT_TEXTSIZE =40; private float mPercent; private Paint mPaint = new Paint(); private Bitmap mBitmap; private Bitmap mScaledBitmap; private float mLeft; private int mSpeed = 15; private int mRepeatCount = 0; private Status mFlag = Status.NONE; private int mTextColor = DEFAULT_TEXTCOLOT; private int mTextSize = DEFAULT_TEXTSIZE; public SinkingView(Context context, AttributeSet attrs) {
super(context, attrs);
} public void setTextColor(int color) {
mTextColor = color;
} public void setTextSize(int size) {
mTextSize = size;
} public void setPercent(float percent) {
mFlag = Status.RUNNING;
mPercent = percent;
postInvalidate(); } public void setStatus(Status status) {
mFlag = status;
} public void clear() {
mFlag = Status.NONE;
if (mScaledBitmap != null) {
mScaledBitmap.recycle();
mScaledBitmap = null;
} if (mBitmap != null) {
mBitmap.recycle();
mBitmap = null;
}
} @Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
int width = getWidth();
int height = getHeight(); //裁剪成圆区域
Path path = new Path();
canvas.save();
path.reset();
canvas.clipPath(path);
path.addCircle(width / 2, height / 2, width / 2, Direction.CCW);
canvas.clipPath(path, Op.REPLACE); if (mFlag == Status.RUNNING) {
if (mScaledBitmap == null) {
mBitmap = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.wave2);
mScaledBitmap = Bitmap.createScaledBitmap(mBitmap, mBitmap.getWidth(), getHeight(), false);
mBitmap.recycle();
mBitmap = null;
mRepeatCount = (int) Math.ceil(getWidth() / mScaledBitmap.getWidth() + 0.5) + 1;
}
for (int idx = 0; idx < mRepeatCount; idx++) {
canvas.drawBitmap(mScaledBitmap, mLeft + (idx - 1) * mScaledBitmap.getWidth(), (1-mPercent) * getHeight(), null);
}
String str = (int) (mPercent * 100) + "%";
mPaint.setColor(mTextColor);
mPaint.setTextSize(mTextSize);
mPaint.setStyle(Style.FILL);
canvas.drawText(str, (getWidth() - mPaint.measureText(str)) / 2, getHeight() / 2 + mTextSize / 2, mPaint); mLeft += mSpeed;
if (mLeft >= mScaledBitmap.getWidth())
mLeft = 0;
// 绘制外圆环
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(4);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.rgb(33, 211, 39));
canvas.drawCircle(width / 2, height / 2, width / 2 - 2, mPaint); postInvalidateDelayed(20);
}
canvas.restore(); } public enum Status {
RUNNING, NONE
} }
调用:
package com.czm.mysinkingview; import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener; /**
* 测试用例页
*
* @author caizhiming
*/
public class MainActivity extends Activity {
private SinkingView mSinkingView; private float percent = 0; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSinkingView = (SinkingView) findViewById(R.id.sinking); findViewById(R.id.btn_test).setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
// TODO Auto-generated method stub
updateProgress();
}
}); percent = 0.3f;
mSinkingView.setPercent(percent);
} private void updateProgress() {
Thread thread = new Thread(new Runnable() { @Override
public void run() { percent = 0;
while (percent <= 1) {
mSinkingView.setPercent(percent);
percent += 0.01f;
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
percent = 0.78f;
if(percent>0.7&&percent<1){
mSinkingView.setTextColor(0xFFFFFFFF);
}
mSinkingView.setPercent(percent);
// mSinkingView.clear();
}
});
thread.start();
} }
调用布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".MainActivity" > <com.czm.mysinkingview.SinkingView
android:id="@+id/sinking"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" > <ImageView
android:id="@+id/image"
android:layout_width="120dp"
android:layout_height="120dp"
android:src="@drawable/charming2" />
</com.czm.mysinkingview.SinkingView> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:orientation="horizontal" > <Button
android:id="@+id/btn_test"
android:textColor="#ffffff"
android:background="#0000ff"
android:textSize="18sp"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="10dp"
android:text="更新" /> </LinearLayout> </RelativeLayout>
清单文件配置:
<activity
android:name="com.czm.mysinkingview.MainActivity"
android:label="@string/app_name"
android:hardwareAccelerated="false"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>