Android 我们如何为固定数量的可滚动选项卡配置TabLayout?
在一个项目中,我们使用了材质设计组件的Android 我们如何为固定数量的可滚动选项卡配置TabLayout?,android,material-components-android,Android,Material Components Android,在一个项目中,我们使用了材质设计组件的TabLayout和ViewPager。共有14个选项卡,我们希望其中7个选项卡在表格布局中一次可见。标签内容足够窄,我们确信7个标签不会太多,设计团队希望无论屏幕宽度如何,都能显示一致数量的标签(标签代表一周中的几天) 所有预定义的选项卡模式似乎都与此不匹配: MODE\u FIXED和MODE\u AUTO控制可见选项卡的数量。。。通过展示所有这些 MODE\u SCROLLABLE允许选项卡滚动。。。但是,我们无法控制可见选项卡的数量 有没有一种不
TabLayout
和ViewPager
。共有14个选项卡,我们希望其中7个选项卡在表格布局中一次可见。标签内容足够窄,我们确信7个标签不会太多,设计团队希望无论屏幕宽度如何,都能显示一致数量的标签(标签代表一周中的几天)
所有预定义的选项卡模式似乎都与此不匹配:
MODE\u FIXED
和MODE\u AUTO
控制可见选项卡的数量。。。通过展示所有这些
MODE\u SCROLLABLE
允许选项卡滚动。。。但是,我们无法控制可见选项卡的数量
有没有一种不涉及不可维护的黑客的方法来实现这一点,比如在运行时使用反射来修补tabPaddingStart
,或者迭代选项卡小部件并调整它们的LayoutParams
我已经看到了,但缺乏解释——特别是,不清楚如何使用app:tabMaxWidth
在运行时作为动态值。另外,这个问题与旧的设计支持库有关,它可能与MDC的实现有所不同 我也必须这样做,我特别注意地调查了这个问题。剧透:我失败了-目前你想通过股票TabLayout
和干净的Android方式实现的目标是不可能的
不过也有黑客)
- 最合适的方法是使用允许这样做的库-例如
- 尽管您提到了这一点,但不想这样做-迭代
TabLayout
子对象更改其LayoutParams
是下一个适当的方法。该方法利用Android提供的公共方法,不需要使用一些不太好的技术。说到这里
*反射开始
- 更改
tabPaddingStart
或requestedTabMinWidth
以及requestedTabMaxWidth
。这很糟糕。我甚至不想开始解释为什么。这是这个列表中最不合适的一种方式。不过,这仍然是一种解决问题的方法
- 这是干净的Android方式和
TabLayout
参数app:tabMaxWidth
和app:tabMinWidth
以及反射的组合。在这种情况下,反射有点不同-它几乎是正常的(尽可能多的反射)。我建议在integers.xml
中创建一个名为tabWidth
的integer
android资源(我相信您已经知道我要去哪里了),在应用程序启动时,您可以通过反射将其替换为screenWidth
的值除以7(或更小,取决于填充)
*反光饰面
- 还有一种方法,它是Android clean,但仍然非常不足。您可以组合使用
查看页面
和/或片段。最简单的是一个ViewPager
,其中有两个ViewPager
s和两个TabLayout
s,每个都有7个页面和7个选项卡。不过,您可能需要调整手势处理程序。还有更多的组合
我将不包括您在RecyclerView
和SnapHelper
的帮助下自己编写TabLayout
的方法,因为在Android中自己编写东西总是一种选择。。。浪费大量的时间
我知道这不是一个答案。此外,这是一个如何在Android中不做事情的列表,但有时我们需要选择黑暗面
希望能有所帮助。有几种方法可以显示固定数量的选项卡,而不考虑屏幕宽度,但所需的功能确实被锁定了。最值得注意的是,如果TabLayout中的getTabMinWidth()不是私有的,那么一个简单的解决方案就是在自定义TabLayout视图中重写该方法
下面是Eugen Pechanec在上面的评论中建议的内容,其中包括选项卡的自定义视图
首先是基地布局
活动\u main.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Tab x"
android:textAppearance="@style/TextAppearance.AppCompat.Body2" />
<!-- If an icon is needed. -->
<!-- <ImageView-->
<!-- android:id="@android:id/icon"-->
<!-- android:layout_width="48dp"-->
<!-- android:layout_height="48dp"-->
<!-- android:scaleType="centerCrop"-->
<!-- android:src="@drawable/ic_launcher_foreground" />-->
</LinearLayout>
tabMinWidth
、tabpaddingnd
和tabPaddingStart
都设置为0dp
tabMinWidth
的默认值可能太大,无法满足我们的需要。填充可以设置为非零,但我更愿意在选项卡的自定义视图中处理
ViewPager没有发生任何事情
至少在材料:1.1.0-beta01
中,有一个选项卡minwidth
XML属性用于表格布局
。您可以将其与自定义选项卡视图(tab.setCustomView(视图)
)结合使用。您必须在创建选项卡时知道所需的宽度,或者在选项卡间迭代,然后更新每个视图。@EugenPechanec:不过,我不知道如何在运行时使用tabMinWidth
。我们不知道编译时屏幕宽度的1/7是多少(至少是dp
维度)。啊,我的错误。我将tabMinWidth
设置为零。然后,选项卡中的自定义视图将有足够的腿部空间,使其尽可能小。其中一个问题是可滚动选项卡的默认最小宽度为72dp。第一步,将其置为零,这就是我们所做的。非常感谢您的详细写作!
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Tab x"
android:textAppearance="@style/TextAppearance.AppCompat.Body2" />
<!-- If an icon is needed. -->
<!-- <ImageView-->
<!-- android:id="@android:id/icon"-->
<!-- android:layout_width="48dp"-->
<!-- android:layout_height="48dp"-->
<!-- android:scaleType="centerCrop"-->
<!-- android:src="@drawable/ic_launcher_foreground" />-->
</LinearLayout>
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val tabLayout = findViewById<TabLayout>(R.id.tabs)
tabLayout.doOnLayout {
val tabWidth = tabLayout.width / 7
for (i in 1..14) {
tabLayout.newTab().run {
setCustomView(R.layout.custom_tab)
customView?.minimumWidth = tabWidth
setText("Tab $i")
tabLayout.addTab(this)
}
}
}
}
}