日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 进度条_Android仿水波纹流球进度条控制器,实现高端大气的主流特效

發布時間:2023/12/10 Android 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 进度条_Android仿水波纹流球进度条控制器,实现高端大气的主流特效 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天看到一個效果挺不錯的,就模仿了下來,加上了一些自己想要的效果,感覺還不錯的樣子,所以就分享出來了,話不多說,上圖

CircleView

這里主要是實現中心圓以及水波特效

package com.lgl.circleview;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.RectF;

import android.os.Handler;

import android.os.Parcel;

import android.os.Parcelable;

import android.util.AttributeSet;

import android.view.View;

import android.widget.ProgressBar;

/**

* 水波圓

*

* @author lgl

*

*/

public class CircleView extends View {

private Context mContext;

private int mScreenWidth;

private int mScreenHeight;

private Paint mRingPaint;

private Paint mCirclePaint;

private Paint mWavePaint;

private Paint linePaint;

private Paint flowPaint;

private Paint leftPaint;

private int mRingSTROKEWidth = 15;

private int mCircleSTROKEWidth = 2;

private int mLineSTROKEWidth = 1;

private int mCircleColor = Color.WHITE;

private int mRingColor = Color.WHITE;

private int mWaveColor = Color.WHITE;

private Handler mHandler;

private long c = 0L;

private boolean mStarted = false;

private final float f = 0.033F;

private int mAlpha = 50;// 透明度

private float mAmplitude = 10.0F; // 振幅

private float mWaterLevel = 0.5F;// 水高(0~1)

private Path mPath;

// 繪制文字顯示在圓形中間,只是我沒有設置,我覺得寫在布局上也挺好的

private String flowNum = "";

private String flowLeft = "還剩余";

/**

* @param context

*/

public CircleView(Context context) {

super(context);

// TODO Auto-generated constructor stub

mContext = context;

init(mContext);

}

/**

* @param context

* @param attrs

*/

public CircleView(Context context, AttributeSet attrs) {

super(context, attrs);

// TODO Auto-generated constructor stub

mContext = context;

init(mContext);

}

/**

* @param context

* @param attrs

* @param defStyleAttr

*/

public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

// TODO Auto-generated constructor stub

mContext = context;

init(mContext);

}

public void setmWaterLevel(float mWaterLevel) {

this.mWaterLevel = mWaterLevel;

}

private void init(Context context) {

mRingPaint = new Paint();

mRingPaint.setColor(mRingColor);

mRingPaint.setAlpha(50);

mRingPaint.setStyle(Paint.Style.STROKE);

mRingPaint.setAntiAlias(true);

mRingPaint.setStrokeWidth(mRingSTROKEWidth);

mCirclePaint = new Paint();

mCirclePaint.setColor(mCircleColor);

mCirclePaint.setStyle(Paint.Style.STROKE);

mCirclePaint.setAntiAlias(true);

mCirclePaint.setStrokeWidth(mCircleSTROKEWidth);

linePaint = new Paint();

linePaint.setColor(mCircleColor);

linePaint.setStyle(Paint.Style.STROKE);

linePaint.setAntiAlias(true);

linePaint.setStrokeWidth(mLineSTROKEWidth);

flowPaint = new Paint();

flowPaint.setColor(mCircleColor);

flowPaint.setStyle(Paint.Style.FILL);

flowPaint.setAntiAlias(true);

flowPaint.setTextSize(36);

leftPaint = new Paint();

leftPaint.setColor(mCircleColor);

leftPaint.setStyle(Paint.Style.FILL);

leftPaint.setAntiAlias(true);

leftPaint.setTextSize(36);

mWavePaint = new Paint();

mWavePaint.setStrokeWidth(1.0F);

mWavePaint.setColor(mWaveColor);

mWavePaint.setAlpha(mAlpha);

mPath = new Path();

mHandler = new Handler() {

@Override

public void handleMessage(android.os.Message msg) {

if (msg.what == 0) {

invalidate();

if (mStarted) {

// 不斷發消息給自己,使自己不斷被重繪

mHandler.sendEmptyMessageDelayed(0, 60L);

}

}

}

};

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int width = measure(widthMeasureSpec, true);

int height = measure(heightMeasureSpec, false);

if (width < height) {

setMeasuredDimension(width, width);

} else {

setMeasuredDimension(height, height);

}

}

/**

* @category 測量

* @param measureSpec

* @param isWidth

* @return

*/

