如何在 TabLayout 中的选项卡之间添加边距?
How to add margin between tabs in TabLayout?
有没有办法在 TabLayout 中的选项卡之间添加边距?我试过为 Widget.Design.TabLayout 使用自定义样式,但有些属性仅与填充相关,但没有边距。
好的朋友们,我花了 2-3 个小时终于找到了解决方案。
如果您使用的是 TabLayout,则无法通过使用样式等为选项卡添加边距。 (如@Connecting life with Android 早先)
但是,您可以通过编写一些 Java 代码来实现。总而言之,您的代码应该类似于以下代码:
for(int i=0; i < mTabLayout.getTabCount(); i++) {
View tab = ((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(i);
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) tab.getLayoutParams();
p.setMargins(0, 0, 50, 0);
tab.requestLayout();
}
为了将每个选项卡作为视图获取,我们必须首先获取包含它们的容器。在这种情况下,TabLayout 使用 SlidingTabStrip 作为选项卡的容器。 SlidingTabStrip 是 TabLayout 的第一个子元素:
View tab = ((ViewGroup) mTabLayout.getChildAt(0))
在这个小细节之后,一切都非常简单。
这就是为四个不同的标签设置边距的方法。您可以更改 setMargins(v1,v2,v3,v4) 函数值以获得适合您正在使用的选项卡数量的值。我希望这有帮助。请注意,tabHost 是 TabHost 托管您正在使用的不同选项卡的对象。
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
View currentView;
for(int i=0;i<tabHost.getTabWidget().getChildCount();i++)
{
//This code removes divider between tabs
tabHost.getTabWidget().setDividerDrawable(null);
tabHost.getTabWidget().getChildAt(i).setLayoutParams(new
LinearLayout.LayoutParams((width/8)-2,50));
currentView = tabHost.getTabWidget().getChildAt(i);
LinearLayout.LayoutParams currentLayout =
(LinearLayout.LayoutParams) currentView.getLayoutParams();
currentLayout.setMargins(30, 5, 80, 0);
}
@Todor Kostov 回答得很好,但是标签的中心被滑走了,因为最后一个标签也有边距。
所以使用 mTabLayout.getTabCount() - 1
而不是 mTabLayout.getCodeCount()
.
for(int i=0; i < mTabLayout.getTabCount() - 1; i++) {
View tab = ((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(i);
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) tab.getLayoutParams();
p.setMargins(0, 0, 50, 0);
tab.requestLayout();
}
这是我在纯 xml.
中的做法
dimens.xml:
<!-- Set this to 50% of what you want the actual space between the tabs to be. -->
<dimen name="tab_spacing_half">5dp</dimen> <!-- i.e., 10dp spacing between tabs. -->
包含您的 TabLayout 的布局:
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/tab_spacing_half"/>
将此添加到您在 styles.xml 中的主题:
<item name="tabBackground">@drawable/tab_background</item>
drawable-nodpi\tab_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@drawable/tab_background_selected"
android:state_selected="true" />
<item
android:drawable="@drawable/tab_background_unselected"
android:state_selected="false"
android:state_focused="false"
android:state_pressed="false" />
</selector>
drawable-nodpi\tab_background_selected.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:left="@dimen/tab_spacing_half"
android:right="@dimen/tab_spacing_half"
android:top="@dimen/tab_spacing_half"
android:bottom="@dimen/tab_spacing_half">
<shape
android:shape="rectangle">
<corners
android:radius="@dimen/border_radius_small">
</corners>
<stroke
android:width="@dimen/divider_height_thick"
android:color="@color/white">
</stroke>
</shape>
</item>
</layer-list>
...这就是诀窍所在。实际上,根据您的 @dimen/tab_spacing_half
值将背景形状包裹在 item
和 "padding" 中。最后...
drawable-nodpi\tab_background_unselected.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:left="@dimen/tab_spacing_half"
android:right="@dimen/tab_spacing_half"
android:top="@dimen/tab_spacing_half"
android:bottom="@dimen/tab_spacing_half">
<shape
android:shape="rectangle">
<corners
android:radius="@dimen/border_radius_small">
</corners>
<stroke
android:width="@dimen/divider_height_thin"
android:color="@color/white">
</stroke>
</shape>
</item>
</layer-list>
这是@Todor Kostov 回答的 Kotlin 版本。
for (i in 0 until applicationList_tabLayout.tabCount) {
val tab = (applicationList_tabLayout.getChildAt(0) as ViewGroup).getChildAt(i)
val p = tab.layoutParams as ViewGroup.MarginLayoutParams
p.setMargins(10, 0, 10, 0)
tab.requestLayout()
}
这里的大多数建议似乎都建议调用 requestLayout() 来更新边距。这将触发一个新的布局过程。我个人也看到了动画布局时的问题,其中定义了 TabLayout,导致多次调用 requestLayout,有时使选项卡“跳转”
我认为设置选项卡之间边距的更好方法是扩展 TabLayout,并监听何时将子视图添加到 SlidingTabIndicator。
private const val YOUR_CUSTOM_MARGIN = 8
class CustomTabLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : TabLayout(
context,
attrs,
defStyleAttr
) {
init {
val tabStrip = (this.getChildAt(0) as ViewGroup)
tabStrip.setOnHierarchyChangeListener(object : OnHierarchyChangeListener {
override fun onChildViewAdded(p0: View?, p1: View?) {
if (p1 is TabView && p1.layoutParams is MarginLayoutParams) {
val params = p1.layoutParams as MarginLayoutParams
params.setMargins(YOUR_CUSTOM_MARGIN, 0, YOUR_CUSTOM_MARGIN, 0)
}
}
override fun onChildViewRemoved(p0: View?, p1: View?) {}
})
}
}
None 的答案对我有用!所以 是适合您的答案,请参阅以下结果。
有没有办法在 TabLayout 中的选项卡之间添加边距?我试过为 Widget.Design.TabLayout 使用自定义样式,但有些属性仅与填充相关,但没有边距。
好的朋友们,我花了 2-3 个小时终于找到了解决方案。
如果您使用的是 TabLayout,则无法通过使用样式等为选项卡添加边距。 (如@Connecting life with Android 早先)
但是,您可以通过编写一些 Java 代码来实现。总而言之,您的代码应该类似于以下代码:
for(int i=0; i < mTabLayout.getTabCount(); i++) {
View tab = ((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(i);
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) tab.getLayoutParams();
p.setMargins(0, 0, 50, 0);
tab.requestLayout();
}
为了将每个选项卡作为视图获取,我们必须首先获取包含它们的容器。在这种情况下,TabLayout 使用 SlidingTabStrip 作为选项卡的容器。 SlidingTabStrip 是 TabLayout 的第一个子元素:
View tab = ((ViewGroup) mTabLayout.getChildAt(0))
在这个小细节之后,一切都非常简单。
这就是为四个不同的标签设置边距的方法。您可以更改 setMargins(v1,v2,v3,v4) 函数值以获得适合您正在使用的选项卡数量的值。我希望这有帮助。请注意,tabHost 是 TabHost 托管您正在使用的不同选项卡的对象。
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
View currentView;
for(int i=0;i<tabHost.getTabWidget().getChildCount();i++)
{
//This code removes divider between tabs
tabHost.getTabWidget().setDividerDrawable(null);
tabHost.getTabWidget().getChildAt(i).setLayoutParams(new
LinearLayout.LayoutParams((width/8)-2,50));
currentView = tabHost.getTabWidget().getChildAt(i);
LinearLayout.LayoutParams currentLayout =
(LinearLayout.LayoutParams) currentView.getLayoutParams();
currentLayout.setMargins(30, 5, 80, 0);
}
@Todor Kostov 回答得很好,但是标签的中心被滑走了,因为最后一个标签也有边距。
所以使用 mTabLayout.getTabCount() - 1
而不是 mTabLayout.getCodeCount()
.
for(int i=0; i < mTabLayout.getTabCount() - 1; i++) {
View tab = ((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(i);
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) tab.getLayoutParams();
p.setMargins(0, 0, 50, 0);
tab.requestLayout();
}
这是我在纯 xml.
中的做法dimens.xml:
<!-- Set this to 50% of what you want the actual space between the tabs to be. -->
<dimen name="tab_spacing_half">5dp</dimen> <!-- i.e., 10dp spacing between tabs. -->
包含您的 TabLayout 的布局:
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/tab_spacing_half"/>
将此添加到您在 styles.xml 中的主题:
<item name="tabBackground">@drawable/tab_background</item>
drawable-nodpi\tab_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@drawable/tab_background_selected"
android:state_selected="true" />
<item
android:drawable="@drawable/tab_background_unselected"
android:state_selected="false"
android:state_focused="false"
android:state_pressed="false" />
</selector>
drawable-nodpi\tab_background_selected.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:left="@dimen/tab_spacing_half"
android:right="@dimen/tab_spacing_half"
android:top="@dimen/tab_spacing_half"
android:bottom="@dimen/tab_spacing_half">
<shape
android:shape="rectangle">
<corners
android:radius="@dimen/border_radius_small">
</corners>
<stroke
android:width="@dimen/divider_height_thick"
android:color="@color/white">
</stroke>
</shape>
</item>
</layer-list>
...这就是诀窍所在。实际上,根据您的 @dimen/tab_spacing_half
值将背景形状包裹在 item
和 "padding" 中。最后...
drawable-nodpi\tab_background_unselected.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:left="@dimen/tab_spacing_half"
android:right="@dimen/tab_spacing_half"
android:top="@dimen/tab_spacing_half"
android:bottom="@dimen/tab_spacing_half">
<shape
android:shape="rectangle">
<corners
android:radius="@dimen/border_radius_small">
</corners>
<stroke
android:width="@dimen/divider_height_thin"
android:color="@color/white">
</stroke>
</shape>
</item>
</layer-list>
这是@Todor Kostov 回答的 Kotlin 版本。
for (i in 0 until applicationList_tabLayout.tabCount) {
val tab = (applicationList_tabLayout.getChildAt(0) as ViewGroup).getChildAt(i)
val p = tab.layoutParams as ViewGroup.MarginLayoutParams
p.setMargins(10, 0, 10, 0)
tab.requestLayout()
}
这里的大多数建议似乎都建议调用 requestLayout() 来更新边距。这将触发一个新的布局过程。我个人也看到了动画布局时的问题,其中定义了 TabLayout,导致多次调用 requestLayout,有时使选项卡“跳转”
我认为设置选项卡之间边距的更好方法是扩展 TabLayout,并监听何时将子视图添加到 SlidingTabIndicator。
private const val YOUR_CUSTOM_MARGIN = 8
class CustomTabLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : TabLayout(
context,
attrs,
defStyleAttr
) {
init {
val tabStrip = (this.getChildAt(0) as ViewGroup)
tabStrip.setOnHierarchyChangeListener(object : OnHierarchyChangeListener {
override fun onChildViewAdded(p0: View?, p1: View?) {
if (p1 is TabView && p1.layoutParams is MarginLayoutParams) {
val params = p1.layoutParams as MarginLayoutParams
params.setMargins(YOUR_CUSTOM_MARGIN, 0, YOUR_CUSTOM_MARGIN, 0)
}
}
override fun onChildViewRemoved(p0: View?, p1: View?) {}
})
}
}
None 的答案对我有用!所以