내 프로젝트에서 새로운 디자인 TabLayout을 사용하려고합니다. 레이아웃이 모든 화면 크기와 방향에 맞게 조정되기를 원하지만 한 방향에서 올바르게 볼 수 있습니다.
내 tabLayout을 다음과 같이 설정하는 Gravity 및 Mode를 다루고 있습니다.
tabLayout.setTabGravity(TabLayout.GRAVITY_CENTER);
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
따라서 공간이 없으면 tabLayout은 스크롤 가능하지만 공간이 있으면 중앙에 배치됩니다.
가이드에서 :
public static final int GRAVITY_CENTER TabLayout 중앙에 탭을 배치하는 데 사용되는 Gravity입니다.
public static final int GRAVITY_FILL 가능한 한 TabLayout을 채우는 데 사용되는 Gravity. 이 옵션은 MODE_FIXED와 함께 사용할 때만 적용됩니다.
public static final int MODE_FIXED 고정 탭은 모든 탭을 동시에 표시하며 탭 간 빠른 피벗의 이점이있는 콘텐츠에 가장 적합합니다. 최대 탭 수는보기의 너비에 의해 제한됩니다. 고정 탭은 가장 넓은 탭 레이블을 기준으로 동일한 너비를 갖습니다.
public static final int MODE_SCROLLABLE 스크롤 가능한 탭은 주어진 순간에 탭의 하위 집합을 표시하며 더 긴 탭 레이블과 더 많은 수의 탭을 포함 할 수 있습니다. 사용자가 탭 레이블을 직접 비교할 필요가 없을 때 터치 인터페이스에서 컨텍스트를 탐색하는 데 가장 적합합니다.
따라서 GRAVITY_FILL은 MODE_FIXED 와만 호환되지만 at은 GRAVITY_CENTER에 대해 아무것도 지정하지 않으며 MODE_SCROLLABLE과 호환 될 것으로 예상하지만 이것이 GRAVITY_CENTER 및 MODE_SCROLLABLE을 사용하여 얻은 것입니다.
따라서 두 방향 모두에서 SCROLLABLE을 사용하고 있지만 GRAVITY_CENTER를 사용하지 않습니다.
이것이 제가 풍경에 기대하는 것입니다. 하지만 이것을 가지려면 MODE_FIXED를 설정해야하므로 세로로 얻는 것은 다음과 같습니다.
tabLayout이 화면에 맞으면 GRAVITY_CENTER가 SCROLLABLE에 대해 작동하지 않는 이유는 무엇입니까? 중력과 모드를 동적으로 설정하고 내가 기대하는 것을 볼 수있는 방법이 있습니까?
대단히 감사합니다!
수정 됨 : 이것은 내 TabLayout의 레이아웃입니다.
<android.support.design.widget.TabLayout
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:background="@color/orange_pager"
android:layout_height="wrap_content" />
답변
탭 중력 전용 효과 MODE_FIXED
.
한 가지 가능한 해결 방법은 설정하는 것입니다 layout_width
에 wrap_content
와 layout_gravity
에center_horizontal
:
<android.support.design.widget.TabLayout
android:id="@+id/sliding_tabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:tabMode="scrollable" />
탭이 화면 너비보다 작 으면 TabLayout
자체도 더 작아지고 중력 때문에 중앙에 위치하게됩니다. 탭이 화면 너비보다 크면이 TabLayout
화면 너비와 일치하고 스크롤이 활성화됩니다.
답변
이것이 내가 한 방법이다
TabLayout.xml
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@android:color/transparent"
app:tabGravity="fill"
app:tabMode="scrollable"
app:tabTextAppearance="@style/TextAppearance.Design.Tab"
app:tabSelectedTextColor="@color/myPrimaryColor"
app:tabIndicatorColor="@color/myPrimaryColor"
android:overScrollMode="never"
/>
온 크리에이트
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
mTabLayout = (TabLayout)findViewById(R.id.tab_layout);
mTabLayout.setOnTabSelectedListener(this);
setSupportActionBar(mToolbar);
mTabLayout.addTab(mTabLayout.newTab().setText("Dashboard"));
mTabLayout.addTab(mTabLayout.newTab().setText("Signature"));
mTabLayout.addTab(mTabLayout.newTab().setText("Booking/Sampling"));
mTabLayout.addTab(mTabLayout.newTab().setText("Calendar"));
mTabLayout.addTab(mTabLayout.newTab().setText("Customer Detail"));
mTabLayout.post(mTabLayout_config);
}
Runnable mTabLayout_config = new Runnable()
{
@Override
public void run()
{
if(mTabLayout.getWidth() < MainActivity.this.getResources().getDisplayMetrics().widthPixels)
{
mTabLayout.setTabMode(TabLayout.MODE_FIXED);
ViewGroup.LayoutParams mParams = mTabLayout.getLayoutParams();
mParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
mTabLayout.setLayoutParams(mParams);
}
else
{
mTabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
}
}
};
실행 가능한 부분에서 @Mario Velasco의 솔루션을 약간 변경했습니다.
답변
간단하게 유지하려면 app : tabMode = “scrollable”및 android : layout_gravity = “bottom”을 추가하면됩니다.
이렇게
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
app:tabMode="scrollable"
app:tabIndicatorColor="@color/colorAccent" />
답변
이 동작이 발생하는 이유를 찾지 못해 다음 코드를 사용했습니다.
float myTabLayoutSize = 360;
if (DeviceInfo.getWidthDP(this) >= myTabLayoutSize ){
tabLayout.setTabMode(TabLayout.MODE_FIXED);
} else {
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
}
기본적으로 tabLayout의 너비를 수동으로 계산 한 다음 tabLayout이 장치에 맞는지 여부에 따라 탭 모드를 설정해야합니다.
레이아웃의 크기를 수동으로 얻는 이유는 스크롤 가능 모드에서 모든 탭의 너비가 같지 않기 때문이며, 이로 인해 일부 이름이 예에서 나에게 일어난 것처럼 2 줄을 사용할 수 있습니다.
답변
TabLayout.MODE_FIXED 및 TabLayout.MODE_SCROLLABLE은 전체 탭 너비에 따라 자동으로 전환됩니다.
답변
이것이 내가 SCROLLABLE
와 FIXED
+ 사이를 자동으로 변경하는 데 사용한 솔루션 FILL
입니다. @ Fighter42 솔루션의 완전한 코드입니다.
(아래 코드는 Google의 탭 활동 템플릿을 사용한 경우 수정을 적용 할 위치를 보여줍니다.)
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
// Set up the tabs
final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
// Mario Velasco's code
tabLayout.post(new Runnable()
{
@Override
public void run()
{
int tabLayoutWidth = tabLayout.getWidth();
DisplayMetrics metrics = new DisplayMetrics();
ActivityMain.this.getWindowManager().getDefaultDisplay().getMetrics(metrics);
int deviceWidth = metrics.widthPixels;
if (tabLayoutWidth < deviceWidth)
{
tabLayout.setTabMode(TabLayout.MODE_FIXED);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
} else
{
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
}
}
});
}
나열한 것:
<android.support.design.widget.TabLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
너비를 채울 필요가 없으면 @karaokyo 솔루션을 사용하는 것이 좋습니다.
답변
이를 위해 AdaptiveTabLayout 클래스를 만들었습니다. 이것은 실제로 문제를 해결하고 질문에 답하며 여기에있는 다른 답변이 제공하지 않는 문제를 피 / 해결할 수있는 유일한 방법이었습니다.
노트:
- 휴대 전화 / 태블릿 레이아웃을 처리합니다.
- 충분한 공간이
MODE_SCROLLABLE
있지만 공간이 부족한 경우 처리MODE_FIXED
. 이 경우를 처리하지 않으면 일부 장치에서 다른 텍스트 크기를 보거나 일부 탭에서 두 줄의 텍스트를 볼 수 있습니다. - 실제 측정 값을 얻고 어떤 가정도하지 않습니다 (예 : 화면 폭이 360dp 또는 무엇이든 …). 이것은 실제 화면 크기와 실제 탭 크기에서 작동합니다. 즉, 탭 크기를 가정하지 않고 탭이 측정되기 때문에 번역과 잘 작동합니다.
- 추가 작업을 피하기 위해 onLayout 단계에서 다른 패스를 처리합니다.
- 레이아웃 너비
wrap_content
는 xml에 있어야합니다 . 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;
}
}
그리고 이것은 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;
}
}
사용 예 :
<?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>
문제 / 도움 요청 :
- 다음과 같이 표시됩니다.
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
어떻게 해결해야할지 모르겠습니다. 어떤 제안?
- TabLayout 자식 측정 값을 만들기 위해 몇 가지 캐스팅과 가정을 만들고 있습니다 (자식이 다른 뷰를 포함하는 LinearLayout 인 것처럼 …). 이로 인해 추가 디자인 지원 라이브러리 업데이트에서 문제가 발생할 수 있습니다. 더 나은 접근 방식 / 제안?