1. Tablelayout序言
在一个app中,Tabs 使不同视图和功能之间的切换变得简单。使用 tabs 将大量关联的数据或者选项划分成更易理解的分组,可以在不需要切换出当先上下文的情况下,有效的进行内容导航和内容组织。
Tablayout
继承自HorizontalScrollView
,用作页面切换指示器
这里给出一个相关Tablayout实现的效果图:
从效果图上可以看出,可以操作的属性有:设置tab属性,指示线的设置,tab的图标设置,超出屏幕滚动tab等
2. 简单使用
Tablayout
的常用属性如下:
tabGravity
fill,填满TabLayout;center,居中显示tabMode
fixed, 固定标签;scrollable,可滚动标签,个数较少的时候可 以使用fixed,如果标签超出了屏幕范围,设置为scrollable比较好tabMaxWidth
Tab的最大宽度tabIndicatorColor
底部滑动的线条的颜色,默认是colorAccenttabIndicatorHeight
底部滑动线条的高度tabPadding*
标签页的paddingtabBackground
标签页的背景tabTextAppearance
文本设置tabSelectedTextColor
选中字体颜色
Tablayout
常见方法如下:
- 构造方法 不显示滚动条,创建标签条就是下面滚来滚去的那个东东,获取自定义属性值
addTab
手动添加Tab页addOnTabSelectedListener
/removeOnTabSelectedListener
、clearOnTabSelectedListeners
添加/移除/清空Tab选择事件监听器newTab
创建Tab页getTabAt
通过index获取TabremoveTab
通过tab实例移除tabremoveTabAt
移除特定位置的tabremoveAllTabs
清空tabssetTabTextColors
设置tab的正常显示颜色和选中后颜色setupWithViewPager
通过ViewPager初始化TabLayoutshouldDelayChildPressedState
判断是否需要delay视图的press状态,一般无法滚动的视图直接返回false,可以滚动的视图看情况返回true或者falseaddView
添加TabItem,如果参数类型不是TabItem会报异常generateLayoutParams
默认生成属性值,防止TabItem没有定义android:layout_*而报异常
TabItem
属性:
text
:标签文字icon
:图标layout
:自定义布局
2.1 默认使用样式
- activity_main.xml布局
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.tablayoutusecase.defaultuse.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@color/colorPrimaryDark">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="一般用法"
android:textColor="#fff"
android:textSize="16sp"/>
</RelativeLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
- MainActivity修改:设置相关属性
public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
private String[] titles = new String[]{"最新","热门","我的"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
tabLayout = (TabLayout) findViewById(R.id.tablayout);
// 创建Tab页
for(int i=0;i<titles.length;i++){
tabLayout.addTab(tabLayout.newTab());
}
// 设置TabItem的标题
for(int i=0;i<titles.length;i++){
tabLayout.getTabAt(i).setText(titles[i]);
}
}
}
2.2 设置Tablayout属性:
简单效果图如下
用Tablayout属性写一个style,给需要的Tablayout引用:
<!-- 设置tablayout样式 -->
<style name="MyTablayoutstyle" parent="Base.Widget.Design.TabLayout">
<item name="tabBackground">@color/white</item>
<item name="tabIndicatorColor">@color/green</item>
<item name="tabIndicatorHeight">2dp</item>
<item name="tabSelectedTextColor">@color/green</item>
<item name="android:textSize">15sp</item>
<item name="android:textColor">@color/text</item>
</style>
Tablayout
引用:
<android.support.design.widget.TabLayout
android:id="@+id/tab1"
style="@style/MyTablayoutstyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
2.3 Tablayout 指示线设置
- 若不想显示指示线,可以给
tabIndicatorHeight
属性设置0dp,或者给tabSelectedTextColor
属性设置透明,就不显示指示线了
- 修改指示线长度:
在布局中无法找到tabIndicatorWidth
属性,进入到Tablayout类里面查找,查看其如何实现指示线。
找到有SlidingTabStrip内部类:
private final SlidingTabStrip mTabStrip;
private class SlidingTabStrip extends LinearLayout {
private int mSelectedIndicatorHeight;
private final Paint mSelectedIndicatorPaint;
int mSelectedPosition = -1;
float mSelectionOffset;
private int mLayoutDirection = -1;
private int mIndicatorLeft = -1;
private int mIndicatorRight = -1;
private ValueAnimator mIndicatorAnimator;
SlidingTabStrip(Context context) {
super(context);
setWillNotDraw(false);
mSelectedIndicatorPaint = new Paint();
}
void setSelectedIndicatorColor(int color) {
if (mSelectedIndicatorPaint.getColor() != color) {
mSelectedIndicatorPaint.setColor(color);
ViewCompat.postInvalidateOnAnimation(this);
}
}
... ...
可知该类就是设置指示线的,继承于Linearlayout。通过反射获得Tablayout的mTabStrip,循环获取到子View,设置leftMargin,rightMargin就可以压缩tab的宽度。
public class IndicatorLineUtil {
/**
* 调节tablayout指示线宽度
* @param tabs
* @param leftDip
* @param rightDip
*/
public static 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();
}
}
}
tablayout调用此方法:注意:margin数值不能设置过大,不然tab宽度压缩为0整个tablayout就不显示了。
tab3.post(new Runnable() {
@Override
public void run() {
IndicatorLineUtil.setIndicator(tab3, 40, 40);
}
});
2.4 设置默认图标
Tablayout自带了setIcon()
方法设置图标资源,不过效果别扭,脸被拉长。可以自己造一个。
tabLayout.getTabAt(i).setText(titles[i]).setIcon(pics[i]);
自己设置图标资源
- 创建图标和文字布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:gravity="center">
<ImageView
android:id="@+id/imageview"
android:layout_gravity="center"
android:layout_width="24dp"
android:layout_height="24dp" />
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="14sp"
android:layout_marginLeft="8dp"/>
</LinearLayout>
- 设置资源方法:
/**
* 设置自定义位置图标
*/
private void setCustomIcon() {
tabLayout2 = (TabLayout) findViewById(R.id.tablayout2);
for(int i=0;i<titles.length;i++){
tabLayout2.addTab(tabLayout2.newTab());
}
for(int i=0;i<titles.length;i++){
tabLayout2.getTabAt(i).setCustomView(makeTabView(i));
}
}
/**
* 引入布局设置图标和标题
* @param position
* @return
*/
private View makeTabView(int position){
View tabView = LayoutInflater.from(this).inflate(R.layout.tab_text_icon,null);
TextView textView = tabView.findViewById(R.id.textview);
ImageView imageView = tabView.findViewById(R.id.imageview);
textView.setText(titles[position]);
imageView.setImageResource(pics[position]);
return tabView;
}
2.5 tab超出屏幕时
当tab数量较多,超出屏幕,如今日头条的分类一样。可以用app:tabMode="scrollable"属性,让Tablayout变得可滚动,可超出屏幕
在布局中引入:
<android.support.design.widget.TabLayout
android:id="@+id/tablayout3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabSelectedTextColor="@color/green"
android:layout_marginTop="20dp"
app:tabMode="scrollable"
android:background="@color/white"/>
2.6 使用TabItem
在创建Tab时,可以直接在xml布局中设置TabItem来创建Tab
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="蓝色"
android:icon="@color/colorPrimary"/>
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="红色"
android:icon="@color/colorAccent"/>
</android.support.design.widget.TabLayout>
如果多默认的TabItem不满,还可以自定义TabItem的布局
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/custom_indicator3"
android:icon="@drawable/three"
android:text="体育"/>
custom_indicator3.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
/>
<ImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
3. Tablayout进阶
3.1 Tab选中监听
Tab切换时,我们需要切换页面的内容,需要为它设置一个监听器Tablayout.OnTabSelectedListener
,
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
Log.i(TAG,"onTabSelected:"+tab.getText());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
然后就可以在onTabSelected
做对应的逻辑处理了