自定义水波纹效果,可设置波纹条数和波纹颜色,使用简单
生活随笔
收集整理的這篇文章主要介紹了
自定义水波纹效果,可设置波纹条数和波纹颜色,使用简单
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1、先上一波效果圖,是會動的哈,我這里上傳了一張靜態圖片,可設置波紋個數、波峰高度、透明度、顏色等等屬性,看大家個人需求。圖中是3條水波紋,使用方法特別簡單,直接xml中調用就可以。接下來上代碼
?
2、用到的類有:
3、調用方式:
4、實現步驟
第一步:創建? MultiWaveHeader? 類
public class MultiWaveHeader extends ViewGroup {protected Path mPath;protected ShapeType mShape = ShapeType.Rect;protected Paint mPaint = new Paint();protected Matrix mMatrix = new Matrix();protected List<Wave> mltWave = new ArrayList<>();protected float mCornerRadius;protected int mWaveHeight;protected int mCloseColor;protected int mStartColor;protected int mGradientAngle;protected boolean mIsRunning;protected boolean mEnableFullScreen;protected float mVelocity;protected float mColorAlpha;protected float mProgress;protected float mCurProgress;protected long mLastTime = 0;protected ValueAnimator reboundAnimator;public MultiWaveHeader(Context context) {this(context, null, 0);}public MultiWaveHeader(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public MultiWaveHeader(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mPaint.setAntiAlias(true);TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MultiWaveHeader);mWaveHeight = ta.getDimensionPixelOffset(R.styleable.MultiWaveHeader_mwhWaveHeight, Util.dp2px(50));mStartColor = ta.getColor(R.styleable.MultiWaveHeader_mwhStartColor, 0xFF056CD0);mCloseColor = ta.getColor(R.styleable.MultiWaveHeader_mwhCloseColor, 0xFF31AFFE);mColorAlpha = ta.getFloat(R.styleable.MultiWaveHeader_mwhColorAlpha, 0.45f);mVelocity = ta.getFloat(R.styleable.MultiWaveHeader_mwhVelocity, 1f);mGradientAngle = ta.getInt(R.styleable.MultiWaveHeader_mwhGradientAngle, 45);mIsRunning = ta.getBoolean(R.styleable.MultiWaveHeader_mwhIsRunning, true);mEnableFullScreen = ta.getBoolean(R.styleable.MultiWaveHeader_mwhEnableFullScreen, false);mCornerRadius = ta.getDimensionPixelOffset(R.styleable.MultiWaveHeader_mwhCornerRadius, Util.dp2px(25));mShape = ShapeType.values()[ta.getInt(R.styleable.MultiWaveHeader_mwhShape, mShape.ordinal())];mProgress = mCurProgress = ta.getFloat(R.styleable.MultiWaveHeader_mwhProgress, 1f);if (ta.hasValue(R.styleable.MultiWaveHeader_mwhWaves)) {setTag(ta.getString(R.styleable.MultiWaveHeader_mwhWaves));} else if (getTag() == null) {setTag("70,25,1.4,1.4,-26\n" +"100,5,1.4,1.2,15\n" +"420,0,1.15,1,-10\n" +"520,10,1.7,1.5,20\n" +"220,0,1,1,-15");}ta.recycle();}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {if (mltWave.isEmpty()) {updateWavePath();updateWavePath(r - l, b - t);}}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);updateShapePath();updateWavePath(w, h);updateLinearGradient(w, h);}@Overrideprotected void dispatchDraw(Canvas canvas) {super.dispatchDraw(canvas);if (mltWave.size() > 0) {if (mPath != null) {canvas.save();canvas.clipPath(mPath);}View thisView = this;int height = thisView.getHeight();long thisTime = System.currentTimeMillis();for (Wave wave : mltWave) {mMatrix.reset();canvas.save();if (mIsRunning && mLastTime > 0 && wave.velocity != 0) {float offsetX = (wave.offsetX - (wave.velocity * mVelocity * (thisTime - mLastTime) / 1000f));if (-wave.velocity > 0) {offsetX %= (float) wave.width / 2;} else {while (offsetX < 0) {offsetX += ((float) wave.width / 2);}}wave.offsetX = offsetX;mMatrix.setTranslate(offsetX, (1 - mCurProgress) * height);//wave.offsetX =canvas.translate(-offsetX, -wave.offsetY - (1 - mCurProgress) * height);} else {mMatrix.setTranslate(wave.offsetX, (1 - mCurProgress) * height);canvas.translate(-wave.offsetX, -wave.offsetY - (1 - mCurProgress) * height);}mPaint.getShader().setLocalMatrix(mMatrix);canvas.drawPath(wave.path, mPaint);canvas.restore();}mLastTime = thisTime;if (mPath != null) {canvas.restore();}if (mIsRunning) {invalidate();}}}private void updateLinearGradient(int width, int height) {int startColor = ColorUtils.setAlphaComponent(mStartColor, (int) (mColorAlpha * 255));int closeColor = ColorUtils.setAlphaComponent(mCloseColor, (int) (mColorAlpha * 255));//noinspection UnnecessaryLocalVariabledouble w = width;double h = height * mCurProgress;double r = Math.sqrt(w * w + h * h) / 2;double y = r * Math.sin(2 * Math.PI * mGradientAngle / 360);double x = r * Math.cos(2 * Math.PI * mGradientAngle / 360);mPaint.setShader(new LinearGradient((int) (w / 2 - x), (int) (h / 2 - y), (int) (w / 2 + x), (int) (h / 2 + y), startColor, closeColor, Shader.TileMode.CLAMP));}protected void updateShapePath() {View thisView = this;int w = thisView.getWidth();int h = thisView.getHeight();if (w > 0 && h > 0 && mShape != null && mShape != ShapeType.Rect) {mPath = new Path();switch (mShape) {case RoundRect:mPath.addRoundRect(new RectF(0, 0, w, h), mCornerRadius, mCornerRadius, Path.Direction.CW);break;case Oval:mPath.addOval(new RectF(0, 0, w, h), Path.Direction.CW);break;}} else {mPath = null;}}protected void updateWavePath() {mltWave.clear();if (getTag() instanceof String) {String[] waves = getTag().toString().split("\\s+");if ("-1".equals(getTag())) {waves = "70,25,1.4,1.4,-26\n100,5,1.4,1.2,15\n420,0,1.15,1,-10\n520,10,1.7,1.5,20\n220,0,1,1,-15".split("\\s+");} else if ("-2".equals(getTag())) {waves = "0,0,1,0.5,90\n90,0,1,0.5,90".split("\\s+");}for (String wave : waves) {String[] args = wave.split("\\s*,\\s*");if (args.length == 5) {mltWave.add(new Wave(Util.dp2px(parseFloat(args[0])), Util.dp2px(parseFloat(args[1])), Util.dp2px(parseFloat(args[4])), parseFloat(args[2]), parseFloat(args[3]), mWaveHeight / 2));}}} else {mltWave.add(new Wave(Util.dp2px(50), Util.dp2px(0), Util.dp2px(5), 1.7f, 2f, mWaveHeight / 2));}}protected void updateWavePath(int w, int h) {for (Wave wave : mltWave) {wave.updateWavePath(w, h, mWaveHeight / 2, mEnableFullScreen, mCurProgress);}}/*** 執行回彈動畫** @param progress 目標值* @param interpolator 加速器* @param duration 時長*/protected void animProgress(float progress, Interpolator interpolator, int duration) {if (mCurProgress != progress) {if (reboundAnimator != null) {reboundAnimator.cancel();}reboundAnimator = ValueAnimator.ofFloat(mCurProgress, progress);reboundAnimator.setDuration(duration);reboundAnimator.setInterpolator(interpolator);reboundAnimator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {reboundAnimator = null;}});reboundAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {updateProgress((float) animation.getAnimatedValue());}});reboundAnimator.start();}}protected void updateProgress(float progress) {View thisView = this;mCurProgress = progress;updateLinearGradient(thisView.getWidth(), thisView.getHeight());if (mEnableFullScreen) {for (Wave wave : mltWave) {wave.updateWavePath(thisView.getWidth(), thisView.getHeight(), mCurProgress);}}if (!mIsRunning) {invalidate();}}//<editor-fold desc="method api">public void setWaves(String waves) {setTag(waves);if (mLastTime > 0) {View thisView = this;updateWavePath();updateWavePath(thisView.getWidth(), thisView.getHeight());}}public int getWaveHeight() {return mWaveHeight;}public void setWaveHeight(int waveHeight) {this.mWaveHeight = Util.dp2px(waveHeight);if (!mltWave.isEmpty()) {View thisView = this;updateWavePath(thisView.getWidth(), thisView.getHeight());}}public float getVelocity() {return mVelocity;}public void setVelocity(float velocity) {this.mVelocity = velocity;}public float getProgress() {return mProgress;}public void setProgress(float progress) {this.mProgress = progress;if (!mIsRunning) {updateProgress(progress);} else {animProgress(progress, new DecelerateInterpolator(), 300);}}public void setProgress(float progress, Interpolator interpolator, int duration) {this.mProgress = progress;animProgress(progress, new DecelerateInterpolator(), duration);}public int getGradientAngle() {return mGradientAngle;}public void setGradientAngle(int angle) {this.mGradientAngle = angle;if (!mltWave.isEmpty()) {View thisView = this;updateLinearGradient(thisView.getWidth(), thisView.getHeight());}}public int getStartColor() {return mStartColor;}public void setStartColor(int color) {this.mStartColor = color;if (!mltWave.isEmpty()) {View thisView = this;updateLinearGradient(thisView.getWidth(), thisView.getHeight());}}public void setStartColorId(@ColorRes int colorId) {final View thisView = this;setStartColor(Util.getColor(thisView.getContext(), colorId));}public int getCloseColor() {return mCloseColor;}public void setCloseColor(int color) {this.mCloseColor = color;if (!mltWave.isEmpty()) {View thisView = this;updateLinearGradient(thisView.getWidth(), thisView.getHeight());}}public void setCloseColorId(@ColorRes int colorId) {final View thisView = this;setCloseColor(Util.getColor(thisView.getContext(), colorId));}public float getColorAlpha() {return mColorAlpha;}public void setColorAlpha(float alpha) {this.mColorAlpha = alpha;if (!mltWave.isEmpty()) {View thisView = this;updateLinearGradient(thisView.getWidth(), thisView.getHeight());}}public void start() {if (!mIsRunning) {mIsRunning = true;mLastTime = System.currentTimeMillis();invalidate();}}public void stop() {mIsRunning = false;}public boolean isRunning() {return mIsRunning;}public void setEnableFullScreen(boolean fullScreen) {this.mEnableFullScreen = fullScreen;}public boolean isEnableFullScreen() {return mEnableFullScreen;}public void setShape(ShapeType shape) {this.mShape = shape;updateShapePath();}public ShapeType getShape() {return mShape;} }第二步:創建? ShapeType? 類
public enum ShapeType {Rect,RoundRect,Oval, }第三步:創建? Util 類
public class Util {/*** 獲取顏色* @param context 上下文* @param colorId 顏色ID* @return 顏色*/@ColorIntpublic static int getColor(@NonNull Context context, @ColorRes int colorId) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {return context.getColor(colorId);}//noinspection deprecationreturn context.getResources().getColor(colorId);}/*** dp轉px* @param dpVal dp 值* @return px*/public static int dp2px(float dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal, Resources.getSystem().getDisplayMetrics());} }第四步:創建? Wave 類
public class Wave {Path path; //水波路徑int width; //畫布寬度(2倍波長)int wave; //波幅(振幅)float offsetX; //水波的水平偏移量float offsetY; //水波的豎直偏移量float velocity; //水波移動速度(像素/秒)private float scaleX; //水平拉伸比例private float scaleY; //豎直拉伸比例private int curWave;int startColor; //開始顏色int closeColor; //結束顏色float alpha; //顏色透明度/*** 通過參數構造一個水波對象* @param offsetX 水平偏移量* @param offsetY 豎直偏移量* @param velocity 移動速度(像素/秒)* @param scaleX 水平拉伸量* @param scaleY 豎直拉伸量* @param wave 波幅(波寬度)*/Wave(/*Context context, */int offsetX, int offsetY, int velocity, float scaleX, float scaleY, int wave) { // super(context);this.wave = wave; //波幅(波寬)this.scaleX = scaleX; //水平拉伸量this.scaleY = scaleY; //豎直拉伸量this.offsetX = offsetX; //水平偏移量this.offsetY = offsetY; //豎直偏移量this.velocity = velocity; //移動速度(像素/秒)this.path = new Path();}protected void updateWavePath(int w, int h, int waveHeight, boolean fullScreen, float progress) {this.wave = waveHeight;this.width = (int) (2* scaleX * w); //畫布寬度(2倍波長)this.path = buildWavePath(width, h, fullScreen, progress);}protected void updateWavePath(int w, int h, float progress) {int wave = (int) (scaleY * this.wave);//計算拉伸之后的波幅float maxWave = h * Math.max(0, (1 - progress));if (wave > maxWave) {wave = (int)maxWave;}if (curWave != wave) {this.width = (int) (2 * scaleX * w); //畫布寬度(2倍波長)this.path = buildWavePath(width, h, true, progress);}}protected Path buildWavePath(int width, int height, boolean fullScreen, float progress) {int DP = Util.dp2px(1);//一個dp在當前設備表示的像素量(水波的繪制精度設為一個dp單位)if (DP < 1) {DP = 1;}int wave = (int) (scaleY * this.wave);//計算拉伸之后的波幅if (fullScreen) {float maxWave = height * Math.max(0, (1 - progress));if (wave > maxWave) {wave = (int) maxWave;}}this.curWave = wave;// Path path = new Path();path.reset();path.moveTo(0, 0);path.lineTo(0, height - wave);if (wave > 0) {for (int x = DP; x < width; x += DP) {path.lineTo(x, height - wave - wave * (float) Math.sin(4.0 * Math.PI * x / width));}}path.lineTo(width, height - wave);path.lineTo(width, 0);path.close();return path;} }接下來就可以實現效果了。不記得是轉載自哪位博主了,如果找到原博主文章,可以@我加上轉載地址,在此只當做筆記使用,有幸的話,幫助解決遇到相同問題的小伙伴。
總結
以上是生活随笔為你收集整理的自定义水波纹效果,可设置波纹条数和波纹颜色,使用简单的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JKS 密钥库使用专用格式。建议使用 “
- 下一篇: Android使用adb命令安装应用-连