參考:
-
https://blog.csdn.net/harvic880925/article/details/50785786
非常感謝,
沒有自己的內(nèi)容,基本上轉(zhuǎn)自上面的博客,非常感謝!
LayoutAnimation
layoutAnimation和gridLayoutAnimation在API 1中就有的函數(shù)。所以他們也只能使用animtion來做動(dòng)畫,而不能使用animator。
layoutAnimation的xml實(shí)現(xiàn)
步驟:
- 在
anim文件夾下,定義layout_animation文件:
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@android:anim/slide_in_left"
android:animationOrder="normal"
android:delay="20" />
- 在ViewGroup類型控件中,配置
android:layoutAnimation,如:
你妹RecylcerView測試,設(shè)置標(biāo)簽無效;通過代碼并且要在設(shè)置后,馬上加載數(shù)據(jù)才有效果,這是什么鬼,真是太坑了;
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layoutAnimation="@anim/tween_layout"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
或通過代碼(設(shè)置后馬上加載數(shù)據(jù))設(shè)置
recycler.apply {
layoutManager = LinearLayoutManager(context)
addItemDecoration(DividerItemDecoration(context, LinearLayoutManager.VERTICAL))
// 設(shè)置無效
// layoutAnimation = AnimationUtils.loadLayoutAnimation(applicationContext, R.anim.tween_layout)
}
btn_start.setOnClickListener {
// 有效,設(shè)置后馬上加載數(shù)據(jù)
recycler.layoutAnimation = AnimationUtils.loadLayoutAnimation(applicationContext, R.anim.tween_layout)
adapter = Adapter(mutableListOf("java", "Android", "Python", "javascript"))
recycler.adapter = adapter
}
注意:
- RecyclerView設(shè)置layoutanimation時(shí)機(jī);
- android:layoutAnimation只在viewGroup創(chuàng)建的時(shí)候,才會(huì)對(duì)其中的item添加動(dòng)畫。在創(chuàng)建成功以后,再向其中添加item將不會(huì)再有動(dòng)畫。
如:
operator fun plus(item: String) {
data += item
notifyItemInserted(data.size - 1)
}
// 調(diào)用
adapter + "Better${Random().nextInt(10)}"
layoutAnimation字段說明
- delay:指每個(gè)Item的動(dòng)畫開始延時(shí),取值是android:animation所指定動(dòng)畫時(shí)長的倍數(shù),默認(rèn)為0.5
- animationOrder: 指viewGroup中的控件動(dòng)畫開始順序,取值有normal(正序)、reverse(倒序)、random(隨機(jī))
- animation:指定每個(gè)item入場所要應(yīng)用的動(dòng)畫;(只能是anim資源文件夾下的動(dòng)畫資源)
layoutAnimation的代碼實(shí)現(xiàn)
xml中l(wèi)ayoutAnimation標(biāo)簽所對(duì)應(yīng)的類為LayoutAnimationController,構(gòu)造如下:
public LayoutAnimationController(Animation animation)
public LayoutAnimationController(Animation animation, float delay)
animation對(duì)應(yīng)xml中的android:animation屬性,delay 為 android:delay屬性;
API方法,參考原博客:
具體例子:
btn_bycode.setOnClickListener {
val anim = AnimationUtils.loadAnimation(baseContext, android.R.anim.slide_in_left)
recycler.layoutAnimation = LayoutAnimationController(anim).apply {
delay = 0.3f
order = LayoutAnimationController.ORDER_REVERSE
}
adapter = Adapter(mutableListOf("java", "Android", "Python", "javascript"))
recycler.adapter = adapter
}
GridLayoutAnimation
android gridview 首次加載數(shù)據(jù)時(shí),各子控件item的過渡動(dòng)畫;GridlayoutAnimation,僅能用于 android 原生控件 GridView;
略,后門專門來弄一個(gè)RecyclerView;
animateLayoutChanges與LayoutTransition
在API 11之后,Android為了支持ViewGroup類控件,在添加和移除其中控件時(shí)自動(dòng)添加動(dòng)畫,為我們提供了一個(gè)非常簡單的屬性:android:animateLayoutChanges=[true/false],所有派生自ViewGroup的控件都具有此屬性,只要在XML中添加上這個(gè)屬性,就能實(shí)現(xiàn)添加/刪除其中控件時(shí),帶有默認(rèn)動(dòng)畫了。
注意:默認(rèn) layoutAnimation動(dòng)畫只是對(duì)首次加載數(shù)據(jù)有效;
android:animateLayoutChanges屬性
通過給容器添加 android:animateLayoutChanges 并設(shè)置為true, 在添加或刪除控件時(shí),就有了自帶動(dòng)畫效果了,默認(rèn)是一個(gè)漸變的動(dòng)畫;
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="horizontal"
android:animateLayoutChanges="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
</LinearLayout>
LayoutTransition
android:animateLayoutChanges默認(rèn)是一個(gè)漸變動(dòng)畫,無法自定義;如果我們想改變這個(gè)默認(rèn)動(dòng)畫效果,需要使用到 LayoutTransition,這也是從API 11 開始支持的;
使用LayoutTransition步驟:
- 創(chuàng)建實(shí)例;
- 創(chuàng)建動(dòng)畫并設(shè)置:
- 將LayoutTransaction設(shè)置進(jìn)ViewGroup
不知道怎么回事,使用kotlin來編寫時(shí),總是報(bào)錯(cuò),Java代碼正常:
btn_layout_transition.setOnClickListener {
val transition = LayoutTransition()
val objAnimator = ObjectAnimator.ofFloat(container, "rotation", 0f, -90f, 90f, 0f)
transition.setAnimator(LayoutTransition.APPEARING, objAnimator)
container.layoutTransition = transition
}
報(bào)錯(cuò)為:
layoutTransition 為 Unresolved reference: setLayoutTransition
以后解決了,再來更新;
Java 代碼實(shí)現(xiàn):
// 1.創(chuàng)建實(shí)例
LayoutTransition transition = new LayoutTransition();
// 2. 創(chuàng)建動(dòng)畫并設(shè)置, 這里為添加子view時(shí),動(dòng)畫
transition.setAnimator(LayoutTransition.APPEARING,
ObjectAnimator.ofFloat(null, "rotation", 0f, -90f, 90f, 0f));
// 3. 將LayoutTransaction設(shè)置進(jìn)ViewGroup
container.setLayoutTransition(transition);
// 這樣添加時(shí),子 view 會(huì)有動(dòng)畫了
container.addView(getCustomView());
LayoutTransition.setAnimator 函數(shù)
public void setAnimator(int transitionType, Animator animator)
參數(shù)說明:
- transitionType 表示當(dāng)前應(yīng)用動(dòng)畫的對(duì)象范圍,取值有:
- APPEARING —— 元素在容器中出現(xiàn)時(shí)所定義的動(dòng)畫。
- DISAPPEARING —— 元素在容器中消失時(shí)所定義的動(dòng)畫。
- CHANGE_APPEARING —— 由于容器中要顯現(xiàn)一個(gè)新的元素,其它需要變化的元素所應(yīng)用的動(dòng)畫
- CHANGE_DISAPPEARING —— 當(dāng)容器中某個(gè)元素消失,其它需要變化的元素所應(yīng)用的動(dòng)畫
- animator 即響應(yīng)的屬性動(dòng)畫;
LayoutTransition.APPEARING與LayoutTransition.DISAPPEARING
表示入場動(dòng)畫,與出場動(dòng)畫
// LayoutTransition.APPEARING,入場
LayoutTransition transition = new LayoutTransition();
transition.setAnimator(LayoutTransition.APPEARING,
ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1.0f, 0.8f, 1.0f));
// LayoutTransition.DISAPPEARING,出場
transition.setAnimator(LayoutTransition.DISAPPEARING,
ObjectAnimator.ofFloat(null, "rotationX", 0f, 90f));
// 設(shè)置給ViewGroup
container.setLayoutTransition(transition);
CHANGE_APPEARING與CHANGE_DISAPPEARING
CHANGE_APPEARING的使用
在添加控件時(shí),除了被添加控件本身的入場動(dòng)畫以外,其它需要移動(dòng)位置的控件,在移動(dòng)位置時(shí),也被添加上了動(dòng)畫(left點(diǎn)位移動(dòng)畫),這些除了被添加控件以外的其它需要移動(dòng)位置的控件組合,所對(duì)應(yīng)的動(dòng)畫就是LayoutTransition.CHANGE_APPEARING
// 添加元素調(diào)用addView()方法時(shí),index之后的元素才有動(dòng)畫
// 必須的left,top
PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 100, 0);
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 1, 1);
transition.setAnimator(LayoutTransition.CHANGE_APPEARING,
ObjectAnimator.ofPropertyValuesHolder(container, pvhLeft,pvhTop));
container.setLayoutTransition(transition);
container.addView(getCustomView(), 0); // 0 之后的所有元素都有動(dòng)畫
注意的地方:
- LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING必須使用PropertyValuesHolder所構(gòu)造的動(dòng)畫才會(huì)有效果,不然無效!
- 在構(gòu)造PropertyValuesHolder動(dòng)畫時(shí),”left”、”top”屬性的變動(dòng)是必寫的。如果不需要變動(dòng),則直接寫為:
PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",0,0);
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top",0,0);
- 在構(gòu)造PropertyValuesHolder時(shí),所使用的ofInt,ofFloat中的參數(shù)值,第一個(gè)值和最后一個(gè)值必須相同,不然此屬性所對(duì)應(yīng)的的動(dòng)畫將被放棄,在此屬性值上將不會(huì)有效果;
// 第一個(gè)value與最后一個(gè)value必須相等
PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",0,100,0);
4.在構(gòu)造PropertyValuesHolder時(shí),所使用的ofInt,ofFloat中,如果所有參數(shù)值都相同,也將不會(huì)有動(dòng)畫效果;
// 動(dòng)畫無效
PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",100,100);
CHANGE_DISAPPEARING的使用
PropertyValuesHolder outLeft = PropertyValuesHolder.ofInt("left", 0, 0);
PropertyValuesHolder outTop = PropertyValuesHolder.ofInt("top", 0, 0);
PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat("rotationY", 0f, 90f, 0f);
transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,
ObjectAnimator.ofPropertyValuesHolder(container, outLeft, outTop, rotation));
if(container.getChildCount() > 0) {
container.removeViewAt(0);
}
坑真多,不用為妙
LayoutTransition其他函數(shù)
/**
* 設(shè)置所有動(dòng)畫完成所需要的時(shí)長
*/
public void setDuration(long duration)
/**
* 針對(duì)單個(gè)type,設(shè)置動(dòng)畫時(shí)長;
* transitionType取值為:APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING
*/
public void setDuration(int transitionType, long duration)
/**
* 針對(duì)單個(gè)type設(shè)置插值器
* transitionType取值為:APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING
*/
public void setInterpolator(int transitionType, TimeInterpolator interpolator)
/**
* 針對(duì)單個(gè)type設(shè)置動(dòng)畫延時(shí)
* transitionType取值為:APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING
*/
public void setStartDelay(int transitionType, long delay)
/**
* 針對(duì)單個(gè)type設(shè)置,每個(gè)子item動(dòng)畫的時(shí)間間隔
*/
public void setStagger(int transitionType, long duration)
setStagger
//設(shè)置單個(gè)item間的動(dòng)畫間隔
transition.setStagger(LayoutTransition.CHANGE_APPEARING, 100);
監(jiān)聽函數(shù)
在任何類型的LayoutTransition開始和結(jié)束時(shí),都會(huì)調(diào)用TransitionListener的startTransition和endTransition方法。
transition.addTransitionListener(new LayoutTransition.TransitionListener() {
public void startTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {}
public void endTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {}
});
參數(shù)說明:
- LayoutTransition transition:當(dāng)前的LayoutTransition實(shí)例
- ViewGroup container:當(dāng)前應(yīng)用LayoutTransition的container
- View view:當(dāng)前在做動(dòng)畫的View對(duì)象
- int transitionType:當(dāng)前的LayoutTransition類型,取值有:APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING