ConstraintLayout2.0一篇寫(xiě)不完之Carousel

點(diǎn)擊上方藍(lán)字關(guān)注我,知識(shí)會(huì)給你力量


?本文譯自 https://github.com/androidx/constraintlayout/wiki/Carousel
?
Carousel是一個(gè)Motion Helper,它可以輕松構(gòu)建自定義的Carousel視圖,顯示用戶可以瀏覽的元素列表。與實(shí)現(xiàn)此類(lèi)視圖的其他解決方案相比,Carousel可以利用MotionLayout迅速為輪播創(chuàng)建復(fù)雜的動(dòng)畫(huà)效果。
Carousel支持帶有開(kāi)始和結(jié)束的列表以及循環(huán)環(huán)繞列表。
概念:輪播如何MotionLayout工作
假設(shè)我們要構(gòu)建一個(gè)簡(jiǎn)單的水平輪播視圖,并放大一個(gè)居中視圖:

我們的基本布局包含幾個(gè)視圖,代表了我們的輪播項(xiàng)目:

通過(guò)MotionLayout創(chuàng)建具有三個(gè)狀態(tài)的ConstraintSet(請(qǐng)確保為它們提供ID):
previous
start
next
如果start狀態(tài)與該基本布局相對(duì)應(yīng),則previous的狀態(tài)則應(yīng)該表示為輪播項(xiàng)目向右移動(dòng)一個(gè)。
例如,假設(shè)我們有5個(gè)視圖:處于開(kāi)始狀態(tài)的A,B,C,D,E。
start時(shí),B,C,D可見(jiàn),而A和E在屏幕外。我們要設(shè)置previous的狀態(tài),以使A,B,C,D的位置現(xiàn)在位于B,C,D,E所在的位置,并且視圖從左向右移動(dòng)。
在next狀態(tài)中,需要相反的情況發(fā)生,與B,C,D,E移動(dòng)到其中A,B,C,D分別為和的觀點(diǎn)從從右向左移動(dòng)。

至關(guān)重要的是,start狀態(tài)必須恰好位于原始視圖的起始狀態(tài)。這種無(wú)限輪播的錯(cuò)覺(jué)的方式,實(shí)際上是將實(shí)際視圖移回它們的位置,然后使用新的匹配內(nèi)容將其重新初始化。下圖顯示了這種機(jī)制(請(qǐng)注意“ item?!敝担?/p>
轉(zhuǎn)場(chǎng)Transitions
在ConstraintSet中定義的這三個(gè)狀態(tài),在start和next,以及start和previous之間創(chuàng)建兩個(gè)Transitions:向前和向后。讓我們添加一個(gè)OnSwipe,以通過(guò)手勢(shì)觸發(fā)Transitions,例如:
<Transition
motion:constraintSetStart="@id/start"
motion:constraintSetEnd="@+id/next"
motion:duration="1000"
android:id="@+id/forward">
<OnSwipe
motion:dragDirection="dragLeft"
motion:touchAnchorSide="left" />
</Transition>
<Transition
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/previous"
android:id="@+id/backward">
<OnSwipe
motion:dragDirection="dragRight"
motion:touchAnchorSide="right" />
</Transition>
添加輪播
一旦創(chuàng)建了這個(gè)基本的Motion Scene,我們只需要在布局中添加一個(gè)Carousel Help并引用這些視圖即可(以實(shí)現(xiàn)上一個(gè)/下一個(gè)動(dòng)畫(huà)的順序)。
Carousel Helper還需要設(shè)置幾個(gè)屬性:
app:carousel_firstView:表示輪播的第一個(gè)元素的視圖,在我們的示例中為C,即首先展示默認(rèn)居中的視圖 app:carousel_previousState:ConstraintSet中previous狀態(tài)的ID app:carousel_nextState:ConstraintSet中next狀態(tài)的ID app:carousel_backwardTransition:Transition在start->previous之間應(yīng)用的ID app:carousel_forwardTransition:Transition在start->next之間應(yīng)用的ID
例如,您的布局XML文件中將包含以下內(nèi)容:
<androidx.constraintlayout.motion.widget.MotionLayout ... >
<ImageView android:id="@+id/imageView0" .. />
<ImageView android:id="@+id/imageView1" .. />
<ImageView android:id="@+id/imageView2" .. />
<ImageView android:id="@+id/imageView3" .. />
<ImageView android:id="@+id/imageView4" .. />
<androidx.constraintlayout.helper.widget.Carousel
android:id="@+id/carousel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:carousel_forwardTransition="@+id/forward"
app:carousel_backwardTransition="@+id/backward"
app:carousel_previousState="@+id/previous"
app:carousel_nextState="@+id/next"
app:carousel_infinite="true"
app:carousel_firstView="@+id/imageView2"
app:constraint_referenced_ids="imageView0,imageView1,imageView2,imageView3,imageView4" />
</androidx.constraintlayout.motion.widget.MotionLayout>
最后,我們還需要在代碼中設(shè)置一個(gè)Carousel適配器:
carousel.setAdapter(object : Carousel.Adapter {
override fun count(): Int {
// need to return the number of items we have in the carousel
}
override fun populate(view: View, index: Int) {
// need to implement this to populate the view at the given index
}
override fun onNewItem(index: Int) {
// called when an item is set
}
})
Additional
根據(jù)輪播中當(dāng)前選中的項(xiàng)目,你可能需要隱藏表示之前或之后的項(xiàng)目的視圖,以便正確考慮輪播的開(kāi)始和結(jié)束。Carousel Helper將自動(dòng)為您處理此問(wèn)題,默認(rèn)情況下會(huì)將這些視圖標(biāo)記為 View.INVISIBLE在那種情況下(這樣,整體布局不會(huì)改變)。
可以使用另一種模式,其中Carousel Helper將這些視圖標(biāo)記為View.GONE。可以使用以下屬性設(shè)置此模式:
app:carousel_emptyViewsBehavior="gone"向大家推薦下我的網(wǎng)站 https://xuyisheng.top/ 點(diǎn)擊原文一鍵直達(dá)
專(zhuān)注 Android-Kotlin-Flutter 歡迎大家訪問(wèn)
往期推薦
更文不易,點(diǎn)個(gè)“三連”支持一下??
