Android支持设计TabLayout:重力中心和模式可滚动

Jav*_*ado 88 android gravity material-design android-5.0-lollipop

我想在我的项目中使用新的Design TabLayout.我希望布局适应每个屏幕尺寸和方向,但可以在一个方向上正确看到.

我正在处理重力和模式设置我的tabLayout为:

    tabLayout.setTabGravity(TabLayout.GRAVITY_CENTER);
    tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
Run Code Online (Sandbox Code Playgroud)

所以我希望如果没有空间,tabLayout是可滚动的,但是如果有空间,它就会居中.

从指南:

public static final int GRAVITY_CENTER Gravity用于布置TabLayout中心的选项卡.

public static final int GRAVITY_FILL Gravity用于尽可能多地填充TabLayout.此选项仅在与MODE_FIXED一起使用时生效.

public static final int MODE_FIXED固定选项卡同时显示所有选项卡,最适用于受益于选项卡之间快速枢轴的内容.选项卡的最大数量受视图宽度的限制.固定标签的宽度相等,基于最宽的标签标签.

public static final int MODE_SCROLLABLE可滚动选项卡在任何给定时刻显示选项卡的子集,并且可以包含更长的选项卡标签和更多数量的选项卡.当用户不需要直接比较标签标签时,它们最适合用于浏览触摸界面中的上下文.

所以GRAVITY_FILL只与MODE_FIXED兼容但是,at没有为GRAVITY_CENTER指定任何内容,我希望它与MODE_SCROLLABLE兼容,但这是我使用GRAVITY_CENTER和MODE_SCROLLABLE

在此输入图像描述

因此它在两个方向都使用SCROLLABLE,但它没有使用GRAVITY_CENTER.

这就是我对景观的期望; 但要拥有这个,我需要设置MODE_FIXED,所以我得到的是肖像:

在此输入图像描述

如果tabLayout适合屏幕,为什么GRAVITY_CENTER不能用于SCROLLABLE?有没有办法动态设置重力和模式(并看看我期待什么)?

非常感谢你!

编辑:这是我的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" />
Run Code Online (Sandbox Code Playgroud)

tac*_*lux 120

标签重力仅影响MODE_FIXED.

一个可能的解决方案是你的设置layout_widthwrap_contentlayout_gravitycenter_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" />
Run Code Online (Sandbox Code Playgroud)

如果标签小于屏幕宽度,则TabLayout它本身也会更小,并且由于重力它将居中.如果选项卡大于屏幕宽度,TabLayout则将匹配屏幕宽度并激活滚动.


小智 13

这就是我做到的

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"
            />
Run Code Online (Sandbox Code Playgroud)

在OnCreate

@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);
            }
        }
    };
Run Code Online (Sandbox Code Playgroud)

我对可运行部分的@Mario Velasco解决方案做了一些小改动


Jav*_*ado 7

因为我没有找到为什么会发生这种行为,所以我使用了以下代码:

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

基本上,我必须手动计算tabLayout的宽度,然后根据tabLayout是否适合设备来设置Tab模式.

我手动获取布局大小的原因是因为并非所有选项卡在Scrollable模式下都具有相同的宽度,这可能会引发一些名称使用2行,因为它在示例中发生在我身上.


Der*_*tie 7

看看android-tablayouthelper

自动切换TabLayout.MODE_FIXED和TabLayout.MODE_SCROLLABLE取决于总标签宽度.


小智 6

保持简单只需添加app: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" />
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 这不是创作者所要求的.这种方法的问题在于,在文本较小的手机中有2个标签或3个三个标签的情况下,您将拥有类似Google Play商店的布局,其中标签位于左侧.创建者希望标签在可能的情况下从边到边到达,否则滚动. (6认同)

Sot*_*tti 5

我创建了一个 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;
    }

}
Run Code Online (Sandbox Code Playgroud)

这是 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;
    }

}
Run Code Online (Sandbox Code Playgroud)

使用示例:

<?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>
Run Code Online (Sandbox Code Playgroud)

要旨

问题/寻求帮助:

  • 你会看到这个:

日志猫:

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
Run Code Online (Sandbox Code Playgroud)

我不知道如何解决它。有什么建议?

  • 为了使 TabLayout 子度量,我进行了一些转换和假设(就像子项是包含其他视图的 LinearLayout....)这可能会在进一步的设计支持库更新中引起问题。更好的方法/建议?


小智 5

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

Run Code Online (Sandbox Code Playgroud)