


Android动画三部曲之一 View Animation & LayoutAnimation_html/css_WEB-ITnose
本篇文章对android的Tween动画和帧动画以及布局动画进行总结。
Tween动画
Tween动画又称补间动画。通过对view的位置、大小、透明度、角度的改变来实现动画效果。
补间动画的基类是Animation。我们通常使用它的直接子类RotateAnimation、TranslateAnimation、ScaleAnimation、AlphaAnimation。
补间动画可以通过xml进行定义(res/anim/xxx),然后通过AnimationUtils类进行加载;也可以通过完全代码进行设置。
XML语法介绍
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@[package:]anim/interpolator_resource" android:shareInterpolator=["true" | "false"] > <alpha android:fromAlpha="float" android:toAlpha="float" /> <scale android:fromXScale="float" android:toXScale="float" android:fromYScale="float" android:toYScale="float" android:pivotX="float" android:pivotY="float" /> <translate android:fromXDelta="float" android:toXDelta="float" android:fromYDelta="float" android:toYDelta="float" /> <rotate android:fromDegrees="float" android:toDegrees="float" android:pivotX="float" android:pivotY="float" /> <set> ... </set></set>
Animation类定义了很多常量和变量的初始值,比如:
public static final int INFINITE = -1;public static final int RESTART = 1;public static final int REVERSE = 2;
主要用到它的子类以及AnimationListener :
public static interface AnimationListener { /** * 动画开始的时候回调 * * @param animation The started animation. */ void onAnimationStart(Animation animation); /** * 动画结束的时候回调。但是当设置动画重复次数为INFINITE的时候,该方法不会回调。 * * @param animation The animation which reached its end. */ void onAnimationEnd(Animation animation); /** * 动画重复播放的时候回调 * * @param animation The animation which was repeated. */ void onAnimationRepeat(Animation animation); }
添加此监听器可以对动画做更多的操作。
插值器 – Interpolator
介绍动画之前,得先说说”插值器”。插值器的意思就是在播放动画的时候,改变播放的速率,可以使动画越来越快,或者越来越慢等。
常用的是一下九个插值器:
AccelerateInterpolator | @android:anim/accelerate_interpolator | 加速变化(开始慢,越来越快) |
DecelerateInterpolator | @android:anim/decelerate_interpolator | 减速变化(开始快,越来越慢) |
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 先加速后减速(中间速度最快) |
LinearInterpolator | @android:anim/linear_interpolator | 线性均匀变化 |
OvershootInterpolator | @android:anim/overshoot_interpolator | 超出结尾的临界值,然后在缓慢回到结束值 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 先向相反的方向改变一点,然后在加速播放 |
AnticipateOvershootInterpolator | @android:anim/anitcipate_overshoot_interpolator | 先向相反的方向改变一点,然后在加速播放至超出结束值一点,然后在缓慢回到结束值 |
BounceInterpolator | @android:anim/bounce_interpolator | 动画快结束的时候,模拟球落地的回弹效果 |
CycleInterpolator | @android:anim/cycle_interpolator | 动画循环播放指定的次数 |
自定义Interpolator
一般来说,官方API给的这几个插值器就够实用了。不过还可以自定义Interpolator。可以简单的对系统的插值器进行一些参数值的修改:
<?xml version="1.0" encoding="utf-8"?><InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android" android:attribute_name="value" />
这里推荐大家一个第三方的Interpolator库:
https://github.com/cimi-chen/EaseInterpolator
公共XML属性及对应的方法
android:duration | setDuration(long) | 动画持续的时间长度(单位是miliseconds) |
android:interpolator | setInterpolator(Interpolator) | 设置动画播放时的插值器 |
android:repeatCount | setRepeatCount(int) | 设置动画播放重复次数 |
android:repeatMode | setRepeatMode(int) | 设置动画重复的方式(当repeat count>0时才有效) “reverse“(2) or “restart“(1) |
android:startOffset | setStartOffset(long) | 设置动画开始播放的延迟时间 |
android:fillAfter | setFillAfter(boolean) | 设置为true时,视图会停留在动画结束的状态。 |
android:fillBefore | setFillBefore(boolean) | 默认值是true,视图会停留在动画开始的状态 |
android:fillEnable | setFillEnable(boolean) | 默认值是false。如果是true,动画将会应用fillBefore值;否则,fillBefore的值会被忽略,transformation会在动画结束的时候被应用。 |
android:detachWallpaper | setDetachWallpaper(boolean) | 默认值是false。如果为true,并且动画窗体有一个壁纸的话,那么动画只会应用给window,墙纸是静态不动的 |
android:zAdjustment | setZAdjustment(int) | 允许在动画播放期间,调整播放内容在Z轴方向的顺序。”top“(1) or “normal“(0) or “bottom“(-1) |
android:zAdjustment:允许在动画播放期间,调整播放内容在Z轴方向的顺序:
ScaleAnimation – 缩放动画
android:fromXScale | 动画起始时,X轴坐标的伸缩尺寸。0.0表示收缩到没有。1.0表示正常没伸缩。>1.0表示放大。<1.0表示收缩。 |
android:toXScale | 动画结束时X轴坐标的伸缩尺寸 |
android:fromYScale | 动画起始时Y轴坐标的伸缩尺寸 |
android:toYScale | 动画结束时Y轴坐标的伸缩尺寸 |
android:pivotX | 缩放动画作用点在X轴方向上的位置。android:pivotX=”50”表示绝对定位,相对于零点偏移50 –> Animation.ABSOLUTE android:pivotX=”50%”表示相对控件本身 –> Animation.RELATE_TO_SELF android:pivotX=”50%p”表示相对控件的父控件 –> Animation.RELATE_TO_PARENT |
android:pivotY | 缩放动画作用点在Y轴方向上的位置 |
<?xml version="1.0" encoding="utf-8"?><scale xmlns:android="http://schemas.android.com/apk/res/android" android:background="@color/blue_light" android:duration="1000" android:fillAfter="false" android:fillBefore="true" android:fromXScale="1" android:fromYScale="1" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:pivotX="50%" android:pivotY="50%" android:repeatCount="1" android:repeatMode="restart" android:startOffset="500" android:toXScale="0" android:toYScale="0" android:zAdjustment="bottom" />
然后通过AnimationUtils类装载动画,进行应用。
Animation scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.scale_anim);targetIv.startAnimation(scaleAnimation);
ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.5f, 1.0f, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);scaleAnimation.setDuration(1000);scaleAnimation.setInterpolator(new OvershootInterpolator());scaleAnimation.setFillAfter(true);targetIv.startAnimation(scaleAnimation);
ScaleAnimation有4个构造方法。
public ScaleAnimation(Context context, AttributeSet attrs) {}
public ScaleAnimation(float fromX, float toX, float fromY, float toY) {}
public ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY) {}
public ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {}
第一个构造用于从资源文件中加载资源。我们主要用后三个。后面三个构造的区别就在设置变换中轴点与否。不指定pivotXType和pivotYType的话,默认采用ABSOLUTE形式,pivotX与pivotY的值都是相对于(0,0)左上角偏移的。
pivotXType可设置的参数有三种:ABSOLUTE、RELATE_TO_SELF、RELATE_TO_PARENT。
效果如下:
RotateAnimation – 旋转动画
android:fromDegrees | 动画起始的角度(可正可负) |
android:toDegrees | 动画终止的角度(可正可负) |
android:pivotX | 旋转作用点在X轴方向上的位置。android:pivotX=”50”表示绝对定位,相对于零点偏移50 android:pivotX=”50%”表示相对控件本身 android:pivotX=”50%p”表示相对控件的父控件 |
android:pivotY | 旋转作用点在Y轴方向上的位置 |
<?xml version="1.0" encoding="utf-8"?><rotate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2500" android:fillAfter="true" android:fromDegrees="-20" android:interpolator="@android:anim/overshoot_interpolator" android:pivotX="50%" android:pivotY="50%" android:toDegrees="320" />
RotateAnimation rotateAnimation = new RotateAnimation(0.0f, 550.0f, Animation.RELATIVE_TO_SELF, 0.3f, Animation.RELATIVE_TO_SELF, 0.3f);rotateAnimation.setDuration(1500);rotateAnimation.setInterpolator(new OvershootInterpolator());rotateAnimation.setFillAfter(true);targetIv.startAnimation(rotateAnimation);
效果图如下:
TranslateAnimation – 平移动画
android:fromXDelta | 平移动画起始位置X轴坐标 |
android:toXDelta | 平移动画结束位置X轴坐标 |
android:fromYDelta | 平移动画起始位置Y轴坐标 |
android:toYDelta | 平移动画结束位置Y轴坐标 |
<?xml version="1.0" encoding="utf-8"?><translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:fromXDelta="0" android:fromYDelta="0" android:interpolator="@android:anim/anticipate_overshoot_interpolator" android:toXDelta="50%p" android:toYDelta="50%p" />
TranslateAnimation translateAnimation = new TranslateAnimation(0, 200, 0, 0);translateAnimation.setDuration(1000);translateAnimation.setInterpolator(new AnticipateOvershootInterpolator());targetIv.startAnimation(translateAnimation);
AlphaAnimation – 渐变动画
android:fromAlpha | 动画开始时操作对象的alpha值 |
android:toAlpha | 动画终止时操作对象的alpha值 |
<?xml version="1.0" encoding="utf-8"?><alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:fromAlpha="1.0" android:interpolator="@android:anim/linear_interpolator" android:repeatCount="1" android:repeatMode="reverse" android:toAlpha="0.0" />
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.2f);alphaAnimation.setDuration(1500);alphaAnimation.setInterpolator(new AccelerateDecelerateInterpolator());alphaAnimation.setRepeatMode(Animation.REVERSE);alphaAnimation.setRepeatCount(1);targetIv.startAnimation(alphaAnimation);
AnimationSet – 动画集合
上面都是一个个的单独的动画,我们可以将很多个单独的动画组合到一起成为一个集合。
动画集合也可以在xml中设置。需要用标签包括其他简单的动画。比上述公共动画属性多了一个android:shareInterpolator=”boolean”,表示是否对子动画设置相同的插值器。
xml中设置set动画集合<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true" android:shareInterpolator="false"> <alpha android:duration="1500" android:fillAfter="true" android:fromAlpha="1.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="0.2" /> <scale android:duration="1000" android:fromXScale="0.8" android:fromYScale="0.8" android:interpolator="@android:anim/linear_interpolator" android:pivotX="60%" android:pivotY="20%" android:startOffset="1500" android:toXScale="0.3" android:toYScale="0.5" /> <translate android:duration="1000" android:fromXDelta="0" android:fromYDelta="0" android:interpolator="@android:anim/bounce_interpolator" android:startOffset="2500" android:toXDelta="200" android:toYDelta="200" /> <rotate android:duration="1000" android:fromDegrees="50" android:interpolator="@android:anim/anticipate_overshoot_interpolator" android:pivotX="50%p" android:pivotY="50%p" android:startOffset="3500" android:toDegrees="360" /></set>
我们来看一个现象:
设置了上面的set动画之后,开始运行的时候,会发现渐变动画开始运行的时候,会先变小,旋转一个角度,然后才开始动画。仔细分析xml代码之后,发现是在动画开始的时候,把scale和rotate中的初始状态给应用了。这时候想起了android:fillBefore属性。
然后在scale、rotate 动画里添加了android:fillBefore=”false”属性之后,发现还是不好使。查看Animation类的源码发现,fillBefore必须在设置fillEnable=”true”的时候才神效。并且fillBefore的默认值是true,所以才会出现上述情况。
再次修改之后,代码如下:
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true" android:shareInterpolator="false"> <alpha android:duration="1500" android:fillAfter="true" android:fromAlpha="1.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="0.2" /> <scale android:duration="1000" android:fillBefore="false" android:fillEnabled="true" android:fromXScale="0.8" android:fromYScale="0.8" android:interpolator="@android:anim/linear_interpolator" android:pivotX="60%" android:pivotY="20%" android:startOffset="1500" android:toXScale="0.3" android:toYScale="0.5" /> <translate android:duration="1000" android:fromXDelta="0" android:fromYDelta="0" android:interpolator="@android:anim/bounce_interpolator" android:startOffset="2500" android:toXDelta="200" android:toYDelta="200" /> <rotate android:duration="1000" android:fillBefore="false" android:fillEnabled="true" android:fromDegrees="50" android:interpolator="@android:anim/anticipate_overshoot_interpolator" android:pivotX="50%p" android:pivotY="50%p" android:startOffset="3500" android:toDegrees="360" /></set>
效果如下:
Frame动画
Frame动画就是把图片一帧一帧的播放出来的显示效果,类似于gif图片。帧动画设置很简单,只需要把每一帧对应的图片按照顺序添加进去,然后设置每一帧的显示时长,然后为view控件设置该动画,播放就行了。
xml设置帧动画:<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/person1" android:duration="100" /> <item android:drawable="@drawable/person2" android:duration="100" /> <item android:drawable="@drawable/person3" android:duration="100" /> <ite android:drawable="@drawable/person4" android:duration="100" /> <item android:drawable="@drawable/person5" android:duration="100" /> <item android:drawable="@drawable/person6" android:duration="100" /> <item android:drawable="@drawable/person7" android:duration="100" /></animation-list>
给ImageView设置动画:
targetIv.setBackgroundResource(R.drawable.frame_anim);AnimationDrawable animationDrawable = (AnimationDrawable) targetIv.getBackground();animationDrawable.start();
AnimationDrawable animationDrawable = new AnimationDrawable();animationDrawable.setOneShot(false);animationDrawable.addFrame(getResources().getDrawable(R.drawable.person1), 200);animationDrawable.addFrame(getResources().getDrawable(R.drawable.person2), 200);animationDrawable.addFrame(getResources().getDrawable(R.drawable.person3), 200);animationDrawable.addFrame(getResources().getDrawable(R.drawable.person4), 200);animationDrawable.addFrame(getResources().getDrawable(R.drawable.person5), 200);targetIv.setImageDrawable(animationDrawable);animationDrawable.start();
LayoutAnimationController
Tween Animation和Frame Animation都是针对单个view操作的。而LayoutAnimationController可以针对一个ViewGroup进行动画操作,可以让一组view的每个view按照一定的规则展示动画。
比如:可以针对listView、gridView或者recyclerView,定义item的出场动画,而不是非常死板的一下子全显示出来。
一般对ListView使用layoutAnimation动画,对GridView使用gridLayoutAnimation动画。对RecyclerView来说,正常情况下只能使用layoutAnimation动画,应用gridLayoutAnimation动画的时候会报错。不错可以针对RecyclerView生成一个子类做一下处理进行支持gridLayoutAnimation动画。
android:delay | setDelay(float) | 动画播放的延迟时间 |
android:animationOrder | setOrder(int) | 子view播放动画的顺序 [ normal |
android:interpolator | setInterpolator(Interpolator) setIntepolator(Context, @InterpolatorRes int) | 插值器 |
android:animation | LayoutAnimationController(animation) | 指定子view的动画 |
<?xml version="1.0" encoding="utf-8"?><layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:animation="@anim/item_list_anim" android:animationOrder="normal" android:delay="0.2" android:interpolator="@android:anim/bounce_interpolator" />
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:shareInterpolator="true"> <alpha android:fromAlpha="0.0" android:toAlpha="1.0" /> <translate android:fromXDelta="-100%" android:toXDelta="0%" /></set>
public LayoutAnimationController(Animation animation) { this(animation, 0.5f);}
public LayoutAnimationController(Animation animation, float delay) { mDelay = delay; setAnimation(animation);}
LayoutAnimationController有三个构造函数,常用的时候上面两个。delay表示每个子view启动动画的延迟时间,默认是0.5f。delay以秒为单位 。
Animation animation = AnimationUtils.loadAnimation(this, R.anim.item_list_anim); LayoutAnimationController layoutAnimationController = new LayoutAnimationController(animation); layoutAnimationController.setInterpolator(new AccelerateInterpolator()); layoutAnimationController.setDelay(0.5f); layoutAnimationController.setOrder(LayoutAnimationController.ORDER_RANDOM); recyclerView.setLayoutAnimation(layoutAnimationController);
GridLayoutAnimationController
GridLayoutAnimationController是LayoutAnimationController的子类。针对GridView做动画操作。
android:delay | setDelay(float) | 动画播放的延迟时间 |
android:columnDelay | setColumnDelay(float) | 列播放动画的延迟时间 |
android:rowDelay | setRowDelay(float) | 行播放动画的延迟时间 |
android:animationOrder | setOrder(int) | 子view播放动画的顺序 [ normal |
android:animation | LayoutAnimationController(animation) | 指定子view的动画 |
<GridView android:id="@+id/test_grid_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:columnWidth="60dp" android:gravity="center" android:horizontalSpacing="10dp" android:layoutAnimation="@anim/grid_layout_anim" android:numColumns="3" android:padding="10dp" android:scrollbars="none" android:stretchMode="columnWidth" android:verticalSpacing="10dp" />
<?xml version="1.0" encoding="utf-8"?><gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:animation="@anim/item_anim_alpha" android:columnDelay="0.5" android:direction="bottom_to_top|right_to_left" android:directionPriority="row" />
<?xml version="1.0" encoding="utf-8"?><alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:fromAlpha="0.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="1.0" />
同样是使用一个Animation构造出GridLayoutAnimation对象,然后设置各种参数,最后设置此动画GridView即可。
Animation animation = AnimationUtils.loadAnimation(this, R.anim.item_anim_alpha);GridLayoutAnimationController gridLayoutAnimationController = new GridLayoutAnimationController(animation);gridLayoutAnimationController.setDirection(GridLayoutAnimationController.DIRECTION_BOTTOM_TO_TOP | GridLayoutAnimationController.DIRECTION_RIGHT_TO_LEFT);gridLayoutAnimationController.setDirectionPriority(GridLayoutAnimationController.PRIORITY_ROW);gridRecyclerView.setLayoutAnimation(gridLayoutAnimationController);
效果如下:
RecyclerView扩展
正常情况下,我们可以对RecyclerView使用LayoutAnimation动画。但是如果对RecycleView使用动画的时候出现以下错误:
AndroidRuntime: FATAL EXCEPTION: main Process: com.jacksen.demo.view, PID: 30770 java.lang.ClassCastException: android.view.animation.LayoutAnimationController$AnimationParameters cannot be cast to android.view.animation.GridLayoutAnimationController$AnimationParameters at android.view.animation.GridLayoutAnimationController.getDelayForView(GridLayoutAnimationController.java:299) at android.view.animation.LayoutAnimationController.getAnimationForView(LayoutAnimationController.java:321) at android.view.ViewGroup.bindLayoutAnimation(ViewGroup.java:3717) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2892) ......
意思就是GridLayoutAnimationController.AnimationParameters不能强转成LayoutAnimationController.AnimationParameters。
RecyclerView的出现本来就是替代Listview的,但是它有可以展示出GridView的效果,但是怎么让RecyclerView设置GridLayoutManager的时候应用gridLayoutAnimation动画呢?
我们先来看看Gridview怎么实现的?
在GridView源码里面搜索”LayoutAnimation”关键字发现,只有一个attachLayoutAnimationParameters()的函数,里面将layoutAnimationParameters强转成GridLayoutAnimationController.AnimationParameters。
@Override protected void attachLayoutAnimationParameters(View child, ViewGroup.LayoutParams params, int index, int count) { GridLayoutAnimationController.AnimationParameters animationParams = (GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters; if (animationParams == null) { animationParams = new GridLayoutAnimationController.AnimationParameters(); params.layoutAnimationParameters = animationParams; } animationParams.count = count; animationParams.index = index; animationParams.columnsCount = mNumColumns; animationParams.rowsCount = count / mNumColumns; if (!mStackFromBottom) { animationParams.column = index % mNumColumns; animationParams.row = index / mNumColumns; } else { final int invertedIndex = count - 1 - index; animationParams.column = mNumColumns - 1 - (invertedIndex % mNumColumns); animationParams.row = animationParams.rowsCount - 1 - invertedIndex / mNumColumns; } }
然后就想到去RecyclerView中去找attachLayoutAnimationParameters()方法,但是没有,其父类ViewGroup里面有此方法:
protected void attachLayoutAnimationParameters(View child, LayoutParams params, int index, int count) { LayoutAnimationController.AnimationParameters animationParams = params.layoutAnimationParameters; if (animationParams == null) { animationParams = new LayoutAnimationController.AnimationParameters(); params.layoutAnimationParameters = animationParams; } animationParams.count = count; animationParams.index = index; }
由此可见RecyclerView默认实现了ViewGroup的LayoutAnimation。我们在RecyclerView中将此方法重写一下。不过要将mStackFromButtom参数的判断去掉。
public class GridRecyclerView extends RecyclerView { public GridRecyclerView(Context context) { super(context); } public GridRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); } public GridRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void setAdapter(Adapter adapter) { super.setAdapter(adapter); } @Override public void setLayoutManager(LayoutManager layout) { if (layout instanceof GridLayoutManager) { super.setLayoutManager(layout); } else { throw new ClassCastException("you should only use the GridLayoutManager as LayoutManager when you use this " + this.getClass().getSimpleName() + " class"); } } @Override protected void attachLayoutAnimationParameters(View child, ViewGroup.LayoutParams params, int index, int count) { if (getLayoutManager() != null && getLayoutManager() instanceof GridLayoutManager) { GridLayoutAnimationController.AnimationParameters animationParams = (GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters; if (animationParams == null) { animationParams = new GridLayoutAnimationController.AnimationParameters(); params.layoutAnimationParameters = animationParams; } int mNumColumns = ((GridLayoutManager) getLayoutManager()).getSpanCount(); animationParams.count = count; animationParams.index = index; animationParams.columnsCount = mNumColumns; animationParams.rowsCount = count / mNumColumns; final int invertedIndex = count - 1 - index; animationParams.column = mNumColumns - 1 - (invertedIndex % mNumColumns); animationParams.row = animationParams.rowsCount - 1 - invertedIndex / mNumColumns; } else { super.attachLayoutAnimationParameters(child, params, index, count); } }}
当我们使用GridLayoutManager的时候,不能使用此属性。
/** * stackFromEnd is not supported by GridLayoutManager. Consider using * {@link #setReverseLayout(boolean)}. */ @Override public void setStackFromEnd(boolean stackFromEnd) { if (stackFromEnd) { throw new UnsupportedOperationException( "GridLayoutManager does not support stack from end." + " Consider using reverse layout"); } super.setStackFromEnd(false); }
此篇blog到此结束~
感谢大家支持!如有错误,请指出~
谢谢~
参考:
http://developer.android.com/intl/zh-cn/guide/topics/graphics/view-animation.html
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0619/3090.html
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0915/3462.html?utm_source=tuicool&utm_medium=referral

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Cache kemas kini laman web akaun rasmi, perkara ini mudah dan mudah, dan ia cukup rumit untuk minum periuknya. Anda bekerja keras untuk mengemas kini artikel akaun rasmi, tetapi pengguna masih membuka versi lama. Dalam artikel ini, mari kita lihat kelainan dan bertukar di belakang ini dan bagaimana menyelesaikan masalah ini dengan anggun. Selepas membacanya, anda boleh dengan mudah menangani pelbagai masalah caching, yang membolehkan pengguna anda sentiasa mengalami kandungan segar. Mari kita bincangkan asas -asas terlebih dahulu. Untuk meletakkannya secara terang -terangan, untuk meningkatkan kelajuan akses, penyemak imbas atau pelayan menyimpan beberapa sumber statik (seperti gambar, CSS, JS) atau kandungan halaman. Kali seterusnya anda mengaksesnya, anda boleh mengambilnya secara langsung dari cache tanpa perlu memuat turunnya lagi, dan ia secara semula jadi cepat. Tetapi perkara ini juga pedang bermata dua. Versi baru dalam talian,

Artikel ini menunjukkan penambahan sempadan PNG yang cekap ke halaman web menggunakan CSS. Ia berpendapat bahawa CSS menawarkan prestasi unggul berbanding dengan JavaScript atau perpustakaan, memperincikan cara menyesuaikan lebar sempadan, gaya, dan warna untuk kesan halus atau menonjol

Artikel ini membincangkan menggunakan atribut pengesahan bentuk HTML5 seperti had, corak, min, max, dan panjang untuk mengesahkan input pengguna secara langsung dalam penyemak imbas.

Artikel membincangkan amalan terbaik untuk memastikan keserasian silang pelayar HTML5, memberi tumpuan kepada pengesanan ciri, peningkatan progresif, dan kaedah ujian.

Artikel ini membincangkan html & lt; datalist & gt; elemen, yang meningkatkan bentuk dengan menyediakan cadangan autokomplete, meningkatkan pengalaman pengguna dan mengurangkan kesilapan. Kira -kira: 159

Artikel ini membincangkan html & lt; meter & gt; elemen, digunakan untuk memaparkan nilai skalar atau pecahan dalam julat, dan aplikasi umum dalam pembangunan web. Ia membezakan & lt; meter & gt; dari & lt; kemajuan & gt; dan Ex

Artikel ini membincangkan html & lt; kemajuan & gt; elemen, tujuan, gaya, dan perbezaan dari & lt; meter & gt; elemen. Tumpuan utama adalah menggunakan & lt; kemajuan & gt; untuk menyelesaikan tugas dan & lt; meter & gt; untuk stati

Artikel ini menerangkan html5 & lt; time & gt; elemen untuk perwakilan tarikh/masa semantik. Ia menekankan pentingnya atribut DateTime untuk pembacaan mesin (format ISO 8601) bersama teks yang boleh dibaca manusia, meningkatkan aksesibilit
