阅读背景:

Android自定义View阻尼动画&贝塞尔曲线的实现

来源:互联网 
效果图:
 
 
直接上代码啦:
package com.example.administrator.myapplication.customview;import android.animation.Animator;import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.animation.PropertyValuesHolder;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Path;import android.graphics.PointF;import android.graphics.drawable.GradientDrawable;import android.util.AttributeSet;import android.util.TypedValue;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.animation.AccelerateDecelerateInterpolator;import android.widget.LinearLayout;import android.widget.RelativeLayout;import com.example.administrator.myapplication.R;import java.util.ArrayList;import java.util.List;/** * Created by Administrator on 2016/9/14. */public class AnimationView extends RelativeLayout {    private final int SMALL_CIRCLE_RADIS = dp2px(20);    private final int LARGE_CIRCLE_RADIS = dp2px(25);    private final int OUT_CIRCLE_RADIS = dp2px(50);    private final int TYPE_SMALL = 0x01;    private final int TYPE_LARGE = 0x02;    private final int TYPE_OUTER = 0x03;    private Context mContext;    //小圆圈颜色    private int mSmallCircleColor;    //大圆圈颜色    private int mLargeCircleColor;    //外圆圈颜色    private int mOutCircleColor;    //动画    private AnimatorSet mAimationSet;    private PropertyValuesHolder mValueScaleX;    private PropertyValuesHolder mValueScaleY;    private PropertyValuesHolder mValuesScale;    //小圆移动路径    private Path mCirclePath;    private LinearLayout mCircleContainer;    private CircleView mOutCircleView;    private CircleView mSmallCircleView;    private CircleView mLargeCircleView;    private List<CircleView> mCircleViews;    //当前默认的位置    private int mFocusPosition;    private int mCount;    public AnimationView(Context context) {        this(context, null);        mContext = context;    }    public AnimationView(Context context, AttributeSet attrs) {        this(context, attrs, 0);        mContext = context;    }    public AnimationView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mContext = context;        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.AnimationView);        mSmallCircleColor = ta.getColor(R.styleable.AnimationView_smallCircleColor, getResources().getColor(R.color.colorAccent));        mLargeCircleColor = ta.getColor(R.styleable.AnimationView_largeCircleColor, getResources().getColor(R.color.colorPrimary));        mOutCircleColor = ta.getColor(R.styleable.AnimationView_outCircleColor, getResources().getColor(android.R.color.holo_orange_light));        ta.recycle();        //初始化布局        View rootView = LayoutInflater.from(getContext()).inflate(R.layout.bg_animationview, this);        mCircleContainer = (LinearLayout) rootView.findViewById(R.id.ll_container);        mOutCircleView = (CircleView) rootView.findViewById(R.id.out_circle2);        mOutCircleView.setRadis(OUT_CIRCLE_RADIS);        //设置背景大圆颜色        View containerWrapper = rootView.findViewById(R.id.wrapper);        mOutCircleView.setColor(mOutCircleColor);        GradientDrawable shape = (GradientDrawable) containerWrapper.getBackground();        shape.setColor(mOutCircleColor);        mValueScaleX = PropertyValuesHolder.ofFloat("scaleX", 1, 0.8f, 1);        mValueScaleY = PropertyValuesHolder.ofFloat("scaleY", 1, 0.8f, 1);        mValuesScale = PropertyValuesHolder.ofFloat("scaleY", 1, 0.5f, 1);        mCirclePath = new Path();        mCircleViews = new ArrayList<CircleView>();    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        super.onLayout(changed, l, t, r, b);        mLargeCircleView = mCircleViews.get(mFocusPosition);        mOutCircleView.setCenter(mLargeCircleView.getCenter());    }    public void setCount(int count, int focus) {        if (count < 2) {            return;        }        if (focus > count || focus < 0) {            return;        }        mFocusPosition = focus;        mCount = count;        /** 1:创建圆         * 2:往linearlayout动态添加圆         * */        mCircleContainer.removeAllViews();        mCircleViews.clear();        //左边放小圆        for (int i = 0; i < focus; i++) {            addSmallCircle();        }        //中间大圆        addLargeCircle();        //右边小圆        for (int i = focus + 1; i < count; i++) {            addSmallCircle();        }    }    private void addLargeCircle() {        CircleView largeCircle = CreateCircle(TYPE_LARGE);        mCircleViews.add(largeCircle);        mCircleContainer.addView(largeCircle);    }    private void addSmallCircle() {        CircleView smallCircle = CreateCircle(TYPE_SMALL);        mCircleViews.add(smallCircle);        mCircleContainer.addView(smallCircle);    }    public void moveRight() {        if (mAimationSet != null && mAimationSet.isRunning()) {            return;        }        move(true);    }    public void moveLeft() {        if (mAimationSet != null && mAimationSet.isRunning()) {            return;        }        move(false);    }    private void move(boolean toRight) {        mLargeCircleView = mCircleViews.get(mFocusPosition);        final int nextPos = getNextPosition(toRight);        if (nextPos < 0) {            return;        }        mSmallCircleView = mCircleViews.get(nextPos);        //计算移动        float largeCircleX = toRight ? mSmallCircleView.getX() - (mLargeCircleView.getWidth() - mSmallCircleView.getWidth()) : mSmallCircleView.getX();        float smallCircleX = toRight ? mLargeCircleView.getX() : mLargeCircleView.getX() + (mLargeCircleView.getWidth() - mSmallCircleView.getWidth());        float outCircleX = toRight ? mSmallCircleView.getX() - (mOutCircleView.getWidth() - mSmallCircleView.getWidth()) : mSmallCircleView.getX();        //l argeCircleView动画 X平移 XY缩放        PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("X", mLargeCircleView.getX(), largeCircleX);        ObjectAnimator largeCircleAnim = ObjectAnimator.ofPropertyValuesHolder(mLargeCircleView, pvhX, mValueScaleX, mValueScaleY);        //2 outCircleView动画 X平移 XY缩放        pvhX = PropertyValuesHolder.ofFloat("X", mOutCircleView.getX(), outCircleX);        ObjectAnimator outCircleAnim = ObjectAnimator.ofPropertyValuesHolder(mOutCircleView, pvhX, mValueScaleX, mValueScaleY);        //3 smallCircleView动画 XY缩放 Path移动        PointF center = mSmallCircleView.getCenter();        PointF endCenter = new PointF(center.x - (mSmallCircleView.getX() - smallCircleX), center.y);        mCirclePath.reset();        mCirclePath.moveTo(center.x, center.y);        //贝塞尔曲线        mCirclePath.quadTo((center.x + endCenter.x) / 2, (center.y + endCenter.y) / 2 + 1.5f * dp2px(30), endCenter.x, endCenter.y);        ObjectAnimator smallCircleAnim = ObjectAnimator.ofObject(mSmallCircleView, "Center", null, mCirclePath);        ObjectAnimator smallCircleAnim2 = ObjectAnimator.ofPropertyValuesHolder(mSmallCircleView, mValuesScale);        mAimationSet = new AnimatorSet();        mAimationSet.play(largeCircleAnim).with(outCircleAnim).with(smallCircleAnim).with(smallCircleAnim2);        mAimationSet.setInterpolator(new AccelerateDecelerateInterpolator());        mAimationSet.setDuration(1000);        mAimationSet.addListener(new Animator.AnimatorListener() {            @Override            public void onAnimationStart(Animator animation) {            }            @Override            public void onAnimationEnd(Animator animation) {                swapCircle(mFocusPosition, nextPos);                mFocusPosition = nextPos;            }            @Override            public void onAnimationCancel(Animator animation) {            }            @Override            public void onAnimationRepeat(Animator animation) {            }        });        mAimationSet.start();    }    void swapCircle(int position1, int position2) {        CircleView tmp = mCircleViews.get(position1);        mCircleViews.set(position1, mCircleViews.get(position2));        mCircleViews.set(position2, tmp);    }    private int getNextPosition(boolean toRight) {        int next = mFocusPosition;        if (toRight) {            next = next + 1;        } else {            next = next - 1;        }        if (next < 0 || next >= mCount) {            next = -1;        }        return next;    }    private CircleView CreateCircle(int type) {        CircleView circle = new CircleView(mContext);        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);        params.weight = 1;        params.gravity = Gravity.CENTER_VERTICAL;        switch (type) {            case TYPE_SMALL:                params.height = params.width = SMALL_CIRCLE_RADIS * 2;                circle.setColor(mSmallCircleColor);                circle.setRadis(SMALL_CIRCLE_RADIS);                break;            case TYPE_LARGE:                params.height = params.width = LARGE_CIRCLE_RADIS * 2;                circle.setColor(mLargeCircleColor);                circle.setRadis(LARGE_CIRCLE_RADIS);                break;            case TYPE_OUTER:                params.height = params.width = OUT_CIRCLE_RADIS * 2;                circle.setColor(mOutCircleColor);                circle.setRadis(OUT_CIRCLE_RADIS);                break;            default:                break;        }        circle.setLayoutParams(params);        return circle;    }    private int dp2px(int dp) {        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());    }    private int sp2px(int sp) {        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());    }}package com.example.adminis



你的当前访问异常,请进行认证后继续阅读剩余内容。

分享到: