Android使用自定義View實現(xiàn)360手機衛(wèi)士波浪球進度的效果
像360衛(wèi)士的波浪球進度的效果,一般最常用的方法就是畫線的方式,先繪sin線或貝塞爾曲線,然后從左到右繪制豎線,然后再裁剪圓區(qū)域。
今天我這用圖片bitmap的方式,大概的方法原理是:
(1)首先用clipPath裁剪園區(qū)域,
(2)然后用4張圖來不斷繪制到畫布上,再用偏移量來控制移動的速度,從而形成波浪動態(tài)效果。
(3)有一點需要注意的是,裁剪圓的時候用到的clipPath這個方法,在android 4.1,和4.2等某些系統(tǒng)上,裁剪出來不是圓,而是矩形,針對這些系統(tǒng) 需要在manifest.xml文件的activity中
將硬件加速關掉,因為默認是開啟的。即添加這個:android:hardwareAccelerated="false"
(源碼在下面最后給出哈)
手機上的效果:


下面咱們就來看看怎么實現(xiàn)吧:
(1)自定義波浪View的實現(xiàn):
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.util.Log;
import android.widget.FrameLayout;
/**
* 水波浪球形進度View
* @author caizhiming
*
*/
public class MySinkingView extends FrameLayout {
private static final int DEFAULT_TEXTCOLOT = 0xFFFFFFFF;
private static final int DEFAULT_TEXTSIZE = 250;
private float mPercent;
private Paint mPaint = new Paint();
private Bitmap mBitmap;
private Bitmap mScaledBitmap;
private float mLeft, mTop;
private int mSpeed = 15;
private int mRepeatCount = 0;
private Status mFlag = Status.NONE;
private int mTextColor = DEFAULT_TEXTCOLOT;
private int mTextSize = DEFAULT_TEXTSIZE;
public MySinkingView(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();
//裁剪成圓區(qū)域
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;
// 繪制外圓環(huán)
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
}
}
(2)布局文件的實現(xiàn):
<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" android:background="#000000" tools:context=".MainActivity" > <com.czm.mysinkingview.MySinkingView 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="400dp" android:layout_height="400dp" android:src="@drawable/charming2" /> </com.czm.mysinkingview.MySinkingView> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:orientation="horizontal" > <Button android:id="@+id/btn_test" android:layout_width="80dp" android:layout_height="wrap_content" android:text="體驗" /> </LinearLayout> </RelativeLayout>
(3)如何使用自定義波浪View:
package com.czm.mysinkingview;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
/**
* 使用并測試用例頁
*
* @author caizhiming
*/
public class MainActivity extends Activity {
private MySinkingView mSinkingView;
private float percent = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSinkingView = (MySinkingView) findViewById(R.id.sinking);
findViewById(R.id.btn_test).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
test();
}
});
percent = 0.56f;
mSinkingView.setPercent(percent);
}
private void test() {
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.56f;
mSinkingView.setPercent(percent);
// mSinkingView.clear();
}
});
thread.start();
}
}
最后,照例,給出源碼地址
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關文章
Android 自定義View之邊緣凹凸的優(yōu)惠券效果的開發(fā)過程
這篇文章主要介紹了Android 自定義View之邊緣凹凸的優(yōu)惠券效果,主要總結一下在自定義View的開發(fā)過程中需要注意的一些地方.需要的朋友可以參考下2018-03-03
使用Jetpack Compose實現(xiàn)翻轉卡片效果流程詳解
Jetpack Compose 是一款基于 Kotlin 的聲明式 UI 工具包,可以方便地創(chuàng)建漂亮的用戶界面。使用 Compose 的動畫 API 和可繪制 API,可以輕松實現(xiàn)翻轉卡片效果。通過設置旋轉角度和透明度等屬性,可以使卡片沿著 Y 軸翻轉,并實現(xiàn)翻頁效果2023-05-05

