End

属性动画 基本使用案例 [MD]

博文地址

我的GitHub 我的博客 我的微信 我的邮箱
baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

目录

属性动画

基本使用演示

MainActivity

// 可操控的属性有:alpha;x/y;scaleX/scaleY;rotation/rotationX/rotationY;transitionX/transitionY;pivotX/pivotY
public class MainActivity extends ListActivity {
    private ImageView iv_src;
    private boolean b = true;
    
    private String[] array = {"重启当前Activity,启动一个新的Activity",
        "最简单的ObjectAnimator,控制scaleX、rotationX",
        "不存在get/set方法时不会有任何效果\n为Object的某个属性手动提供get/set方法",
        "只有set没有get方法时,get的值不存在,但是set可以正常使用",
        "监听动画更新:AnimatorUpdateListener\n监听动画状态:AnimatorListener",
        "组合动画:AnimatorSet.playTogether\n组合动画:AnimatorSet.with/before/after",
        "组合动画:AnimatorUpdateListener\n组合动画:PropertyValuesHolder",
        "组合动画:PVHolder + KeyFrame\nView的animate动画,最简洁的属性动画",
        "View的animate动画也可以组合动画\n可以在animate动画前/后执行一些操作",
        "最简单的ValueAnimator,控制translationY\n要明白ValueAnimator只是帮你计算插值的"};
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏
        setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array));
        
        iv_src = new ImageView(this);
        iv_src.setBackgroundColor(0x330000ff);
        iv_src.setImageResource(R.drawable.icon);
        getListView().addHeaderView(iv_src);
    }
    
    @Override
    protected void onListItemClick(ListView l, View view, int position, long id) {
        switch (position) {
            case 0:
                b = !b;
                Toast.makeText(this, "目前为:" + b, Toast.LENGTH_SHORT).show();
                break;
            case 1:
                if (b) recreate();//重启当前Activity
                else startActivity(new Intent(this, SecondActivity.class));
                break;
            case 2://最简单的ObjectAnimator,控制scaleX、rotationX
                if (b) ObjectAnimator.ofFloat(iv_src, "scaleX", 1f, 0.1f, 3f, 0.1f, 1f)//X轴缩放
                    .setDuration(1000)
                    .start();
                else ObjectAnimator.ofFloat(iv_src, "rotationX", 0.0f, 720.0f)//沿X轴旋转
                    .setDuration(500)
                    .start();
                break;
            case 3://不存在get/set方法时不会有任何效果,可以为Object的某个属性手动提供get/set方法
                int i = new Random().nextInt(8) + 1;
                if (b) ObjectAnimator.ofFloat(iv_src, "width", 100 * i)//没任何效果,但并不会报错
                    .setDuration(500)
                    .start();
                else ObjectAnimator.ofInt(new WrapperView(iv_src), "width", 100 * i) //提供set方法
                    .setDuration(500)
                    .start();
                break;
            case 4://只有set没有get方法时,get的值不存在,但是set可以正常使用
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    iv_src.setBackgroundColor(Color.WHITE); //有set方法,但是没有get方法,所以get结果为0
                    if (b) ObjectAnimator.ofArgb(iv_src, "backgroundColor", Color.RED)
                        .setDuration(1000)
                        .start();
                    else ObjectAnimator.ofArgb(iv_src, "backgroundColor", Color.RED, Color.GREEN, Color.BLUE)
                        .setDuration(3000)
                        .start();
                }
                break;
            case 5://监听动画更新:AnimatorUpdateListener,监听动画状态:AnimatorListener
                AnimHelper.addAnimListener(iv_src).start();
                break;
            case 6://组合动画:AnimatorSet.playTogether/with/before/after
                if (b) AnimHelper.combinedAnimPlayTogether(iv_src).start();
                else AnimHelper.combinedAnimAfterBefore(iv_src).start();
                break;
            case 7://组合动画:AnimatorUpdateListener,PropertyValuesHolder
                if (b) AnimHelper.combinedAnimUpdate(iv_src).start();
                else AnimHelper.propertyValuesHolder(iv_src).start();
                break;
            case 8://组合动画:PVHolder + KeyFrame,View的animate动画,最简洁的属性动画
                if (b) AnimHelper.pVHolderKeyFrame(iv_src).start();
                else iv_src.animate().y(200 * (new Random().nextInt(8))).setDuration(500).start();//ViewPropertyAnimator
                break;
            case 9://View的animate动画也可以组合动画,也可以在animate动画前/后执行一些操作
                if (b) iv_src.animate()
                    .setDuration(1000)
                    .rotation(360 * new Random().nextInt(8))
                    .scaleX(new Random().nextInt(8) * 0.5f)
                    .setInterpolator(new DecelerateInterpolator())
                    .start();
                else iv_src.animate()
                    .alpha(0.1f)
                    .y(1500)
                    .setDuration(800)
                    .withStartAction(() -> iv_src.setX(300))
                    .withEndAction(() -> {
                        iv_src.setX(0);
                        iv_src.setY(0);
                        iv_src.setAlpha(1f);
                    })
                    .start();
                break;
            case 10://最简单的ValueAnimator,控制translationY,要明白ValueAnimator只是帮你计算插值的
                if (b) AnimHelper.valueAnimator(iv_src).start();
                else AnimHelper.valueAnimator(iv_src, getListView()).start();
                break;
        }
    }
}