private int measure(int measureSpec, boolean isWidth) {

int result;

int mode = MeasureSpec.getMode(measureSpec);

int size = MeasureSpec.getSize(measureSpec);

int padding = isWidth ? getPaddingLeft() + getPaddingRight()

: getPaddingTop() + getPaddingBottom();

if (mode == MeasureSpec.EXACTLY) {

result = size;

} else {

result = isWidth ? getSuggestedMinimumWidth()

: getSuggestedMinimumHeight();

result += padding;

if (mode == MeasureSpec.AT_MOST) {

if (isWidth) {

result = Math.max(result, size);

} else {

result = Math.min(result, size);

}

}

}

return result;

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

// TODO Auto-generated method stub

super.onSizeChanged(w, h, oldw, oldh);

mScreenWidth = w;

mScreenHeight = h;

}

@Override

protected void onDraw(Canvas canvas) {

// TODO Auto-generated method stub

super.onDraw(canvas);

// 得到控件的寬高

int width = getWidth();

int height = getHeight();

setBackgroundColor(mContext.getResources().getColor(R.color.main_bg));

// 計算當前油量線和水平中線的距離

float centerOffset = Math.abs(mScreenWidth / 2 * mWaterLevel

- mScreenWidth / 4);

// 計算油量線和與水平中線的角度

float horiAngle = (float) (Math.asin(centerOffset / (mScreenWidth / 4)) * 180 / Math.PI);

// 扇形的起始角度和掃過角度

float startAngle, sweepAngle;

if (mWaterLevel > 0.5F) {

startAngle = 360F - horiAngle;

sweepAngle = 180F + 2 * horiAngle;

} else {

startAngle = horiAngle;

sweepAngle = 180F - 2 * horiAngle;

}

canvas.drawLine(mScreenWidth * 3 / 8, mScreenHeight * 5 / 8,

mScreenWidth * 5 / 8, mScreenHeight * 5 / 8, linePaint);

float num = flowPaint.measureText(flowNum);

canvas.drawText(flowNum, mScreenWidth * 4 / 8 - num / 2,

mScreenHeight * 4 / 8, flowPaint);

float left = leftPaint.measureText(flowLeft);

canvas.drawText(flowLeft, mScreenWidth * 4 / 8 - left / 2,

mScreenHeight * 3 / 8, leftPaint);

// 如果未開始(未調用startWave方法),繪制一個扇形

if ((!mStarted) || (mScreenWidth == 0) || (mScreenHeight == 0)) {

// 繪制,即水面靜止時的高度

RectF oval = new RectF(mScreenWidth / 4, mScreenHeight / 4,

mScreenWidth * 3 / 4, mScreenHeight * 3 / 4);

canvas.drawArc(oval, startAngle, sweepAngle, false, mWavePaint);

return;

}

// 繪制,即水面靜止時的高度

// 繪制,即水面靜止時的高度

RectF oval = new RectF(mScreenWidth / 4, mScreenHeight / 4,

mScreenWidth * 3 / 4, mScreenHeight * 3 / 4);

canvas.drawArc(oval, startAngle, sweepAngle, false, mWavePaint);

if (this.c >= 8388607L) {

this.c = 0L;

}

// 每次onDraw時c都會自增

c = (1L + c);

float f1 = mScreenHeight * (1.0F - (0.25F + mWaterLevel / 2))

- mAmplitude;

// 當前油量線的長度

float waveWidth = (float) Math.sqrt(mScreenWidth * mScreenWidth / 16

- centerOffset * centerOffset);

// 與圓半徑的偏移量

float offsetWidth = mScreenWidth / 4 - waveWidth;

int top = (int) (f1 + mAmplitude);

mPath.reset();

// 起始振動X坐標,結束振動X坐標

int startX, endX;

if (mWaterLevel > 0.50F) {

startX = (int) (mScreenWidth / 4 + offsetWidth);

endX = (int) (mScreenWidth / 2 + mScreenWidth / 4 - offsetWidth);

} else {

startX = (int) (mScreenWidth / 4 + offsetWidth - mAmplitude);

endX = (int) (mScreenWidth / 2 + mScreenWidth / 4 - offsetWidth + mAmplitude);

}

// 波浪效果

while (startX < endX) {

int startY = (int) (f1 - mAmplitude

* Math.sin(Math.PI

* (2.0F * (startX + this.c * width * this.f))

/ width));

canvas.drawLine(startX, startY, startX, top, mWavePaint);

startX++;

}

canvas.drawCircle(mScreenWidth / 2, mScreenHeight / 2, mScreenWidth / 4

+ mRingSTROKEWidth / 2, mRingPaint);

canvas.drawCircle(mScreenWidth / 2, mScreenHeight / 2,

mScreenWidth / 4, mCirclePaint);

canvas.restore();

}

