Android Support Design TabLayout: Gravity Center และ Mode Scrollable


104

ฉันกำลังพยายามใช้ Design TabLayout ใหม่ในโครงการของฉัน ฉันต้องการให้เค้าโครงปรับให้เข้ากับทุกขนาดหน้าจอและการวางแนว แต่สามารถมองเห็นได้อย่างถูกต้องในทิศทางเดียว

ฉันกำลังจัดการกับ Gravity และ Mode ที่ตั้งค่า tabLayout ของฉันเป็น:

    tabLayout.setTabGravity(TabLayout.GRAVITY_CENTER);
    tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);

ดังนั้นฉันคาดว่าถ้าไม่มีที่ว่าง tabLayout ก็เลื่อนได้ แต่ถ้ามีที่ว่างมันจะอยู่ตรงกลาง

จากคำแนะนำ:

GRAVITY_CENTER int สุดท้ายแบบคงที่สาธารณะใช้เพื่อจัดวางแท็บที่อยู่ตรงกลางของ TabLayout

GRAVITY_FILL int สุดท้ายแบบคงที่สาธารณะใช้เพื่อเติม TabLayout ให้มากที่สุด ตัวเลือกนี้จะมีผลเมื่อใช้กับ MODE_FIXED เท่านั้น

สาธารณะคง int สุดท้าย MODE_FIXED แท็บคงที่แสดงแท็บทั้งหมดพร้อมกันและใช้กับเนื้อหาที่ได้รับประโยชน์จากการหมุนอย่างรวดเร็วระหว่างแท็บ จำนวนแท็บสูงสุดถูก จำกัด โดยความกว้างของมุมมอง แท็บคงที่มีความกว้างเท่ากันตามป้ายแท็บที่กว้างที่สุด

MODE_SCROLLABLE int สุดท้ายแบบคงที่สาธารณะแท็บที่เลื่อนได้จะแสดงชุดย่อยของแท็บในช่วงเวลาใดเวลาหนึ่งและสามารถมีป้ายกำกับแท็บที่ยาวขึ้นและแท็บจำนวนมากขึ้น เหมาะที่สุดสำหรับการเรียกดูบริบทในอินเทอร์เฟซแบบสัมผัสเมื่อผู้ใช้ไม่จำเป็นต้องเปรียบเทียบป้ายกำกับแท็บโดยตรง

ดังนั้น GRAVITY_FILL จึงเข้ากันได้กับ MODE_FIXED เท่านั้น แต่ที่ไม่ได้ระบุอะไรสำหรับ GRAVITY_CENTER ฉันคาดว่ามันจะเข้ากันได้กับ MODE_SCROLLABLE แต่นี่คือสิ่งที่ฉันได้รับจากการใช้ GRAVITY_CENTER และ MODE_SCROLLABLE

ป้อนคำอธิบายภาพที่นี่

ดังนั้นจึงใช้ SCROLLABLE ในทั้งสองทิศทาง แต่ไม่ได้ใช้ GRAVITY_CENTER

นี่คือสิ่งที่ฉันคาดหวังสำหรับแนวนอน แต่ในการมีสิ่งนี้ฉันต้องตั้งค่า MODE_FIXED ดังนั้นสิ่งที่ฉันได้รับในแนวตั้งคือ:

ป้อนคำอธิบายภาพที่นี่

เหตุใด GRAVITY_CENTER จึงไม่ทำงานสำหรับ SCROLLABLE หาก tabLayout พอดีกับหน้าจอ มีวิธีใดในการตั้งค่าแรงโน้มถ่วงและโหมดแบบไดนามิก (และเพื่อดูสิ่งที่ฉันคาดหวัง)

ขอบคุณมาก!

แก้ไข: นี่คือเค้าโครงของ TabLayout ของฉัน:

<android.support.design.widget.TabLayout
    android:id="@+id/sliding_tabs"
    android:layout_width="match_parent"
    android:background="@color/orange_pager"
    android:layout_height="wrap_content" />

@ Fighter42 คุณพบวิธีแก้ปัญหานี้หรือไม่? ฉันกำลังเผชิญกับปัญหาเดียวกัน
Spynet

วิธีเดียวที่ฉันพบคือรับขนาดของแท็บของคุณ (ด้วยตนเอง) จากนั้นกำหนดค่าพารามิเตอร์เลย์เอาต์โดยขึ้นอยู่กับว่าเหมาะสมหรือไม่
Javier Delgado

