我已将TabLayout
(来自支持库v22.2.1)添加到我的片段中:
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
style="@style/MyColorAccentTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"/>
问题在于,当片段的方向是横向时(在片段的初始创建之前或之后),TabLayout
与Fragment
的宽度不匹配(是的,父级的宽度也设置为match_parent
)。
如果我将tabMode
更改为固定,则填充宽度但标签太小。那里有适当的解决方案吗?
答案 0 :(得分:26)
而不是创建自定义TabLayout和黑客攻击或创建更多布局,作为TabLayout的包装仅用于背景。试试这个,
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
style="@style/MyColorAccentTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
<!-- Instead of setting app:tabBackground -->
android:background="@color/colorAccent"
app:tabGravity="fill"
app:tabMode="scrollable"/>
这会将背景设置为tabLayout后面,而不是在每个标签后面设置背景。
答案 1 :(得分:19)
试试这个,它是一个设置tabMaxWidth="0dp"
,tabGravity="fill"
和tabMode="fixed"
的解决方法。
<android.support.v4.view.ViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabGravity="fill"
app:tabMode="fixed"/>
</android.support.v4.view.ViewPager>
10英寸平板电脑的屏幕截图:
答案 2 :(得分:16)
我想这是达到你想要的最简单方法。
public class CustomTabLayout extends TabLayout {
public CustomTabLayout(Context context) {
super(context);
}
public CustomTabLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
try {
if (getTabCount() == 0)
return;
Field field = TabLayout.class.getDeclaredField("mTabMinWidth");
field.setAccessible(true);
field.set(this, (int) (getMeasuredWidth() / (float) getTabCount()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
答案 3 :(得分:4)
这是我的 2021 Kotlin 解决方案。 它实现了我无法从其他答案中做到的以下内容:
为了实现这一点,我创建了一个 TabLayout
的子类来覆盖 onMeasure
class ScalableTabLayout : 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 onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val tabLayout = getChildAt(0) as ViewGroup
val childCount = tabLayout.childCount
if (childCount > 0) {
val widthPixels = MeasureSpec.getSize(widthMeasureSpec)
val tabMinWidth = widthPixels / childCount
var remainderPixels = widthPixels % childCount
tabLayout.forEachChild {
if (remainderPixels > 0) {
it.minimumWidth = tabMinWidth + 1
remainderPixels--
} else {
it.minimumWidth = tabMinWidth
}
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
然后在我的布局文件中使用它:
<com.package.name.ScalableTabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabMode="scrollable" />
同时需要 tabMaxWidth="0dp"
和 tabMode="scrollable"
答案 4 :(得分:3)
请使用它,它肯定会解决这个问题
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabGravity="fill"
app:tabMode="fixed" />
答案 5 :(得分:1)
尝试进行此更改
<android.support.design.widget.TabLayout
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill" />
答案 6 :(得分:1)
我几乎尝试了所有答案,最后发现这就像一个咒语。
public void dynamicSetTabLayoutMode(TabLayout tabLayout) {
int tabWidth = calculateTabWidth(tabLayout);
int screenWidth = getApplicationContext().getResources().getDisplayMetrics().widthPixels;
if (tabWidth <= screenWidth) {
tabLayout.setTabMode(TabLayout.MODE_FIXED);
} else {
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
}
}
private int calculateTabWidth(TabLayout tabLayout) {
int tabWidth = 0;
for (int i = 0; i < tabLayout.getChildCount(); i++) {
final View view = tabLayout.getChildAt(i);
view.measure(0, 0);
tabWidth += view.getMeasuredWidth();
}
return tabWidth;
}
答案 7 :(得分:1)
这是一种确保制表符的宽度等于制表符的字符串长度的简便方法
<androidx.viewpager.widget.ViewPager
android:id="@+id/vpTabs"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabMode="scrollable"/>
</androidx.viewpager.widget.ViewPager>
使用以下代码:-
app:tabMaxWidth="0dp"
app:tabMode="scrollable"
答案 8 :(得分:1)
此解决方案的工作原理是让android创建标签,然后计算标签的总宽度。然后检查选项卡是否适合屏幕宽度,如果适合,则将tabMode设置为“固定”,从而缩放所有选项卡以适合屏幕宽度。
选项卡布局xml,父级无关紧要:
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"/>
然后在您的活动onCreate或onCreateView的片段中
var totalWidth = 0
var maxWidth = 0
for (i in 0 until tabLayout.tabCount) {
val tabWidth = (tabLayout.getChildAt(0) as ViewGroup).getChildAt(i)!!.width
totalWidth += tabWidth
maxWidth = max(maxWidth, tabWidth)
}
val screenWidth = Resources.getSystem().displayMetrics.widthPixels
if (totalWidth < screenWidth&& screenWidth/ tabLayout.tabCount >= maxWidth) {
tabLayout.tabMode = TabLayout.MODE_FIXED
}
如果您将TabLayout与Viewpager一起使用,则必须设置layoutChangeListener,因为选项卡在开始时不会膨胀。
在您的活动onCreate或onCreateView片段中:
tabLayout.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
var totalWidth = 0
var maxWidth = 0
for (i in 0 until tabLayout.tabCount) {
val tabWidth = (tabLayout.getChildAt(0) as ViewGroup).getChildAt(i)!!.width
totalWidth += tabWidth
maxWidth = max(maxWidth, tabWidth)
}
val screenWidth = Resources.getSystem().displayMetrics.widthPixels
if (totalWidth < screenWidth && screenWidth / tabLayout.tabCount >= maxWidth) {
tabLayout.tabMode = TabLayout.MODE_FIXED
}
}
注意:如果希望tabMode为“ fixed”时所有选项卡的文本大小都相同,则必须从styles.xml中手动设置textSize。
答案 9 :(得分:0)
我也很挣扎,上面的大多数选项对我都不起作用,因此我根据DTX12的答案创建了一个版本。
我有一个布尔值可否检查平板电脑,并检查风景和肖像。然后根据标签数量设置布局。
您可能需要公开该方法,并在轮换/配置更改时调用它。
在CustomTabLayout代码中,我替换了mintabswidth方法
private void initTabMinWidth()
{
boolean isTablet = getContext().getResources().getBoolean(R.bool.device_is_tablet);
boolean isLandscape = (wh[WIDTH_INDEX] > wh[HEIGHT_INDEX]) ? true : false;
if (isTablet)
{
if (isLandscape)
{
if (this.getTabCount() > 8)
{
this.setTabGravity(TabLayout.GRAVITY_FILL);
this.setTabMode(TabLayout.MODE_SCROLLABLE);
} else
{
this.setTabGravity(TabLayout.GRAVITY_FILL);
this.setTabMode(TabLayout.MODE_FIXED);
}
} else
{
if (this.getTabCount() > 6)
{
this.setTabGravity(TabLayout.GRAVITY_FILL);
this.setTabMode(TabLayout.MODE_SCROLLABLE);
} else
{
this.setTabGravity(TabLayout.GRAVITY_FILL);
this.setTabMode(TabLayout.MODE_FIXED);
}
}
} else
{
if (isLandscape)
{
if (this.getTabCount() > 6)
{
this.setTabGravity(TabLayout.GRAVITY_FILL);
this.setTabMode(TabLayout.MODE_SCROLLABLE);
} else
{
this.setTabGravity(TabLayout.GRAVITY_FILL);
this.setTabMode(TabLayout.MODE_FIXED);
}
} else
{
if (this.getTabCount() > 4)
{
this.setTabGravity(TabLayout.GRAVITY_FILL);
this.setTabMode(TabLayout.MODE_SCROLLABLE);
} else
{
this.setTabGravity(TabLayout.GRAVITY_FILL);
this.setTabMode(TabLayout.MODE_FIXED);
}
}
}
}
答案 10 :(得分:0)
花了两天时间找出问题后,现在终于可以为我工作了。请参阅@Tyler V的答案check here 泰勒(Tyler)的回答 “在调用super.onMeasure()之前设置最小宽度是关键。” 非常重要
答案 11 :(得分:0)
只需按照这种方式进行操作,然后添加user_token
并同时使用Intent i = new Intent(context, hshowreminderpic1.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
app:tabMaxWidth="0dp"
答案 12 :(得分:0)
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:tabMode="scrollable"/>
答案 13 :(得分:0)
这是我的解决方案,其中tabMode设置为: app:tabMode =“ scrollable”
class MyTabLayout(
context: Context,
attrs: AttributeSet?
) : TabLayout(context, attrs) {
override fun onMeasure(
widthMeasureSpec: Int,
heightMeasureSpec: Int
) {
val equalTabWidth= (MeasureSpec.getSize(widthMeasureSpec) / tabCount.toFloat()).toInt()
for (index in 0..tabCount) {
val tab = getTabAt(index)
val tabMeasuredWidth = tab?.view?.measuredWidth ?: equalTabWidth
if (tabMeasuredWidth < equalTabWidth) {
tab?.view?.minimumWidth = equalTabWidth
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
答案 14 :(得分:-1)
你可以在tablayout中使用 app:tabMaxWidth =“0dp”
答案 15 :(得分:-1)
如果要显示标签'fill',则应设置app:tabMode =“fixed”。
scanf()
答案 16 :(得分:-1)
请检查一下,我认为它有效
公共类MainActivity扩展了AppCompatActivity {
private TextView mTxv_Home, mTxv_News, mTxv_Announcement;
private View mView_Home, mView_News, mView_Announcements;
private HorizontalScrollView hsv;
private ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTxv_Home = (TextView) findViewById(R.id.txv_home);
mTxv_News = (TextView) findViewById(R.id.txv_news);
mTxv_Announcement = (TextView) findViewById(R.id.txv_announcements);
mView_Home = (View) findViewById(R.id.view_home);
mView_News = (View) findViewById(R.id.view_news);
mView_Announcements = (View) findViewById(R.id.view_announcements);
hsv = (HorizontalScrollView) findViewById(R.id.hsv);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int wt = displaymetrics.widthPixels/3;
mTxv_Home.setWidth(wt);
mTxv_News.setWidth(wt);
// mTxv_Announcement.setWidth(wt);
mTxv_Home.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mTxv_Home.setTextColor(Color.parseColor("#3F51B5"));
mTxv_News.setTextColor(Color.parseColor("#808080"));
mTxv_Announcement.setTextColor(Color.parseColor("#808080"));
mView_Home.setBackgroundColor(Color.parseColor("#3F51B5"));
mView_News.setBackgroundColor(Color.parseColor("#E8E8E8"));
mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8"));
hsv.post(new Runnable() {
public void run() {
hsv.fullScroll(HorizontalScrollView.FOCUS_LEFT);
}
});
viewPager.setCurrentItem(0);
}
});
mTxv_News.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mTxv_Home.setTextColor(Color.parseColor("#808080"));
mTxv_News.setTextColor(Color.parseColor("#3F51B5"));
mTxv_Announcement.setTextColor(Color.parseColor("#808080"));
mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8"));
mView_News.setBackgroundColor(Color.parseColor("#3F51B5"));
mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8"));
hsv.post(new Runnable() {
public void run() {
int centerX = hsv.getChildAt(0).getWidth()/2;
hsv.scrollTo(centerX, 0);
}
});
viewPager.setCurrentItem(1);
}
});
mTxv_Announcement.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mTxv_Home.setTextColor(Color.parseColor("#808080"));
mTxv_News.setTextColor(Color.parseColor("#808080"));
mTxv_Announcement.setTextColor(Color.parseColor("#3F51B5"));
mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8"));
mView_News.setBackgroundColor(Color.parseColor("#E8E8E8"));
mView_Announcements.setBackgroundColor(Color.parseColor("#3F51B5"));
hsv.post(new Runnable() {
public void run() {
hsv.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
});
viewPager.setCurrentItem(2);
}
});
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (position == 0) {
mTxv_Home.setTextColor(Color.parseColor("#3F51B5"));
mTxv_News.setTextColor(Color.parseColor("#808080"));
mTxv_Announcement.setTextColor(Color.parseColor("#808080"));
mView_Home.setBackgroundColor(Color.parseColor("#3F51B5"));
mView_News.setBackgroundColor(Color.parseColor("#E8E8E8"));
mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8"));
hsv.post(new Runnable() {
public void run() {
hsv.fullScroll(HorizontalScrollView.FOCUS_LEFT);
}
});
} else if (position == 1) {
mTxv_Home.setTextColor(Color.parseColor("#808080"));
mTxv_News.setTextColor(Color.parseColor("#3F51B5"));
mTxv_Announcement.setTextColor(Color.parseColor("#808080"));
mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8"));
mView_News.setBackgroundColor(Color.parseColor("#3F51B5"));
mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8"));
hsv.post(new Runnable() {
public void run() {
int centerX = hsv.getChildAt(0).getWidth()/2;
hsv.scrollTo(centerX, 0);
}
});
} else if (position == 2) {
mTxv_Home.setTextColor(Color.parseColor("#808080"));
mTxv_News.setTextColor(Color.parseColor("#808080"));
mTxv_Announcement.setTextColor(Color.parseColor("#3F51B5"));
mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8"));
mView_News.setBackgroundColor(Color.parseColor("#E8E8E8"));
mView_Announcements.setBackgroundColor(Color.parseColor("#3F51B5"));
hsv.post(new Runnable() {
public void run() {
hsv.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
});
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new HomeFragment(), "Home");
adapter.addFragment(new NewsFragment(), "News");
adapter.addFragment(new AnnouncementsFragment(), "Announcements");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
<HorizontalScrollView
android:id="@+id/hsv"
android:layout_width="fill_parent"
android:layout_height="56dp"
android:layout_weight="0"
android:fillViewport="true"
android:measureAllChildren="false"
android:scrollbars="none" >
<LinearLayout
android:id="@+id/innerLay"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/txv_home"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Home"
android:singleLine="true"
android:paddingLeft="35dp"
android:paddingRight="35dp"
android:gravity="center"
android:textSize="15sp"/>
<View
android:id="@+id/view_home"
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="@color/colorPrimary"
/>
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:visibility="gone"
android:background="#e8e8e8"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/txv_news"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="News"
android:singleLine="true"
android:paddingLeft="35dp"
android:paddingRight="35dp"
android:gravity="center"
android:textSize="15sp"/>
<View
android:id="@+id/view_news"
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="#e8e8e8"/>
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:visibility="gone"
android:background="#e8e8e8"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/txv_announcements"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:singleLine="true"
android:text="Announcements"
android:paddingLeft="35dp"
android:paddingRight="35dp"
android:gravity="center"
android:textSize="15sp"/>
<View
android:id="@+id/view_announcements"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#e8e8e8"/>
</LinearLayout>
</LinearLayout>
</HorizontalScrollView>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/hsv" />
答案 17 :(得分:-1)
我并不关心填充宽度的标签,但我关心的是背景颜色没有扩展到全宽。所以我想到了这个解决方案,我在其后面放置一个FrameLayout,其背景颜色与标签相同。
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/MyColor">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
style="@style/MyCustomTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"/>
</FrameLayout>
答案 18 :(得分:-2)
@ dtx12 answer不起作用。
这种情况有我的TabLayout
子类(在Kotlin中)。我希望这会对某人有所帮助。
class FullWidthTabLayout : 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 onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
if (changed) {
val widths = mutableListOf<Int>()
for (i in 0..this.tabCount - 1) {
widths.add(this.getTabAt(i)!!.customView!!.width)
}
if (widths.sum() < this.measuredWidth) {
var equalPart: Long = this.measuredWidth.toLong() / this.tabCount.toLong()
var biggerWidths = widths.filter { it > equalPart }
var smallerWidths = widths.filter { it <= equalPart }
var rest: Long = this.measuredWidth.toLong() - biggerWidths.sum()
while (biggerWidths.size != 0) {
equalPart = rest / smallerWidths.size
biggerWidths = smallerWidths.filter { it >= equalPart }
smallerWidths = smallerWidths.filter { it < equalPart }
rest -= biggerWidths.sum()
}
val minWidth = (rest / smallerWidths.size) + 10 //dont know why there is small gap on the end, thats why +10
for (i in 0..this.tabCount - 1) {
this.getTabAt(i)!!.customView!!.minimumWidth = minWidth.toInt()
}
}
}
}
}