Search code examples
androidandroid-custom-viewandroid-tabsandroid-tablayoutclip

Android - Prevent TabLayout's children from clipping Tab contents


The problem is simple. I have a TabLayout inside a CoordinatorLayout, and I dynamically set a CustomView for each Tab at runtime. The tabs have some animations and custom content that currently gets clipped at the Tab's edges.

I've set clipToPadding and clipChildren to false throughout all the view hierarchy with no success. Tabs are still getting clipped.

So the question is, how to avoid clipping tab's custom views inside a TabLayout?

Here's some code so you can see what I'm doing:

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:clipChildren="false"
    android:fitsSystemWindows="false"
    tools:context=".MainTabbedActivity">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/appbar_padding_top"
    android:elevation="4dp"
    android:clipToPadding="false"
    android:clipChildren="false"
    android:fitsSystemWindows="false"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:clipToPadding="false"
        android:clipChildren="false"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/AppTheme.PopupOverlay">

    </android.support.v7.widget.Toolbar>

    <android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clipToPadding="false"
        android:clipChildren="false"
        app:tabPaddingBottom="-1dp"
        app:tabPaddingEnd="-1dp"
        app:tabPaddingStart="-1dp"
        app:tabPaddingTop="-1dp"
        app:tabIndicatorColor="@android:color/white"/>

</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    ... />

And then, a custom Tab looks like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:layout_height="wrap_content">

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="32dp"
    android:scaleType="fitCenter"
    android:layout_marginBottom="-4dp"
    android:adjustViewBounds="true"
    android:id="@+id/tab_pic" />

<TextView
    android:id="@+id/tab_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/something"
    android:textColor="@color/white"
    android:textStyle="bold"
    android:textSize="12sp"
    android:visibility="invisible"/>

The result is the ImageView being clipped when animating its position/bounds.

Cheers


Solution

  • Ok, this was quick. I found the solution. It seems to me that Android creates an intermediate parent view between the TabLayout and the actual tab content.

    So doing the following for each tab...:

    ViewGroup realTabs = ((ViewGroup) mTabLayout.getChildAt(0));
        realTabs.setClipToPadding(false);
        realTabs.setClipChildren(false);
    
        if (realTabs.getChildAt(0) instanceof ViewGroup) { // <-- This is the intermediate parent ViewGroup
            ((ViewGroup)realTab0.getChildAt(0)).setClipToPadding(false);
            ((ViewGroup)realTab0.getChildAt(0)).setClipChildren(false);
        }
    

    ...will solve the problem.

    Thanks