5 Star 3 Fork 0

CHINASOFT3_OHOS / ChromeLikeTabSwitcher

Create your Gitee Account
Explore and code with more than 12 million developers,Free private repositories !:)
Sign up
Clone or Download
contribute
Sync branch
Cancel
Notice: Creating folder will generate an empty file .keep, because not support in Git
Loading...
README
Apache-2.0

ChromeLikeTabSwitcher

项目介绍

  • 项目名称:ChromeLikeTabSwitcher
  • 所属系列:openharmony的第三方组件适配移植
  • 功能:ChromeLikeTabSwitcher是一个仿Chrome浏览器中Tab切换的库,它提供的标签切换器类似于在Chrome浏览器中使用的标签切换器。
  • 项目移植状态:主功能完成
  • 调用差异:无
  • 开发版本:sdk6,DevEco Studio2.2 beta1
  • 基线版本:tag 0.4.6

效果演示

  • 主页上下滑动

  • UNDO功能

-添加新Tab页

安装教程

1.在项目根目录下的build.gradle文件中,

allprojects {
   repositories {
       maven {
           url 'https://s01.oss.sonatype.org/content/repositories/releases/'
       }
   }
}

2.在entry模块的build.gradle文件中,

dependencies {
   implementation('com.gitee.chinasoft_ohos:ChromeLikeTabSwitcher:1.0.1')
   implementation('com.gitee.chinasoft_ohos:ChromeLikeTabSwitcher_ohos_util:1.0.0')
   implementation('com.gitee.chinasoft_ohos:ChromeLikeTabSwitcher_java_util:1.0.0')
   implementation('com.gitee.chinasoft_ohos:ChromeLikeTabSwitcher_materialviewlibrary:1.0.0')
   ......  
}

在sdk6,DevEco Studio2.2 beta1下项目可直接运行 如无法运行,删除项目.gradle,.idea,build,gradle,build.gradle文件, 并依据自己的版本创建新项目,将新项目的对应文件复制到根目录下

使用说明

库的选项卡切换器实现为自定义视图TabSwitcher。可以通过编程方式声明或通过XML资源将其添加到活动或片段中。以下XML代码显示了如何将视图添加到XML布局资源。通常应通过将属性设置为layout_width和layout_height将标签切换器全屏显示match_parent。此外,该视图提供了各种自定义属性以自定义其外观,这在给定的示例中也可以看到。

<?xml version="1.0" encoding="utf-8"?>
<de.mrapp.tabswitcher.colorUi.widget.ColorDirectionalLayout
    ohos:id="$+id:root"
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    xmlns:app="http://schemas.huawei.com/apk/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:orientation="vertical"
    ohos:theme_prefix="main">

    <de.mrapp.tabswitcher.TabSwitcher
        ohos:id="$+id:tab_switcher"
        ohos:height="match_parent"
        ohos:width="match_parent"
        app:emptyView="$layout:empty_view"
        app:tabIcon="$media:ic_file_outline_18dp"
        ...
        />

</de.mrapp.tabswitcher.colorUi.widget.ColorDirectionalLayout>

以TabSwitcher编程方式实例化时,可以使用以下Java代码。对于上面示例中显示的所有XML属性,都可以使用相应的setter方法。

TabSwitcher tabSwitcher = new TabSwitcher(context);
tabSwitcher.showAddTabButton(createAddTabButtonListener());
tabSwitcher.setToolbarNavigationIcon(ResourceTable.Media_ic_plus_white_24dp, createAddTabListener());

由a包含的选项卡TabSwitcher由class的实例表示Tab。以下Java代码演示了如何创建新标签并将其添加到标签切换器。通过设置自定义图标,背景颜色,标题颜色等,TabSwitcher可以覆盖特定标签的默认设置(应用于)。所述setParameters-method允许以一个标签相关联Bundle,其可包含关于标签的附加信息。通过实现接口Tab.Callback并Tab使用其addCallback-method在a处注册实例,可以在选项卡的属性已更改时观察到它。

Tab tab = new Tab("Title");
PacMap parameters = new PacMap();
tab.setIcon(ResourceTable.Media_ic_file_outline_18dp);
...
tab.setParameters(parameters);