View包装类

View包装类,为不存在get/set方法的属性提供get/set方法

// View包装类,为不存在get/set方法的属性提供get/set方法
public class WrapperView {
    private View mTarget;
    
    public WrapperView(View target) {
        mTarget = target;
    }
    
    public int getWidth() {
        return mTarget.getLayoutParams().width;
    }
    
    public void setWidth(int width) {
        mTarget.getLayoutParams().width = width;
        mTarget.requestLayout();
    }
    
    public int getHeight() {
        return mTarget.getLayoutParams().height;
    }
    
    public void setHeight(int height) {
        mTarget.getLayoutParams().height = height;
        mTarget.requestLayout();//Call this when something has changed which has invalidated the layout of this view
    }
}

构建动画的工具类

public class AnimHelper {
    
    //监听动画绘制过程
    public static ObjectAnimator addAnimListener(View view) {
        ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", 0.1f, 1f).setDuration(1000);
        //方法一,实现AnimatorListener接口,监听开始Start、结束End、被取消Cancel、重复Repeat等事件
        //方法二,继承AnimatorListenerAdapter,只实现自己想实现的事件
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                Log.i("bqt", "【onAnimationStart】");
            }
            
            @Override
            public void onAnimationEnd(Animator animation) {
                Log.i("bqt", "【onAnimationEnd】");
            }
        });
        anim.addUpdateListener(animation -> {
            Float value = (Float) animation.getAnimatedValue();
            view.setRotationX((1 - value) * 360);
            Log.i("bqt", "onAnimationUpdate--" + value); //非常频繁
        });
        return anim;
    }
    
    public static AnimatorSet combinedAnimPlayTogether(View view) {
        ObjectAnimator anim1 = ObjectAnimator.ofFloat(view, "scaleX", 0, 2f, 1f);
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(view, "alpha", 0, 1f);
        ObjectAnimator anim3 = ObjectAnimator.ofFloat(view, "rotationY", 360);
        
        AnimatorSet animSet = new AnimatorSet().setDuration(2000);
        animSet.playTogether(anim1, anim2, anim3);
        return animSet;
    }
    
    public static AnimatorSet combinedAnimAfterBefore(View view) {
        ObjectAnimator anim1 = ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 2f);
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(view, "scaleY", 0.1f, 1f);
        ObjectAnimator anim3 = ObjectAnimator.ofFloat(view, "x", 0, -view.getWidth(), 0);
        ObjectAnimator anim4 = ObjectAnimator.ofFloat(view, "y", 0, view.getY() + 500f, 0);
        ObjectAnimator anim5 = ObjectAnimator.ofFloat(view, "rotationX", 360 * 2);
        
        AnimatorSet animSet = new AnimatorSet();
        animSet.play(anim1).with(anim2);//anim1,anim2同时执行
        animSet.play(anim2).with(anim3);//anim1,anim2,anim3同时执行
        animSet.play(anim4).after(anim3).before(anim5);//anim4在anim1,anim2,anim3之后,在anim5之前
        animSet.setDuration(1000);
        return animSet;
    }
    
    public static Animator combinedAnimUpdate(View view) {
        //ObjectAnimator anim = ObjectAnimator.ofFloat(view, "包青天", 0.5f, 0.1f, 2f).setDuration(2000);
        ValueAnimator anim = ValueAnimator.ofFloat(0.5f, 0.1f, 2f).setDuration(2000); //效果和上面的ObjectAnimator完全一样
        anim.addUpdateListener(animation -> {
            float cVal = (Float) animation.getAnimatedValue();
            view.setScaleX(cVal);
            view.setAlpha(cVal);
            view.setRotationX(cVal * 360);
        });
        return anim;
    }
    
    public static ObjectAnimator propertyValuesHolder(View view) {
        PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 0.2f, 1f);
        PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 0.8f, 0, 2f);
        PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("rotationY", 360 * 2f, 0);
        return ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY, pvhZ).setDuration(1000);//三个动画是同时执行的
    }
    
    public static ObjectAnimator pVHolderKeyFrame(View view) {
        Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
        Keyframe kf1 = Keyframe.ofFloat(0.5f, 360f);
        Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
        kf1.setInterpolator(new AccelerateInterpolator());
        PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
        return ObjectAnimator.ofPropertyValuesHolder(view, pvhRotation).setDuration(1000);
    }
    
    public static ValueAnimator valueAnimator(View view) {
        ValueAnimator animator = ValueAnimator.ofFloat(0, 800, 0).setDuration(500);//没有设置要操作的【对象】及【对象的属性】
        //animator.setTarget(view);//对ValueAnimator来说,这个方法是空方法(没有意义),因为它不会作用在任何View上
        //对ValueAnimator来说,是通过addUpdateListener,在回调中根据动画的值来手动设置属性的值的
        animator.addUpdateListener(animation -> {
            Float f = (Float) animation.getAnimatedValue();//这里只能强转为of**时指定的类型
            view.setTranslationY(f);//设置要操作的对象的属性。或者你可以使用获取到的值做任何事情
        });
        return animator;
    }
    
    public static ValueAnimator valueAnimator(View view, ListView listView) {
        ValueAnimator animator = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            animator = ValueAnimator.ofArgb(Color.GREEN).setDuration(5000);
            animator.addUpdateListener(animation -> {
                Integer greenColor = (Integer) animation.getAnimatedValue(); //实时获取值
                int myColor = (int) (animation.getAnimatedFraction() * Color.YELLOW);
                int count = listView.getAdapter().getCount();
                for (int i = 1; i < count; i++) {
                    if (i % 2 == 0) listView.getChildAt(i).setBackgroundColor(greenColor);
                    else listView.getChildAt(i).setBackgroundColor(myColor);
                }
            });
        }
        return animator;
    }
}

