鴻蒙開源第三方組件——連續滾動圖像組件
前言
基于安卓平臺的連續滾動圖像組件ContinuousScrollableImageView(https://github.com/Cutta/ContinuousScrollableImageView),實現了鴻蒙化遷移和重構,代碼已經開源到(https://gitee.com/isrc_ohos/continuous-scrollable-image-view_ohos),歡迎各位開發者下載使用并提出寶貴意見!
背景
ContinuousScrollableImageView_ohos組件通過讓圖像連續滾動,來實現動畫效果。組件支持對圖像的滾動效果進行設置,包括:圖像源、縮放類型、持續時間和方向等。該組件提供動態的視覺效果,可以用來開發應用的背景等。
組件效果展示
ContinuousScrollableImageView_ohos組件庫中設置了飛機、云、山三種圖像:飛機的滾動方向設置為“RIGHT”,向右側滾動;云和山的滾動方向設置為“LEFT”,向左滾動。三者組合成一幅完整的、具有連續滾動效果的動畫圖像,如圖1所示。
圖1 ContinuousScrollableImageView_ohos組件運行效果圖
Sample解析
Sample部分主要負責搭建整體的顯示布局,并實例化飛機、云、山三種圖像的對象。通過調用Library提供的接口,對三個對象的滾動效果進行屬性設置。想要實現圖1所示的動畫效果,需要以下3個步驟:
步驟1. 導入ContinuousScrollableImageView類。
步驟2. 實例化類對象并設置各個對象的屬性。
步驟3. 將對象添加到整體顯示布局中。
下面我們來看一下每個步驟涉及的詳細操作。
1、導入ContinuousScrollableImageView類
- import com.cunoraz.continuousscrollable.ContinuousScrollableImageView;
2、實例化類對象并設置各個對象的屬性
圖1中的動畫效果需要實例化3個ContinuousScrollableImageView對象分別代指包含飛機、云、山三種圖像。
設置各對象屬性的方式有兩種:常用方式和Builder方式。常用方式是指通過對象單獨調用類接口的方式;Builder方式即建造者模式。用戶可根據個人需要,自行確定使用哪種方式設置對象屬性。此處為了證明兩種方式的有效性,飛機和云圖像采用常用方式設置屬性,山圖像采用Builder方式設置屬性。 ContinuousScrollableImageView對象的可設置屬性有4個,包括:滾動方向、滾動周期、縮放類型、圖像源。
(1)實例化飛機圖像的對象并進行屬性設置
- // 實例化對象
- ContinuousScrollableImageView plane=new ContinuousScrollableImageView(this);
- // 采用常用方式進行屬性設置
- LayoutConfig planeConfig=new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,0,LayoutConfig.UNSPECIFIED_ALIGNMENT,1);
- plane.setLayoutConfig(planeConfig);
- plane.setDirection(ContinuousScrollableImageView.RIGHT); //設置滾動方向向右
- plane.setDuration(2500); //設置滾動周期
- plane.setScaleType(ContinuousScrollableImageView.CENTER_INSIDE); //設置縮放類型
- plane.setResourceId(ResourceTable.Media_plane); // 設置圖像源
(2)實例化云圖像的對象并進行屬性設置
- // 實例化對象
- ContinuousScrollableImageView cloud=new ContinuousScrollableImageView(this);
- // 采用常用方法進行屬性設置
- LayoutConfig cloudConfig=new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,0,LayoutConfig.UNSPECIFIED_ALIGNMENT,1);
- cloud.setLayoutConfig(cloudConfig);
- cloud.setDirection(ContinuousScrollableImageView.LEFT); //設置滾動方向向左
- cloud.setDuration(4000); //設置滾動周期
- cloud.setResourceId(ResourceTable.Media_cloud); //設置圖像源
(3)實例化山圖像的對象并進行屬性設置
- LayoutConfig mountainConfig=new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,0,LayoutConfig.UNSPECIFIED_ALIGNMENT,1);
- //采用Builder方式進行對象創建和屬性設置
- ContinuousScrollableImageView mountain=new ContinuousScrollableImageView.Builder(this.getAbility())
- .setDirection(ContinuousScrollableImageView.LEFT) //設置方向向左
- .setDuration(6000) //設置時間間隔
- .setResourceId(ResourceTable.Media_mountain) //設置圖像源
- .build();
- mountain.setLayoutConfig(mountainConfig);
3、對象添加到整體顯示布局中
- layout.addComponent(cloud); //飛機對象添加到布局
- layout.addComponent(mountain); //云對象添加到布局
- layout.addComponent(mountain); //山對象添加到布局
Library解析
Library向開發者提供ContinuousScrollableImageView類對象的啟動接口和屬性設置接口。以圖1的效果為例,通過調用啟動接口,可以讓飛機、云和山對象開始滾動;通過調用屬性設置接口,可以改變上述對象的滾動效果。由Sample部分可知,ContinuousScrollableImageView類對象的屬性設置有兩種方式,本節將揭示,不同屬性設置方式下屬性設置接口的功能實現也存在差異。
1、ContinuousScrollableImageView類對象啟動接口
該接口的功能實現內容較多,但主要邏輯較為清晰,主要可以分為四個部分:設置布局、創建數值動畫、對不同的滾動方向設置監聽和啟動動畫。
(1)設置布局
圖2 兩個布局依次出現
如圖2所示,畫面中所有的ContinuousScrollableImageView類對象都需要具有循環滾動的效果,以飛機為例:飛機滾動至最右側時,逐漸顯示的部分需要在最左側重新出現。為此,設計了兩個布局:firstImage和secondImage,二者布局相同且循環顯示,其中一個布局顯示另一個布局消失的部分。
- private void setImages() {
- ......
- firstImage = (Image) this.findComponentById(ResourceTable.Id_first_image);
- secondImage = (Image) this.findComponentById(ResourceTable.Id_second_image);
- firstImage.setImageAndDecodeBounds(resourceId);
- secondImage.setImageAndDecodeBounds(resourceId);
- setScaleType(scaleType);
- }
(2)創建數值動畫
飛機、云和山都是靜態的,想讓實現滾動效果,需要借助動畫類。此處采用的是數值動畫的方式,來啟動各對象。同時還需要設置動畫的循環次數、線性變化、循環周期等屬性。
- animator.setLoopedCount(AnimatorValue.INFINITE); //動畫無限重復
- animator.setCurveType(Animator.CurveType.LINEAR); //動畫線性變化
- animator.setDuration(duration); //動畫的持續時間
(3)對不同的滾動方向設置監聽
飛機、云和山都可以設置不同的滾動方向,針對不同的方向設置不同的值動畫監聽,以飛機為例:當飛機橫向滾動時,通過設置firstImage和secondImage的橫坐標變化,達到二者循環顯示的目的。當飛機豎向滾動動,通過設置firstImage和secondImage的坐標變化,達到二者循環顯示的目的。
- switch (DEFAULT_ASYMPTOTE) {
- case HORIZONTAL: // 橫向滾動
- animator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() { //值動畫監聽
- @Override
- public void onUpdate(AnimatorValue animatorValue, float v) {
- // firstImage和secondImage循環顯示算法
- float progress;
- if (DIRECTION_MULTIPLIER == 1)
- progress = DIRECTION_MULTIPLIER * (v);
- else
- progress = DIRECTION_MULTIPLIER * (-v);
- float width = DIRECTION_MULTIPLIER * (-firstImage.getWidth());
- float translationX = width * progress;
- firstImage.setTranslationX(translationX); //設置firstImage的橫坐標
- secondImage.setTranslationX(translationX - width); //設置secondImage的橫坐標
- }
- });
- break;
- ......
(4)啟動動畫
動畫啟動后,飛機、云和山的坐標就會發生變化,此時他們的動畫效果就由靜態的變成滾動的。
- animator.start(); //動畫啟動
2、常用方式下屬性設置接口功能實現
飛機和云采用常用方式設置屬性,其屬性包含:滾動周期、滾動方向、圖像源、圖像縮放類型。各接口的功能實現較為簡單,值得注意的是,在滾動方向和滾動周期功能實現中分別調用了啟動接口,此處是為了適應下文即將指出的Builder方式,具體原因將在下文講述。若開發者只采用常用方式進行屬性設置,可以將啟動接口從滾動方向和滾動周期功能實現中分離出來,通過飛機或者云的對象單獨調用。
- //設置滾動周期
- public void setDuration(int duration) {
- this.duration = duration;
- isBuilt = false;
- build();
- }
- //設置方向
- public void setDirection(@Directions int direction) {
- this.direction = direction;
- isBuilt = false;
- setDirectionFlags(direction);
- build();
- }
- //設置圖像源
- public void setResourceId(int resourceId) {
- this.resourceId = resourceId;
- firstImage.setImageAndDecodeBounds(this.resourceId);
- secondImage.setImageAndDecodeBounds(this.resourceId);
- }
- //設置圖像縮放類型
- public void setScaleType(@ScaleType int scaleType) {
- if (firstImage == null || secondImage == null) {
- throw new NullPointerException();
- }
- Image.ScaleMode type = Image.ScaleMode.CENTER;
- switch (scaleType) {
- ···
- }
- this.scaleType = scaleType;
- firstImage.setScaleMode(type);
- secondImage.setScaleMode(type);
- }
3、Builder方式設置屬性
對山采用Builder方式進行屬性設置,各屬性在功能實現時分別調用了常用方式下的屬性設置接口,但是缺少啟動接口的調用。
為了在Builder方式下也能正常啟動動畫,常用方式下的滾動方向和滾動周期功能實現中包含了啟動接口,這樣當在Builder方式下調用上述接口時,就可以實現動畫的啟動。
- public static final class Builder {
- private ContinuousScrollableImageView scrollableImage;
- public Builder(Ability ability) {
- scrollableImage = new ContinuousScrollableImageView(ability);
- }
- //設置滾動周期
- public Builder setDuration(int duration) {
- scrollableImage.setDuration(duration);
- return this;
- }
- //設置圖像源
- public Builder setResourceId(int resourceId) {
- scrollableImage.setResourceId(resourceId);
- return this;
- }
- //設置滾動方向
- public Builder setDirection(@Directions int direction) {
- scrollableImage.setDirection(direction);
- return this;
- }
- //設置縮放類型
- public Builder setScaleType(@ScaleType int scaleType) {
- scrollableImage.setScaleType(scaleType);
- return this;
- }
- public ContinuousScrollableImageView build() {
- return scrollableImage;
- }
- }
項目貢獻人
劉磊 鄭森文 朱偉 陳美汝 王佳思 張馨心