@ Fighter42 คุณสามารถโพสต์โค้ดตัวอย่างสำหรับโซลูชันที่คุณใช้อยู่ได้ไหม
Sammys

1
ฉันรู้ว่าคำตอบของฉันไม่ดีสำหรับเหตุผล แต่มันช่วยฉันได้ เว้นวรรคก่อนและหลังข้อความ จากนั้นจะเลื่อนได้ ในทั้งสองโหมด
อามมี่

คำตอบ:


134

แท็บแรงโน้มถ่วงเท่านั้นเอฟเฟกMODE_FIXEDต์

ทางเลือกหนึ่งที่เป็นไปได้คือตั้งค่าlayout_widthเป็นwrap_contentและlayout_gravityเป็นcenter_horizontal:

<android.support.design.widget.TabLayout
    android:id="@+id/sliding_tabs"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    app:tabMode="scrollable" />

หากแท็บมีขนาดเล็กกว่าความกว้างของหน้าจอTabLayoutตัวเองก็จะเล็กลงเช่นกันและจะอยู่กึ่งกลางเนื่องจากแรงโน้มถ่วง หากแท็บใหญ่กว่าความกว้างของหน้าจอTabLayoutจะตรงกับความกว้างของหน้าจอและการเลื่อนจะเปิดใช้งาน


1
ฉันใช้ดีไซน์ Material สำหรับแอปของฉัน ฉันติดตามตัวอย่างจากandroidhive.info/2015/09/… Tab scrollable ไม่ทำงานในอุปกรณ์ Kitkat และ Jelly bean ใน lollipop ฉันสามารถเลื่อนแท็บได้ แต่ในอุปกรณ์อื่นที่ไม่ใช่อมยิ้มแท็บที่เลื่อนไม่ทำงาน แต่การปัดใช้งานได้ดี ฉันขอทราบว่าจะมีปัญหาอะไร
user2681579

สิ่งนี้ใช้ไม่ได้กับฉันใน API 15 / support.design:25.1.0 แท็บถูกปล่อยให้เป็นธรรมเมื่อแคบกว่าความกว้างของหน้าต่าง การตั้งค่า app:tabMaxWidth="0dp"และandroid:layout_centerHorizontal="true"ทำงานกับแท็บกลาง
Baker

1
มันได้ผลสำหรับฉัน แท็บจะอยู่กึ่งกลางตลอดเวลา แต่เมื่อเลื่อนไม่ได้จริงแท็บจะไม่เต็มความกว้างทั้งหมด
José Augustinho

15

นี่คือวิธีที่ฉันทำ

TabLayout.xml

<android.support.design.widget.TabLayout
            android:id="@+id/tab_layout"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:background="@android:color/transparent"
            app:tabGravity="fill"
            app:tabMode="scrollable"
            app:tabTextAppearance="@style/TextAppearance.Design.Tab"
            app:tabSelectedTextColor="@color/myPrimaryColor"
            app:tabIndicatorColor="@color/myPrimaryColor"
            android:overScrollMode="never"
            />

สร้าง

@Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mToolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
        mTabLayout = (TabLayout)findViewById(R.id.tab_layout);
        mTabLayout.setOnTabSelectedListener(this);
        setSupportActionBar(mToolbar);

        mTabLayout.addTab(mTabLayout.newTab().setText("Dashboard"));
        mTabLayout.addTab(mTabLayout.newTab().setText("Signature"));
        mTabLayout.addTab(mTabLayout.newTab().setText("Booking/Sampling"));
        mTabLayout.addTab(mTabLayout.newTab().setText("Calendar"));
        mTabLayout.addTab(mTabLayout.newTab().setText("Customer Detail"));

        mTabLayout.post(mTabLayout_config);
    }

    Runnable mTabLayout_config = new Runnable()
    {
        @Override
        public void run()
        {

           if(mTabLayout.getWidth() < MainActivity.this.getResources().getDisplayMetrics().widthPixels)
            {
                mTabLayout.setTabMode(TabLayout.MODE_FIXED);
                ViewGroup.LayoutParams mParams = mTabLayout.getLayoutParams();
                mParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
                mTabLayout.setLayoutParams(mParams);

            }
            else
            {
                mTabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
            }
        }
    };

ฉันทำการเปลี่ยนแปลงเล็กน้อยของโซลูชันของ @Mario Velasco ในส่วนที่รันได้


โซลูชันนี้มีปัญหาเดียวกันกับที่ฉันพูดถึงในโซลูชันของ Tiago
Sotti

