美文网首页
水波浪贝塞尔效果(六边形)

水波浪贝塞尔效果(六边形)

作者: 涂涂家的小七呀 | 来源:发表于2019-09-30 10:35 被阅读0次

    先看效果


    image.png

    代码

    /**
     * 六边形水位效果
     */
    public class SixWave extends View {
        private static final float DEFAULT_AMPLITUDE_RATIO = 0.1f;
        private static final float DEFAULT_AMPLITUDE_VALUE = 50.0f;
        private static final float DEFAULT_WATER_LEVEL_RATIO = 0.5f;
        private static final float DEFAULT_WAVE_LENGTH_RATIO = 1.0f;
        private static final float DEFAULT_WAVE_SHIFT_RATIO = 0.0f;
        private static final int DEFAULT_WAVE_PROGRESS_VALUE = 50;
        private static final int DEFAULT_WAVE_COLOR = Color.parseColor("#212121");
        private static final int DEFAULT_WAVE_BACKGROUND_COLOR = Color.parseColor("#00000000");
        private static final float DEFAULT_BORDER_WIDTH = 0;
    
        private int mCanvasSize;
        private float mAmplitudeRatio;//振幅度比列大小
        private int mWaveBgColor;
        private int mWaveColor;
    
        private float mDefaultWaterLevel;//默认水位等级
        private float mWaterLevelRatio = 1f;//变速等级
        private float mWaveShiftRatio = DEFAULT_WAVE_SHIFT_RATIO;//变速比率
        private int mProgressValue = DEFAULT_WAVE_PROGRESS_VALUE;//进度
    
        private BitmapShader mWaveShader;//水位渲染
    
        private Matrix mShaderMatrix;//矩阵着色
    
        private Paint mWavePaint;
    
        private Paint mWaveBgPaint;
    
        private Paint mBorderPaint;
    
        private ObjectAnimator waveShiftAnim;//执行动画
        private AnimatorSet mAnimatorSet;//动画组合 用来控制 暂停开始
    
        private Context mContext;
    
        public SixWave(final Context context) {
            this(context, null);
        }
    
        public SixWave(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public SixWave(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context, attrs, defStyleAttr);
        }
    
        private void init(Context context, AttributeSet attrs, int defStyleAttr) {
            mContext = context;
    
            mShaderMatrix = new Matrix();
            mWavePaint = new Paint();
    
            mWavePaint.setAntiAlias(true);
            mWaveBgPaint = new Paint();
            mWaveBgPaint.setAntiAlias(true);
    
            initAnimation();
    
            TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.SixWave, defStyleAttr, 0);
    
            mWaveColor = attributes.getColor(R.styleable.SixWave_sw_waveColor, DEFAULT_WAVE_COLOR);
            mWaveBgColor = attributes.getColor(R.styleable.SixWave_sw_wave_background_Color, DEFAULT_WAVE_BACKGROUND_COLOR);
    
            mWaveBgPaint.setColor(mWaveBgColor);
    
            float amplitudeRatioAttr = attributes.getFloat(R.styleable.SixWave_sw_waveAmplitude, DEFAULT_AMPLITUDE_VALUE) / 1000;
            mAmplitudeRatio = (amplitudeRatioAttr > DEFAULT_AMPLITUDE_RATIO) ? DEFAULT_AMPLITUDE_RATIO : amplitudeRatioAttr;
    
            mProgressValue = attributes.getInteger(R.styleable.SixWave_sw_progressValue, DEFAULT_WAVE_PROGRESS_VALUE);
            setProgressValue(mProgressValue);
    
            mBorderPaint = new Paint();
            mBorderPaint.setAntiAlias(true);
            mBorderPaint.setStyle(Paint.Style.STROKE);
            mBorderPaint.setStrokeWidth(attributes.getDimension(R.styleable.SixWave_sw_borderWidth, dp2px(DEFAULT_BORDER_WIDTH)));
            mBorderPaint.setColor(attributes.getColor(R.styleable.SixWave_sw_borderColor, DEFAULT_WAVE_COLOR));
    
            attributes.recycle();
        }
    
        @Override
        public void onDraw(Canvas canvas) {
            mCanvasSize = canvas.getWidth();
            if (canvas.getHeight() < mCanvasSize) {
                mCanvasSize = canvas.getHeight();
            }
    
            if (mWaveShader != null) {
    
                if (mWavePaint.getShader() == null) {
                    mWavePaint.setShader(mWaveShader);
                }
    
                mShaderMatrix.setScale(1, mAmplitudeRatio / DEFAULT_AMPLITUDE_RATIO, 0, mDefaultWaterLevel);
    
                mShaderMatrix.postTranslate(mWaveShiftRatio * getWidth(),
                        (DEFAULT_WATER_LEVEL_RATIO - mWaterLevelRatio) * getHeight());
    
                mWaveShader.setLocalMatrix(mShaderMatrix);
    
                //六边形主要代码
                drawPolygon(canvas);
    
            } else {
                mWavePaint.setShader(null);
            }
        }
    
        private void drawPolygon(Canvas canvas) {
            Path path = new Path();
            float radius, centerX, centerY;
            radius = centerX = centerY = Math.min(getWidth(), getHeight()) * 0.5f;
            radius -= getBorderWidth() * 0.5f;
            float offsetAngle = 0;
            offsetAngle = (float) (Math.PI * offsetAngle / 180);
            for (int i = 0; i < getSides(); i++) {
                float x = (float) (centerX + radius * Math.cos(offsetAngle));
                float y = (float) (centerY + radius * Math.sin(offsetAngle));
                offsetAngle += 2 * Math.PI / getSides();
                if (i == 0) {
                    path.moveTo(x, y);
                } else {
                    path.lineTo(x, y);
                }
            }
            path.close();
            if (getSides() % 2 != 0) {
                Matrix mMatrix = new Matrix();
                mMatrix.postRotate(-90, centerX, centerY);
                path.transform(mMatrix);
            }
            canvas.drawPath(path, mBorderPaint);
            canvas.drawPath(path, mWavePaint);
        }
    
        private int getSides() {
            return 6;//6边形
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mCanvasSize = w;
            if (h < mCanvasSize) mCanvasSize = h;
            updateWaveShader();
        }
    
        /**
         * 初始动画
         */
        private void initAnimation() {
            waveShiftAnim = ObjectAnimator.ofFloat(this, "waveShiftRatio", 0f, 1f);
            waveShiftAnim.setRepeatCount(ValueAnimator.INFINITE);
            waveShiftAnim.setDuration(1000);
            waveShiftAnim.setInterpolator(new LinearInterpolator());
            mAnimatorSet = new AnimatorSet();
            mAnimatorSet.play(waveShiftAnim);
        }
    
        /**
         * 进度值动画
         *
         * @param progress
         */
        public void setProgressValue(int progress) {
            mProgressValue = progress;
            ObjectAnimator waterLevelAnim = ObjectAnimator.ofFloat(this, "waterLevelRatio", mWaterLevelRatio, ((float) mProgressValue / 100));
            waterLevelAnim.setDuration(1000);
            waterLevelAnim.setInterpolator(new DecelerateInterpolator());
            AnimatorSet animatorSetProgress = new AnimatorSet();
            animatorSetProgress.play(waterLevelAnim);
            animatorSetProgress.start();
        }
    
        /*
        大波浪
         */
        private void updateWaveShader() {
            int width = getMeasuredWidth();
            int height = getMeasuredHeight();
            if (width > 0 && height > 0) {
                double defaultAngularFrequency = 2.0f * Math.PI / DEFAULT_WAVE_LENGTH_RATIO / width;
                float defaultAmplitude = height * DEFAULT_AMPLITUDE_RATIO;
                mDefaultWaterLevel = height * DEFAULT_WATER_LEVEL_RATIO;
    
                Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(bitmap);
    
                Paint wavePaint = new Paint();
                wavePaint.setStrokeWidth(2);
                wavePaint.setAntiAlias(true);
    
                final int endX = width + 1;
                final int endY = height + 1;
    
                float[] waveY = new float[endX];
    
                wavePaint.setColor(adjustAlpha(mWaveColor, 0.3f));
                for (int beginX = 0; beginX < endX; beginX++) {
                    double wx = beginX * defaultAngularFrequency;
                    float beginY = (float) (mDefaultWaterLevel + defaultAmplitude * Math.sin(wx));
                    canvas.drawLine(beginX, beginY, beginX, endY, wavePaint);
                    waveY[beginX] = beginY;
                }
    
                wavePaint.setColor(mWaveColor);
                final int wave2Shift = (int) ((float) width / 4);
                for (int beginX = 0; beginX < endX; beginX++) {
                    canvas.drawLine(beginX, waveY[(beginX + wave2Shift) % endX], beginX, endY, wavePaint);
                }
    
                mWaveShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
                this.mWavePaint.setShader(mWaveShader);
            }
    
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int width = measureWidth(widthMeasureSpec);
            int height = measureHeight(heightMeasureSpec);
            int imageSize = (width < height) ? width : height;
            setMeasuredDimension(imageSize, imageSize);
        }
    
        private int measureWidth(int measureSpec) {
            int result;
            int specMode = MeasureSpec.getMode(measureSpec);
            int specSize = MeasureSpec.getSize(measureSpec);
            if (specMode == MeasureSpec.EXACTLY) {
                result = specSize;
            } else {
                result = specSize;
            }
            return result;
        }
    
        private int measureHeight(int measureSpecHeight) {
            int result;
            int specMode = MeasureSpec.getMode(measureSpecHeight);
            int specSize = MeasureSpec.getSize(measureSpecHeight);
    
            if (specMode == MeasureSpec.EXACTLY) {
                result = specSize;
            } else {
                result = specSize;
            }
            return (result + 2);
        }
    
    
        public void setWaveBgColor(int color) {
            this.mWaveBgColor = color;
            mWaveBgPaint.setColor(this.mWaveBgColor);
            updateWaveShader();
            invalidate();
        }
    
        public int getWaveBgColor() {
            return mWaveBgColor;
        }
    
        public void setWaveColor(int color) {
            mWaveColor = color;
            updateWaveShader();
            invalidate();
        }
    
        public int getWaveColor() {
            return mWaveColor;
        }
    
        public void setBorderWidth(float width) {
            mBorderPaint.setStrokeWidth(width);
            invalidate();
        }
    
        public float getBorderWidth() {
            return mBorderPaint.getStrokeWidth();
        }
    
        public void setBorderColor(int color) {
            mBorderPaint.setColor(color);
            updateWaveShader();
            invalidate();
        }
    
        public int getBorderColor() {
            return mBorderPaint.getColor();
        }
    
        public void setAmplitudeRatio(int amplitudeRatio) {
            if (this.mAmplitudeRatio != (float) amplitudeRatio / 1000) {
                this.mAmplitudeRatio = (float) amplitudeRatio / 1000;
                invalidate();
            }
        }
    
        public float getAmplitudeRatio() {
            return mAmplitudeRatio;
        }
    
        public int getProgressValue() {
            return mProgressValue;
        }
    
        public void setWaveShiftRatio(float waveShiftRatio) {
            if (this.mWaveShiftRatio != waveShiftRatio) {
                this.mWaveShiftRatio = waveShiftRatio;
                invalidate();
            }
        }
    
        public float getWaveShiftRatio() {
            return mWaveShiftRatio;
        }
    
        public void setWaterLevelRatio(float waterLevelRatio) {
            if (this.mWaterLevelRatio != waterLevelRatio) {
                this.mWaterLevelRatio = waterLevelRatio;
                invalidate();
            }
        }
    
        public float getWaterLevelRatio() {
            return mWaterLevelRatio;
        }
    
        public void startAnimation() {
            if (mAnimatorSet != null) {
                mAnimatorSet.start();
            }
        }
    
        public void endAnimation() {
            if (mAnimatorSet != null) {
                mAnimatorSet.end();
            }
        }
    
        public void cancelAnimation() {
            if (mAnimatorSet != null) {
                mAnimatorSet.cancel();
            }
        }
    
        @TargetApi(Build.VERSION_CODES.KITKAT)
        @SuppressWarnings("deprecation")
        public void pauseAnimation() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                if (mAnimatorSet != null) {
                    mAnimatorSet.pause();
                }
            }
        }
    
        @TargetApi(Build.VERSION_CODES.KITKAT)
        @SuppressWarnings("deprecation")
        public void resumeAnimation() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                if (mAnimatorSet != null) {
                    mAnimatorSet.resume();
                }
            }
        }
    
        public void setAnimDuration(long duration) {
            waveShiftAnim.setDuration(duration);
        }
    
        @Override
        protected void onAttachedToWindow() {
            startAnimation();
            super.onAttachedToWindow();
        }
    
        @Override
        protected void onDetachedFromWindow() {
            cancelAnimation();
            super.onDetachedFromWindow();
        }
    
        private int adjustAlpha(int color, float factor) {
            int alpha = Math.round(Color.alpha(color) * factor);
            int red = Color.red(color);
            int green = Color.green(color);
            int blue = Color.blue(color);
            return Color.argb(alpha, red, green, blue);
        }
    
        private int dp2px(float dp) {
            final float scale = mContext.getResources().getDisplayMetrics().density;
            return (int) (dp * scale + 0.5f);
        }
    }
    

    attrs

       <declare-styleable name="SixWave">
            <attr name="sw_borderWidth" format="dimension" />
            <attr name="sw_borderColor" format="color" />
            <attr name="sw_progressValue" format="integer" />
            <attr name="sw_waveColor" format="color" />
            <attr name="sw_wave_background_Color" format="color" />
            <attr name="sw_waveAmplitude" format="float" />
        </declare-styleable>
    

    xml

       <com.example.kotlin.widget.SixWave
                android:id="@+id/sixWave"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:sw_borderColor="@color/colorAccent"
                app:sw_borderWidth="3dp"
                app:sw_progressValue="70"
                app:sw_waveAmplitude="50"
                app:sw_waveColor="@color/colorAccent" />
    

    activity

        override fun initData() {
    //        sixWave.setBorderColor(Color.BLUE)
    //        sixWave.setWaveColor(Color.BLUE)
    //        sixWave.setWaveBgColor(Color.TRANSPARENT)
    //        sixWave.setAmplitudeRatio(40)
    //        sixWave.setWaveShiftRatio(0.2f)
    //        sixWave.setProgressValue(70)
            sixWave.setAnimDuration(3000)
        }
    

    六边形图形效果根据WaveLoadingView修改。可以改多种样式,三角形,正方形,矩形,圆形,圆角矩形
    WaveLoadingView传送门Github地址

    相关文章

      网友评论

          本文标题:水波浪贝塞尔效果(六边形)

          本文链接:https://www.haomeiwen.com/subject/fzecpctx.html