HarmonyOS基礎(chǔ)之PageSlider和PageFlipper
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
前言
眾所周知,PageSlider是用于頁(yè)面之間切換的組件,它通過(guò)響應(yīng)滑動(dòng)事件完成頁(yè)面間的切換,而PageFlipper可能知道的人就比較少了,其實(shí)PageFlipper和PageSlider類似,都是視圖切換組件,它們都繼承自StackLayout,因此可以將多個(gè)component層疊在一起,每次只顯示一個(gè)組件,當(dāng)視圖從一個(gè)component切換到另一個(gè)component時(shí),PageFlipper支持指定動(dòng)畫(huà)效果。
區(qū)別:PageFlipper通過(guò)addComponent()添加component,可使用動(dòng)畫(huà)控制多個(gè)component之間的切換效果,是個(gè)輕量級(jí)的組件,適合展示少量靜態(tài)數(shù)據(jù);而PageSlide是由provider來(lái)提供component的,更適用復(fù)雜的視圖切換,實(shí)現(xiàn)數(shù)據(jù)的動(dòng)態(tài)加載。
下面是一個(gè)PageSlider和PageFlipper結(jié)合起來(lái)的使用效果,頁(yè)面中間的卡片使用的是PageSlider,背景圖片和底部的數(shù)字指示器用的是PageFlipper,通過(guò)回調(diào)將三個(gè)組件聯(lián)動(dòng)起來(lái)就實(shí)現(xiàn)了這樣的效果:

正文
1.pageSlider
PageSlider可以說(shuō)是鴻蒙中最常用的視圖切換組件了,使用方法不用多做介紹,官方文檔有詳細(xì)的說(shuō)明,這里主要說(shuō)一下一個(gè)特殊的效果。
一屏多頁(yè)效果
其實(shí)鴻蒙本身有提供一個(gè)setClipEnabled()的方法,作用是設(shè)置是否允許在組件超出其父布局時(shí)自動(dòng)裁剪組件,理論上通過(guò)給pageSlider父布局設(shè)置setClipEnabled(false),加上給子組件設(shè)置合適的寬度可以實(shí)現(xiàn)一屏多頁(yè)效果,但是經(jīng)過(guò)測(cè)試并沒(méi)達(dá)到效果,這個(gè)方法我也單獨(dú)拿出來(lái)在其他場(chǎng)景驗(yàn)證過(guò)確實(shí)無(wú)效,下面是驗(yàn)證的效果。

但是鴻蒙卻提供了另外一個(gè)方法setPageMargin(),它的作用是設(shè)置PageSlider中子組件邊距的,當(dāng)傳入一個(gè)合適的負(fù)數(shù)時(shí)(必須是負(fù)數(shù)),就能實(shí)現(xiàn)一屏同時(shí)顯示多個(gè)子組件的效果:

動(dòng)態(tài)設(shè)置縮放透明度變化
設(shè)置透明度和縮放比例就不細(xì)說(shuō)了,主要就是在PageSlider子組件加載完成后和頁(yè)面切換中的回調(diào)方法中改變alpha值和scale值,直接上代碼:
- public final class AlphaScalePageTransformer {
- /**
- * 縮放
- */
- public static final float INACTIVE_SCALE = 0.8f;
- /**
- * 透明度
- */
- public static final float INACTIVE_ALPHA = 0.5f;
- /**
- * 設(shè)置初始狀態(tài)的縮放和透明度
- *
- * @param child
- * @param position
- * @param current
- */
- public static void defaultPage(ListContainer child, int position, float current) {
- if (position != current) {
- child.setAlpha(INACTIVE_ALPHA);
- child.setScaleX(INACTIVE_SCALE);
- child.setScaleY(INACTIVE_SCALE);
- }
- }
- /**
- * 設(shè)置滑動(dòng)中的縮放和透明度
- *
- * @param childList
- * @param position
- * @param offset
- * @param direction
- */
- public static void transformPage(List<ListContainer> childList, int position, float offset, float direction) {
- Component child = childList.get(position);
- float scale = INACTIVE_SCALE + (1 - INACTIVE_SCALE) * (1 - Math.abs(offset));
- float alpha = INACTIVE_ALPHA + (1 - INACTIVE_ALPHA) * (1 - Math.abs(offset));
- child.setScaleX(scale);
- child.setScaleY(scale);
- child.setAlpha(alpha);
- if (direction > 0) {
- if (position < childList.size() - 1) {
- child = childList.get(position + 1);
- }
- } else {
- if (position >= 1) {
- child = childList.get(position - 1);
- }
- }
- scale = INACTIVE_SCALE + (1 - INACTIVE_SCALE) * Math.abs(offset);
- alpha = INACTIVE_ALPHA + (1 - INACTIVE_ALPHA) * Math.abs(offset);
- child.setScaleX(scale);
- child.setScaleY(scale);
- child.setAlpha(alpha);
- }
- }
設(shè)置兩邊的component透明度和縮放效果:
- //設(shè)置初始狀態(tài)縮放和透明度
- AlphaScalePageTransformer.defaultPage(image, i, pageSlider.getCurrentPage());
- //設(shè)置頁(yè)面切換中縮放和透明度
- pageSlider.addPageChangedListener(new PageChangedListener() {
- @Override
- public void onPageSliding(int position, float positionOffset, int positionOffsetPixels) {
- AlphaScalePageTransformer.transformPage(listContainers, position,
- positionOffset, positionOffsetPixels);
- }
- });
2.PageFlipper(翻頁(yè)器)
PageFlipper是一個(gè)翻頁(yè)器,當(dāng)它有兩個(gè)或多個(gè)子組件時(shí),切換過(guò)程中可以輕松設(shè)置入場(chǎng)動(dòng)畫(huà)和出場(chǎng)動(dòng)畫(huà),以達(dá)到意想不到的效果。雖然PageFlipper的使用率遠(yuǎn)不及PageSlider,但這并不意味著PageFlipper就不強(qiáng)大,他能通過(guò)簡(jiǎn)單的代碼實(shí)現(xiàn)許多動(dòng)畫(huà)效果,比如淘寶頭條的效果,日歷翻頁(yè)效果,背景圖淡入淡出效果等等。
常用方法:
- getCurrentComponent()//獲取當(dāng)前組件
- showNext():顯示下一個(gè)組件(如果當(dāng)前子組件是最后一個(gè),則顯示第一個(gè)子組件)
- showPrevious():顯示上一個(gè)組件(如果當(dāng)前子組件是第一個(gè),則顯示最后一個(gè)子組件)
- getFlipInterval() :獲取自動(dòng)翻轉(zhuǎn)時(shí)間
- setFlipPeriod(int period) :設(shè)置翻轉(zhuǎn)周期
- startFlipping() :開(kāi)啟自動(dòng)翻轉(zhuǎn)
- stopFlipping() :停止自動(dòng)翻轉(zhuǎn)
- addComponent() :添加組件
- setIncomingAnimationA() :設(shè)置轉(zhuǎn)入動(dòng)畫(huà)
- setOutgoingAnimation() :設(shè)置轉(zhuǎn)出動(dòng)畫(huà)
下面通過(guò)設(shè)置文字翻頁(yè)效果來(lái)了解下它的使用方法:

- public class IndicatorComponent extends DirectionalLayout {
- /**
- * 文字大小
- */
- private static final int TEXT_SIZE = 130;
- /**
- * 動(dòng)畫(huà)時(shí)長(zhǎng)
- */
- private static final int DURATION = 600;
- private PageFlipper textSwitcher;
- private Text textcomponent;
- /**
- * ItemsCountcomponent
- *
- * @param context
- * @param attrSet
- */
- public IndicatorComponent(Context context, AttrSet attrSet) {
- super(context, attrSet);
- init(context);
- }
- private void init(Context context) {
- setOrientation(ComponentContainer.HORIZONTAL);
- textSwitcher = new PageFlipper(context);
- //理論上PageFlipper只需要添加兩個(gè)子component就能實(shí)現(xiàn)動(dòng)畫(huà)效果,但是實(shí)際測(cè)試發(fā)現(xiàn)如果切換速度太快就導(dǎo)致子組件銜接不上出現(xiàn)組件消失的額情況,
- //因此這里通過(guò)實(shí)踐多添加了幾個(gè)子component,防止滑動(dòng)過(guò)快出現(xiàn)bug
- textSwitcher.addComponent(createcomponentForTextSwitcher(context));
- textSwitcher.addComponent(createcomponentForTextSwitcher(context));
- textSwitcher.addComponent(createcomponentForTextSwitcher(context));
- textSwitcher.addComponent(createcomponentForTextSwitcher(context));
- addComponent(textSwitcher, new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT,
- ComponentContainer.LayoutConfig.MATCH_CONTENT));
- textcomponent = new Text(context);
- textcomponent.setTextSize(TEXT_SIZE);
- textcomponent.setFont(Font.DEFAULT_BOLD);
- textcomponent.setTextColor(new Color(Color.getIntColor("#8cffffff")));
- addComponent(textcomponent, new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT,
- ComponentContainer.LayoutConfig.MATCH_CONTENT));
- }
- /**
- * 創(chuàng)建組件
- *
- * @param context 上下文
- * @return text
- */
- private Text createcomponentForTextSwitcher(Context context) {
- Text text = new Text(context);
- text.setTextSize(TEXT_SIZE);
- text.setFont(Font.DEFAULT_BOLD);
- text.setTextColor(Color.WHITE);
- text.setLayoutConfig(new PageFlipper.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT,
- PageFlipper.LayoutConfig.MATCH_CONTENT));
- return text;
- }
- /**
- * update
- *
- * @param newPosition 新位置
- * @param oldPosition 舊位置
- * @param totalElements 總數(shù)
- */
- public void update(int newPosition, int oldPosition, int totalElements) {
- textcomponent.setText(" / " + totalElements);
- int offset = textSwitcher.getHeight();
- if (newPosition > oldPosition) {
- //設(shè)置組件進(jìn)入和退出的動(dòng)畫(huà)
- textSwitcher.setIncomingAnimation(createPositionAnimation(-offset, 0, 0f, 1f, DURATION));
- textSwitcher.setOutgoingAnimation(createPositionAnimation(0, offset, 1f, 0f, DURATION));
- } else if (oldPosition > newPosition) {
- textSwitcher.setIncomingAnimation(createPositionAnimation(offset, 0, 0f, 1f, DURATION));
- textSwitcher.setOutgoingAnimation(createPositionAnimation(0, -offset, 1f, 0f, DURATION));
- }
- //顯示下一個(gè)組件并執(zhí)行動(dòng)畫(huà)
- textSwitcher.showNext();
- Text text = (Text) textSwitcher.getCurrentComponent();
- text.setText(String.valueOf(newPosition + 1));
- }
- /**
- * 創(chuàng)建屬性動(dòng)畫(huà)
- *
- * @param fromY
- * @param toY
- * @param fromAlpha
- * @param toAlpha
- * @param duration
- * @return
- */
- private AnimatorProperty createPositionAnimation(int fromY, int toY, float fromAlpha, float toAlpha, int duration) {
- AnimatorProperty animatorProperty = new AnimatorProperty();
- animatorProperty.setCurveType(Animator.CurveType.DECELERATE);
- animatorProperty.alphaFrom(fromAlpha);
- animatorProperty.alpha(toAlpha);
- animatorProperty.moveFromY(fromY);
- animatorProperty.moveToY(toY);
- animatorProperty.setDuration(duration);
- return animatorProperty;
- }
- }
結(jié)束
以上主要介紹了PageSlider和PageFlipper的一些簡(jiǎn)單使用,最后補(bǔ)充一個(gè)小功能,設(shè)置漸變效果,這個(gè)簡(jiǎn)單的效果可能很多人還不知道如何設(shè)置:
首先生成一個(gè)foreground_gradient.xml
- <shape
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:shape="rectangle">
- //設(shè)置填充的顏色,可以根據(jù)實(shí)際需要設(shè)置多個(gè)
- <solid
- ohos:colors="#000000,#00ffffff,#d8000000"/>
- //設(shè)置漸變方向,有三個(gè)值可供選擇:linear_gradient,radial_gradient,sweep_gradient
- <gradient
- ohos:shader_type="linear_gradient"
- />
- </shape>
然后給目標(biāo)組件設(shè)置前景色,即:
- ohos:foreground_element="$graphic:foreground_gradient"
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)