我想减少指示器的宽度-例如,使它的宽度不是整个制表符宽度,而是制表符宽度的1/2。这就是我所需要做的,所以我不想下载一些自定义库和搜索在哪里我可以这样做。这是一种方法,还是我应该自己写这样的观点?
x3naxklr1#
如果您想要一个固定大小制表符指示器,那么您可以通过drawable创建一个固定大小的指示器形状:
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:gravity="center"> <shape android:shape="rectangle"> <solid android:color="@color/colorAccent" /> <corners android:topLeftRadius="2dp" android:topRightRadius="2dp" /> <size android:width="16dp" android:height="2dp" /> </shape> </item> </layer-list>
然后在TabLayout上,你可以设置制表符为可绘制。同时,你还必须设置tabIndicatorColor
tabIndicatorColor
app:tabIndicatorColor="@color/tabIndicatorColor" app:tabIndicator="@drawable/tab_indicator"
由于可绘制对象本身将形状居中放置在其边界内,因此指示器将具有固定大小。如果您希望指示符与标签的宽度匹配,则可以删除tabIndicator android:gravity。
android:gravity
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:shape="rectangle"> <solid android:color="@color/colorAccent" /> <corners radius="2dp" /> <size android:width="16dp" android:height="2dp" /> </shape> </item> </layer-list>
gab6jxml2#
对于任何最终遇到这个问题的人,我找到了一个简单的解决方案,用矢量可绘制的标签宽度指示器的~90%:ic_tab_indicator_24dp:
<vector android:height="24dp" android:width="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:strokeWidth="4" android:fillColor="@android:color/white" android:pathData="M2,0 L22,0 L22,24 L2,24 z"/>
然后在布局中设置tabIndicator:
app:tabIndicator="@drawable/ic_tab_indicator_24dp"
或者在styles.xml中:
<item name="tabIndicator">@drawable/ic_tab_indicator_24dp</item>
**编辑:**由于我的解决方案引起了人们的注意,我想补充一点,您可以通过修改pathData(“M2,0 L22,0 L22,24 L2,24 z”)改变2和22的值来调整宽度。“M4、0 L20、0 L20、24 L4、24 z”或“M6、0 L18、0 L18、24 L 6、24 z...”
cbeh67ev3#
试试这个。
public void setIndicator (TabLayout tabs,int leftDip,int rightDip){ Class<?> tabLayout = tabs.getClass(); Field tabStrip = null; try { tabStrip = tabLayout.getDeclaredField("mTabStrip"); } catch (NoSuchFieldException e) { e.printStackTrace(); } tabStrip.setAccessible(true); LinearLayout llTab = null; try { llTab = (LinearLayout) tabStrip.get(tabs); } catch (IllegalAccessException e) { e.printStackTrace(); } int left = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, leftDip, Resources.getSystem().getDisplayMetrics()); int right = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightDip, Resources.getSystem().getDisplayMetrics()); for (int i = 0; i < llTab.getChildCount(); i++) { View child = llTab.getChildAt(i); child.setPadding(0, 0, 0, 0); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1); params.leftMargin = left; params.rightMargin = right; child.setLayoutParams(params); child.invalidate(); } }
然后
tab.post(new Runnable() { @Override public void run() { setIndicator(tab,60,60); } });
我的修改无反射(应设置自定义视图!)。
for (int i = 0; i < tabs.getTabCount(); i++) { TabLayout.Tab tab = tabs.getTabAt(i); if (tab != null) { View customView = tab.getCustomView(); if (customView != null) { View targetViewToApplyMargin = (View) customView.getParent(); ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) targetViewToApplyMargin.getLayoutParams(); layoutParams.rightMargin = totalTabMargin; targetViewToApplyMargin.setLayoutParams(layoutParams); } } }
q43xntqr4#
尝试了所有的解决方案,但都不满意,最后我自己找到了一个解决方案,我们只需要修改SlidingTabIndicator的indicatorLeft和indicatorRight字段,扩展表格布局,并在需要时调用setIndicaotrWidth(),例如:setIndicatorWidth(70);完整代码:
setIndicatorWidth(70);
import android.content.Context; import android.content.res.Resources; import android.util.AttributeSet; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewTreeObserver; import android.widget.LinearLayout; import android.widget.TextView; import com.google.android.material.tabs.TabLayout; import java.lang.reflect.Field; import androidx.annotation.NonNull; public class TabLayoutEx extends TabLayout { public TabLayoutEx(Context context) { this(context, null); } public TabLayoutEx(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TabLayoutEx(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(attrs); } private void init(AttributeSet attrs) { setTabIndicatorFullWidth(false); setIndicatorWidth(70); } private class DefPreDrawListener implements ViewTreeObserver.OnPreDrawListener { private LinearLayout tabStrip = null; private int tabWidth; private Field fieldLeft; private Field fieldRight; public void setTabStrip(LinearLayout tabStrip, int width) { try { this.tabStrip = tabStrip; this.tabWidth = width; Class cls = tabStrip.getClass(); fieldLeft = cls.getDeclaredField("indicatorLeft"); fieldLeft.setAccessible(true); fieldRight = cls.getDeclaredField("indicatorRight"); fieldRight.setAccessible(true); } catch (Exception e) { e.printStackTrace(); } } @Override public boolean onPreDraw() { try { if (tabWidth > 0) { int left = fieldLeft.getInt(this.tabStrip); int right = fieldRight.getInt(this.tabStrip); //根据目标宽度及现在的宽度调整为合适的left和right int diff = right - left - tabWidth; left = left + diff / 2; right = right - diff / 2; fieldLeft.setInt(this.tabStrip, left); fieldRight.setInt(this.tabStrip, right); } } catch (Exception e) { e.printStackTrace(); } return true; } } private DefPreDrawListener defPreDrawListener = new DefPreDrawListener(); public void setIndicatorWidth(int widthDp) { Class<?> tabLayout = TabLayout.class; Field tabStrip = null; try { tabStrip = tabLayout.getDeclaredField("slidingTabIndicator"); tabStrip.setAccessible(true); LinearLayout tabIndicator = (LinearLayout) tabStrip.get(this); int width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, widthDp, Resources.getSystem().getDisplayMetrics()); //avoid add preDrawListener multi times tabIndicator.getViewTreeObserver().removeOnPreDrawListener(defPreDrawListener); tabIndicator.getViewTreeObserver().addOnPreDrawListener(defPreDrawListener); defPreDrawListener.setTabStrip(tabIndicator, width); } catch (Exception e) { e.printStackTrace(); } } }
dpiehjr45#
您可以复制TabLayout,并修改计算指标宽度的逻辑。请参阅updateIndicatorPosition()和animateIndicatorToPosition()。一个简单的演示https://github.com/xybean/CustomTabLayout
5条答案
按热度按时间x3naxklr1#
如果您想要一个固定大小制表符指示器,那么您可以通过drawable创建一个固定大小的指示器形状:
然后在TabLayout上,你可以设置制表符为可绘制。同时,你还必须设置
tabIndicatorColor
由于可绘制对象本身将形状居中放置在其边界内,因此指示器将具有固定大小。
如果您希望指示符与标签的宽度匹配,则可以删除tabIndicator
android:gravity
。gab6jxml2#
对于任何最终遇到这个问题的人,我找到了一个简单的解决方案,用矢量可绘制的标签宽度指示器的~90%:
ic_tab_indicator_24dp:
然后在布局中设置tabIndicator:
或者在styles.xml中:
**编辑:**由于我的解决方案引起了人们的注意,我想补充一点,您可以通过修改pathData(“M2,0 L22,0 L22,24 L2,24 z”)改变2和22的值来调整宽度。“M4、0 L20、0 L20、24 L4、24 z”或“M6、0 L18、0 L18、24 L 6、24 z...”
cbeh67ev3#
试试这个。
然后
我的修改无反射(应设置自定义视图!)。
q43xntqr4#
尝试了所有的解决方案,但都不满意,最后我自己找到了一个解决方案,我们只需要修改SlidingTabIndicator的indicatorLeft和indicatorRight字段,扩展表格布局,并在需要时调用setIndicaotrWidth(),例如:
setIndicatorWidth(70);
完整代码:
dpiehjr45#
您可以复制TabLayout,并修改计算指标宽度的逻辑。请参阅updateIndicatorPosition()和animateIndicatorToPosition()。一个简单的演示https://github.com/xybean/CustomTabLayout