Is it possible for ActionBar Navigation Tabs to be displayed same on both phones and tablets?
See images for phone and tablets below:
PHONE:
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?
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.
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.
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
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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With