HarmonyOS应用开发--基于TabList和PageSlider的自制平行视界MyParallelView[我的平行视界][API V6]
HarmonyOS应用开发--基于TabList和PageSlider的自制平行视界MyParallelView[我的平行视界][API V6]
- 1. 名称
- 2. app实现关键技巧
- 3. 源代码
-
- 3.1 Java源代码
-
- 3.1.1 PSProvider.java
- 3.1.2 DetailSlice.java
- 3.1.3 MainAbilitySlice.java
- 3.1.4 MainAbility.java
- 3.1.5 MyApplication.java
- 3.2 XML源代码
-
- 3.2.1 UI背景XML
-
- 3.2.1.1 background_ability_main.xml
- 3.2.2 主页面与子布局XML
-
- 3.2.2.1 ability_main.xml
- 3.2.2.2 english_detailpage.xml
- 3.2.2.3 pageslider_page1.xml
- 3.2.2.4 pageslider_page2.xml
- 4.config.json
- 5.app图标(放在media文件夹中)
- 6.三个element文件夹中的json
-
- 6.3.1 element中的json
- 6.3.1 en.element中的json
- 6.3.1 zh.element中的json
- 7. app运行视频(远程模拟器运行)
1. 名称
本次项目将TabList和Tab用作PageSlider的页面指示器,并且通过判段屏幕是否横屏开启自制平行视界功能。
将本次项目命名为:我的平行视界,MyParallelView。
项目已经放在Gitee仓库中:MyParallelView
2. app实现关键技巧
- TabList和Tab是鸿蒙api提供的页签功能,即常见的类别标签选择功能。PageSlider是鸿蒙api提供的多页面切换功能组件。而本次项目,将TabList和Tab作为PageSlier的页面指示器。
- 即有:点击某个页签,则会切换至某个页面;滑动到某个页面,则会选中某个页签。
PageSlier每页显示不同组件内容----实现技巧:
- 第一种方法:首先写好几个需要的页面XML,使用动态装载XML的手段,然后将装载返回的DirectionalLayout变量按照页面顺序,放在ArrayList pageslist = new ArrayList()中,最后将此列表设置为Provider的数据源。
- 第二种方法:通过java代码创建相应的组件,将组件的布局容器放入pageslist列表中。
TabList与PageSlider双向指示----实现技巧:
- 给TabList设置一个addTabSelectedListener,当某个页签从未选中状态变换到选中状态时,使用tablist.getSelectedTabIndex()得到选中的是其第i个页签,然后通过pageslider.setCurrentPage(i)将对应的第i个页面设置为当前显示页面。【由TabList控制PageSlider】
- 给PageSlider设置一个addPageChangedListener,当某个页面处于选中时即处于当前显示状态,则使用tablist.selectTabAt(i)选中对应的页签。【由PageSlider控制TabList】
- 由上述的的两个单向控制组合,即可实现双向控制与指示!
自制平行视界----实现技巧:
- 将页面划分为左右两部分,其中右半部分的DirectionalLayout默认设置为HIDE,当PageSlider某个页面通过点击需要显示详情的时候,判断此时Ability是横屏还是竖屏,如果是横屏则使得右半部分的DirectionalLayout默认设置为VISIBLE,然后将详情页的XML动态的装载进去,当点击“取消”按钮时,则会将其移除且设置右半部分的DirectionalLayout默认设置为HIDE。
3. 源代码
3.1 Java源代码
3.1.1 PSProvider.java
package com.tdtxdcxm.myparallelview.provider;import ohos.agp.components.Component;import ohos.agp.components.ComponentContainer;import ohos.agp.components.DirectionalLayout;import ohos.agp.components.PageSliderProvider;import java.util.ArrayList;public class PSProvider extends PageSliderProvider { ArrayList<DirectionalLayout> pageslist = new ArrayList<>(); public PSProvider(ArrayList<DirectionalLayout> pageslist) { this.pageslist = pageslist; } @Override public int getCount() { return pageslist.size(); } @Override public Object createPageInContainer(ComponentContainer componentContainer, int i) { DirectionalLayout directionalLayout = pageslist.get(i); componentContainer.addComponent(directionalLayout); return directionalLayout; } @Override public void destroyPageFromContainer(ComponentContainer componentContainer, int i, Object o) { componentContainer.removeComponent((Component) o); } @Override public boolean isPageMatchToObject(Component component, Object o) { return true; }}
3.1.2 DetailSlice.java
package com.tdtxdcxm.myparallelview.slice;import com.tdtxdcxm.myparallelview.ResourceTable;import ohos.aafwk.ability.AbilitySlice;import ohos.aafwk.content.Intent;import ohos.agp.components.Button;import ohos.agp.components.Component;import ohos.agp.components.DirectionalLayout;import ohos.agp.components.webengine.WebAgent;import ohos.agp.components.webengine.WebView;public class DetailSlice extends AbilitySlice { private DirectionalLayout englishdetail_rootdl; private Button englishdetail_backbut; private WebView englishdetail_webview; public void initDetailSliceComponents(){ englishdetail_rootdl = (DirectionalLayout) findComponentById(ResourceTable.Id_englishdetail_rootdl); englishdetail_backbut = (Button) findComponentById(ResourceTable.Id_englishdetail_backbut); englishdetail_webview = (WebView) findComponentById(ResourceTable.Id_englishdetail_webview); englishdetail_backbut.setClickedListener(new Component.ClickedListener() { @Override public void onClick(Component component) { terminate(); } }); englishdetail_webview.getWebConfig().setJavaScriptPermit(true); englishdetail_webview.setWebAgent(new WebAgent()); englishdetail_webview.load("https:www.csdn.net/"); } @Override public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_english_detailpage); initDetailSliceComponents(); } @Override public void onActive() { super.onActive(); } @Override public void onInactive() { super.onInactive(); } @Override public void onForeground(Intent intent) { super.onForeground(intent); } @Override public void onBackground() { super.onBackground(); } @Override public void onStop() { super.onStop(); }}
3.1.3 MainAbilitySlice.java
package com.tdtxdcxm.myparallelview.slice;import com.tdtxdcxm.myparallelview.ResourceTable;import com.tdtxdcxm.myparallelview.provider.PSProvider;import ohos.aafwk.ability.AbilitySlice;import ohos.aafwk.content.Intent;import ohos.agp.components.*;import ohos.agp.components.webengine.WebAgent;import ohos.agp.components.webengine.WebView;import ohos.agp.utils.TextAlignment;import ohos.bundle.AbilityInfo;import java.util.ArrayList;public class MainAbilitySlice extends AbilitySlice { private DirectionalLayout main_one,main_two; private TabList main_one_tablist; private TabList.Tab tab1,tab2,tab3,tab4,tab5,tab6,tab7,tab8,tab9; private PageSlider main_one_pageslider; private ArrayList<DirectionalLayout> pageslist = new ArrayList<>(); private boolean islandscape = false; public void fillPagesList(){ pageslist.clear(); /**<********************************************加载已经的不同页面到pageslider中******************************************/ DirectionalLayout directionalLayout = (DirectionalLayout) LayoutScatter.getInstance(this.getContext()).parse(ResourceTable.Layout_pageslider_page1,null,false); pageslist.add(directionalLayout); directionalLayout = (DirectionalLayout) LayoutScatter.getInstance(this.getContext()).parse(ResourceTable.Layout_pageslider_page2,null,false); pageslist.add(directionalLayout); /***********************************************加载已经的不同页面到pageslider中**************************************>*/ /**<******************************************根据java代码创建页面到pageslider中****************************************/ directionalLayout = new DirectionalLayout(this); Text text = new Text(this.getContext()); text.setTextAlignment(TextAlignment.CENTER); text.setText("点我查看详细内容"+"\n"+"竖屏-跳Slice,横屏-平行视界"); text.setTextSize(70); text.setMultipleLine(true); text.setClickedListener(new Component.ClickedListener() { @Override public void onClick(Component component) { if(islandscape == true){ //如果此时是横屏状态,则详情内容打开在“自制平行视界”中 main_two.setVisibility(Component.VISIBLE); DirectionalLayout englishdetail_rootdl = (DirectionalLayout) LayoutScatter.getInstance(MainAbilitySlice.this.getContext()).parse(ResourceTable.Layout_english_detailpage,null,false); Button englishdetail_backbut = (Button) englishdetail_rootdl.findComponentById(ResourceTable.Id_englishdetail_backbut); WebView englishdetail_webview = (WebView) englishdetail_rootdl.findComponentById(ResourceTable.Id_englishdetail_webview); englishdetail_backbut.setClickedListener(new Component.ClickedListener() { @Override public void onClick(Component component) {main_two.removeComponentAt(0);main_two.setVisibility(Component.HIDE); } }); main_two.addComponent(englishdetail_rootdl); englishdetail_webview.getWebConfig().setJavaScriptPermit(true); englishdetail_webview.setWebAgent(new WebAgent()); englishdetail_webview.load("https:www.csdn.net/"); } else{ main_two.setVisibility(Component.HIDE); present(new DetailSlice(), new Intent()); } } }); directionalLayout.addComponent(text); pageslist.add(directionalLayout); /*********************************************根据java代码创建页面到pageslider中**************************************>*/ } public void initPageSlider(PageSlider pageslider){ if(pageslider == null){ return; } pageslider.setPageSwitchTime(50); pageslider.setSlidingPossible(true); pageslider.setReboundEffect(true); pageslider.addPageChangedListener(new PageSlider.PageChangedListener() { @Override public void onPageSliding(int i, float v, int i1) { } @Override public void onPageSlideStateChanged(int i) { } @Override public void onPageChosen(int i) { main_one_tablist.selectTabAt(i); } }); pageslider.setProvider(new PSProvider(pageslist)); } public void initTabList(TabList tablist){ if(tablist == null){ return; } tablist.addTabSelectedListener(new TabList.TabSelectedListener() { @Override public void onSelected(TabList.Tab tab) { int i = tablist.getSelectedTabIndex(); System.out.println("选中的TAB序号是:"+i); main_one_pageslider.setCurrentPage(i); } @Override public void onUnselected(TabList.Tab tab) { return; } @Override public void onReselected(TabList.Tab tab) { return; } }); tab1 = tablist.new Tab(this.getContext()); tab1.setText("语文"); tablist.addTab(tab1); tab2 = tablist.new Tab(this.getContext()); tab2.setText("数学"); tablist.addTab(tab2); tab3 = tablist.new Tab(this.getContext()); tab3.setText("英语"); tablist.addTab(tab3); tab4 = tablist.new Tab(this.getContext()); tab4.setText("物理"); tablist.addTab(tab4); tab5 = tablist.new Tab(this.getContext()); tab5.setText("化学"); tablist.addTab(tab5); tab6 = tablist.new Tab(this.getContext()); tab6.setText("生物"); tablist.addTab(tab6); tab7 = tablist.new Tab(this.getContext()); tab7.setText("地理"); tablist.addTab(tab7); tab8 = tablist.new Tab(this.getContext()); tab8.setText("历史"); tablist.addTab(tab8); tab9 = tablist.new Tab(this.getContext()); tab9.setText("政治"); tablist.addTab(tab9); tablist.selectTabAt(0); } public void initMASliceComponents(){ main_one = (DirectionalLayout) findComponentById(ResourceTable.Id_main_one); main_two = (DirectionalLayout) findComponentById(ResourceTable.Id_main_two); main_one_tablist = (TabList) findComponentById(ResourceTable.Id_main_one_tablist); main_one_pageslider = (PageSlider) findComponentById(ResourceTable.Id_main_one_pageslider); } @Override protected void onOrientationChanged(AbilityInfo.DisplayOrientation displayOrientation) { System.out.println(displayOrientation); if(displayOrientation == AbilityInfo.DisplayOrientation.LANDSCAPE){ islandscape = true; } else{ islandscape = false; if(main_two.getComponentAt(0) != null){ main_two.removeComponentAt(0); } main_two.setVisibility(Component.HIDE); } } @Override public void onStart(Intent intent) { super.onStart(intent); super.setUIContent(ResourceTable.Layout_ability_main); initMASliceComponents(); initTabList(main_one_tablist); fillPagesList(); initPageSlider(main_one_pageslider); } @Override public void onActive() { super.onActive(); } @Override public void onInactive() { super.onInactive(); } @Override public void onForeground(Intent intent) { super.onForeground(intent); } @Override public void onBackground() { super.onBackground(); } @Override public void onStop() { super.onStop(); }}
3.1.4 MainAbility.java
package com.tdtxdcxm.myparallelview;import com.tdtxdcxm.myparallelview.slice.MainAbilitySlice;import ohos.aafwk.ability.Ability;import ohos.aafwk.content.Intent;public class MainAbility extends Ability { @Override public void onStart(Intent intent) { super.onStart(intent); super.setMainRoute(MainAbilitySlice.class.getName()); }}
3.1.5 MyApplication.java
package com.tdtxdcxm.myparallelview;import ohos.aafwk.ability.AbilityPackage;public class MyApplication extends AbilityPackage { @Override public void onInitialize() { super.onInitialize(); }}
3.2 XML源代码
3.2.1 UI背景XML
3.2.1.1 background_ability_main.xml
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:shape="rectangle"> <solid ohos:color="#FFFFFF"/></shape>
3.2.2 主页面与子布局XML
3.2.2.1 ability_main.xml
<DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:id="$+id:main" ohos:height="match_parent" ohos:width="match_parent" ohos:alignment="vertical_center" ohos:orientation="horizontal"> <DirectionalLayout ohos:id="$+id:main_one" ohos:height="match_parent" ohos:width="0" ohos:weight="1" ohos:alignment="horizontal_center" ohos:orientation="vertical"> <TabList ohos:id="$+id:main_one_tablist" ohos:height="0" ohos:weight="1" ohos:width="match_parent" ohos:tab_margin="3vp" ohos:normal_text_color="#FFD9CCBE" ohos:selected_text_color="#FFAC56B5" ohos:tab_indicator_type="bottom_line" ohos:selected_tab_indicator_color="#FF348998" ohos:selected_tab_indicator_height="3vp" ohos:text_size="26vp" ohos:text_alignment="center" ohos:orientation="horizontal" ohos:background_element="#FFF8F6F3"> </TabList> <PageSlider ohos:id="$+id:main_one_pageslider" ohos:height="0" ohos:weight="9" ohos:width="match_parent" ohos:orientation="horizontal" ohos:page_cache_size="4" ohos:background_element="#FFF7FAF3"> </PageSlider> </DirectionalLayout> <DirectionalLayout ohos:id="$+id:main_two" ohos:height="match_parent" ohos:width="0" ohos:weight="1" ohos:visibility="hide" ohos:alignment="horizontal_center" ohos:orientation="vertical"> </DirectionalLayout></DirectionalLayout>
3.2.2.2 english_detailpage.xml
<DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:id="$+id:englishdetail_rootdl" ohos:height="match_parent" ohos:width="match_parent" ohos:orientation="vertical"> <Button ohos:id="$+id:englishdetail_backbut" ohos:height="40vp" ohos:width="match_parent" ohos:top_margin="10vp" ohos:text="取消" ohos:text_color="red" ohos:text_size="20vp" ohos:text_alignment="center" ohos:background_element="#FFD4FFF3"> </Button> <ohos.agp.components.webengine.WebView ohos:id="$+id:englishdetail_webview" ohos:height="match_parent" ohos:width="match_parent"> </ohos.agp.components.webengine.WebView></DirectionalLayout>
3.2.2.3 pageslider_page1.xml
<DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:id="$+id:page1" ohos:height="match_parent" ohos:width="match_parent" ohos:alignment="vertical_center" ohos:orientation="horizontal"> <TextField ohos:height="match_parent" ohos:width="match_parent" ohos:hint="请输入【语文】—最多10行..." ohos:hint_color="#FFBAADAD" ohos:multiple_lines="true" ohos:max_text_lines="10" ohos:text_size="25vp" ohos:text_alignment="start"> </TextField></DirectionalLayout>
3.2.2.4 pageslider_page2.xml
<DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:id="$+id:page2" ohos:height="match_parent" ohos:width="match_parent" ohos:alignment="vertical_center" ohos:orientation="horizontal"> <Image ohos:height="match_parent" ohos:width="match_parent" ohos:image_src="$media:icon"> </Image></DirectionalLayout>
4.config.json
{ "app": { "bundleName": "com.tdtxdcxm.myparallelview", "vendor": "tdtxdcxm", "version": { "code": 1000000, "name": "1.0.0" } }, "deviceConfig": { "default": { "network": { "cleartextTraffic": true } } }, "module": { "package": "com.tdtxdcxm.myparallelview", "name": ".MyApplication", "mainAbility": "com.tdtxdcxm.myparallelview.MainAbility", "deviceType": [ "phone", "tablet" ], "distro": { "deliveryWithInstall": true, "moduleName": "entry", "moduleType": "entry", "installationFree": false }, "abilities": [ { "skills": [ { "entities": ["entity.system.home" ], "actions": ["action.system.home" ] } ], "configChanges":["orientation"], "orientation": "unspecified", "visible": true, "name": "com.tdtxdcxm.myparallelview.MainAbility", "icon": "$media:myparallelview", "description": "$string:mainability_description", "label": "$string:entry_MainAbility", "type": "page", "launchType": "standard" } ], "reqPermissions": [ { "name": "ohos.permission.GET_NETWORK_INFO" }, { "name": "ohos.permission.INTERNET" }, { "name": "ohos.permission.SET_NETWORK_INFO" }, { "name": "ohos.permission.MANAGE_WIFI_CONNECTION" }, { "name": "ohos.permission.SET_WIFI_INFO" }, { "name": "ohos.permission.GET_WIFI_INFO" } ], "metaData": { "customizeData": [ { "name": "hwc-theme", "value": "androidhwext:style/Theme.Emui.Light.NoTitleBar", "extra": "" } ] } }}
5.app图标(放在media文件夹中)
6.三个element文件夹中的json
6.3.1 element中的json
{ "string": [ { "name": "entry_MainAbility", "value": "MyParallelView" }, { "name": "mainability_description", "value": "Java_Empty Ability" }, { "name": "mainability_HelloWorld", "value": "Hello World" } ]}
6.3.1 en.element中的json
{ "string": [ { "name": "entry_MainAbility", "value": "MyParallelView" }, { "name": "mainability_description", "value": "Java_Empty Ability" }, { "name": "mainability_HelloWorld", "value": "Hello World" } ]}
6.3.1 zh.element中的json
{ "string": [ { "name": "entry_MainAbility", "value": "我的平行视界" }, { "name": "mainability_description", "value": "Java_Empty Ability" }, { "name": "mainability_HelloWorld", "value": "你好,世界" } ]}
7. app运行视频(远程模拟器运行)
基于TabList和PageSlider的自制平行视界