{"id":15034480,"url":"https://github.com/michael-rapp/chromeliketabswitcher","last_synced_at":"2025-05-15T20:05:45.385Z","repository":{"id":57721503,"uuid":"79662592","full_name":"michael-rapp/ChromeLikeTabSwitcher","owner":"michael-rapp","description":"Provides a tab switcher similar to the one, which is used in Google Chrome on Android","archived":false,"fork":false,"pushed_at":"2024-03-10T05:41:43.000Z","size":16985,"stargazers_count":1234,"open_issues_count":9,"forks_count":143,"subscribers_count":38,"default_branch":"master","last_synced_at":"2025-05-15T20:05:31.054Z","etag":null,"topics":["android","cards","chrome","google","navigation","switcher","tab"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/michael-rapp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-21T17:57:17.000Z","updated_at":"2025-05-15T16:51:21.000Z","dependencies_parsed_at":"2024-08-02T01:38:27.882Z","dependency_job_id":null,"html_url":"https://github.com/michael-rapp/ChromeLikeTabSwitcher","commit_stats":null,"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-rapp%2FChromeLikeTabSwitcher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-rapp%2FChromeLikeTabSwitcher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-rapp%2FChromeLikeTabSwitcher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michael-rapp%2FChromeLikeTabSwitcher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michael-rapp","download_url":"https://codeload.github.com/michael-rapp/ChromeLikeTabSwitcher/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254414499,"owners_count":22067272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","cards","chrome","google","navigation","switcher","tab"],"created_at":"2024-09-24T20:25:15.430Z","updated_at":"2025-05-15T20:05:40.328Z","avatar_url":"https://github.com/michael-rapp.png","language":"Java","funding_links":["https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=X75YSLEJV3DWE"],"categories":[],"sub_categories":[],"readme":"# ChromeLikeTabSwitcher - README\n\n*THIS LIBRARY IS STILL WORK IN PROGRESS. THE LAYOUT OPTIMIZED FOR TABLETS IS NOT IMPLEMENTED YET.*\n\n[![API-Level](https://img.shields.io/badge/API-14%2B-orange.svg)](https://android-arsenal.com/api?level=14) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-ChromeLikeTabSwitcher-brightgreen.svg?style=true)](https://android-arsenal.com/details/1/5654) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=X75YSLEJV3DWE)\n\n\"ChromeLikeTabSwitcher\" is an Android-library, which provides a tab switcher similar to the one, which is used in the Android version of Google's Chrome browser. It provides layouts optimized for smartphone and tablet devices. The following GIFs illustrate the appearance of the library:\n\n![](doc/images/smartphone_layout.gif)\n\nThe library provides the following features:\n\n- Provides layouts optimized for smartphones and tablets.\n- Tabs can dynamically be added and removed either programmatically or by using the UI. Different types of animations are available for said purpose.\n- The tab switcher's state is automatically restored on configuration changes.\n- In order to provide great performance, views are automatically recycled and the previews of tabs are rendered as bitmaps.\n- The appearance of tabs, e.g. their background or title color, can be customized.\n \n## License Agreement\n\nThis project is distributed under the Apache License version 2.0. For further information about this license agreement's content please refer to its full version, which is available at http://www.apache.org/licenses/LICENSE-2.0.txt.\n\n## Download\n\nThe latest release of this library can be downloaded as a zip archive from the download section of the project's Github page, which is available [here](https://github.com/michael-rapp/ChromeLikeTabSwitcher/releases). Furthermore, the library's source code is available as a Git repository, which can be cloned using the URL https://github.com/michael-rapp/ChromeLikeTabSwitcher.git.\n\nAlternatively, the library can be added to your Android app as a Gradle dependency by adding the following to the respective module's `build.gradle` file:\n\n```groovy\ndependencies {\n    compile 'com.github.michael-rapp:chrome-like-tab-switcher:0.4.6'\n}\n```\n\n## Examples\n\nThe library's tab switcher is implemented as a custom view `TabSwitcher`. It can be added to an activity or fragment by being declared programmatically or via a XML resource. The following XML code shows how the view can be added to a XML layout resource. A tab switcher should typically be shown fullscreen by setting the attributes `layout_width` and `layout_height` to `match_parent`. Furthermore, the view provides various custom attributes for customizing its appearance, which can as well be seen in the given example. \n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cde.mrapp.android.tabswitcher.TabSwitcher \n        android:id=\"@+id/tab_switcher\"\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:custom=\"http://schemas.android.com/apk/res-auto\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@color/tab_switcher_background_color\"\n        custom:layoutPolicy=\"auto\"\n        custom:tabIcon=\"@drawable/ic_file_outline_18dp\"\n        custom:tabIconTint=\"@android:color/black\"\n        custom:tabBackgroundColor=\"@color/tab_background_color\"\n        custom:tabContentBackgroundColor=\"@color/tab_content_background_color\"\n        custom:tabTitleTextColor=\"@color/tab_title_text_color\"\n        custom:tabCloseButtonIcon=\"@ic_close_18dp\"\n        custom:tabCloseBUttonIconTint=\"@android:color/black\"\n        custom:toolbarTitle=\"@string/tab_switcher_toolbar_title\"\n        custom:toolbarMenu=\"@menu/tab_switcher_toolbar_menu\"\n        custom:toolbarNavigationIcon=\"@drawable/ic_add_box_24dp\"\n        custom:toolbarNavigationIconTint=\"@android:color/white\"/\u003e\n```\n\nWhen instantiating a `TabSwitcher` programmatically, the following Java code can be used. For all XML attributes shown in the example above, corresponding setter methods are available. \n\n```java\nTabSwitcher tabSwitcher = new TabSwitcher(context);\ntabSwitcher.setBackground(ContextCompat.getColor(context, R.color.tab_switcher_background_color));\ntabSwitcher.setLayoutPolicy(LayoutPolicy.AUTO);\ntabSwitcher.setTabIcon(R.drawable.ic_file_outline_18dp);\ntabSwitcher.setTabIconTint(ContextCompat.getColor(context, android.R.color.black));\ntabSwitcher.setTabBackgroundColor(ContextCompat.getColor(context, R.color.tab_background_color));\ntabSwitcher.setTabContentBackgroundColor(ContextCompat.getColor(context, R.color.tab_content_background_color));\ntabSwitcher.setTabTitleTextColor(ContextCompat.getColor(context, R.color.tab_title_text_color));\ntabSwitcher.setTabCloseButtonIcon(R.drawable.ic_close_18dp);\ntabSwitcher.setTabCloseButtonIcon(ContextCompat.getColor(context, android.R.color.black));\ntabSwitcher.setToolbarTitle(context.getString(R.string.tab_switcher_toolbar_title));\ntabSwitcher.inflateToolbarMenu(R.menu.tab_switcher_toolbar_menu, null);\ntabSwitcher.setToolbarNavigationIcon(R.drawable.ic_add_box_white_24dp, null);\ntabSwitcher.setToolbarNavigationIconTint(ContextCompat.getColor(context, android.R.color.black));\n```\n\nThe tabs, which are contained by a `TabSwitcher` are represented by instances of the class `Tab`. The following Java code demonstrates, how a new tab can be created and added to a tab switcher. By setting a custom icon, background color, title color etc., the defaults, which are applied to the `TabSwitcher` can be overridden for that particular tab. The `setParameters`-method allows to associate a tab with a `Bundle`, which may contain additional information about the tab. By implementing the interface `Tab.Callback` and registering an instance at a `Tab` by using its `addCallback`-method, it can be observed, when the properties of a tab has been changed. \n\n```java\nTab tab = new Tab(\"Title\");\ntab.setCloseable(true);\ntab.setIcon(R.drawable.ic_file_outline_18dp);\ntab.setIconTint(ContextCompat.getColor(context, androidR.color.black));\ntab.setBackgroundColor(ContextCompat.getColor(context, R.color.tab_background_color));\ntab.setContentBackgroundColor(ContextCompat.getColor(context, R.color.tab_content_background_color));\ntab.setTitleTextColor(ContextCompat.getColor(context, R.color.tab_title_text_color));\ntab.setCloseButtonIcon(R.drawable.ic_close_18dp);\ntab.setCloseButtonIconTint(ContextCompat.getColor(context, android.R.color.black));\ntab.setParameters(new Bundle());\ntab.addCallback(new Tab.Callback() { /* ... */ });\ntabSwitcher.addTab(tab);\n```\n\nIn order to specify how the tabs of a `TabSwitcher` should look like, the abstract class `TabSwitcherDecorator` must be overridden and an instance of the implementing class must be applied to the tab switcher by using its `setDecorator`-method. This is very similar to the paradigm of adapters commonly used in Android developing for populating a `ListView`, `RecyclerView`, etc. Each custom implementation of the class `TabSwitcherDecorator` must override the `onInflateView`- and `onShowTab`-method. The first one is used to inflate the view, which should be used by a tab, the latter allows to customize the appearance of the inflated view, depending on the current state. Within the scope of the `onShowTab`-method the decorator's `findViewById`-method can be used to reference views. It uses a built-in view holder for better performance.\n\nIf different views should be inflated for different tabs, the `getViewTypeCount`- and `getViewType`-methods must be overridden as well. The first one should return the total number of different views, which are inflated by the `onInflateView`-method, the latter one must return a distinct integer value, which specifies the view type of a specific tab. The following code illustrates how the class `TabSwitcherDecorator` can be implemented.\n\nFurthermore, the class `TabSwitcherDecorator` enables to override the `onSaveInstanceState`-method in order to store the current state of a tab within a `Bundle`. When the tab is shown again, the `Bundle` will be passed to the `onShowTab`-method in order to be able to restore the previously saved state. If you want to take care of clearing saved state by yourself, false can be passed to the `clearSavedStatesWhenRemovingTabs`-method. To manually clear the saved state of a single tab, the `clearSavedState`-method can be used. For clearing all saved states, the `clearAllSavedStates`-method is provided.\n\n\n```java\nclass Decorator extends TabSwitcherDecorator {\n\n    @NonNull\n    @Override\n    public View onInflateView(@NonNull LayoutInflater inflater,\n                              @Nullable ViewGroup parent, int viewType) {\n        if (viewType == 0) {\n            return inflater.inflate(R.layout.tab_view_1, parent, false);\n        } else {\n            return inflater.inflate(R.layout.tab_view_2, parent, false);\n        }\n    }\n\n    @Override\n    public void onShowTab(@NonNull Context context, @NonNull TabSwitcher tabSwitcher, \n                          @NonNull View view, @NonNull Tab tab, int index, int viewType,\n                          @Nullable Bundle savedInstanceState) {\n        if (viewType == 0) {\n            TextView textView = findViewById(R.id.text_view);\n            textView.setText(tab.getTitle());\n        } else {\n            Button button = findViewById(R.id.button);\n            button.setText(tab.getTitle());\n        }\n        \n        if (savedInstanceState != null) {\n            // Restore the tab's state if necessary\n        }\n    }\n\n    @Override\n    public int getViewTypeCount() {\n        return 2;\n    }\n\n    @Override\n    public int getViewType(@NonNull Tab tab, int index) {\n        Bundle parameters = tab.getParameters();\n        return parameters != null ? parameters.getInt(\"view_type\") : 0;\n    }\n    \n    @Override\n    public void onSaveInstanceState(@NonNull View view, @NonNull Tab tab, int index,\n                                    int viewType, @NonNull Bundle outState) {\n        // Store the tab's current state in the Bundle outState if necessary\n    }\n\n}\n```\n\nIn order to apply a decorator to a `TabSwitcher` its `setDecorator`-method must be used as shown below. If no decorator has been set, an `IllegalStateException` will be thrown as soon as the view should become visible.\n\n```java\ntabSwitcher.setDecorator(new Decorator());\n```\n\nIn order to observe the state of a `TabSwitcher`, the interface `TabSwitcherListener` listener can be implemented. The interface provides methods, which are invoked, when tabs are added to or removed from a tab switcher, or if the tab switcher has been hidden or shown (only when using the smartphone layout). Instances of the type `TabSwitcherListener` can be added by using a `TabSwitcher`'s `addListener`-method. In order to observe, when the close button of a tab has been clicked, the interface `TabCloseListener` can be implemented and added by using the `addTabCloseListener`-method accordingly.\n\n## Stateful Decorators\n\nAs an alternative of the class `TabSwitcherDecorator`, the class `StatefulTabSwitcherDecorator` can be used. It is an extension of the class `TabSwitcherDecorator`, which allows to maintain arbitrary states for a `TabSwitcher`'s tab (it is recommended to use the class `AbstractState` as a base class though). This is for example useful, if list items are shown within a tab and a reference to the used adapter should be stored to easy the modification of the list items. The states are kept even if the corresponding tab is currently not shown. However, they are not restored after orientation changes and may be vanished when the device is low on memory.\n\nTo create states, they must be returned by the decorator's `onCreateState`-method. When a state is about to be deleted, the `onClearState`-method is invoked. \n\nBy default, the states of tabs are automatically clear, when the corresponding tab is removed. However, when passing `false` to the `clearSavedStatesWhenRemovingTabs`-method, this mechanism is turned off. To manually remove states, the `clearState`- and `clearAllStates`-methods can be used.\n\nThe library's example app illustrates how the class `StatefulTabSwitcherDecorator` can be used for asynchronouly loading list items, which are shown in a tab using an `ArrayAdapter` and a `Listener`. Please refer to its code for further information.\n\n## Using Animations\n\nThe class `TabSwitcher` provides various methods to add or remove one or several tabs. If the tab switcher is currently shown, tabs are added or removed in an animated manner. In order to use custom animations, an instance of the class `Animation` can be passed to the methods.\n\n### Swipe Animation\n\nWhen using the smartphone layout, a `SwipeAnimation` is used to add or remove tabs by default. It causes tabs to be swiped horizontally (or vertically in landscape mode). By specifying a value of the enum `SwipeAnimation.SwipeDirection`, it can be specified, whether the tab should be moved to/from the left or right (respectively to/from the top or bottom in landscape mode). The following code sample illustrates how instances of the class `SwipeAnimation` can be created by using a builder.\n \n```java\nAnimation animation = new SwipeAnimation.Builder().setDuration(2000)\n        .setInterpolator(new LinearInterpolator()).setDirection(SwipeAnimation.SwipeDirection.LEFT)\n        .create();\n```\n\n![](doc/images/swipe_animation.gif)\n\n### Reveal Animation\n\nWhen using the smartphone layout, a `RevealAnimation` can be used to add a single tab. Starting at a specific position, the size of the tab will be animated until it is shown fullscreen. Using a `RevealAnimation` causes the tab switcher to become hidden and the added tab is selected automatically. The following code shows, how a `RevealAnimation` can be instantiated. All of the builder's setter methods are optional. If they are not called, default values are used.\n\n```java\nAnimation animation = new RevealAnimation.Builder().setDuration(2000)\n        .setInterpolator(new LinearInterpolator().setX(20).setY(50)\n        .create();\n```\n\n![](doc/images/reveal_animation.gif)\n\n### PeekAnimation\n\nA `PeekAnimation` can be used to add a tab, if the smartphone layout is used and when the switcher is currently not shown. Similar to a `RevealAnimation`, the size of the added tab is animated, starting at a specific position. The tab is then shown at the bottom (or right in landscape mode) of the tab switcher for a short time. Unlike a `RevealAnimation`, a `PeekAnimation` does not cause the added tab to become selected. Its purpose is to give a preview of the added tab, while another tab is still shown fullscreen. This corresponds to the animation, which is used in the Google Chrome browser when opening a link in a new tab. A `PeekAnimation` can be created by using the builder pattern as shown below.\n\n```java\nAnimation animation = new PeekAnimation.Builder().setDuration(2000)\n        .setInterpolator(new LinearInterpolator().setX(20).setY(50)\n        .create();\n```\n\n![](doc/images/peek_animation.gif)\n\n# Using drag gestures\n\nThe library provides multiple drag gestures, which can be used to perform certain actions. They can be set to a `TabSwitcher` by using its `addDragGesture`-method. If a previously added drag gesture should be removed, the `removeDragGesture`-method can be used accordingly. Usually, a onscreen area is specified for each gesture in order to specify the area, where drag gestures should be detected. In the following, the available drag gestures are discussed.\n\n## SwipeGesture\n\nSwipe gestures allow to switch between neighboring tabs, when the tab switcher is not currently shown, by swiping horizontally. Such gestures are represented by instances of the class `SwipeGesture`. In order to create a swipe gesture the builder pattern can be used as shown below. The `setTouchableArea` method call is used to specify the onscreen area, which should be taken into account for recognizing the gesture, the `setAnimationDuration`-method allows to set the duration of the swipe animation and the `setThreshold`-method call sets the distance in pixels, the gesture must last until it is recognized. All of these method calls  are optional.\n\n```java\nDragGesture gesture = new SwipeGesture.Builder().setTouchableArea(0, 0, 200, 100)\n        .setAnimationDuration(1000L).setThreshold(10)\n        .create();\n```\n\n![](doc/images/swipe_gesture.gif)\n\n## PullDownGesture\n\nA `PullDownGesture` can be used on smartphones to show the tab switcher by pulling down from the top. It does not have any effects when using the tablet layout. Instances of the class `PullDownGesture` can be created as follows.\n\n```java\nDragGesture gesture = new PullDownGesture.Builder().setTouchableArea(0, 0, 200, 100)\n        .setThreshold(10)\n        .create();\n```\n\n![](doc/images/pull_down_gesture.gif)\n\n## Toolbars and Menus\n\nThe view `TabSwitcher`, which is provided by the library, allows to show a toolbar. By default, the toolbar is always hidden. In order to show it, the `showToolbars`-method must be used. When using the smartphone layout, the toolbar is shown when the tab switcher is currently shown, or if no tabs are contained by the tab switcher. When using the tablet layout, two toolbars - one to the left and one to the right of the tabs - are always shown. The toolbars can be referenced by using the `getToolbars`-method. It returns an array, which contains the layout's toolbars. When using the smartphone layout, only one `Toolbar` is contained by the array, when using the tablet layout, the left one is contained at index 0 and the right one is contained at index 1.\n\nThe class `TabSwitcher` provides a few methods, which allow to set the toolbar's title, navigation icon and menu. The `setToolbarTitle`-method allows to set a title. When using the tablet layout, the title is applied to the left toolbar. The `setToolbarNavigationIcon`-method allows to specify the navigation icon of the toolbar as well as a listener which is invoked when the icon is clicked. When using the tablet layout, the navigation icon is applied to the left toolbar. In order to add a menu to a `TabSwitcher`'s toolbar, the `inflateToolbarMenu`-method can be used. Besides the resource id of the menu resource, which should be applied, it also allows to specify a listener, which is notified when a menu item is clicked.\n\nIn order to provide a button, similar to the one, which is used in Google's Chrome browser, which shows the total number of tabs contained by a `TabSwitcher` and allows to toggle the visibility of the tab switcher, the class `TabSwitcherButton` is exposed by the library. It implements a custom `ImageButton`, which implements the interface `TabSwitcherListener` in order to keep the displayed number of tabs up-to-date. The appearance of the button is given by the class `TabSwitcherDrawable`. If a `TabSwitcherButton` should be used as part of a toolbar menu, it must be included in a menu resource as shown in the following XML code.\n\n```xml\n\u003cmenu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n      xmlns:app=\"http://schemas.android.com/apk/res-auto\"\u003e\n\n    \u003citem\n        android:id=\"@+id/toggle_tab_switcher_menu_item\"\n        android:title=\"@string/toggle_tab_switcher_menu_item\"\n        app:actionLayout=\"@layout/tab_switcher_menu_item\"\n        app:showAsAction=\"ifRoom\"/\u003e\n\n\u003c/menu\u003e\n```\n\nIn order to register a menu's `TabSwitcherButton` as a listener of a `TabSwitcher`, the static `setupWithMenu`-method can be used. It automatically registers all items of a `Menu`, that use a `TabSwitcherButton`, as listeners of a specific `TabSwitcher`. The `OnClickListener`, which can optionally be specified, is invoked when one of these buttons is clicked. The following code shows, how the method can be used together with an arbitrary menu.\n\n```java\nTabSwitcher.setupWithMenu(tabSwitcher, menu, new OnClickListener() { /* ... */ });\n```\nIf the menu, which is part of the tab switcher itself, should be set up, the following method call can be used. \n```java\nTabSwitcher.setupWithMenu(tabSwitcher, new OnClickListener() { /* ... */ });\n```\n\n## Using Themes\n\nBy default, a light theme is used by the library's `TabSwitcher`. However, the library comes with a predefined dark theme `TabSwitcher` in addition to the theme `TabSwitcher.Light`. The appearance of the dark theme (on a smartphone in landscape mode) is shown in the screenshot below. \n\n![](doc/images/dark_theme.png)\n\nThemes can be applied globally to all tab switchers by specifying the following attributes in the app's theme as shown below. The attributes `tabSwitcherThemePhone` and `tabSwitcherThemeTablet` allow to specify different themes for the smartphone and tablet layout. These attributes take priority over the attribute `tabSwitcherThemeGlobal`, which specifies the theme regardless of the used layout.\n\n```xml\n\u003cstyle name=\"AppTheme\" parent=\"@style/Theme.AppCompat.Light.NoActionBar\"\u003e\n        \u003citem name=\"tabSwitcherThemeGlobal\"\u003e@style/TabSwitcher\u003c/item\u003e\n        \u003citem name=\"tabSwitcherThemePhone\"\u003e@style/TabSwitcher.Light\u003c/item\u003e\n        \u003citem name=\"tabSwitcherThemeTablet\"\u003e@style/TabSwitcher\u003c/item\u003e\n\u003c/style\u003e\n```\n\nThe same attributes are also available to be applied to a single tab switcher, when defined as part of a XML layout:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cde.mrapp.android.tabswitcher.TabSwitcher \n        android:id=\"@+id/tab_switcher\"\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:custom=\"http://schemas.android.com/apk/res-auto\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@color/tab_switcher_background_color\"\n        custom:themeGlobal=\"@style/TabSwitcher\"\n        custom:themePhone=\"@style/TabSwitcher.Light\"\n        custom:themeTablet=\"@style/TabSwitcher\"/\u003e\n```\n\nThe attributes, which are available when defining a tab switcher in a XML layout resource, can also be used when extending the predefined themes. All of them are shown in the following example. The attribute `tabSwitcherToolbarPopupTheme` enables to force the tab switcher's toolbar to use a dark theme for its popup menu.\n\n```xml\n\u003cstyle name=\"MyTabSwitcher\" parent=\"@style/TabSwitcher.Light\"\u003e\n        \u003citem name=\"tabSwitcherBackground\"\u003e@color/tab_switcher_background_color\u003c/item\u003e\n        \u003citem name=\"tabSwitcherLayoutPolicy\"\u003eauto\u003c/item\u003e\n        \u003citem name=\"tabSwitcherTabIcon\"\u003e@drawable/tab_switcher_tab_icon\u003c/item\u003e\n        \u003citem name=\"tabSwitcherTabBackgroundColor\"\u003e@color/tab_switcher_tab_background_color\u003c/item\u003e\n        \u003citem name=\"tabSwitcherTabContentBackgroundColor\"\u003e@color/tab_switcher_tab_content_background_color\u003c/item\u003e\n        \u003citem name=\"tabSwitcherTabTitleTextColor\"\u003e@color/tab_switcher_tab_title_text_color\u003c/item\u003e\n        \u003citem name=\"tabSwitcherTabCloseButtonIcon\"\u003e@drawable/tab_switcher_tab_close_button_icon\u003c/item\u003e\n        \u003citem name=\"tabSwitcherToolbarTitle\"\u003e@string/tab_switcher_toolbar_title\u003c/item\u003e\n        \u003citem name=\"tabSwitcherToolbarMenu\"\u003e@menu/tab_switcher_toolbar_menu\u003c/item\u003e\n        \u003citem name=\"tabSwitcherToolbarNavigationIcon\"\u003e@drawable/tab_switcher_toolbar_navigation_icon\u003c/item\u003e\n        \u003citem name=\"tabSwitcherToolbarPopupTheme\"\u003e@style/ThemeOverlay.AppCompat.Dark\u003c/item\u003e\n\u003c/style\u003e\n```\n\nAs an alternative to creating a custom theme, the theme attribute shown above can also be applied globally by including them in the global app theme. This causes them to take priority over the attributes of the theme, which is applied to a tab switcher. \n\n## Showing a Placeholder when TabSwitcher is empty\n\nThe class `TabSwitcher` provides `setEmptyView`-methods, which can be used to specify a custom view, which is shown, when the tab switcher is empty. The specified view is shown or hidden by using a fade in, respectively a fade out, animation. The duration of these animations can be specified optionally. The first possibility to use the `setEmptyView`-methods is to specify an instance of the class `android.view.View`:\n\n```java\nView view = // ... inflate view\ntabSwitcher.setEmptyView(view); \n// or tabSwitcher.setEmptyView(view, 1000L) if an animation duration should be specified\n```\n\nAlternatively, the `setEmpyView`-methods can be used by specifying the layout resource id of a view:\n\n```java\ntabSwitcher.setEmptyView(R.layout.empty_view); \n// or tabSwitcher.setEmptyView(R.layout.empty_view, 1000L) if an animation duration should be specified\n```\n\nAn example of a placeholder view being shown, when the tab switcher is empty, can be seen in the screenshot below.\n\n![](doc/images/empty_view.png)\n\n## Padding\n\nThe view `TabSwitcher` overrides the `setPadding`-methods of the class `View` in order to apply the padding to all tabs as well as to their parent view. The main purpose of this behavior is to apply window insets, when using a translucent status and/or navigation bar as it can be seen in the library's example app. The following code sample demonstrates, how the window insets of an activity can be applied to a tab switcher by using a `OnApplyWindowInsetsListener`. It is meant to be used in the activity's `onCreate`-method.\n\n```java\nViewCompat.setOnApplyWindowInsetsListener(tabSwitcher, new OnApplyWIndowInsetsListener() {\n\n    @Override\n    public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {\n        tabSwitcher.setPadding(insets.getSystemWindowInsetsLeft(), \n                insets.getSystemWindowInsetsTop(),\n                insets.getSystemWindowInsetsRight(),\n                insets.getSystemWindowInsetsBottom());\n        return insets;\n    }\n\n});\n```\n\nIf the padding of a `TabSwitcher` should not be applied to the content of tabs, `false` can be passed to the `applyPaddingToTabs`-method. This prevents the content of tabs from being inset, but does not affect the position of tabs or the position of a `TabSwitcher`'s toolbar(s). This might be useful, if you want to take care of the padding, which is applied to tabs by yourself, e.g. when the content should scroll below the system's status and/or navigation bar.\n\n## Contact information\n\nFor personal feedback or questions feel free to contact me via the mail address, which is mentioned on my [Github profile](https://github.com/michael-rapp). If you have found any bugs or want to post a feature request please use the [bugtracker](https://github.com/michael-rapp/ChromeLikeTabSwitcher/issues) to report them.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichael-rapp%2Fchromeliketabswitcher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichael-rapp%2Fchromeliketabswitcher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichael-rapp%2Fchromeliketabswitcher/lists"}