为了指定选项卡的TabSwitcher 外观,TabSwitcherDecorator必须重写抽象类,并且必须使用setDecorator方法将实现类的实例应用于选项卡切换器。这是非常常用的适配器,用于填充一个发展中的范式 ListViewRecyclerView等等之类的每一个自定义实现 TabSwitcherDecorator必须重写 onInflateViewonShowTab方法。第一个用于使视图膨胀,应由选项卡使用,后者允许根据当前状态自定义膨胀视图的外观。在 onShowTab的范围内,装饰器的findComponentById方法可用于引用视图。它使用内置的视图保持器以获得更好的性能。

如果对不同的选项卡使用不同的视图,则getViewTypeCountgetViewType方法也必须被覆盖。第一个返回的是onInflateView 方法放大的不同视图的总数,后一个必须返回一个不同的整数值,该值指定特定选项卡 的视图类型。以下代码说明了如何实现该类TabSwitcherDecorator

class Decorator extends TabSwitcherDecorator {

    @NonNull
    @Override
    public View onInflateView(@NonNull LayoutInflater inflater,
                              @Nullable ViewGroup parent, int viewType) {
        Component view;
        if (viewType == 0) {
            LogUtil.loge("=== onInflateView 0");
            view = inflater.parse(ResourceTable.Layout_tab_text_view, parent, false);
        } else if (viewType == 1) {
            LogUtil.loge("=== onInflateView 1");
            view = inflater.parse(ResourceTable.Layout_tab_edit_text, parent, false);
        } else {
            LogUtil.loge("=== onInflateView 2");
            view = inflater.parse(ResourceTable.Layout_tab_list_view, parent, false);
        }

        Toolbar toolbar = (Toolbar) view.findComponentById(ResourceTable.Id_toolbar);
        toolbar.inflateMenu(ResourceTable.Layout_tab);
        toolbar.setOnMenuItemClickListener(tabSwitcher, createToolbarMenuListener());
        TabSwitcher.setupWithToolbar(tabSwitcher, toolbar, createTabSwitcherButtonListener());
        return view;
    }

    @Override
    public void onShowTab(@NonNull Context context, @NonNull TabSwitcher tabSwitcher, 
                          @NonNull View view, @NonNull Tab tab, int index, int viewType,
                          @Nullable Bundle savedInstanceState) {
        Text textView = findComponentById(ResourceTable.Id_title);
        textView.setText((String) tab.getTitle());
        Toolbar toolbar = findComponentById(ResourceTable.Id_toolbar);
        toolbar.addMenuClickListener();
        toolbar.setVisibility(tabSwitcher.isSwitcherShown() ? Component.HIDE : Component.VISIBLE);
        if (toolbar.getMenu() != null) {
            String theme_name = getThemeValue("theme_name");
            if ("dark".equals(theme_name)) {
                toolbar.getMenu().setImageSrc(de.mrapp.tabswitcher.ResourceTable.Media_more_menu_white);
                toolbar.setButtonColor(1, Color.WHITE);
            } else {
                toolbar.getMenu().setImageSrc(de.mrapp.tabswitcher.ResourceTable.Media_more_menu);
                toolbar.setButtonColor(0.5f, Color.DKGRAY);
            }
        }
        ColorUiUtil.changeTheme(view, getContext().getTheme());
        if (viewType == 1) {
            LogUtil.loge("=== onShowTab viewType -> 1");
            TextField editText = findComponentById(ResourceTable.Id_edit);

            if (savedInstanceState == null) {
                editText.setText("");
            }

            editText.requestFocus();
        } else if (viewType == 2 && state != null) {
            LogUtil.loge("=== onShowTab viewType -> 2");
            ListContainer listView = findComponentById(ResourceTable.Id_list);
            state.loadItems(listView);
        }
    }

    @Override
    public int getViewTypeCount() {
        return 3;
    }

    @Override
    public int getViewType(@NonNull Tab tab, int index) {
        Bundle parameters = tab.getParameters();
        return parameters != null ? parameters.getInt("view_type") : 0;
    }
    
    @Override
    public void onSaveInstanceState(@NonNull View view, @NonNull Tab tab, int index,
                                    int viewType, @NonNull Bundle outState) {
        // Store the tab's current state in the Bundle outState if necessary
    }

}

为了将装饰器应用于TabSwitchersetDecorator 方法,必须如下所示使用。如果未设置装饰器,IllegalStateException 则在视图应可见时将立即引发。