โซลูชันนี้ทำงานบนแท็บที่ไม่มีไอคอนจะเกิดอะไรขึ้นถ้าฉันมีไอคอนพร้อมข้อความ ?? : /
Emre Tekin

@EmreTekin ใช่มันใช้งานได้กับไอคอนแท็บของฉันมีไอคอนพร้อมข้อความ
Flux

tabLayout.getWidth()คืนค่าศูนย์ให้ฉันเสมอ
ishandutta2007

8

เนื่องจากฉันไม่พบว่าเหตุใดพฤติกรรมนี้จึงเกิดขึ้นฉันจึงใช้รหัสต่อไปนี้:

float myTabLayoutSize = 360;
if (DeviceInfo.getWidthDP(this) >= myTabLayoutSize ){
    tabLayout.setTabMode(TabLayout.MODE_FIXED);
} else {
    tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
}

โดยทั่วไปฉันต้องคำนวณความกว้างของแท็บเลย์เอาต์ด้วยตนเองจากนั้นตั้งค่าโหมดแท็บขึ้นอยู่กับว่า tabLayout พอดีกับอุปกรณ์หรือไม่

สาเหตุที่ฉันได้ขนาดของเลย์เอาต์ด้วยตนเองนั้นเป็นเพราะแท็บทั้งหมดไม่ได้มีความกว้างเท่ากันในโหมดเลื่อนได้และอาจกระตุ้นให้บางชื่อใช้ 2 บรรทัดเหมือนที่เกิดขึ้นกับฉันในตัวอย่าง


ด้วยวิธีนี้ข้อความอาจถูกย่อและใช้ 2 บรรทัดเช่นกัน ดูคำตอบและวิธีแก้ปัญหาอื่น ๆ ในหัวข้อนี้เกี่ยวกับเรื่องนี้ คุณกำลังลดความเสี่ยงที่จะปรากฏขึ้น แต่จะปรากฏบ่อยครั้งเมื่อ TabLayout มีขนาดเล็กกว่า screenWidth เล็กน้อย
Sotti

8

ทำให้ทุกอย่างง่ายขึ้นเพียงแค่เพิ่มแอป: tabMode = "scrollable" และ android: layout_gravity = "bottom"

เช่นนี้

<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
app:tabMode="scrollable"
app:tabIndicatorColor="@color/colorAccent" />

ป้อนคำอธิบายภาพที่นี่


7
นี่ไม่ใช่สิ่งที่ผู้สร้างกำลังขอ ปัญหาเกี่ยวกับแนวทางนี้คือในสถานการณ์ที่คุณมี 2 แท็บหรือ 3 สามแท็บในโทรศัพท์ที่ข้อความมีขนาดเล็กคุณจะมีเค้าโครงเหมือน Google Play Store ซึ่งแท็บจะอยู่ทางด้านซ้าย ผู้สร้างต้องการให้แท็บเข้าถึงจากขอบหนึ่งไปอีกขอบหนึ่งเมื่อทำได้และเลื่อนไปอย่างอื่น
Sotti

ปัญหาเดียวกัน. คุณสามารถแก้ไขได้หรือไม่?
Hoang Duc Tuan

7

ดูที่android-tablayouthelper

สลับ TabLayout โดยอัตโนมัติ MODE_FIXED และ TabLayout MODE_SCROLLABLE ขึ้นอยู่กับความกว้างของแท็บทั้งหมด


แต่เมื่อชื่อแท็บเป็นแบบไดนามิก ข้อความจะอยู่ในบรรทัดถัดไป และถ้าใช้เค้าโครงที่กำหนดเองสำหรับแท็บ ข้อความจุดไข่ปลาที่ท้ายเช่น
AndroidGeek

4

นี่คือวิธีการแก้ปัญหาที่ผมใช้ในการเปลี่ยนโดยอัตโนมัติระหว่างSCROLLABLEและ+FIXED FILLเป็นรหัสที่สมบูรณ์สำหรับโซลูชัน @ Fighter42:

(โค้ดด้านล่างแสดงตำแหน่งที่จะทำการแก้ไขหากคุณใช้เทมเพลตกิจกรรมแบบแท็บของ Google)

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.
    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mSectionsPagerAdapter);

    // Set up the tabs
    final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(mViewPager);

    // Mario Velasco's code
    tabLayout.post(new Runnable()
    {
        @Override
        public void run()
        {
            int tabLayoutWidth = tabLayout.getWidth();

            DisplayMetrics metrics = new DisplayMetrics();
            ActivityMain.this.getWindowManager().getDefaultDisplay().getMetrics(metrics);
            int deviceWidth = metrics.widthPixels;

            if (tabLayoutWidth < deviceWidth)
            {
                tabLayout.setTabMode(TabLayout.MODE_FIXED);
                tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
            } else
            {
                tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
            }
        }
    });
}

