android 类似于支付宝咻咻咻界面的按钮波纹效果

<pre name="code" class="java"><pre name="code" class="java">1.RippleLayout.java
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.RelativeLayout;

import com.baxian.qingjia.qingjia.R;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorSet;
import com.nineoldandroids.animation.ObjectAnimator;


import java.util.ArrayList;
/**
 * Created by Administrator on 2016/7/19 0019.
 */
public class RippleLayout extends RelativeLayout {
    /**
     * static final fields
     */
    private static final int DEFAULT_RIPPLE_COUNT = 3; //有几个圈圈
    private static final int DEFAULT_DURATION_TIME = 1500; //一轮的时间
    private static final float DEFAULT_SCALE = 2.0f; //放大倍数
    private static final int DEFAULT_RIPPLE_COLOR = R.color.blueripple; //里圈颜色
    private static final int DEFAULT_STROKE_WIDTH = 0;
    private static final int DEFAULT_RADIUS = 80; //里圈半径px

    /**
     *
     */
    private int mRippleColor = DEFAULT_RIPPLE_COLOR;
    private float mStrokeWidth = DEFAULT_STROKE_WIDTH;
    private float mRippleRadius = DEFAULT_RADIUS;
    private int mAnimDuration;
    private int mRippleViewNums;
    private int mAnimDelay;
    private float mRippleScale;
    private boolean animationRunning = false;
    /**
     *
     */
    private Paint mPaint = new Paint();

    /**
     * 动画集,执行缩放、alpha动画,使得背景色渐变
     */
    private AnimatorSet mAnimatorSet = new AnimatorSet();
    /**
     * 动画列表,保存几个动画
     */
    private ArrayList<Animator> mAnimatorList = new ArrayList<Animator>();
    /**
     * RippleView Params
     */
    private LayoutParams mRippleViewParams;

    /**
     * @param context
     */
    public RippleLayout(Context context) {
        super(context);
        init(context, null);
    }

    public RippleLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public RippleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(final Context context, final AttributeSet attrs) {
        if (isInEditMode()) {
            return;
        }

        if (null != attrs) {
            initTypedArray(context, attrs);
        }

        initPaint();
        initRippleViewLayoutParams();
        generateRippleViews();

    }

    private void initTypedArray(Context context, AttributeSet attrs) {
        final TypedArray typedArray = context.obtainStyledAttributes(attrs,
                R.styleable.RippleLayout);
        //
        mRippleColor = typedArray.getColor(R.styleable.RippleLayout_colors,
                getResources().getColor(DEFAULT_RIPPLE_COLOR));
        mStrokeWidth =
                typedArray.getDimension(R.styleable.RippleLayout_strokeWidth, DEFAULT_STROKE_WIDTH);
        mRippleRadius = typedArray.getDimension(R.styleable.RippleLayout_radius,
                DEFAULT_RADIUS);
        mAnimDuration = typedArray.getInt(R.styleable.RippleLayout_duration,
                DEFAULT_DURATION_TIME);
        mRippleViewNums = typedArray.getInt(R.styleable.RippleLayout_rippleNums,
                DEFAULT_RIPPLE_COUNT);
        mRippleScale = typedArray.getFloat(R.styleable.RippleLayout_scale,
                DEFAULT_SCALE);

        // oh, baby, don't forget recycle the typedArray !!
        typedArray.recycle();
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mStrokeWidth = 0;
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(mRippleColor);
    }

    private void initRippleViewLayoutParams() {
        // ripple view的大小为 半径 + 笔宽的两倍
        int rippleSide = (int) (2 * (mRippleRadius + mStrokeWidth));
        mRippleViewParams = new LayoutParams(rippleSide, rippleSide);
        // 居中显示
        mRippleViewParams.addRule(CENTER_IN_PARENT, TRUE);
    }

    /**
     * 计算每个RippleView之间的动画时间间隔,从而产生波纹效果
     */
    private void calculateAnimDelay() {
        mAnimDelay = mAnimDuration / mRippleViewNums;
    }

    /**
     * 初始化RippleViews,并且将动画设置到RippleView上,使之在x, y不断扩大,并且背景色逐渐淡化
     */
    private void generateRippleViews() {

        calculateAnimDelay();
        initAnimSet();
        // 添加RippleView
        for (int i = 0; i < mRippleViewNums; i++) {
            RippleView rippleView = new RippleView(getContext());
            addView(rippleView, mRippleViewParams);
            // 添加动画
            addAnimToRippleView(rippleView, i);
        }

        // x, y, alpha动画一块执行
        mAnimatorSet.playTogether(mAnimatorList);
    }