自定义 TypeEvaluator 实现抛物线动画效果

// 自定义TypeEvaluator实现抛物线动画效果
public class TypeEvaluatorActivity extends Activity {
    private static final int RADIUS_BALL = 10; //小球的半径
    private static final int RADIUS_TRACE = 3; //轨迹的半径
    private ImageView iv_src;
    RelativeLayout layout;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏
        initView();
        layout = new RelativeLayout(this);
        layout.setBackgroundColor(Color.LTGRAY);
        layout.setOnClickListener(v -> anim());
        layout.addView(iv_src, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        setContentView(layout);
    }
    
    private void initView() {
        Bitmap bitmap = Bitmap.createBitmap(2 * RADIUS_BALL, 2 * RADIUS_BALL, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);
        paint.setDither(true);
        canvas.drawCircle(RADIUS_BALL, RADIUS_BALL, RADIUS_BALL, paint);
        iv_src = new ImageView(this);
        iv_src.setImageBitmap(bitmap);
    }
    
    private void anim() {
        final int color = 0xFF000000 + new Random().nextInt(0xFFFFFF);
        Point point = new Point();
        ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(point);
        PointF startPointF = new PointF(0, 0);
        PointF endPointF = new PointF(point.x - iv_src.getWidth(), point.y - iv_src.getHeight());
        
        ValueAnimator animator = new ValueAnimator().setDuration(1000);
        animator.setInterpolator(new LinearInterpolator()); //插值器,默认为AccelerateDecelerateInterpolator【慢-快-慢】
        //通过new创建的ValueAnimator必须setObjectValues和setEvaluator,并且一定要先setObjectValues,再setEvaluator
        animator.setObjectValues(startPointF, endPointF);
        
        animator.setEvaluator((TypeEvaluator<PointF>) (fraction, startValue, endValue) -> { //估值器
            //只要能保证:当fraction=0时返回值为startValue,并且当fraction=1时返回值为endValue,就是一个比较合理的函数
            PointF pointF = new PointF();
            pointF.x = startValue.x + fraction * (endValue.x - startValue.x);// x方向匀速移动
            pointF.y = startValue.y + fraction * fraction * (endValue.y - startValue.y);// y方向抛物线加速移动
            return pointF;
        });
        
        animator.addUpdateListener(animation -> {
            PointF pointf = (PointF) animation.getAnimatedValue();
            iv_src.setX(pointf.x);
            iv_src.setY(pointf.y);
            addTrace(pointf, color);
        });
        animator.start();
    }
    
