TabLayout not filling width when tabMode set to 'scrollable'

前端 未结 17 718
傲寒
傲寒 2020-12-02 16:58

I have added TabLayout (from support library v22.2.1) to my Fragment as:



        
相关标签:
17条回答
  • 2020-12-02 17:19

    Please check this i think it works

    public class MainActivity extends AppCompatActivity {

    private TextView mTxv_Home, mTxv_News, mTxv_Announcement;
    private View mView_Home, mView_News, mView_Announcements;
    private HorizontalScrollView hsv;
    private ViewPager viewPager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTxv_Home = (TextView) findViewById(R.id.txv_home);
        mTxv_News = (TextView) findViewById(R.id.txv_news);
        mTxv_Announcement = (TextView) findViewById(R.id.txv_announcements);
        mView_Home = (View) findViewById(R.id.view_home);
        mView_News = (View) findViewById(R.id.view_news);
        mView_Announcements = (View) findViewById(R.id.view_announcements);
        hsv = (HorizontalScrollView) findViewById(R.id.hsv);
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager);
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int wt = displaymetrics.widthPixels/3;
        mTxv_Home.setWidth(wt);
        mTxv_News.setWidth(wt);
       // mTxv_Announcement.setWidth(wt);
        mTxv_Home.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
    
                mTxv_Home.setTextColor(Color.parseColor("#3F51B5"));
                mTxv_News.setTextColor(Color.parseColor("#808080"));
                mTxv_Announcement.setTextColor(Color.parseColor("#808080"));
                mView_Home.setBackgroundColor(Color.parseColor("#3F51B5"));
                mView_News.setBackgroundColor(Color.parseColor("#E8E8E8"));
                mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8"));
                hsv.post(new Runnable() {
                    public void run() {
                        hsv.fullScroll(HorizontalScrollView.FOCUS_LEFT);
                    }
                });
                viewPager.setCurrentItem(0);
            }
        });
        mTxv_News.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mTxv_Home.setTextColor(Color.parseColor("#808080"));
                mTxv_News.setTextColor(Color.parseColor("#3F51B5"));
                mTxv_Announcement.setTextColor(Color.parseColor("#808080"));
                mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8"));
                mView_News.setBackgroundColor(Color.parseColor("#3F51B5"));
                mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8"));
                hsv.post(new Runnable() {
                    public void run() {
                        int centerX = hsv.getChildAt(0).getWidth()/2;
                        hsv.scrollTo(centerX, 0);
                    }
                });
                viewPager.setCurrentItem(1);
    
    
            }
        });
        mTxv_Announcement.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mTxv_Home.setTextColor(Color.parseColor("#808080"));
                mTxv_News.setTextColor(Color.parseColor("#808080"));
                mTxv_Announcement.setTextColor(Color.parseColor("#3F51B5"));
                mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8"));
                mView_News.setBackgroundColor(Color.parseColor("#E8E8E8"));
                mView_Announcements.setBackgroundColor(Color.parseColor("#3F51B5"));
                hsv.post(new Runnable() {
                    public void run() {
                        hsv.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
                    }
                });
                viewPager.setCurrentItem(2);
            }
        });
    
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
            }
    
            @Override
            public void onPageSelected(int position) {
    
                if (position == 0) {
                    mTxv_Home.setTextColor(Color.parseColor("#3F51B5"));
                    mTxv_News.setTextColor(Color.parseColor("#808080"));
                    mTxv_Announcement.setTextColor(Color.parseColor("#808080"));
                    mView_Home.setBackgroundColor(Color.parseColor("#3F51B5"));
                    mView_News.setBackgroundColor(Color.parseColor("#E8E8E8"));
                    mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8"));
                    hsv.post(new Runnable() {
                        public void run() {
                            hsv.fullScroll(HorizontalScrollView.FOCUS_LEFT);
                        }
                    });
    
    
                } else if (position == 1) {
                    mTxv_Home.setTextColor(Color.parseColor("#808080"));
                    mTxv_News.setTextColor(Color.parseColor("#3F51B5"));
                    mTxv_Announcement.setTextColor(Color.parseColor("#808080"));
                    mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8"));
                    mView_News.setBackgroundColor(Color.parseColor("#3F51B5"));
                    mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8"));
                    hsv.post(new Runnable() {
                        public void run() {
                            int centerX = hsv.getChildAt(0).getWidth()/2;
                            hsv.scrollTo(centerX, 0);
                        }
                    });
    
    
                } else if (position == 2) {
                    mTxv_Home.setTextColor(Color.parseColor("#808080"));
                    mTxv_News.setTextColor(Color.parseColor("#808080"));
                    mTxv_Announcement.setTextColor(Color.parseColor("#3F51B5"));
                    mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8"));
                    mView_News.setBackgroundColor(Color.parseColor("#E8E8E8"));
                    mView_Announcements.setBackgroundColor(Color.parseColor("#3F51B5"));
                    hsv.post(new Runnable() {
                        public void run() {
                            hsv.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
                        }
                    });
                }
    
            }
            @Override
            public void onPageScrollStateChanged(int state) {
    
            }
        });
    }
    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new HomeFragment(), "Home");
        adapter.addFragment(new NewsFragment(), "News");
        adapter.addFragment(new AnnouncementsFragment(), "Announcements");
        viewPager.setAdapter(adapter);
    }
    
    class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();
    
        public ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }
    
        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }
    
        @Override
        public int getCount() {
            return mFragmentList.size();
        }
    
        public void addFragment(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
        }
    }
    

    }

    <HorizontalScrollView
        android:id="@+id/hsv"
        android:layout_width="fill_parent"
        android:layout_height="56dp"
        android:layout_weight="0"
        android:fillViewport="true"
        android:measureAllChildren="false"
        android:scrollbars="none" >
        <LinearLayout
            android:id="@+id/innerLay"
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:orientation="horizontal" >
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
    
                <TextView
                    android:id="@+id/txv_home"
                    android:layout_width="wrap_content"
                    android:layout_height="0dp"
                    android:layout_weight="1"
                    android:text="Home"
                    android:singleLine="true"
                    android:paddingLeft="35dp"
                    android:paddingRight="35dp"
                    android:gravity="center"
                    android:textSize="15sp"/>
                <View
                    android:id="@+id/view_home"
                    android:layout_width="match_parent"
                    android:layout_height="3dp"
                    android:background="@color/colorPrimary"
                   />
            </LinearLayout>
            <View
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:visibility="gone"
                android:background="#e8e8e8"/>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
    
                <TextView
                    android:id="@+id/txv_news"
                    android:layout_width="wrap_content"
                    android:layout_height="0dp"
                    android:layout_weight="1"
                    android:text="News"
                    android:singleLine="true"
                    android:paddingLeft="35dp"
                    android:paddingRight="35dp"
                    android:gravity="center"
                    android:textSize="15sp"/>
                <View
                    android:id="@+id/view_news"
                    android:layout_width="match_parent"
                    android:layout_height="3dp"
                    android:background="#e8e8e8"/>
            </LinearLayout>
            <View
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:visibility="gone"
                android:background="#e8e8e8"/>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
    
                <TextView
                    android:id="@+id/txv_announcements"
                    android:layout_width="wrap_content"
                    android:layout_height="0dp"
                    android:layout_weight="1"
                    android:singleLine="true"
                    android:text="Announcements"
                    android:paddingLeft="35dp"
                    android:paddingRight="35dp"
                    android:gravity="center"
                    android:textSize="15sp"/>
                <View
                    android:id="@+id/view_announcements"
                    android:layout_width="match_parent"
                    android:layout_height="1dp"
                    android:background="#e8e8e8"/>
            </LinearLayout>
    
        </LinearLayout>
    </HorizontalScrollView>
    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/hsv" />
    
    0 讨论(0)
  • 2020-12-02 17:21

    This solution works by letting android create the tabs then calculating the total width of them. Then checks if the tabs will fit the screen width, if it will fit then sets the tabMode to "fixed" which scales all the tabs to fit the screen width.

    The tab layout xml, parent doesn't matter:

    <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMode="scrollable"/>
    

    Then in your activity onCreate or fragment onCreateView:

    var totalWidth = 0
    var maxWidth = 0
    for (i in 0 until tabLayout.tabCount) {
        val tabWidth = (tabLayout.getChildAt(0) as ViewGroup).getChildAt(i)!!.width
        totalWidth += tabWidth
        maxWidth = max(maxWidth, tabWidth)
    }
    val screenWidth = Resources.getSystem().displayMetrics.widthPixels
    
    if (totalWidth <  screenWidth&& screenWidth/ tabLayout.tabCount >= maxWidth) {
    
        tabLayout.tabMode = TabLayout.MODE_FIXED
    }
    

    If you are using TabLayout with Viewpager, then you have to set a layoutChangeListener since the tabs are not inflated at the start.

    In your activity onCreate or fragment onCreateView:

    tabLayout.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
        var totalWidth = 0
        var maxWidth = 0
        for (i in 0 until tabLayout.tabCount) {
            val tabWidth = (tabLayout.getChildAt(0) as ViewGroup).getChildAt(i)!!.width
            totalWidth += tabWidth
            maxWidth = max(maxWidth, tabWidth)
        }
    
         val screenWidth = Resources.getSystem().displayMetrics.widthPixels
    
        if (totalWidth < screenWidth && screenWidth / tabLayout.tabCount >= maxWidth) {
    
            tabLayout.tabMode = TabLayout.MODE_FIXED
        }
    }
    

    Note: If you want all of your tabs to have same text size when the tabMode is "fixed", then you have to set the textSize manually from styles.xml.

    0 讨论(0)
  • 2020-12-02 17:22

    androidx version:

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" >
        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMaxWidth="0dp"
            app:tabGravity="fill"
            app:tabMode="fixed"
            />
    </androidx.viewpager.widget.ViewPager>
    

    ***** BELOW IS OLD ANSWER *****

    Try this one, it's a workaround which sets tabMaxWidth="0dp", tabGravity="fill" and tabMode="fixed".

     <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.TabLayout
             android:id="@+id/tabs"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             app:tabMaxWidth="0dp"
             app:tabGravity="fill"
             app:tabMode="fixed"/>
    </android.support.v4.view.ViewPager>
    

    Screenshot on a 10 inch tablet:

    0 讨论(0)
  • 2020-12-02 17:22

    I have tried almost all answeres, atlast found this one works like a charm.

    public void dynamicSetTabLayoutMode(TabLayout tabLayout) {
                int tabWidth = calculateTabWidth(tabLayout);
                int screenWidth =  getApplicationContext().getResources().getDisplayMetrics().widthPixels;
                if (tabWidth <= screenWidth) {
                    tabLayout.setTabMode(TabLayout.MODE_FIXED);
                } else {
                    tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
                }
            }
        
          private int calculateTabWidth(TabLayout tabLayout) {
                int tabWidth = 0;
                for (int i = 0; i < tabLayout.getChildCount(); i++) {
                    final View view = tabLayout.getChildAt(i);
                    view.measure(0, 0); 
                    tabWidth += view.getMeasuredWidth();
                }
                return tabWidth;
            }
    
    0 讨论(0)
  • 2020-12-02 17:22

    I was struggling as well and most options above did not work for me, so I created a version on the answer of DTX12.

    I have a boolean to check for tablet or not and make a check on landscape and portrait. Then set the layout based on amount of tabs.

    You might need to make the method public and call it on rotation / configurationchange.

    In the CustomTabLayout Code i replaced the mintabswidth method

    private void initTabMinWidth()
    {
    
    
    
        boolean isTablet = getContext().getResources().getBoolean(R.bool.device_is_tablet);
        boolean isLandscape = (wh[WIDTH_INDEX] > wh[HEIGHT_INDEX]) ? true : false;
    
    
        if (isTablet)
        {
            if (isLandscape)
            {
                if (this.getTabCount() > 8)
                {
                    this.setTabGravity(TabLayout.GRAVITY_FILL);
                    this.setTabMode(TabLayout.MODE_SCROLLABLE);
                } else
                {
                    this.setTabGravity(TabLayout.GRAVITY_FILL);
                    this.setTabMode(TabLayout.MODE_FIXED);
                }
            } else
            {
                if (this.getTabCount() > 6)
                {
                    this.setTabGravity(TabLayout.GRAVITY_FILL);
                    this.setTabMode(TabLayout.MODE_SCROLLABLE);
                } else
                {
                    this.setTabGravity(TabLayout.GRAVITY_FILL);
                    this.setTabMode(TabLayout.MODE_FIXED);
                }
            }
        } else
        {
            if (isLandscape)
            {
                if (this.getTabCount() > 6)
                {
                    this.setTabGravity(TabLayout.GRAVITY_FILL);
                    this.setTabMode(TabLayout.MODE_SCROLLABLE);
                } else
                {
                    this.setTabGravity(TabLayout.GRAVITY_FILL);
                    this.setTabMode(TabLayout.MODE_FIXED);
                }
            } else
            {
                if (this.getTabCount() > 4)
                {
                    this.setTabGravity(TabLayout.GRAVITY_FILL);
                    this.setTabMode(TabLayout.MODE_SCROLLABLE);
                } else
                {
                    this.setTabGravity(TabLayout.GRAVITY_FILL);
                    this.setTabMode(TabLayout.MODE_FIXED);
                }
            }
        }
    
    
    }
    
    0 讨论(0)
  • 2020-12-02 17:23

    Instead of creating custom TabLayout and hacking around or creating more layouts which acts as wrapper around TabLayout only for background. Try this,

    <android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        style="@style/MyColorAccentTabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        <!-- Instead of setting app:tabBackground -->
        android:background="@color/colorAccent"
        app:tabGravity="fill"
        app:tabMode="scrollable"/>
    

    This will set background to behind tabLayout instead of setting background behind every tab.

    0 讨论(0)
提交回复
热议问题