仿水波纹流球进度条控制器,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,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 * 3 / 4); canvas.drawArc(oval,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,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<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; }}
我们运行一下
其实他是十分的空旷的,所以也值得我们去定制,我们在中间加个流量显示,再加个进度条
activity_main.xml
<?xml version="1.0" enCoding="utf-8"?><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="@color/main_bg" > <TextVIEw 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" /> <com.lgl.circlevIEw.CircleVIEw androID:ID="@+ID/wave_vIEw" androID:layout_wIDth="fill_parent" androID:layout_height="fill_parent" androID:layout_centerInParent="true" /> <TextVIEw androID:ID="@+ID/power" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_centerInParent="true" androID:textcolor="@androID:color/white" /> <Seekbar androID:ID="@+ID/seekbar" androID:layout_wIDth="match_parent" androID:layout_height="wrap_content" androID:layout_alignParentBottom="true" androID:layout_marginBottom="150dp" /></relativeLayout>
我们要实现这个,就要调用它的初始化以及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",progress); //装载 message.setData(bundle); //发送消息 handler.sendMessage(message); //创建表示 message.what = 1;
消息发送过去了,我们就在前面写个Handler去接收就是了
private Handler handler = new Handler() { public voID handleMessage(androID.os.Message msg) { if (msg.what == 1) { int num = msg.getData().getInt("progress"); Log.i("num",num + ""); power.setText((float) num / 100 * max + "M/" + max + "M"); } } };
这里的计算公式尼,是当前的数值/100得到百分比再去*最大值。我们现在可以完整的运行一下了,其实和最上面运行的图片是一样的
MainActivity
package com.lgl.circlevIEw;import androID.app.Activity;import androID.os.Bundle;import androID.os.Handler;import androID.os.Message;import androID.util.Log;import androID.Widget.Seekbar;import androID.Widget.TextVIEw;public class MainActivity extends Activity { private CircleVIEw mCircleVIEw; private Seekbar mSeekbar; private TextVIEw power; private int max = 1024; private int min = 102; private Handler handler = new Handler() { public voID handleMessage(androID.os.Message msg) { if (msg.what == 1) { int num = msg.getData().getInt("progress"); Log.i("num",num + ""); power.setText((float) num / 100 * max + "M/" + max + "M"); } } }; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getActionbar().hIDe(); setContentVIEw(R.layout.activity_main); power = (TextVIEw) findVIEwByID(R.ID.power); power.setText(min + "M/" + max + "M"); mCircleVIEw = (CircleVIEw) findVIEwByID(R.ID.wave_vIEw); // 设置多高,float,0.1-1F mCircleVIEw.setmWaterLevel(0.1F); // 开始执行 mCircleVIEw.startWave(); mSeekbar = (Seekbar) findVIEwByID(R.ID.seekbar); mSeekbar.setonSeekbarchangelistener(new Seekbar.OnSeekbarchangelistener() { @OverrIDe public voID onProgressChanged(Seekbar seekbar,boolean fromUser) { mCircleVIEw.setmWaterLevel((float) progress / 100); // 创建一个消息 Message message = new Message(); Bundle bundle = new Bundle(); // put一个int值 bundle.putInt("progress",progress); // 装载 message.setData(bundle); // 发送消息 handler.sendMessage(message); // 创建表示 message.what = 1; } @OverrIDe public voID onStartTrackingtouch(Seekbar seekbar) { } @OverrIDe public voID onStopTrackingtouch(Seekbar seekbar) { } }); } @OverrIDe protected voID onDestroy() { // Todo auto-generated method stub mCircleVIEw.stopWave(); mCircleVIEw = null; super.onDestroy(); }}
代码下载:Android仿水波纹流量球进度条
以上就是本文的全部内容,希望对大家学习AndroID软件编程有所帮助。
总结以上是内存溢出为你收集整理的Android仿水波纹流量球进度条控制器全部内容,希望文章能够帮你解决Android仿水波纹流量球进度条控制器所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)