@Override

public Parcelable onSaveInstanceState() {

Parcelable superState = super.onSaveInstanceState();

SavedState ss = new SavedState(superState);

ss.progress = (int) c;

return ss;

}

@Override

public void onRestoreInstanceState(Parcelable state) {

SavedState ss = (SavedState) state;

super.onRestoreInstanceState(ss.getSuperState());

c = ss.progress;

}

@Override

protected void onAttachedToWindow() {

super.onAttachedToWindow();

// 關閉硬件加速,防止異常unsupported operation exception

this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

}

@Override

protected void onDetachedFromWindow() {

super.onDetachedFromWindow();

}

/**

* @category 開始波動

*/

public void startWave() {

if (!mStarted) {

this.c = 0L;

mStarted = true;

this.mHandler.sendEmptyMessage(0);

}

}

/**

* @category 停止波動

*/

public void stopWave() {

if (mStarted) {

this.c = 0L;

mStarted = false;

this.mHandler.removeMessages(0);

}

}

/**

* @category 保存狀態

*/

static class SavedState extends BaseSavedState {

int progress;

/**

* Constructor called from {@link ProgressBar#onSaveInstanceState()}

*/

SavedState(Parcelable superState) {

super(superState);

}

/**

* Constructor called from {@link #CREATOR}

*/

private SavedState(Parcel in) {

super(in);

progress = in.readInt();

}

@Override

public void writeToParcel(Parcel out, int flags) {

super.writeToParcel(out, flags);

out.writeInt(progress);

}

public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {

public SavedState createFromParcel(Parcel in) {

return new SavedState(in);

}

public SavedState[] newArray(int size) {

return new SavedState[size];

}

};

}

}

我們運行一下

其實他是十分的空曠的,所以也值得我們去定制,我們在中間加個流量顯示,再加個進度條

activity_main.xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@color/main_bg" >

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentTop="true"

android:layout_centerHorizontal="true"

android:layout_marginTop="10dp"

android:text="流量"

android:textColor="@android:color/white"

android:textSize="18sp" />

android:id="@+id/wave_view"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:layout_centerInParent="true" />

android:id="@+id/power"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:textColor="@android:color/white" />

android:id="@+id/seekBar"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentBottom="true"

android:layout_marginBottom="150dp" />

```

>我們要實現這個,就要調用它的初始化以及start方法

```

mCircleView = (CircleView) findViewById(R.id.wave_view);

// 設置多高,float,0.1-1F

mCircleView.setmWaterLevel(0.1F);

// 開始執行

mCircleView.startWave();

別忘了activity銷毀的時候把它回收哦

@Override

protected void onDestroy() {

// TODO Auto-generated method stub

mCircleView.stopWave();

mCircleView = null;

super.onDestroy();

}

我們再運行一遍

但是我們要怎么讓水波紋隨著進度條一起上升下降尼?,這里我們就要用到我們剛才寫的SeekBar了,我們實現它的setOnSeekBarChangeListener來監聽,這樣我們就要復寫他的三個方法,這里我們只要用到一個

public void onProgressChanged(SeekBar seekBar, int progress,

boolean fromUser) {

//跟隨進度條滾動

mCircleView.setmWaterLevel((float) progress / 100);

}

這里,我們要這樣算的,我們設置高度的單位是float,也就是從0-1F,而我們的進度是int progress,從0-100,我們就要用(float) progress / 100)并且強轉來得到單位,好了,我們現在水波紋的高度就是隨著我們的進度條一起變化了,我們再來運行一下

好的,這樣的話,我們就只剩下一個了,就是讓大小隨著我們的進度條變化了,這里我們因為更新UI不能再主線程中操作,所以我們需要用到我們的老伙計Handler了,但是用到handler還不夠,我們的進度條數值也是在內部類里面,所以這里我們需要用到Handler來傳值了,這里我們用的是Bundle,我們還是在onProgressChanged方法中操作了

//創建一個消息

Message message = new Message();

Bundle bundle = new Bundle();

//put一個int值

bundle.putInt("progress

總結

以上是生活随笔為你收集整理的android 进度条_Android仿水波纹流球进度条控制器,实现高端大气的主流特效的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。