属性动画 补间动画 帧动画 基本使用案例 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
属性动画 补间动画 帧动画 基本使用案例 MD的更多相关文章
- js 动画补间 Tween
1 /* RunningList (触发过程中可以安全的删除自己) 2 如果触发过程中删除(回调函数中删除正在遍历的数组), 不仅 len 没有变(遍历前定义的len没有变, 真实的len随之减少), ...
- android 帧动画,补间动画,属性动画的简单总结
帧动画——FrameAnimation 将一系列图片有序播放,形成动画的效果.其本质是一个Drawable,是一系列图片的集合,本身可以当做一个图片一样使用 在Drawable文件夹下,创建ani ...
- Android动画-补间(Tween)动画
Android动画的两种方式,其中帧动画上篇文章已经讲了,这次主要讲解的就是补间动画,补间动画就是动画业务场景中常用的旋转,平移,缩放,和渐变效果,帧动画是通过轮播动画实现动画效果,补间动画通过在两个 ...
- Android笔记(六十四) android中的动画——补间动画(tweened animation)
补间动画就是只需要定义动画开始和结束的位置,动画中间的变化由系统去补齐. 补间动画由一下四种方式: 1.AplhaAnimation——透明度动画效果 2.ScaleAnimation ——缩放动画效 ...
- Android Animation 动画Demo(Frame帧动画)
上一页介绍Animation动画第一:Tween吐温动画. 本文介绍了以下Animation也有动画的形式:Frame帧动画. Frame动画是一系列照片示出的顺序按照一定的处理,和机制,以放电影很阶 ...
- Android 动画 属性动画 视图动画 补间动画 帧动画 详解 使用
Android动画 Property Animation res/animator/filename.xml In Java: R.animator.filename In XML: @[packag ...
- android104 帧动画,补间动画,属性动画
##帧动画FrameAnimation* 多张图片快速切换,形成动画效果* 帧动画使用xml定义 package com.itheima.frameanimation; import android. ...
- Android基础笔记(十)- 帧动画、补间动画具体解释、对话框
帧动画 补间动画Tween Animation 对话框以及面试中的注意点 帧动画 帧动画非常easy,我们首先看一下Google官方解释This is a traditional animation ...
- Android中的帧动画与补间动画的使用
前言 在日常开发中,我们有时候须要一些好看的动画效果,这时能够充分利用Android提供的这几种动画来实现. Android提供了3种类型的动画: 补间动画:补间动画能够应用于View,让你能够定义一 ...
随机推荐
- 关于golang-mod的使用方法
简单粗暴仅需要三步即可 $ go mod download $ go mod tidy $ go build -v 这里保持默认什么都不用添加,项目无需在 gopath里面 Vendoring mod ...
- 5G 融合计费系统架构设计与实现(一)
5G 融合计费系统架构设计与实现(一) 随着5G商用临近,5G的各个子系统也在加紧研发调试,本人有兴全程参与5G中的融合计费系统(CCS)的设计.开发.联调工作.接下来将用几篇文章介绍我们在CCS实现 ...
- 通过mitmproxy爬取APP的数据
安装: https://mitmproxy.org/ 小米安装证书 设置->系统安全->从存储设备安装->选择*.pem文件 模拟器安装证书 (请从C:\Users\John\.mi ...
- EChart 标题 title 样式,x轴、y轴坐标显示,调整图表位置等
示例里工作一般情况是够用了,更复杂的可以查询教程: title 官方解说:http://echarts.baidu.com/option.html#title 坐标相关: X轴:http://echa ...
- Nginx的configure脚本支持选项整理
在不同版本间,选项可能会有些许变化,请总是使用./configure –help命令来检查当前的选项列表. --prefix=<PATH> #Nginx安装路径.如果没有指定,默认为 /u ...
- Navicat连接MySQL8.0出现1251-Client does not support authentication protocol requested by server;
因为安装的MySQL是8.0版本的,因为在安装的时候采用了新的加密方式. 我们需要使用 cmd命令,连接mysql 1. 更改加密方式 mysql> ALTER USER 'root'@'l ...
- 【GMT43智能液晶模块】例程十五:LAN_TCPC实验——以太网数据传输
源代码下载链接: 链接:https://pan.baidu.com/s/1bFX8_UpUlML29oqoDGaw5g提取码:mrf5 复制这段内容后打开百度网盘手机App,操作更方便哦 GMT43购 ...
- Spring IoC 的实现机制
Spring 中的 IoC 的实现原理就是工厂模式加反射机制. interface Fruit { public abstract void eat(); } class Apple impl ...
- PMP 第6章错题总结
项目进度管理的步骤: 1.项目的商业价值指特定项目的成果能够为相关方带来的有形的或无形的效益. 其中有形的效益包括:股东权益.市场份额.货币资产 无形的效益包括:品牌认知度.商誉.战略一致性等2. ...
- 文件组 'PRIMARY' 已满 解决办法
修改一个字段类型时,报的这个错. 此时需要增加次要数据文件 次要数据文件 次要数据文件包含除主要数据文件外的所有数据文件.有些数据库可能没有次要数据文件,而有些数据库则有多个次要数据文件.次要数据文件 ...