    private void addTrace(PointF pointf, int color) {
        View view = new View(this);
        view.setBackgroundColor(color);
        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(2 * RADIUS_TRACE, 2 * RADIUS_TRACE);
        layoutParams.leftMargin = (int) pointf.x + RADIUS_TRACE;
        layoutParams.topMargin = (int) pointf.y + RADIUS_TRACE;
        layout.addView(view, layoutParams);
    }
}

使用 LayoutTransition 为布局容器中子View的显示与消失设置过渡动画

public class LayoutTransitionActivity extends ListActivity {
    
    private GridLayout gl_container;//父布局
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String[] array = {"点击添加一个View,点击添加的View删除此View"};
        setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array));
        
        gl_container = new GridLayout(this);
        gl_container.setColumnCount(4);
        gl_container.setLayoutTransition(new LayoutTransition());//布局动画,当容器中的视图发生变化时存在过渡的动画效果
        getListView().addFooterView(gl_container);
        
        addCheckBox(LayoutTransition.APPEARING, "APPEARING");//当一个View在VG中【出现】时设置的动画
        addCheckBox(LayoutTransition.CHANGE_APPEARING, "CHANGE_APPEARING");
        //当一个View在ViewGroup中【出现】时,对此View对其他View位置造成影响,对【其他View】设置的动画
        addCheckBox(LayoutTransition.DISAPPEARING, "DISAPPEARING");//当一个View在VG中【消失】时设置的动画
        addCheckBox(LayoutTransition.CHANGE_DISAPPEARING, "CHANGE_DISAPPEARING");
        //当一个View在ViewGroup中【消失】时,对此View对其他View位置造成影响,对【其他View】设置的动画
        addCheckBox(-1, "等价于是否设置xml中GridLayout的animateLayoutChanges属性为true");
    }
    
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Button button = new Button(this);
        button.setText(gl_container.getChildCount() + 1 + "");
        gl_container.addView(button, gl_container.getChildCount());//放置在最后那个位置
        button.setOnClickListener(view -> gl_container.removeView(button));
    }
    
    private void addCheckBox(int transitionType, String text) {
        CheckBox checkBox = new CheckBox(this);
        checkBox.setText(text);
        checkBox.setChecked(true);
        checkBox.setOnCheckedChangeListener((v, isChecked) -> {
            LayoutTransition mTransition = new LayoutTransition(); //默认为全部开启状态,默认的动画效果都是可以更改的
            if (transitionType == -1) mTransition = isChecked ? mTransition : null;
            else mTransition.setAnimator(transitionType, isChecked ? mTransition.getAnimator(transitionType) : null);
            gl_container.setLayoutTransition(mTransition);
        });
        getListView().addFooterView(checkBox);
    }
}