เค้าโครง:

    <android.support.design.widget.TabLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

หากไม่ต้องการเติมความกว้างควรใช้น้ำยา @karaokyo ดีกว่า


ใช้งานได้ดี การสลับไปมาระหว่างแนวนอนและแนวตั้งจะทำในสิ่งที่คุณคาดหวัง Google ควรใช้สิ่งนี้ในเทมเพลตเริ่มต้นสำหรับกิจกรรมแบบแท็บ
ใครสักคน

คำตอบนี้มีปัญหาเดียวกันกับที่ฉันพูดถึงในโซลูชันของ Tiago
Sotti

4

ฉันสร้างคลาส AdaptiveTabLayout เพื่อให้บรรลุสิ่งนี้ นี่เป็นวิธีเดียวที่ฉันพบว่าสามารถแก้ปัญหาได้จริงตอบคำถามและหลีกเลี่ยง / แก้ไขปัญหาที่คำตอบอื่น ๆ ที่นี่ไม่มี

หมายเหตุ:

  • จัดการรูปแบบโทรศัพท์ / แท็บเล็ต
  • กรณีจับที่มีที่ว่างพอสำหรับแต่ห้องพักไม่เพียงพอสำหรับMODE_SCROLLABLE MODE_FIXEDหากคุณไม่จัดการกรณีนี้มันจะเกิดขึ้นกับอุปกรณ์บางอย่างคุณจะเห็นขนาดข้อความที่แตกต่างกันหรือเตาอบข้อความสองบรรทัดในบางแท็บซึ่งดูไม่ดี
  • ได้รับการวัดจริงและไม่ได้ตั้งสมมติฐานใด ๆ (เช่นหน้าจอกว้าง 360dp หรืออะไรก็ตาม ... ) ซึ่งใช้ได้กับขนาดหน้าจอจริงและขนาดแท็บจริง ซึ่งหมายความว่าใช้งานได้ดีกับการแปลเนื่องจากไม่ถือว่าขนาดแท็บใด ๆ แท็บจะได้รับการวัด
  • จัดการกับการส่งผ่านที่แตกต่างกันในเฟส onLayout เพื่อหลีกเลี่ยงการทำงานพิเศษ
  • ความกว้างของเค้าโครงต้องอยู่wrap_contentบน xml อย่าตั้งค่าโหมดหรือแรงโน้มถ่วงใด ๆ บน xml

AdaptiveTabLayout.java

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.util.AttributeSet;
import android.widget.LinearLayout;

public class AdaptiveTabLayout extends TabLayout
{
    private boolean mGravityAndModeSeUpNeeded = true;

    public AdaptiveTabLayout(@NonNull final Context context)
    {
        this(context, null);
    }

    public AdaptiveTabLayout(@NonNull final Context context, @Nullable final AttributeSet attrs)
    {
        this(context, attrs, 0);
    }

    public AdaptiveTabLayout
    (
            @NonNull final Context context,
            @Nullable final AttributeSet attrs,
            final int defStyleAttr
    )
    {
        super(context, attrs, defStyleAttr);
        setTabMode(MODE_SCROLLABLE);
    }

    @Override
    protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b)
    {
        super.onLayout(changed, l, t, r, b);

        if (mGravityAndModeSeUpNeeded)
        {
            setModeAndGravity();
        }
    }

    private void setModeAndGravity()
    {
        final int tabCount = getTabCount();
        final int screenWidth = UtilsDevice.getScreenWidth();
        final int minWidthNeedForMixedMode = getMinSpaceNeededForFixedMode(tabCount);

        if (minWidthNeedForMixedMode == 0)
        {
            return;
        }
        else if (minWidthNeedForMixedMode < screenWidth)
        {
            setTabMode(MODE_FIXED);
            setTabGravity(UtilsDevice.isBigTablet() ? GRAVITY_CENTER : GRAVITY_FILL) ;
        }
        else
        {
            setTabMode(TabLayout.MODE_SCROLLABLE);
        }

        setLayoutParams(new LinearLayout.LayoutParams
                (LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));

        mGravityAndModeSeUpNeeded = false;
    }

    private int getMinSpaceNeededForFixedMode(final int tabCount)
    {
        final LinearLayout linearLayout = (LinearLayout) getChildAt(0);
        int widestTab = 0;
        int currentWidth;

        for (int i = 0; i < tabCount; i++)
        {
            currentWidth = linearLayout.getChildAt(i).getWidth();

            if (currentWidth == 0) return 0;

            if (currentWidth > widestTab)
            {
                widestTab = currentWidth;
            }
        }

        return widestTab * tabCount;
    }

}

