【问题标题】:How set the fixed count in TabLayout?如何在 TabLayout 中设置固定计数?
【发布时间】:2016-01-28 18:28:37
【问题描述】:

我将 TabLayout 与 viewPager 一起使用,而 viewPager 使用 RecyclerView 来作为它扩展 FragmentStatePageAdapter 的片段。

这一切都很好。 但是,我有一个场景,我想在可滚动模式下(当 tabMode 设置为可滚动时)将 tabLayout 的项目数设置为仅 (7)。

不知何故,当 tabLayout 设置为可滚动时,它只为每个设备设置 5 个项目,但在我的场景中,我希望它调整 7 个项目而不考虑任何设备。

我尝试将项目宽度设为 totalDeviceWidht/7 ,但没有运气,因为它仍然采用相同的宽度。

我还尝试通过编写自定义 tabLayout 来覆盖 onMeasure() 方法。但是,没有运气。

我不确定问题是否出在 pagerTabStrip 上,或者当 tabMode 设置为可滚动时 viewPager 和 tabLayout 如何计算要修复的项目数。

我在过去 3 天一直被这个问题困扰。

这是我的主要 xml 布局..

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"

    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.movie.bms.views.activities.TimeActivity"
    tools:showIn="@layout/activity_time"
    >

    <android.support.design.widget.TabLayout
        android:id="@+id/time_sliding_tab"
        android:layout_width="match_parent"
        android:layout_height="61.8dp"
        android:background="#06acef"
        android:elevation="0dp"
        android:theme="@style/ThemeOverlay.AppCompat.Dark"
        app:elevation="@dimen/elevation.small"
        app:tabGravity="center"
        app:tabIndicatorColor="@color/white"
        app:tabMode="scrollable"
        app:tabPaddingEnd="-1dp"
        app:tabPaddingStart="-1dp"
        android:fillViewport="false"
        ></android.support.design.widget.TabLayout>

     <com.utils.customcomponents.CustomViewPager
            android:id="@+id/time_view_pager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:transitionName="@string/event_body_transition">
    </com.utils.customcomponents.CustomViewPager>
</LinearLayout>

任何形式的帮助或建议将不胜感激。

【问题讨论】:

  • 如果您将 TabLayout 封装在水平可滚动布局中并在代码中检查您是否有 7 个并仅从 7 个开始激活可滚动布局怎么办?
  • 这种方法可能行不通,因为在 7 个项目之后我可能还有 20 个项目。我真正想要的是,我希望 scrollView tabMode 适合 7 个项目,就目前而言,它将项目作为设备宽度。
  • 发布您的布局文件
  • @NJNileshJ 更新了,请看一下。

标签: android android-viewpager android-tablayout


【解决方案1】:

您可以通过在 xml 中的 TabLayout 上设置 app:tabMinWidthapp:tabMaxWidth 元素来影响选项卡的实际宽度。

以 Nexus 5 (360dp) 为例:

<android.support.design.widget.TabLayout
        android:id="@+id/time_sliding_tab"
        android:layout_width="match_parent"
        android:layout_height="62dp"
        android:background="#06acef"
        app:tabGravity="center"
        app:tabMaxWidth="50dp"
        app:tabMinWidth="50dp"
        app:tabMode="scrollable" />

但说实话,您需要估计“猜测”您的目标宽度是多少,并为此进行优化。它在实际设备上的外观将取决于其实际宽度。

如果您想让它 100% 适合,您需要:

  • 在代码中实例化 TabLayout 并将正确的 app:tabMinWidthtabMaxWidth 值作为 AttributeSet 传递。 (根据屏幕宽度计算)
  • 在现有的 TabLayout 实例上使用 reflection 来设置 mRequestedTabMinWidthmRequestedTabMaxWidth 私有字段。 (不推荐)

反射案例如何工作的示例:

import android.content.Context;
import android.support.design.widget.TabLayout;
import android.util.AttributeSet;

import java.lang.reflect.Field;

public class SevenTabLayout extends TabLayout {

    public class SetTabWidthException extends RuntimeException {

    }

    public SevenTabLayout(Context context) {
        super(context);
    }

    public SevenTabLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        initializeTabWidths();
    }

    public SevenTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initializeTabWidths();
    }

    public void initializeTabWidths() {
        int tabwidth = 140; // Screensize divided by 7
        setPrivateField("mRequestedTabMinWidth", tabwidth);
        setPrivateField("mRequestedTabMaxWidth", tabwidth);
    }

    private void setPrivateField(String tabMinWidthFieldName, int value) {
        try {
            Field f = TabLayout.class.getDeclaredField(tabMinWidthFieldName);
            f.setAccessible(true);
            f.setInt(this, value);
        } catch (NoSuchFieldException e) {
            throw new SetTabWidthException();
        } catch (IllegalAccessException e2) {
            throw new SetTabWidthException();
        }
    }
}

现在您可以轻松地为initializeTabWidths() 方法添加单元测试,以便在升级设计支持库后检测该方法何时停止工作。

【讨论】:

  • 哦,伙计...谢谢一吨...工作得很好,在我试图从程序设置属性之间,但 tabLayout 实例给了我这两个属性。你提到过AttributeSet,我应该如何使用tabLayout中的属性实例。
  • 这似乎比我想象的要难,但我要做的是创建一个 TabLayout 的子类,并重写采用 AttributeSet 的构造函数。然后创建您自己的 AttributeSet 实现,它包裹了 android 生成的 AttributeSet,但为 tabMaxWidthtabMinWidth 属性返回不同的值。很复杂,但应该可以。
  • 我想得越多,我实际上会简单地使用反射来覆盖字段:创建 TabLayout 的子类,覆盖构造函数并在 super 之后调用一个使用反射设置 @ 的新方法987654335@ 和mRequestedTabMaxWidth。虽然这有点脆弱(如果有人更改了参数名称),因此您还需要为此方法添加单元测试。这样您就可以确定何时停止工作。
  • 好的,但是如果我使用反射,我需要编写单元测试用例,然后在失败时我再次需要处理失败用例。为什么不我只是创建一个属性集,然后使用修改后的 tabMaxWidth 和 tabMinWidth 值传入构造函数。我认为,这应该适用于所有情况。
  • 是的,我只是认为编写代码会稍微复杂一些。 :) 关于单元测试,只有在更新设计支持库时才会失败,因此在这种情况下,您需要修复它。 (它不是灵丹妙药,但至少你可以检测到什么时候坏了)
猜你喜欢
  • 2020-11-29
  • 2016-06-17
  • 2023-04-10
  • 1970-01-01
  • 2012-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多