使用 LayoutAnimationController 为布局容器中的控件播放同样的动画

public class LayoutAnimationControllerActivity extends ListActivity {
    LinearLayout linearLayout;
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String[] array = {"点击添加HeaderView",
            "点击添加的HeaderView",
            "移除添加移除View时没任何动画效果",
            "ListView不支持addView操作"//UnsupportedOperationException:addView(View) is not supported in AdapterView
        };
        setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array));
        getListView().setLayoutAnimation(getLayoutAnimationController());//android:layoutAnimation="@anim/layout_anim"
        addFooterView();
    }
    
    private void addFooterView() {
        linearLayout = new LinearLayout(this);
        linearLayout.setOrientation(LinearLayout.VERTICAL);
        new Handler().postDelayed(() -> linearLayout.addView(getView(v -> linearLayout.removeView(v))), 500);
        new Handler().postDelayed(() -> linearLayout.addView(getView(v -> linearLayout.removeView(v))), 1500);
        new Handler().postDelayed(() -> linearLayout.addView(getView(v -> linearLayout.removeView(v))), 3500);
        linearLayout.setLayoutAnimation(getLayoutAnimationController());
        getListView().addHeaderView(linearLayout);
    }
    
    private LayoutAnimationController getLayoutAnimationController() {
        Animation animation = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);//补间动画
        LayoutAnimationController lac = new LayoutAnimationController(animation);//布局动画
        lac.setOrder(LayoutAnimationController.ORDER_NORMAL);//显示顺序 normal=0 默认,reverse=1 倒序,random=2 随机
        lac.setDelay(0.6f);//显示间隔时间,注意单位是秒,可以为70%,也可以是一个浮点数
        return lac;
    }
    
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        int index = position - getListView().getHeaderViewsCount();
        if (index == 0) {
            getListView().addHeaderView((getView(view -> getListView().removeHeaderView(view))));
        } else if (index == 1) {
            linearLayout.addView(getView(view -> linearLayout.removeView(view)));
        }
    }
    
    private ImageView getView(View.OnClickListener listener) {
        ImageView iv = new ImageView(this);
        iv.setImageResource(R.drawable.ic_launcher);
        iv.setOnClickListener(listener);
        return iv;
    }
}

几十种 Interpolator 演示

SecondActivity