และนี่คือคลาส DeviceUtils:

import android.content.res.Resources;

public class UtilsDevice extends Utils
{
    private static final int sWIDTH_FOR_BIG_TABLET_IN_DP = 720;

    private UtilsDevice() {}

    public static int pixelToDp(final int pixels)
    {
        return (int) (pixels / Resources.getSystem().getDisplayMetrics().density);
    }

    public static int getScreenWidth()
    {
        return Resources
                .getSystem()
                .getDisplayMetrics()
                .widthPixels;
    }

    public static boolean isBigTablet()
    {
        return pixelToDp(getScreenWidth()) >= sWIDTH_FOR_BIG_TABLET_IN_DP;
    }

}

ใช้ตัวอย่าง:

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

<FrameLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.com.stackoverflow.example.AdaptiveTabLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="?colorPrimary"
        app:tabIndicatorColor="@color/white"
        app:tabSelectedTextColor="@color/text_white_primary"
        app:tabTextColor="@color/text_white_secondary"
        tools:layout_width="match_parent"/>

</FrameLayout>

ส่วนสำคัญ

ปัญหา / ขอความช่วยเหลือ:

  • คุณจะเห็นสิ่งนี้:

Logcat:

W/View: requestLayout() improperly called by android.support.design.widget.TabLayout$SlidingTabStrip{3e1ebcd6 V.ED.... ......ID 0,0-466,96} during layout: running second layout pass
W/View: requestLayout() improperly called by android.support.design.widget.TabLayout$TabView{3423cb57 VFE...C. ..S...ID 0,0-144,96} during layout: running second layout pass
W/View: requestLayout() improperly called by android.support.design.widget.TabLayout$TabView{377c4644 VFE...C. ......ID 144,0-322,96} during layout: running second layout pass
W/View: requestLayout() improperly called by android.support.design.widget.TabLayout$TabView{19ead32d VFE...C. ......ID 322,0-466,96} during layout: running second layout pass

ผมไม่แน่ใจว่าจะแก้อย่างไร ข้อเสนอแนะใด ๆ ?

  • ในการสร้างมาตรการย่อยของ TabLayout ฉันกำลังสร้างการแคสต์และสมมติฐานบางอย่าง (เช่นเดียวกับเด็กเป็น LinearLayout ที่มีมุมมองอื่น ๆ .... ) ซึ่งอาจทำให้เกิดปัญหากับการอัปเดตไลบรารี Design Support เพิ่มเติม แนวทาง / ข้อเสนอแนะที่ดีกว่า?


2

ตัวอย่างที่ง่ายมากและใช้ได้ผลเสมอ

/**
 * Setup stretch and scrollable TabLayout.
 * The TabLayout initial parameters in layout must be:
 * android:layout_width="wrap_content"
 * app:tabMaxWidth="0dp"
 * app:tabGravity="fill"
 * app:tabMode="fixed"
 *
 * @param context   your Context
 * @param tabLayout your TabLayout
 */
public static void setupStretchTabLayout(Context context, TabLayout tabLayout) {
    tabLayout.post(() -> {

        ViewGroup.LayoutParams params = tabLayout.getLayoutParams();
        if (params.width == ViewGroup.LayoutParams.MATCH_PARENT) { // is already set up for stretch
            return;
        }

        int deviceWidth = context.getResources()
                                 .getDisplayMetrics().widthPixels;

        if (tabLayout.getWidth() < deviceWidth) {
            tabLayout.setTabMode(TabLayout.MODE_FIXED);
            params.width = ViewGroup.LayoutParams.MATCH_PARENT;
        } else {
            tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
            params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
        }
        tabLayout.setLayoutParams(params);

    });

}

ขอบคุณสำหรับความคิด ด้วยการเปลี่ยนแปลงเล็กน้อยสำหรับกรณีของฉันทำงานได้อย่างมีเสน่ห์
Eren Tüfekçi

1

