自定义动画,水球波纹,因为不知道怎么上传动态图,所以就用静态的了:
自定义控件,重写View
/** * 自定义动画水波球 * Created by IKL on 2018/6/5. */ public class WaterWaveProgress extends View { // 水的画笔 // 画圆环的画笔// 进度百分比的画笔 private Paint mPaintWater = null, mRingPaint = null, mTextPaint = null; // 圆环颜色 // 圆环背景颜色 // 当前进度 //水波颜色 // 水波背景色 //进度条和水波之间的距离 //进度百分比字体大小 // //进度百分比字体颜色 private int mRingColor, mRingBgColor, mWaterColor, mWaterBgColor, mFontSize, mTextColor; // 进度 //浪峰个数 float crestCount = 1.5f; //描述 private String s = ""; float mProgress = 10f, mMaxProgress = 100; // 画布中心点 private Point mCenterPoint; // 圆环宽度 private float mRingWidth, mProgress2WaterWidth; // 是否显示进度条 //是否显示进度百分比 private boolean mShowProgress = false, mShowNumerical = true; /** * 产生波浪效果的因子 */ private long mWaveFactor = 0L; /** * 正在执行波浪动画 */ private boolean isWaving = false; /** * 振幅 */ private float mAmplitude = 10.0F; // 20F /** * 波浪的速度 */ private float mWaveSpeed = 0.040F; // 0.020F /** * 水的透明度 */ private int mWaterAlpha = 255; // 255 WaterWaveAttrInit attrInit; private MyHandler mHandler = null; private Paint mDesTextPaint; private int mScreenWidth; private int mScreenHeight; private int mDesFontSize; private static class MyHandler extends Handler { private WeakReference<WaterWaveProgress> mWeakRef = null; private int refreshPeriod = 100; public MyHandler(WaterWaveProgress host) { mWeakRef = new WeakReference<WaterWaveProgress>(host); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (mWeakRef.get() != null) { mWeakRef.get().invalidate(); sendEmptyMessageDelayed(0, refreshPeriod); } } } public WaterWaveProgress(Context paramContext) { super(paramContext); } public WaterWaveProgress(Context context, AttributeSet attributeSet) { this(context, attributeSet, 0); } public WaterWaveProgress(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); attrInit = new WaterWaveAttrInit(context, attrs, defStyleAttr); init(context); } @SuppressLint("NewApi") private void init(Context context) { mCenterPoint = new Point(); mRingColor = attrInit.getProgressColor(); mRingBgColor = attrInit.getProgressBgColor(); mWaterColor = attrInit.getWaterWaveColor(); mWaterBgColor = attrInit.getWaterWaveBgColor(); mRingWidth = attrInit.getProgressWidth(); mProgress2WaterWidth = attrInit.getProgress2WaterWidth(); mShowProgress = attrInit.isShowProgress(); mShowNumerical = attrInit.isShowNumerical(); mFontSize = attrInit.getFontSize(); mDesFontSize = attrInit.getDesFontSize(); mTextColor = attrInit.getTextColor(); mProgress = attrInit.getProgress(); mMaxProgress = attrInit.getMaxProgress(); // 如果手机版本在4.0以上,则开启硬件加速 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { setLayerType(View.LAYER_TYPE_HARDWARE, null); // setLayerType(View.LAYER_TYPE_SOFTWARE, null); } mRingPaint = new Paint(); mRingPaint.setAntiAlias(true); mRingPaint.setColor(mRingColor); // 圆环颜色 mRingPaint.setStyle(Paint.Style.STROKE); mRingPaint.setStrokeWidth(mRingWidth); // 圆环宽度 mPaintWater = new Paint(); mPaintWater.setStrokeWidth(1.0F); // mPaintWater.setColor(mWaterColor); //设置水的颜色 mPaintWater.setColor(getResources().getColor(R.color.blue)); mPaintWater.setAlpha(mWaterAlpha); mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); mTextPaint.setColor(mTextColor); mTextPaint.setStyle(Paint.Style.FILL); mTextPaint.setTextSize(mFontSize); mDesTextPaint = new Paint();//描述 mDesTextPaint.setColor(mTextColor); mDesTextPaint.setStyle(Paint.Style.FILL); mDesTextPaint.setAntiAlias(true); mDesTextPaint.setTextSize(mDesFontSize); mHandler = new MyHandler(this); } public void animateWave() { if (!isWaving) { mWaveFactor = 0L; isWaving = true; mHandler.sendEmptyMessage(0); } } @SuppressLint({"DrawAllocation", "NewApi"}) protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 获取整个View(容器)的宽、高 int width = getWidth(); int height = getHeight(); width = height = (width < height) ? width : height; //计算的波峰高度 // mAmplitude = width / 20f; mCenterPoint.x = width / 2; mCenterPoint.y = height / 2; { // 重新设置进度条的宽度和水波与进度条的距离,,至于为什么写在这,我脑袋抽了可以不 mRingWidth = mRingWidth == 0 ? width / 20 : mRingWidth; mProgress2WaterWidth = mProgress2WaterWidth == 0 ? mRingWidth * 0.6f : mProgress2WaterWidth; mRingPaint.setStrokeWidth(mRingWidth); mTextPaint.setTextSize(mFontSize == 0 ? width / 5 : mFontSize); mDesTextPaint.setTextSize(mDesFontSize == 0 ? width / 5 : mDesFontSize); if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) { setLayerType(View.LAYER_TYPE_SOFTWARE, null); } else { setLayerType(View.LAYER_TYPE_HARDWARE, null); } } RectF oval = new RectF(); oval.left = mRingWidth / 2; oval.top = mRingWidth / 2; oval.right = width - mRingWidth / 2; oval.bottom = height - mRingWidth / 2; if (isInEditMode()) { mRingPaint.setColor(mRingBgColor); canvas.drawArc(oval, -90, 360, false, mRingPaint); mRingPaint.setColor(mRingColor); canvas.drawArc(oval, -90, 90, false, mRingPaint); canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, mCenterPoint.x - mRingWidth - mProgress2WaterWidth, mPaintWater); return; } // 如果没有执行波浪动画,或者也没有指定容器宽高,就画个简单的矩形 if ((width == 0) || (height == 0) || isInEditMode()) { canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, width / 2 - mProgress2WaterWidth - mRingWidth, mPaintWater); return; } // 水与边框的距离 float waterPadding = mShowProgress ? mRingWidth + mProgress2WaterWidth : 0; // 水最高处 int waterHeightCount = mShowProgress ? (int) (height - waterPadding * 2) : height; // 重新生成波浪的形状 mWaveFactor++; if (mWaveFactor >= Integer.MAX_VALUE) { mWaveFactor = 0L; } // 画进度条背景 mRingPaint.setColor(mRingBgColor); // canvas.drawArc(oval, -90, 360, false, mRingPaint); // //和下面效果一样,只不过这个是画个360度的弧,下面是画圆环 canvas.drawCircle(width / 2, width / 2, waterHeightCount / 2 + waterPadding - mRingWidth / 2, mRingPaint); mRingPaint.setColor(mRingColor); // 100为 总进度 canvas.drawArc(oval, -90, (mProgress * 1f) / mMaxProgress * 360f, false, mRingPaint); // 计算出水的高度 float waterHeight = waterHeightCount * (1 - (mProgress * 1f) / mMaxProgress) + waterPadding; int staticHeight = (int) (waterHeight + mAmplitude); Path mPath = new Path(); mPath.reset(); if (mShowProgress) { mPath.addCircle(width / 2, width / 2, waterHeightCount / 2, Path.Direction.CCW); } else { mPath.addCircle(width / 2, width / 2, waterHeightCount / 2, Path.Direction.CCW); } // canvas添加限制,让接下来的绘制都在园内 canvas.clipPath(mPath, Region.Op.INTERSECT); // canvas.clipPath(mPath, Op.REPLACE); Paint bgPaint = new Paint(); bgPaint.setColor(mWaterBgColor); // 绘制背景 canvas.drawRect(waterPadding, waterPadding, waterHeightCount + waterPadding, waterHeightCount + waterPadding, bgPaint); // 绘制静止的水 canvas.drawRect(waterPadding, staticHeight, waterHeightCount + waterPadding, waterHeightCount + waterPadding, mPaintWater); // 待绘制的波浪线的x坐标 int xToBeDrawed = (int) waterPadding; int waveHeight = (int) (waterHeight - mAmplitude * Math.sin(Math.PI * (2.0F * (xToBeDrawed + (mWaveFactor * width) * mWaveSpeed)) / width)); // 波浪线新的高度 int newWaveHeight = waveHeight; while (true) { if (xToBeDrawed >= waterHeightCount + waterPadding) { break; } // 根据当前x值计算波浪线新的高度 newWaveHeight = (int) (waterHeight - mAmplitude * Math.sin(Math.PI * (crestCount * (xToBeDrawed + (mWaveFactor * waterHeightCount) * mWaveSpeed)) / waterHeightCount)); // 先画出梯形的顶边 canvas.drawLine(xToBeDrawed, waveHeight, xToBeDrawed + 1, newWaveHeight, mPaintWater); // 画出动态变化的柱子部分 canvas.drawLine(xToBeDrawed, newWaveHeight, xToBeDrawed + 1, staticHeight, mPaintWater); xToBeDrawed++; waveHeight = newWaveHeight; } if (mShowNumerical) { String progressTxt = String.format("%.0f", (mProgress * 1f) / mMaxProgress * 100f) + "%"; float mTxtWidth = mTextPaint.measureText(progressTxt, 0, progressTxt.length()); canvas.drawText(progressTxt, mCenterPoint.x - mTxtWidth / 2, mCenterPoint.x * 1.5f - mFontSize / 2, mTextPaint); } //描述 float left = mDesTextPaint.measureText(s,0,s.length()); canvas.drawText(s, mScreenWidth * 4 / 8 - left / 2, mScreenHeight * 3 / 8, mDesTextPaint); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mScreenWidth = w; mScreenHeight = h; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = widthMeasureSpec; int height = heightMeasureSpec; width = height = (width < height) ? width : height; setMeasuredDimension(width, height); } /** * 设置波浪的振幅 */ public void setAmplitude(float amplitude) { mAmplitude = amplitude; } /** * 设置水的透明度 * * @param alpha 透明的百分比,值为0到1之间的小数,越接近0越透明 */ public void setWaterAlpha(float alpha) { mWaterAlpha = (int) (255.0F * alpha); mPaintWater.setAlpha(mWaterAlpha); } /** * 设置水的颜色 */ public void setWaterColor(int color) { mWaterColor = color; } /** * 设置当前进度 */ public void setProgress(float progress) { progress = progress > 100 ? 100 : progress < 0 ? 0 : progress; mProgress = progress; invalidate(); } /** * 获取进度 动画时会用到 */ public float getProgress() { return mProgress; } /** * 设置波浪速度 */ public void setWaveSpeed(float speed) { mWaveSpeed = speed; } /** * 是否显示进度条 * * @param b */ public void setShowProgress(boolean b) { mShowProgress = b; } /** * 是否显示进度值 * * @param b */ public void setShowNumerical(boolean b) { mShowNumerical = b; } /** * 设置进度条前景色 * * @param mRingColor */ public void setmRingColor(int mRingColor) { this.mRingColor = mRingColor; } /** * 设置进度条背景色 * * @param mRingBgColor */ public void setmRingBgColor(int mRingBgColor) { this.mRingBgColor = mRingBgColor; } /** * 设置水波颜色 * * @param mWaterColor */ public void setmWaterColor(int mWaterColor) { this.mWaterColor = mWaterColor; } /** * 设置水波背景色 * * @param mWaterBgColor */ public void setWaterBgColor(int mWaterBgColor) { this.mWaterBgColor = mWaterBgColor; } /** * 设置进度值显示字体大小 * * @param mFontSize */ public void setFontSize(int mFontSize) { this.mFontSize = mFontSize; } /** * 设置描述显示字体大小 * * @param mDesFontSize */ public void setDesFontSize(int mDesFontSize) { this.mDesFontSize = mDesFontSize; } /** * 设置进度值显示字体颜色 * * @param mTextColor */ public void setTextColor(int mTextColor) { this.mTextColor = mTextColor; } /** * 设置进度条最大值 * * @param mMaxProgress */ public void setMaxProgress(int mMaxProgress) { this.mMaxProgress = mMaxProgress; } /** * 设置浪峰个数 * * @param crestCount */ public void setCrestCount(float crestCount) { this.crestCount = crestCount; } /** * 设置进度条宽度 * * @param mRingWidth */ public void setRingWidth(float mRingWidth) { this.mRingWidth = mRingWidth; } /** * 设置水波到进度条之间的距离 * * @param mProgress2WaterWidth */ public void setProgress2WaterWidth(float mProgress2WaterWidth) { this.mProgress2WaterWidth = mProgress2WaterWidth; } }
设置水波动画
/** * 水波动画 * Created by IKL on 2018/6/5. */ public class WaterWaveAttrInit { private final int desFontSize; private int progressWidth; // 进度条宽度 private int progressColor; private int progressBgColor; private int waterWaveColor; private int waterWaveBgColor; private int progress2WaterWidth; // 进度条和水波之间的间距 private boolean showProgress; // 是否显示进度条 private boolean showNumerical; // 是否显示百分比 private int fontSize; private int textColor; private int progress; private int maxProgress; @SuppressLint("Recycle") public WaterWaveAttrInit(Context context, AttributeSet attrs, int defStyle) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WaterWaveProgress, defStyle, 0); progressWidth = typedArray.getDimensionPixelOffset( R.styleable.WaterWaveProgress_progressWidth, 0); progressColor = typedArray.getColor( R.styleable.WaterWaveProgress_progressColor, 0xFF33B5E5); progressBgColor = typedArray.getColor( R.styleable.WaterWaveProgress_progressBgColor, 0xFFBEBEBE); waterWaveColor = typedArray.getColor( R.styleable.WaterWaveProgress_waterWaveColor, 0XFF4BBDFE); waterWaveBgColor = typedArray.getColor( R.styleable.WaterWaveProgress_waterWaveBgColor, 0xFFDDDDDD); progress2WaterWidth = typedArray.getDimensionPixelOffset( R.styleable.WaterWaveProgress_progress2WaterWidth, 0); showProgress = typedArray.getBoolean( R.styleable.WaterWaveProgress_showProgress, true); showNumerical = typedArray.getBoolean( R.styleable.WaterWaveProgress_showNumerical, true); fontSize = typedArray.getDimensionPixelOffset( R.styleable.WaterWaveProgress_fontSize, 0); desFontSize = typedArray.getDimensionPixelOffset( R.styleable.WaterWaveProgress_desFontSize, 0); textColor = typedArray.getColor( R.styleable.WaterWaveProgress_textColor, 0xFFFFFFFF); progress = typedArray.getInteger( R.styleable.WaterWaveProgress_progress, 0); maxProgress = typedArray.getInteger( R.styleable.WaterWaveProgress_maxProgress, 100); typedArray.recycle(); } public int getProgressWidth() { return progressWidth; } public int getProgressColor() { return progressColor; } public int getProgressBgColor() { return progressBgColor; } public int getWaterWaveColor() { return waterWaveColor; } public int getWaterWaveBgColor() { return waterWaveBgColor; } public int getProgress2WaterWidth() { return progress2WaterWidth; } public boolean isShowProgress() { return showProgress; } public boolean isShowNumerical() { return showNumerical; } public int getFontSize() { return fontSize; } public int getDesFontSize() { return desFontSize; } public int getTextColor() { return textColor; } public int getProgress() { return progress; } public int getMaxProgress() { return maxProgress; } }
布局中调用
注意!!!!不要复制粘贴!!不要复制粘贴!!不要复制粘贴!!!工程的路径是不一样的!
<qnkj.cn.practice.shuibo.WaterWaveProgress android:layout_width="300px" android:layout_height="300px" android:id="@+id/water_wave_ball_view" android:layout_gravity="center_horizontal" /> </com.zhy.autolayout.AutoLinearLayout> 找到控件:
WaterWaveProgress waterWaveProgress = findViewById(R.id.water_wave_ball_view);
调用
//水波动画,传入字符串,表示所占据的百分比大小 waterWaveProgress.setProgress(Float.parseFloat("71.5")); //progress外圈圆形进度条未达到颜色 waterWaveProgress.setmRingBgColor(getResources().getColor(R.color.light_white)); //progress,外圈圆形进度条达到颜色 waterWaveProgress.setmRingColor(getResources().getColor(R.color.blue)); //球内未到达的颜色 waterWaveProgress.setWaterBgColor(getResources().getColor(R.color.dark_blue)); waterWaveProgress.setFontSize(52); // waterWaveBallView.setDesFontSize(36); waterWaveProgress.setProgress2WaterWidth(1); waterWaveProgress.setRingWidth(3); //振幅 // watercircleview.setAmplitude(10f); // watercircleview.setWaveSpeed(0.04f); waterWaveProgress.setCrestCount(2); if (waterWaveProgress.getProgress() != 0) { waterWaveProgress.animateWave();//打开波动动画从 } setGrade(waterWaveProgress); 加载水波进度
/** * 动画加载水波纹进度 */ private int mProgress; public void setGrade(final WaterWaveProgress watercircleview) { final float progress = watercircleview.getProgress(); mProgress = 1; final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 0x1223) { watercircleview.setProgress(mProgress * (1)); } else if (msg.what == 0x1224) { watercircleview.setProgress(progress); } } }; new Timer().schedule(new TimerTask() { @Override public void run() { Message msg = new Message(); if (mProgress < progress) { msg.what = 0x1223; mProgress++; } else { msg.what = 0x1224; this.cancel(); } handler.sendMessage(msg); } }, 0, 25); }