tabSwitcher.setDecorator(new Decorator());

为了观察TabSwitcher状态,可以实现TabSwitcher接口TabSwitcherListener 侦听器。该界面提供了以下方法:在将选项卡添加到选项卡切换器或从选项卡切换器中删除时, 或者如果选项卡切换器已隐藏或显示(仅在使用智能手机布局时),则将调用这些方法。TabSwitcherListener 可以使用TabSwitcheraddListener方法添加类型的实例。 为了观察,当单击选项卡的关闭按钮时,TabCloseListener 可以相应地使用addTabCloseListener方法来实现和添加接口。

使用动画

该类 TabSwitcher 提供了添加或删除一个或几个选项卡的各种方法。如果当前显示选项卡切换器,则以动画方式添加或删除选项卡。为了使用自定义动画,Animation 可以将类的实例传递给方法。

滑动动画

使用智能手机布局时,SwipeAnimation 默认情况下使用a来添加或删除选项卡。这会导致标签页水平滑动(或在横向模式下垂直滑动)。通过指定enum的值SwipeAnimation.SwipeDirection, 可以指定选项卡是否应该向左或向右移动(在横向模式下分别从顶部或底部移动)。以下代码示例说明了如何 SwipeAnimation 使用构建器来创建类的实例。

Animation animation = new SwipeAnimation.Builder().setDuration(2000)
        .setInterpolator(new LinearInterpolator()).setDirection(SwipeAnimation.SwipeDirection.LEFT)
        .create();

工具栏和菜单

TabSwitcher库提供的视图允许显示工具栏。默认情况下,工具栏始终处于隐藏状态。为了显示它, showToolbars 必须使用-method。使用智能手机布局时,当前显示选项卡切换器或选项卡切换器不 包含任何选项卡时,将显示工具栏。使用数位板布局时,始终显示两个工具栏-一个在选项卡的左侧 ,另一个在选项卡的右侧。可以使用 getToolbars 方法来引用工具栏。它返回一个数组, 其中包含布局的工具栏。 使用智能手机布局时,Toolbar数组仅包含一个;使用平板电脑布局时,左一个包含在索引0中, 右一个包含在索引1中。

该类 TabSwitcher 提供了一些方法,可用于设置工具栏的标题,导航图标和菜单。 本 setToolbarTitle 方法允许设置一个标题。使用数位板布局时,标题将应用到左侧工具栏。 所述 setToolbarNavigationIcon 方法允许指定工具栏的导航图标以及点击图标时被调用的监听器。 使用数位板布局时,导航图标将应用于左侧工具栏。为了将菜单添加到 TabSwitcher 的工具栏, inflateToolbarMenu 可以使用-method。除了应该应用的菜单资源的资源ID外,它还允许指定一个侦听器, 当单击菜单项时会通知该侦听器。

为了提供类似于Chrome浏览器中使用的按钮的按钮,该按钮显示了a包含的选项卡总数, TabSwitcher 并允许切换选项卡切换器的可见性,该类 TabSwitcherButton 由库公开。 它实现了一个自定义的 ImageButton ,它实现了接口 TabSwitcherListener ,以使显示的选项 卡数目保持最新。 该按钮的外观由类指定 TabSwitcherDrawable 。如果 TabSwitcherButton 应将用作工具栏菜单的一部分, 则必须将其包含在菜单资源中。具体使用如下所示

TabSwitcherDrawable使用方法:

 private void initImage() {
    image = new Image(getContext());

    Resource resource = convertRes(getContext(), ResourceTable.Media_tab_switcher_drawable_background);
    //The drawable, which is used by the image button.
    drawable = new TabSwitcherDrawable(getContext(), resource);
    image.setImageElement(drawable);
    StackLayout.LayoutConfig imageParams = new LayoutConfig(StackLayout.LayoutConfig.MATCH_PARENT, StackLayout.LayoutConfig.MATCH_PARENT);
    imageParams.alignment = TextAlignment.CENTER;
    addComponent(image, imageParams);
    }

TabSwitcherButton使用方法:

TabSwitcherButton actionView = new TabSwitcherButton(getContext());
DirectionalLayout.LayoutConfig actionConfig = new LayoutConfig();
int tabHeight = (int) PixelUtil.fp2px(DimensionUtil.parseDimension(getContext().getString(ResourceTable.String_tablet_tab_height)));
actionConfig.height = tabHeight;
actionConfig.width = tabHeight;
addComponent(actionView, actionConfig);