นี่เป็นรหัสเดียวที่ใช้ได้กับฉัน:

public static void adjustTabLayoutBounds(final TabLayout tabLayout,
                                         final DisplayMetrics displayMetrics){

    final ViewTreeObserver vto = tabLayout.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {

            tabLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            int totalTabPaddingPlusWidth = 0;
            for(int i=0; i < tabLayout.getTabCount(); i++){

                final LinearLayout tabView = ((LinearLayout)((LinearLayout) tabLayout.getChildAt(0)).getChildAt(i));
                totalTabPaddingPlusWidth += (tabView.getMeasuredWidth() + tabView.getPaddingLeft() + tabView.getPaddingRight());
            }

            if (totalTabPaddingPlusWidth <= displayMetrics.widthPixels){

                tabLayout.setTabMode(TabLayout.MODE_FIXED);
                tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);

            }else{
                tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
            }

            tabLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
        }
    });
}

สามารถดึง DisplayMetrics ได้โดยใช้สิ่งนี้:

public DisplayMetrics getDisplayMetrics() {

    final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    final Display display = wm.getDefaultDisplay();
    final DisplayMetrics displayMetrics = new DisplayMetrics();

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
        display.getMetrics(displayMetrics);

    }else{
        display.getRealMetrics(displayMetrics);
    }

    return displayMetrics;
}

และ TabLayout XML ของคุณควรมีลักษณะดังนี้ (อย่าลืมตั้งค่า tabMaxWidth เป็น 0):

<android.support.design.widget.TabLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/tab_layout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:tabMaxWidth="0dp"/>

1
ใกล้จะถึงแล้ว แต่มีปัญหาบางอย่าง ปัญหาที่ชัดเจนที่สุดคือในบางอุปกรณ์ (และอุปกรณ์ที่ทำงานช้าส่วนใหญ่) คุณจะเห็นว่าเค้าโครงมีการแก้ไขและเปลี่ยนแปลงอย่างไร
Sotti

1
มีปัญหาอีกอย่างคือวิธีนี้จะวัดความกว้างทั้งหมดของ TabLayout เพื่อตัดสินใจว่าจะเลื่อนได้หรือไม่ นั่นไม่ถูกต้องมากนัก มีสถานการณ์ที่ TabLayout ไปไม่ถึงขอบทั้งสองในขณะที่โหมดเลื่อนได้ แต่ไม่มีที่ว่างเพียงพอสำหรับโหมดคงที่โดยไม่ต้องย่อขนาดข้อความที่ใช้จำนวนบรรทัดบนแท็บในทางที่ผิด (โดยปกติคือ 2) นี่เป็นผลโดยตรงของแท็บในโหมดคงที่มีความกว้างคงที่ (screenWidth / numberOfTabs) ในขณะที่อยู่ในโหมดเลื่อนได้แท็บจะตัดข้อความ + พาย
Sotti

1

สิ่งที่คุณต้องมีคือเพิ่มสิ่งต่อไปนี้ใน TabLayout ของคุณ

custom:tabGravity="fill"

ดังนั้นคุณจะมี:

xmlns:custom="http://schemas.android.com/apk/res-auto"
<android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        custom:tabGravity="fill"
        />

นี่ไม่ใช่สิ่งที่ครีเอเตอร์ขอ ปัญหาที่นี่คือแท็บต่างๆจะไม่สามารถเลื่อนได้และคุณจะถูกกำจัดพื้นที่ในหน้าจอ แท็บจะเริ่มหดตัวเป็นข้อความและในที่สุดก็จะมีสองเส้น
Sotti

1

ฉันแก้ไขสิ่งนี้โดยใช้สิ่งต่อไปนี้

if(tabLayout_chemistCategory.getTabCount()<4)
    {
        tabLayout_chemistCategory.setTabGravity(TabLayout.GRAVITY_FILL);
    }else
    {
        tabLayout_chemistCategory.setTabMode(TabLayout.MODE_SCROLLABLE);

    }

1

ทางออกสุดท้ายของฉัน

class DynamicModeTabLayout : TabLayout {

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    override fun setupWithViewPager(viewPager: ViewPager?) {
        super.setupWithViewPager(viewPager)

        val view = getChildAt(0) ?: return
        view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
        val size = view.measuredWidth

        if (size > measuredWidth) {
            tabMode = MODE_SCROLLABLE
            tabGravity = GRAVITY_CENTER
        } else {
            tabMode = MODE_FIXED
            tabGravity = GRAVITY_FILL
        }
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.