Android水波纹扩散效果

先上图

囧!没有图片所以就拿了小安代替了

先看一下如何使用这个View

<jianpan.com.mybutton.view.RippleDiffuse
    android:layout_width="200dp"
    android:layout_height="200dp"
    app:btn_img_res="@drawable/rd"
    app:ripple_img_res="@drawable/rd">
</jianpan.com.mybutton.view.RippleDiffuse>

是的,没有别的代码了,就这么简单

实现思路

自定义ViewGroup,创建一个用显示图片的view,在创建几个,大小相同的ImageView。当按下时,对这几个ImageView进行放大和渐变

代码

首先它肯定是一个正方形

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, widthMeasureSpec);
    if (!mInitDataSucceed){
        initData();
    }
}

显示图片的View的大小,该怎么给?这是个比较蛋疼的问题。给大了就看不到扩散效果了,给小,给多少的值合适呢?有没有正好的值,有的
用父 view 的 size / 子 view 放大的倍数,恩这样肯定会达到理想的效果

private static final int ANIMATION_EACH_OFFSET = 800; // 每个动画的播放时间间隔
private static final int RIPPLE_VIEW_COUNT     = 3;//波纹view的个数
private static final float DEFAULT_SCALE       = 1.6f;//波纹放大后的大小

//点击有扩散效果的view
private CircleImageView mBtnImg;
private int mBtnViewHeight;
private int mBtnViewWidth;
private float mScale = DEFAULT_SCALE;
//图片资源
private int mBtnImgRes;
private int mRippleRes;
//是否初始化完成
private boolean mInitDataSucceed = false;

private void initData(){
    if (getMeasuredHeight() > 0 && getMeasuredWidth() > 0){
        mInitDataSucceed = true;

        int height = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
        int width  = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
        mBtnViewHeight = (int) (height / mScale);
        mBtnViewWidth  = (int) (width / mScale);

        mBtnImg = new CircleImageView(getContext());
        mBtnImg.setImageResource(mBtnImgRes);
        mBtnImg.setOnTouchListener(this);

        addView(mBtnImg, getWaveLayoutParams());

        for (int i = 0; i < RIPPLE_VIEW_COUNT; i++){
            //创建view
            CircleImageView wave = createWave();
            mWaves.add(wave);
            //创建动画
            mAnimas.add(getNewAnimationSet());

            addView(wave, 0, getWaveLayoutParams());
        }
    }
}
private CircleImageView createWave(){
    CircleImageView CircleImageView = new CircleImageView(getContext());
    CircleImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    CircleImageView.setImageResource(mRippleRes);
    return CircleImageView;
}

private LayoutParams getWaveLayoutParams(){
    LayoutParams lp = new LayoutParams(mBtnViewWidth, mBtnViewHeight);
    return  lp;
}

private AnimationSet getNewAnimationSet() {
    AnimationSet as = new AnimationSet(true);
    ScaleAnimation sa = new ScaleAnimation(1f, mScale, 1f, mScale,
            ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
            ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
    sa.setDuration(ANIMATION_EACH_OFFSET * 3);
    sa.setRepeatCount(-1);// 设置循环
    AlphaAnimation aniAlp = new AlphaAnimation(1, 0.1f);
    aniAlp.setRepeatCount(-1);// 设置循环
    as.setDuration(ANIMATION_EACH_OFFSET * 3);
    as.addAnimation(sa);
    as.addAnimation(aniAlp);
    return as;
}

View 都初始化完成了,好像还差一步,onLayout,只要把子 View 都显示到中先就可以了

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    if (mInitDataSucceed) {
        int childLeft = (getMeasuredWidth() - mBtnViewWidth) / 2;
        int childTop = (getMeasuredHeight() - mBtnViewHeight) / 2;
        for (int i = 0; i < RIPPLE_VIEW_COUNT; i++) {
            CircleImageView wave = mWaves.get(i);
            wave.layout(childLeft, childTop, mBtnViewWidth + childLeft, mBtnViewHeight + childTop);
        }
        mBtnImg.layout(childLeft, childTop, mBtnViewWidth + childLeft, mBtnViewHeight + childTop);
    }else {
        initData();
    }
}

ok最后处理一下图片的onTouch事件

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            showWaveAnimation();
            break;
        case MotionEvent.ACTION_MOVE:
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            cancelWaveAnimation();
            break;
        default:
            cancelWaveAnimation();
            break;
    }
    return true;
}

private void showWaveAnimation() {
    for (int i = 0; i < RIPPLE_VIEW_COUNT; i++){
        Message message = new Message();
        message.obj = i;
        handler.sendMessageDelayed(message, ANIMATION_EACH_OFFSET * i);
    }
}

private void cancelWaveAnimation() {
    for (int i = 0; i < RIPPLE_VIEW_COUNT; i++){
        CircleImageView wave = mWaves.get(i);
        wave.clearAnimation();
    }
}

private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        int position = (int) msg.obj;
        CircleImageView wave = mWaves.get(position);
        wave.startAnimation(mAnimas.get(position));
        super.handleMessage(msg);
    }
};

下载地址

http://blog.csdn.net/shineflowers/article/details/47280545

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值