android 阻尼动画,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.view.animation.AnimationSet;

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 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_circle);

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();

}

@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动态添加圆

* */

if (mCircleViews.size() != count) {

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() {

move(true);

}

public void moveLeft() {

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()) : 0;

float smallCircleX = toRight ? mLargeCircleView.getX() : mLargeCircleView.getX() + (mLargeCircleView.getWidth() - mSmallCircleView.getWidth());

float outCircleX = mOutCircleView.getX() + (largeCircleX - 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) {

}

@Override

public void onAnimationCancel(Animator animation) {

swapCircle(mFocusPosition, nextPos);

mFocusPosition = nextPos;

}

@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) {

if (toRight) {

mFocusPosition = mFocusPosition + 1;

} else {

mFocusPosition = mFocusPosition - 1;

}

if (mFocusPosition < 0 || mFocusPosition >= mCount) {

mFocusPosition = -1;

}

return mFocusPosition;

}

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());

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值