public class SecondActivity extends ListActivity {
    private final String[][] array = {INTERPOLATORS1, INTERPOLATORS2, INTERPOLATORS3, INTERPOLATORS4, INTERPOLATORS5, INTERPOLATORS6,};
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏
        requestWindowFeature(Window.FEATURE_NO_TITLE);//取消标题栏
        String[] names = {"-1-", "-2-", "-3-", "-4-", "-5-", "-6-", //
            "自定义TypeEvaluator实现抛物线动画效果", //
            "使用LayoutTransition为布局容器中子View的显示与消失设置过渡动画", //
            "使用LayoutAnimationController为布局容器中的控件播放同样的动画",};
        setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, names));
    }
    
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        switch (position) {
            case 6:
                startActivity(new Intent(this, TypeEvaluatorActivity.class));
                break;
            case 7:
                startActivity(new Intent(this, LayoutTransitionActivity.class));
                break;
            case 8:
                startActivity(new Intent(this, LayoutAnimationControllerActivity.class));
                break;
            default:
                Intent intent = new Intent(this, InterpolatorActivity.class);
                intent.putExtra(InterpolatorActivity.EXTRA_NAME, array[position]);
                startActivity(intent);
                break;
        }
    }
    
    public static final String[] INTERPOLATORS1 = new String[]{"EaseBackInInterpolator", "EaseBackInOutInterpolator", "EaseBackOutInterpolator",
        "EaseBounceInInterpolator", "EaseBounceInOutInterpolator", "EaseBounceOutInterpolator", "EaseBreathInterpolator", "EaseCircularInInterpolator",
        "EaseCircularInOutInterpolator", "EaseCircularOutInterpolator",};
    public static final String[] INTERPOLATORS2 = new String[]{"EaseCubicInInterpolator", "EaseCubicInOutInterpolator", "EaseCubicOutInterpolator",
        "EaseExponentialInInterpolator", "EaseExponentialInOutInterpolator", "EaseExponentialOutInterpolator", "EaseInBackInterpolator",
        "EaseInBounceInterpolator", "EaseInCircInterpolator", "EaseInCubicInterpolator",};
    public static final String[] INTERPOLATORS3 = new String[]{"EaseInElasticInterpolator", "EaseInExpoInterpolator", "EaseInOutBackInterpolator",
        "EaseInOutBounceInterpolator", "EaseInOutCircInterpolator", "EaseInOutCubicInterpolator", "EaseInOutElasticInterpolator",
        "EaseInOutExpoInterpolator", "EaseInOutQuadInterpolator", "EaseInOutQuartInterpolator",};
    public static final String[] INTERPOLATORS4 = new String[]{"EaseInOutQuintInterpolator", "EaseInOutSineInterpolator", "EaseInQuadInterpolator",
        "EaseInQuartInterpolator", "EaseInQuintInterpolator", "EaseInSineInterpolator", "EaseOutBackInterpolator", "EaseOutBounceInterpolator",
        "EaseOutCircInterpolator", "EaseOutCubicInterpolator",};
    public static final String[] INTERPOLATORS5 = new String[]{"EaseOutElasticInterpolator", "EaseOutExpoInterpolator", "EaseOutQuadInterpolator",
        "EaseOutQuartInterpolator", "EaseOutQuintInterpolator", "EaseOutSineInterpolator", "EaseQuadInInterpolator", "EaseQuadInOutInterpolator",
        "EaseQuadOutInterpolator", "EaseQuartInInterpolator",};
    public static final String[] INTERPOLATORS6 = new String[]{"EaseQuartInOutInterpolator", "EaseQuartOutInterpolator", "EaseQuintInInterpolator",
        "EaseQuintInOutInterpolator", "EaseQuintOutInterpolator",};
}

InterpolatorActivityInterpolatorActivity

public class InterpolatorActivity extends ListActivity {
    private ObjectAnimator mAnimator;
    private static final String IN_PG_NAME = "com.bqt.anim.interpolator.";
    public static final String EXTRA_NAME = "interpolators";
    private String[] mInterpolators;
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏
        mInterpolators = getIntent().getStringArrayExtra(EXTRA_NAME); //传过来的名字
        setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mInterpolators));
        
        ImageView iv_src = new ImageView(this);
        iv_src.setBackgroundColor(0x330000ff);
        iv_src.setImageResource(R.drawable.icon);
        getListView().addHeaderView(iv_src);
        
        DisplayMetrics metric = new DisplayMetrics();
        ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metric);
        mAnimator = ObjectAnimator.ofFloat(iv_src, "y", 0, metric.heightPixels, 0).setDuration(1500);
    }
    
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        if (position == 0) recreate();
        else anim(position - 1);
    }
    
    private void anim(int position) {
        String name = mInterpolators[position];
        try {
            Class<?> clazz = Class.forName(IN_PG_NAME + name);
            TimeInterpolator interpolator = (TimeInterpolator) clazz.newInstance();
            mAnimator.cancel();
            mAnimator.setInterpolator(interpolator);
            mAnimator.start();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

2019-5-11

posted @ 2019-05-11 22:17  白乾涛  阅读(548)  评论(0编辑  收藏  举报