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

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

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

動態(tài)設(shè)置縮放透明度變化
設(shè)置透明度和縮放比例就不細(xì)說了,主要就是在PageSlider子組件加載完成后和頁面切換中的回調(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è)置滑動中的縮放和透明度
- *
- * @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è)置頁面切換中縮放和透明度
- pageSlider.addPageChangedListener(new PageChangedListener() {
- @Override
- public void onPageSliding(int position, float positionOffset, int positionOffsetPixels) {
- AlphaScalePageTransformer.transformPage(listContainers, position,
- positionOffset, positionOffsetPixels);
- }
- });
2.PageFlipper(翻頁器)
PageFlipper是一個翻頁器,當(dāng)它有兩個或多個子組件時,切換過程中可以輕松設(shè)置入場動畫和出場動畫,以達(dá)到意想不到的效果。雖然PageFlipper的使用率遠(yuǎn)不及PageSlider,但這并不意味著PageFlipper就不強(qiáng)大,他能通過簡單的代碼實現(xiàn)許多動畫效果,比如淘寶頭條的效果,日歷翻頁效果,背景圖淡入淡出效果等等。
常用方法:
- getCurrentComponent()//獲取當(dāng)前組件
- showNext():顯示下一個組件(如果當(dāng)前子組件是最后一個,則顯示第一個子組件)
- showPrevious():顯示上一個組件(如果當(dāng)前子組件是第一個,則顯示最后一個子組件)
- getFlipInterval() :獲取自動翻轉(zhuǎn)時間
- setFlipPeriod(int period) :設(shè)置翻轉(zhuǎn)周期
- startFlipping() :開啟自動翻轉(zhuǎn)
- stopFlipping() :停止自動翻轉(zhuǎn)
- addComponent() :添加組件
- setIncomingAnimationA() :設(shè)置轉(zhuǎn)入動畫
- setOutgoingAnimation() :設(shè)置轉(zhuǎn)出動畫
下面通過設(shè)置文字翻頁效果來了解下它的使用方法:

- public class IndicatorComponent extends DirectionalLayout {
- /**
- * 文字大小
- */
- private static final int TEXT_SIZE = 130;
- /**
- * 動畫時長
- */
- 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只需要添加兩個子component就能實現(xiàn)動畫效果,但是實際測試發(fā)現(xiàn)如果切換速度太快就導(dǎo)致子組件銜接不上出現(xiàn)組件消失的額情況,
- //因此這里通過實踐多添加了幾個子component,防止滑動過快出現(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)入和退出的動畫
- 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));
- }
- //顯示下一個組件并執(zhí)行動畫
- textSwitcher.showNext();
- Text text = (Text) textSwitcher.getCurrentComponent();
- text.setText(String.valueOf(newPosition + 1));
- }
- /**
- * 創(chuàng)建屬性動畫
- *
- * @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的一些簡單使用,最后補(bǔ)充一個小功能,設(shè)置漸變效果,這個簡單的效果可能很多人還不知道如何設(shè)置:
首先生成一個foreground_gradient.xml
- <shape
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:shape="rectangle">
- //設(shè)置填充的顏色,可以根據(jù)實際需要設(shè)置多個
- <solid
- ohos:colors="#000000,#00ffffff,#d8000000"/>
- //設(shè)置漸變方向,有三個值可供選擇:linear_gradient,radial_gradient,sweep_gradient
- <gradient
- ohos:shader_type="linear_gradient"
- />
- </shape>
然后給目標(biāo)組件設(shè)置前景色,即:
- ohos:foreground_element="$graphic:foreground_gradient"
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)