Search code examples
androidandroid-viewpagerandroid-viewandroid-scrollviewandroid-tablayout

TabLayout inside ViewPager prohibits swiping


I have the following ViewPager's FINANCIAL fragment page.

enter image description here

It is built using the following mythology

this.detailedStockFragmentPagerAdapter = new DetailedStockFragmentPagerAdapter(this.getSupportFragmentManager(), bundle);
viewPager.setAdapter(detailedStockFragmentPagerAdapter);
viewPager.setOffscreenPageLimit(Math.max(1, detailedStockFragmentPagerAdapter.getCount() - 1));
tabLayout.setupWithViewPager(viewPager);

private static class DetailedStockFragmentPagerAdapter extends FragmentPagerAdapter {
    public DetailedStockFragmentPagerAdapter(FragmentManager fm, Bundle bundle) {
        super(fm);
        this.bundle = bundle;
    }

    @Override
    public int getCount() {
        return 3;
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
            {
                ...
            }
            case 1:
            {
                ...
            }
            case 2:
            {
                FinancialFragment financialFragment = FinancialFragment.newInstance();
                financialFragment.setArguments(bundle);
                return financialFragment;
            }
            default:
                assert(false);
        }
        return null;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return JStockApplication.instance().getString(R.string.info);
            case 1:
                return JStockApplication.instance().getString(R.string.news);
            case 2:
                return JStockApplication.instance().getString(R.string.financial);
            default:
                return null;
        }
    }
}

In FINANCIAL page, there are 3 components

  1. Button
  2. TextView
  3. inner TabLayout (The bar with 1D, 1W, 1M, 3M, ...)

If I touch any of the following components, and swipe toward right, it works as expected.

  1. Button
  2. TextView
  3. Any empty area of the fragment

enter image description here


However, if my touch area is inner TabLayout, swipe doesn't work. It seems that the TabLayout has "eaten" my swipe event.

Any idea how I can have inner TabLayout in ViewPager fragment, yet doesn't affect my swipe event?

The XML of my ViewPager fragment page is as follow

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_marginBottom="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is button"
        android:textSize="18sp" />

    <TextView
        android:layout_marginBottom="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#ff000000"
        android:textSize="18sp"
        android:text="This fragment is not scrollable. How to make toolbar visible?"/>

    <LinearLayout
        android:id="@+id/period_tablayout_linear_layout"
        android:layout_width="match_parent"
        android:layout_height="38dp"
        android:orientation="vertical">

        <android.support.design.widget.TabLayout
            android:id="@+id/period_tab_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"

            app:tabTextAppearance="@style/TradingChartPeriodTabTextAppearance"
            app:tabPaddingStart="0dp"
            app:tabPaddingEnd="0dp"
            app:tabIndicatorHeight="2dp"
            app:tabMode="fixed"
            app:tabGravity="fill"
            app:tabBackground="?attr/tradingHistorySummaryChartBackgroundColor"
            app:tabSelectedTextColor="?attr/primaryTextColor"
            app:tabIndicatorColor="?attr/primaryTextColor">

            <android.support.design.widget.TabItem
                android:id="@+id/tab_item_1d"
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:text="@string/trading_day_1_short" />

            <android.support.design.widget.TabItem
                android:id="@+id/tab_item_1w"
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:text="@string/trading_week_1_short" />

            <android.support.design.widget.TabItem
                android:id="@+id/tab_item_1m"
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:text="@string/trading_month_1_short" />

            <android.support.design.widget.TabItem
                android:id="@+id/tab_item_3m"
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:text="@string/trading_months_3_short" />

            <android.support.design.widget.TabItem
                android:id="@+id/tab_item_6m"
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:text="@string/trading_months_6_short" />

            <android.support.design.widget.TabItem
                android:id="@+id/tab_item_1y"
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:text="@string/trading_year_1_short" />

            <android.support.design.widget.TabItem
                android:id="@+id/tab_item_5y"
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:text="@string/trading_years_5_short" />

            <android.support.design.widget.TabItem
                android:id="@+id/tab_item_10y"
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:text="@string/trading_period_max" />

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

    </LinearLayout>

</LinearLayout>

Solution

  • TabLayout is a subclass of HorizontalScrollView, which in turn is a subclass of ScrollView. If you disable horizontal scrolling, then the MotionEvent won't be swallowed by TabLayout, instead would be passed higher up the view hierarchy - to ViewPager.

    You can subclass TabLayout performing following changes:

    
        public class MyTabLayout extends TabLayout {
    
            public MyTabLayout(Context context) {
                super(context);
            }
    
            public MyTabLayout(Context context, AttributeSet attrs) {
                super(context, attrs);
            }
    
            public MyTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
                super(context, attrs, defStyleAttr);
            }
    
            @Override
            public boolean onTouchEvent(MotionEvent ev) {
                switch (ev.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        return false;
                    default:
                        return super.onTouchEvent(ev);
                }
            }
    
            @Override
            public boolean onInterceptTouchEvent(MotionEvent ev) {
                return false;
            }
    
        }
    
    

    Output:

    enter image description here