TabLayout 是一个很好用的指示器。但是缺点是指示器的宽度不可自定义。有时候并不能达到项目的需求。
百度上面大多数利用反射,(具体可百度查询),这种方法确实可以把下划线变短,但是同时也会缩短Tab的点击区域,并且过于短后会影响Tab上TextView的UI显示效果。总之,治标不治本,不是我想要的结果。
下面的是可订制的TabLayout,可定制性非常高。亲测有效。
1、首先。添加依赖:
implementation 'com.ogaclejapan.smarttablayout:library:1.6.1@aar'
2、然后是在xml中的用法 (配合ViewPager):
<com.ogaclejapan.smarttablayout.SmartTabLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/smart_tablayout"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@color/colorPrimary"
app:stl_clickable="true"
app:stl_customTabTextLayoutId="@layout/view_tab_text"
app:stl_distributeEvenly="true"
app:stl_dividerThickness="0dp"
app:stl_indicatorColor="@color/colorAccent"
app:stl_indicatorGravity="bottom"
app:stl_indicatorInterpolation="linear"
app:stl_indicatorThickness="2dp"
app:stl_indicatorWidth="20dp"
app:stl_overlineThickness="0dp"
app:stl_titleOffset="auto_center"
app:stl_underlineThickness="0dp">
com.ogaclejapan.smarttablayout.SmartTabLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
注: 具体的属性可查看文章底部的说明。
3、在Activity中SmartTabLayout用法基本与TabLayout相同,基本完工。运行代码可以发现下划线宽度确实是可以自定义。当然它还支持很多属性的自定义。
4、SmartTabLayout中并没有设置选中和未选中Tab时的效果,我们可以通过app:stl_customTabTextLayoutId 属性引入自定义设置。
此处定义的view_tab_text.xml是tab中的title。可根据自己业务个性订制
view_tab_text.xml:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tab_text"
style="@style/Tabtext"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingRight="20dp">
TextView>
下面的 style.xml 则是 view_tab_text 中的样式订制
style.xml:
<style name="Tabtext">
- "android:textColor"
>@color/selector_tab_text
- "android:textSize">20dp
style>
此处为选择器,为title中的选中和未选中颜色
selector_tab_text.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/holo_blue_light" android:state_selected="true" />
<item android:color="@color/colorWhite100" />
selector>
因为引用了自定义Tab布局,所以原生布局带有的Tab点击效果消失(类似于水波纹)
我们可以在 view_tab_text.xml 文件中添加想要的水波纹效果。
android:foreground="@drawable/ripple_app_color"
ripple_app_color.xml: 水波纹效果
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#292421">
ripple>
下面是在Activity中的具体用法:
MainActivity:
public class MainActivity extends AppCompatActivity {
private SmartTabLayout smartTabLayout;
private ViewPager viewPager;
private ArrayList<String> list = new ArrayList<>();
private MyAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
smartTabLayout = findViewById(R.id.smart);
viewPager = findViewById(R.id.viewPager);
for (int i = 0; i <= 10; i++) {
list.add("测试" + i);
}
adapter = new MyAdapter(this, list);
viewPager.setAdapter(adapter);
smartTabLayout.setViewPager(viewPager);
}
}
还有ViewPager的配套Adapter也奉上:
MyAdapter:
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.PagerAdapter;
import java.util.List;
public class MyAdapter extends PagerAdapter {
private Context context;
private List<String> list;
public MyAdapter(Context context, List<String> list) {
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
/**
* 此处为用于往viewpage中添加控件,添加内容,
* @param container
* @param position
* @return
*/
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
TextView textView = new TextView(context);
textView.setText(list.get(position));
textView.setGravity(Gravity.CENTER);
container.addView(textView);
//最后要返回的是控件本身
return textView;
}
/***
* 加入页面的时候,默认缓存三个,如不做处理,滑多了程序就会崩
* @param container
* @param position
* @param object
*/
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
}
/**
* 展示和viewpager上面tltle的展示文字的效果
* @param position
* @return
*/
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return list.get(position);
}
}
到此,订制TabLayout就算完成了。
下面是 SmartTabLayout 属性对照:
属性 | 描述 |
---|---|
stl_indicatorAlwaysInCenter | 如果设置为true,选中的标签总是显示在中心(如报刊亭的谷歌应用程序),默认为false |
stl_indicatorWithoutPadding | 如果设置为真,画出没有填充标签的指标,默认为假 |
stl_indicatorInFront | 在前面的下划线,默认的假画 |
stl_indicatorInterpolation | 指标的行为:: ‘linear’ or ‘smart’ |
stl_indicatorGravity | 指示器的位置: ‘bottom’ or ‘top’ or ‘center’, default ‘bottom’ |
stl_indicatorColor | 指示剂颜色 |
stl_indicatorColors | 该指标的多个颜色,可以设置每个标签的颜色 |
stl_indicatorThickness | 指标的高度 |
stl_indicatorWidth | 指标的宽度(width), default ‘auto’ |
stl_indicatorCornerRadius | 圆角半径的指示器 |
stl_overlineColor | 顶线的颜色 |
stl_overlineThickness | 顶线厚度 |
stl_underlineColor | 底线的颜色 |
stl_underlineThickness | 底线的厚度 |
stl_dividerColor | 标签的颜色之间的分隔 |
stl_dividerColors | 制表符分隔的多个颜色,可以设置每个标签的颜色 |
stl_dividerThickness | 间隔(divider)的厚度 |
stl_defaultTabBackground | 背景中每个选项卡。一般来说,设置statelistdrawable |
stl_defaultTabTextAllCaps | 如果设置为真,所有标签的标题将是大写的,default true |
stl_defaultTabTextColor | 默认的选项卡的文本颜色 |
stl_defaultTabTextSize | 默认的选项卡的文本大小 |
stl_defaultTabTextHorizontalPadding | 默认情况下包含的选项卡的文本布局填充 |
stl_defaultTabTextMinWidth | tab最小宽度 |
stl_customTabTextLayoutId | 布局标识自定义选项卡。如果不指定布局,使用默认选项卡 |
stl_customTabTextViewId | 自定义选项卡布局中的文本视图标识。如果你不确定customtabtextlayoutid,不工作 |
stl_distributeEvenly | 如果设置为真,每个标签都有相同的权重, default false |
stl_clickable | 如果设置为假,请禁用选项卡的选择, default true |
stl_titleOffset | 如果设置为“auto_center,滑块位置的标签中会不断向中心。如果指定一个维度将它从左边偏移,默认24dp |
stl_drawDecorationAfterTab | Draw the decoration(indicator and lines) after drawing of tab, default false 绘制标签后的装饰(指标和线) |