    private void initAnimSet() {
        mAnimatorSet.setDuration(mAnimDuration);
        mAnimatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
    }

    /**
     * 为每个RippleView添加动画效果,并且设置动画延时,每个视图启动动画的时间不同,就会产生波纹
     *
     * @param rippleView
     * @param i 视图所在的索引
     */
    private void addAnimToRippleView(RippleView rippleView, int i) {

        // x轴的缩放动画
        final ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(rippleView, "scaleX",
                1.0f, mRippleScale);
        scaleXAnimator.setRepeatCount(ObjectAnimator.INFINITE);
        scaleXAnimator.setRepeatMode(ObjectAnimator.RESTART);
        scaleXAnimator.setStartDelay(i * mAnimDelay);
        scaleXAnimator.setDuration(mAnimDuration);
        mAnimatorList.add(scaleXAnimator);

        // y轴的缩放动画
        final ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(rippleView, "scaleY",
                1.0f, mRippleScale);
        scaleYAnimator.setRepeatMode(ObjectAnimator.RESTART);
        scaleYAnimator.setRepeatCount(ObjectAnimator.INFINITE);
        scaleYAnimator.setStartDelay(i * mAnimDelay);
        scaleYAnimator.setDuration(mAnimDuration);
        mAnimatorList.add(scaleYAnimator);

        // 颜色的alpha渐变动画
        final ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(rippleView, "alpha", 1.0f,
                0f);
        alphaAnimator.setRepeatMode(ObjectAnimator.RESTART);
        alphaAnimator.setRepeatCount(ObjectAnimator.INFINITE);
        alphaAnimator.setDuration(mAnimDuration);
        alphaAnimator.setStartDelay(i * mAnimDelay);
        mAnimatorList.add(alphaAnimator);
    }

    public void startRippleAnimation() {
        if (!isRippleAnimationRunning()) {
            makeRippleViewsVisible();
            mAnimatorSet.start();
            animationRunning = true;
        }
    }

    private void makeRippleViewsVisible() {
        int childCount = this.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = this.getChildAt(i);
            if (childView instanceof RippleView) {
                childView.setVisibility(VISIBLE);
            }
        }
    }

    public void stopRippleAnimation() {
        if (isRippleAnimationRunning()) {
            mAnimatorSet.end();
            animationRunning = false;
        }
    }

    public boolean isRippleAnimationRunning() {
        return animationRunning;
    }

    /**
     * RippleView产生波纹效果, 默认不可见,当启动动画时才设置为可见
     *
     * @author mrsimple
     */
    private class RippleView extends View {

        public RippleView(Context context) {
            super(context);
            this.setVisibility(View.INVISIBLE);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            int radius = (Math.min(getWidth(), getHeight())) / 2;
            canvas.drawCircle(radius, radius, radius - mStrokeWidth, mPaint);
        }
    }


 
 
<pre name="code" class="java">2.attrs.xml
     <declare-styleable name="RippleLayout">
        <attr name="colors" format="color" />
        <attr name="strokeWidth" format="dimension" />
        <attr name="radius" format="dimension" />
        <attr name="duration" format="integer" />
        <attr name="rippleNums" format="integer" />
        <attr name="scale" format="float" />
    </declare-styleable>
 
<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;"></span><pre name="code" class="java">3.布局文件里插入一下代码
 <com.baxian.qingjia.qingjia.utils.RippleLayout xmlns:ripple="http://schemas.android.com/apk/org.simple.ripplelayout"
            android:id="@+id/ripple_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            ripple:colors="@color/alpha"
            android:layout_centerHorizontal="true"
            ripple:duration="1500"
            ripple:radius="30dp"
            ripple:rippleNums="3"
            ripple:scale="2">
            <!--  可以改成其他控件,看需求吧-->
            <TextView
                android:id="@+id/centerImage"
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:textSize="16dp"
                android:layout_marginTop="200dp"
                android:gravity="center"
                android:visibility="gone"
                android:text="双击\n放大"
                android:background="@drawable/blue_yuan"
                android:textColor="@color/white"
                android:layout_above="@+id/tv_title2"
                android:layout_centerVertical="true"
                android:layout_centerHorizontal="true" />
        </com.baxian.qingjia.qingjia.utils.RippleLayout>
 
<pre name="code" class="java"> 4.activity里使用
 RippleLayout layout; 
 TextView txtview;
   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_monthreport);
        layout=(RippleLayout )findViewById(R.id.layout);
        txtview=(TextView)findViewById(R.id.centerImage);
        txtview.setOnClickListener(new OnClickListener(){
	@Override
  	public void onClick(View v) {
  		layout.startRippleAnimation();//layout.stopRippleAnimation();
	}
	});
     }


 

 

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值