前言:
最近开发的Android项目中,需要根据当前Tab来做相应的事件处理。
开始通过给 TabLayout 添加 addOnTabSelectedListener 监听的方式来解决(如下)。
但是发现这个方法不够灵活,在页面跳转的时候会出现没有tab被选中,不能在 onTabSelected() 进行相应事件处理的情况。
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
// 根据业务需求处理事件
Log.e(TAG, "选中的tab = " + tab.getPosition());
if (1 != tab.getPosition()) {
Log.e(TAG, "设置autoSwitch = false");
MonitorFragment.autoSwitch = false;
} else if (1 == tab.getPosition()) {
Log.e(TAG, "设置autoSwitch = true");
MonitorFragment.autoSwitch = true;
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
因此,考虑通过给 TabLayout 添加自定义点击事件来做相应的处理,之前没做过,百度后有很多答案。
但是,在项目上使用发现有问题,暴力反射获取TabLayout私有属性的时候不通过,
最后翻看TabLayout源码找到问题原因:
TabLayout源码更新,私有属性名已经从“mView"变为”view“
解决办法:
把Tab的私有属性名称 mView 改为 view 即可解决问题
Field field = c.getDeclaredField("mView"); ======> Field field = c.getDeclaredField("view");
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
Log.e(TAG, "tab点击事件");
TabLayout.Tab tab = mTabLayout.getTabAt(i);
if (null == tab) return;
// 这里使用到反射,拿到Tab对象后获取Class
Class c = tab.getClass();
try {
// Filed “字段、属性”的意思,c.getDeclaredField 获取私有属性。
// "view"是Tab的私有属性名称(可查看TabLayout源码),类型是 TabView,TabLayout私有内部类。
Field field = c.getDeclaredField("view");
field.setAccessible(true);
final View view = (View) field.get(tab);
if (null == view) return;
view.setTag(i);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 根据业务需求处理点击事件
int position = (int) view.getTag();
if (1 != position) {
Log.e(TAG, "设置autoSwitch = false");
MonitorFragment.autoSwitch = false;
} else if (1 == position) {
Log.e(TAG, "设置autoSwitch = true");
MonitorFragment.autoSwitch = true;
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}