HarmonyOS应用开发--基于TabList和PageSlider的自制平行视界MyParallelView[我的平行视界][API V6]
1. 名称
本次项目将TabList和Tab用作PageSlider的页面指示器,并且通过判段屏幕是否横屏开启自制平行视界功能。 将本次项目命名为:我的平行视界,MyParallelView。 项目已经放在Gitee仓库中:MyParallelView
2. app实现关键技巧
- TabList和Tab是鸿蒙api提供的页签功能,即常见的类别标签选择功能。PageSlider是鸿蒙api提供的多页面切换功能组件。而本次项目,将TabList和Tab作为PageSlier的页面指示器。
- 即有:点击某个页签,则会切换至某个页面;滑动到某个页面,则会选中某个页签。
PageSlier每页显示不同组件内容----实现技巧:
- 第一种方法:首先写好几个需要的页面XML,使用动态装载XML的手段,然后将装载返回的DirectionalLayout变量按照页面顺序,放在ArrayList<DirectionalLayout> 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();
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);
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);
}
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
<?xml version="1.0" encoding="UTF-8" ?>
<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
<?xml version="1.0" encoding="utf-8"?>
<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
<?xml version="1.0" encoding="utf-8"?>
<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
<?xml version="1.0" encoding="utf-8"?>
<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
<?xml version="1.0" encoding="utf-8"?>
<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的自制平行视界
|