Tôi đã tạo một lớp AdaptiveTabLayout để đạt được điều này. Đây là cách duy nhất tôi tìm thấy để thực sự giải quyết vấn đề, trả lời câu hỏi và tránh / giải quyết các vấn đề mà các câu trả lời khác ở đây không làm được.
Ghi chú:
- Xử lý bố cục điện thoại / máy tính bảng.
- Xử lý các trường hợp có đủ chỗ
MODE_SCROLLABLE
nhưng không đủ chỗ MODE_FIXED
. Nếu bạn không xử lý trường hợp này, nó sẽ xảy ra trên một số thiết bị, bạn sẽ thấy các kích thước văn bản khác nhau hoặc hiển thị hai dòng văn bản trong một số tab, trông rất tệ.
- Nó có các thước đo thực tế và không đưa ra bất kỳ giả định nào (như màn hình rộng 360dp hoặc bất cứ thứ gì ...). Điều này hoạt động với kích thước màn hình thực và kích thước tab thực. Điều này có nghĩa là hoạt động tốt với các bản dịch vì không giả sử bất kỳ kích thước tab nào, các tab sẽ được đo lường.
- Thỏa thuận với các đường chuyền khác nhau trong giai đoạn OnLayout để tránh làm việc thêm.
- Chiều rộng bố cục cần phải nằm
wrap_content
trên xml. Không đặt bất kỳ chế độ hoặc trọng lực nào trên 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;
}
}
Và đây là lớp 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;
}
}
Sử dụng ví dụ:
<?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>
Ý chính
Sự cố / Yêu cầu trợ giúp:
Logcat:
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
Tôi không chắc làm thế nào để giải quyết nó. Bất kỳ đề xuất?
- Để thực hiện các phép đo con của TabLayout, tôi đang thực hiện một số đúc và giả định (Giống như con là một LinearLayout chứa các khung nhìn khác ....) Điều này có thể gây ra sự cố trong các bản cập nhật Thư viện hỗ trợ thiết kế. Một cách tiếp cận / đề xuất tốt hơn?