为了将菜单注册 TabSwitcherButton 为的侦听器,可以使用TabSwitcher静态 setupWithMenu方法。它会自动为所有的items 注入一个Menu菜单,将使用的所有项注册 TabSwitcherButton 为 特定的侦听器 TabSwitcher 。在 OnClickListener 当被点击这些按钮中的一个,其可任选被指定, 被调用。以下代码显示了如何将该方法与任意菜单一起使用。

TabSwitcher.setupWithMenu(tabSwitcher, menu, new OnClickListener() { /* ... */ });

If the menu, which is part of the tab switcher itself, should be set up, the following method call can be used.

TabSwitcher.setupWithMenu(tabSwitcher, new OnClickListener() { /* ... */ });
使用主题

默认情况下,图书馆的会使用浅色主题TabSwitcher。但是,该库TabSwitcher除主题外还带有预定义的深色主题。 下面的屏幕快照显示了深色主题的外观

当TabSwitcher为空时显示一个占位符

该类 TabSwitcher 提供setEmptyView 方法,可用于指定选项卡切换器为空时显示的自定义视图。 通过使用淡入或淡出动画来显示或隐藏指定的视图。可以选择指定这些动画的持续时间。使用 setEmptyView 方法 的第一种可能性是指定该类的实例ohos.agp.components.Component

Component component = // ... inflate component
tabSwitcher.setEmptyView(component); 

或者,setEmpyView可以通过指定视图的布局资源ID来使用:

tabSwitcher.setEmptyView(ResourceTable.Id_empty_view); 

当标签切换器为空时,显示的占位符视图的示例可以在下面的屏幕快照中看到。

填充

该视图将 TabSwitcher 覆盖 setPadding 该类的方法 View ,以便将填充应用于所有选项卡及其父视图。此行为的主要目的是在使用半透明状态和/或导航栏时应用窗口插图, 如在库的示例应用程序中可以看到的那样。以下代码示例演示如何通过使用活动将窗口插入到选项卡切换器OnApplyWindowInsetsListener 。它应在活动的 onCreate 方法中使用。

 tabSwitcher.getComponentTreeObserver().addWindowBoundListener(
    new ComponentTreeObserver.WindowBoundListener() {
            @Override
            public void onWindowBound() {
                int left = main_root.getLeft();
                int top = main_root.getTop();
                int right = main_root.getRight();
                int bottom = main_root.getBottom();
                float touchableAreaTop = top;

                if (tabSwitcher.getLayout() == Layout.TABLET) {
//                    touchableAreaTop += getResources().getDimensionPixelSize(R.dimen.tablet_tab_container_height);
                }

                LogUtil.loge("===" + left + ":" + top + ":" + right + ":" + bottom);
                int actionBarSize = (int) PixelUtil.fp2px(DimensionUtil.parseDimension(tabSwitcher.getContext().getString(ResourceTable.String_actionBarSize)));
                LogUtil.loge("===" + actionBarSize);
                RectFloat touchableArea = new RectFloat(left, touchableAreaTop, right, touchableAreaTop + actionBarSize);
                tabSwitcher.addDragGesture(
                        new SwipeGesture.Builder().setTouchableArea(touchableArea).create());
                tabSwitcher.addDragGesture(
                        new PullDownGesture.Builder().setTouchableArea(touchableArea).create());
            }

            @Override
            public void onWindowUnbound() {

            }
        }
);

测试信息

CodeCheck代码测试无异常

CloudTest代码测试无异常

病毒安全检测通过

当前版本demo功能与原组件基本无差异

版本迭代

  • 1.0.2
  • 1.0.1
  • 1.0.0
  • 0.0.1-SNAPSHOT
Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS

About

ChromeLikeTabSwitcher是一个仿Chrome浏览器中Tab切换的库 expand collapse
Java
Apache-2.0
Cancel

Releases

No release

Contributors

All

Activities

Load More
can not load any more
Java
1
https://gitee.com/chinasoft3_ohos/ChromeLikeTabSwitcher.git
git@gitee.com:chinasoft3_ohos/ChromeLikeTabSwitcher.git
chinasoft3_ohos
ChromeLikeTabSwitcher
ChromeLikeTabSwitcher
master

Search