3

Background

I have a TabLayout with some elements in it.

In portrait mode, the elements don't have enough space to appear. So I used:

app:tabMode="scrollable"

On the other hand, in landscape mode, the elements have excess space and I want it to be centered. So I used this approach:

<android.support.design.widget.TabLayout
    android:id="@+id/tabs"
    style="@style/Tab"
    android:layout_width="wrap_content" <!-- Used wrap_content -->
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true" <!-- And CenterHorizontal -->
    app:tabMode="scrollable" />

But since the background color is null in my MainActivity:

window.setBackgroundDrawable(null)

The TabLayout appears with (Black Wings) in Landscape Mode.

I want it to have @color/colorPrimary wings instead.


So I had two options:

1- Make the background of my MainActivity, not null (aka @color/colorPrimary)

I don't want to do that since all my fragments in the companion ViewPager will experience Overdraw because they all have different backgrounds set programmatically.

OR

2- Add a Container to incubate my TabLayout and set its background with my @color/colorPrimary, like so:

<RelativeLayout
    android:id="@+id/tabs_parent"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary">

    <android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        style="@style/Tab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        app:tabMode="scrollable" />
</RelativeLayout>

I will discuss the problems of this approach below.


Problem

Using Option #2 above:

There is still a tiny bit of Overdraw where the two views, parent RelativeLayout and child TabLayout, overlap.

So how can I remove this extra bit of Overdraw?


Thoughts

I am thinking of overriding the OnDraw method in the View class to suit my needs, but the challenge is that how to know the actual positions I would need to ClipRect()

Another thought is to come up with a, you know, (simpler) approach different from Option #2 above, to solve the Background issue.

Thanks in advance.

Android Admirer
  • 2,310
  • 2
  • 17
  • 38
  • Have you considered setting two different designs for landscape and portrait modes? [This](http://developer.android.com/training/basics/supporting-devices/screens.html) – Abhi Jun 16 '18 at 00:39
  • Yes, but what if the device is a tablet, the portrait mode will also have excess space @Abhi – Android Admirer Jun 16 '18 at 00:40
  • 1
    I posted my solution to this problem on https://stackoverflow.com/questions/39002684/tabs-dont-fit-to-screen-with-tabmode-scrollable-even-with-a-custom-tab-layout/50382854#50382854 I would set it to scrollable and resize the tabs if they were smaller than the screen width. The other solutions posted there didn't work for me. – Tyler V Jun 16 '18 at 02:23
  • Thanks, that worked for me. You can add this as an answer @TylerV – Android Admirer Jun 16 '18 at 08:07

2 Answers2

1

I looked all over for an answer to this exact problem. In my case I was dynamically adding and removing tabs, so I wanted it to fill the screen when there were only a few tabs, but start scrolling when there were too many rather than shrinking them or putting the titles on two lines. Using the following custom tab layout finally got it working for me. It was key to set the minimum width before calling super.onMeasure().

public class CustomTabLayout extends TabLayout {

    public CustomTabLayout(Context context) {
        super(context);
    }

    public CustomTabLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        ViewGroup tabLayout = (ViewGroup)getChildAt(0);
        int childCount = tabLayout.getChildCount();

        DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
        int tabMinWidth = displayMetrics.widthPixels/childCount;

        for(int i = 0; i < childCount; ++i){
            tabLayout.getChildAt(i).setMinimumWidth(tabMinWidth);
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

Set the tab mode to scrollable in the xml.

    <com.package.name.CustomTabLayout
        android:id="@+id/my_tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="scrollable">
Tyler V
  • 9,694
  • 3
  • 26
  • 52
0

I think you don't need to wrap your TabLayout with the additional RelativeLayout

just add the background to your tabLayout like so,

<android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        style="@style/Tab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:layout_centerHorizontal="true"
        app:tabMode="scrollable" />
KGeeks
  • 173
  • 6
  • Thanks, but giving the `TabLayout` a background didn't help because 1- the color is already overdrawn with the items' `@color/DarkPrimaryColor` and 2- Since we have `android:layout_width="wrap_content"` we still have the (Black Wings) I talked about above. – Android Admirer Jun 16 '18 at 07:35