自定义View——水波纹效果

我尽量不打错别字,用词准确,不造成阅读障碍。

本文实现一个水波纹状的自定义View,很简单的代码,没什么计算难度。

效果如下:

waveView

代码:

1.首先在values下的attrs中添加如下自定义属性:

 <declare-styleable name="MyWaveView">
        <attr name="waveColor" format="color" />
        <attr name="oneWaveDuration" format="integer" />
        <attr name="newWaveSpeed" format="integer" />
        <attr name="textContent" format="string|reference" />
    </declare-styleable>

2.自定义View的主要代码:

public class MyWaveView extends View {
    private int mInitialRadius;           //初始波纹大小
    private int mMaxRadius;               //最大波纹大小
    private int mOneWaveDuration = 5000;  //一个波纹从创建到消失时间为5秒
    private int mNewWaveSpeed = 750;      //新的波纹创建的速度为750毫秒
    private String text;

    private Rect textBound = new Rect();

    private ArrayList<Circle> mCircleList = new ArrayList<>();
    private Paint mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);  //画圆的画笔
    private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);    //写字的画笔

    private Interpolator mInterpolator = new LinearInterpolator();

    private long mLastCreateTime;

    private int waveColor;

    private Runnable mCreateCircle = new Runnable() {
        @Override
        public void run() {
            newCircle();
            postDelayed(mCreateCircle, mNewWaveSpeed); //循环调用runable,持续向list添加数据源
        }
    };

    public MyWaveView(Context context) {
        this(context, null);
    }

    public MyWaveView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyWaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    //获取属性
    public void init(AttributeSet attrs) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MyWaveView);
        waveColor = typedArray.getColor(R.styleable.MyWaveView_waveColor, 0);
        text = typedArray.getString(R.styleable.MyWaveView_textContent);
        mOneWaveDuration = typedArray.getInteger(R.styleable.MyWaveView_oneWaveDuration, 5000);
        mNewWaveSpeed = typedArray.getInteger(R.styleable.MyWaveView_newWaveSpeed, 750);
        typedArray.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Iterator<Circle> iterator = mCircleList.iterator();

        mTextPaint.setTextSize(getResources().getDimension(R.dimen.textsp));
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.getTextBounds(text, 0, text.length(), textBound);

        mCirclePaint.setColor(waveColor);
        mCirclePaint.setAntiAlias(true);
        mCirclePaint.setStyle(Paint.Style.FILL);
        mCirclePaint.setAlpha((int) (255 * 0.3));

        mInitialRadius = getWidth() / 7;  //设置初始波纹的大小
        mMaxRadius = getWidth() / 2;      //设置最大波纹的大小
        while (iterator.hasNext()) {
            Circle circle = iterator.next();
            float radius = circle.getCurrentRadius();
            canvas.drawText(text, getWidth() / 2 - textBound.width() / 2, getHeight() / 2, mTextPaint);
            if (System.currentTimeMillis() - circle.mCreateTime < mOneWaveDuration) {
                mCirclePaint.setAlpha(circle.getAlpha());
              //真正画波纹
                canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, mCirclePaint);
            } else {
                iterator.remove();
            }
            if (mCircleList.size() > 0) {
                postInvalidateDelayed(10);//每10毫秒刷新view,让动画看起来连贯
            }
        }
    }

    private void newCircle() {
        long currentTime = System.currentTimeMillis();
        if (currentTime - mLastCreateTime >= mNewWaveSpeed) {
            Circle circle = new Circle();
            mCircleList.add(circle);
            invalidate();
            mLastCreateTime = currentTime;
        }
    }

    public void start() {
        mCreateCircle.run();
    }

    public class Circle {
        private long mCreateTime;

        Circle() {
            mCreateTime = System.currentTimeMillis();
        }

        public int getAlpha() {
            float percent = (getCurrentRadius() - mInitialRadius) / (mMaxRadius - mInitialRadius);
            return (int) ((int) (255 - mInterpolator.getInterpolation(percent) * 255) * 0.3);
        }

        public float getCurrentRadius() {
            float percent = (System.currentTimeMillis() - mCreateTime) * 1.0f / mOneWaveDuration;
            return mInitialRadius + mInterpolator.getInterpolation(percent) * (mMaxRadius - mInitialRadius);
        }
    }
}

3.xml布局文件中:

 <com.teststudy.longl.myapplication3.Views.MyWaveView
        android:id="@+id/wv_my_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        app:newWaveSpeed="750"
        app:oneWaveDuration="5000"
        app:textContent="进行中..."
        app:waveColor="@color/colorPrimaryDark" />

4.Activity中:

MyWaveView myWaveView = findViewById(R.id.wv_my_test);
myWaveView.start();

这个动画效果其实可以用其他更高端的方式实现,这里只是写出一种方式,记录的同时可以给大家一下思路,有问题欢迎评论。

集合了一些简单自定义View的github地址:
https://github.com/longlong-2l/MySelfViewDemo
很简单,没有太多高深的用法,适合学习入门。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值