Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android ActionBar Navigation Tabs looks differ in phones and tablets

Is it possible for ActionBar Navigation Tabs to be displayed same on both phones and tablets?

See images for phone and tablets below:

PHONE: Phone Image

TABLET: Tablet

The Android documentation states "...when the screen is wide enough the tabs appear in the action bar alongside the action buttons...". We don't want them to appear in ActionBar. Any solutions?

like image 452
Abdullah Shoaib Avatar asked Nov 20 '13 10:11

Abdullah Shoaib


1 Answers

The ActionBar tabs are created by the ScrollingTabContainerView. The ActionBarView, the actual View for the ActionBar, contains a method ActionBarView.setEmbeddedTabView which is essentially responsible for the placement of the tabs either below or embedded in the ActionBar.

When the ActionBar is initialized in Activity, it uses the ActionBarPolicy to determine when to use the embedded tabs based on a boolean value that's defined as true in the system's resources, but false in portrait mode. So, upon this initialization ActionBarImpl.setHasEmbeddedTabs is called to determine where to place the tabs. And also, as the docs state:

...when the screen is wide enough the tabs appear in the action bar alongside the action buttons

So how do I stop it from embedding the tabs?

Seems like you have two choices here and one is clearly, at least to me, better than the other.

  1. You can use reflection to invoke ActionBarImpl.setHasEmbeddedTabs and set it to always be false. You need to use reflection because ActionBarImpl is an internal class and there is no public ActionBar method to indicate when to embed tabs.

  2. You can stop using the ActionBar.Tab API and switch to an alternative, like Google's SlidingTabLayout. This one will require you to use a ViewPager, which is usually is a nice plus when using tabs anyway and you may even already be using it.

Here are examples for both:

Using reflection

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    final ActionBar actionBar = getActionBar();
    // Implement your tabs
    ...
    try {
        final Class<?> clazz = actionBar.getClass();
        final Method embedTabs = clazz.getDeclaredMethod("setHasEmbeddedTabs", boolean.class);
        embedTabs.invoke(actionBar, false);
    } catch (final Exception ignored) {
        // Nothing to do
    }
}

Reflection results

Example

Switching from the fixed tabs to scrollable tabs

To use Google's SlidingTabLayout, you'll need to copy over two classes into your project. The classes you need are:

  • SlidingTabLayout
  • SlidingTabStrip

An example layout implementing the SlidingTabLayout would looks this like:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical">

    <your_path_to.SlidingTabLayout
          android:id="@+id/slidingTabs"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />

    <android.support.v4.view.ViewPager
          android:id="@+id/viewPager"
          android:layout_width="match_parent"
          android:layout_height="0dp"
          android:layout_weight="1" />

</LinearLayout> 

After inflating the layout and initializing the SlidingTabLayout using View.findViewById, you call SlidingTabLayout.setViewPager to bind the ViewPager to the tabs.

Check out Google's example for a full project

Scrollable tab results

Scrollable tabs are used in several of Google's app, like the Play Store and Play Music. For a short video demonstrating them, if you're unfamiliar, check out the Android design docs on tabs.

Conclusion

In short, I would recommend using scrollable tabs rather than fixed tabs (at least in landscape mode), if you don't want them to be embedded.

like image 163
adneal Avatar answered Oct 19 '22 22:10

adneal