[置顶] 记录:Android api 24+的TabLayout问题处理
2016-12-14 17:00
417 查看
API 24的TabLayout更新了一些方法 用着有些问题 比如像我遇到的自定义处理某些tab点击时想要不切换viewPager 而是弹出一个activity
下面是一个简单的懒人处理方式 附带源码分析
看上面的源码你会发现 这个方法里 TabLayout会帮你add一个OnTabSelectedListener 就是下面这个
然后罪魁祸首是TabLayout的这个方法 从上面可以看出来 在你addOnTabSelectedListener之前已经有一个OnTabSelectedListener了
所以 执行完你自己加的OnTabSelectedListener的onTabSelected之后 总会执行TabLayout会帮你add那个OnTabSelectedListener的onTabSelected
所以 我想到的解决方案是强行remove掉它给你加的那个OnTabSelectedListener 可以 这很反射 当然 你要换成github上的一些TabLayout也无妨
然后自定义自己的OnTabSelectedListener
最后addOnTabSelectedListener
release版本开了混淆的话在proguard-rules.pro加上
下面是一个简单的懒人处理方式 附带源码分析
ViewPager vp = (ViewPager)findViewById(R.id.viewPager); TabLayout tabLayout = (TabLayout)findViewById(R.id.tabLayout); tabLayout.setupWithViewPager(vp);//看看这个方法做了什么
private void setupWithViewPager(@Nullable final ViewPager viewPager, boolean autoRefresh, boolean implicitSetup) { if (mViewPager != null) { // If we've already been setup with a ViewPager, remove us from it if (mPageChangeListener != null) { mViewPager.removeOnPageChangeListener(mPageChangeListener); } if (mAdapterChangeListener != null) { mViewPager.removeOnAdapterChangeListener(mAdapterChangeListener); } } if (mCurrentVpSelectedListener != null) { // If we already have a tab selected listener for the ViewPager, remove it removeOnTabSelectedListener(mCurrentVpSelectedListener); mCurrentVpSelectedListener = null; } if (viewPager != null) { mViewPager = viewPager; // Add our custom OnPageChangeListener to the ViewPager if (mPageChangeListener == null) { mPageChangeListener = new TabLayoutOnPageChangeListener(this); } mPageChangeListener.reset(); viewPager.addOnPageChangeListener(mPageChangeListener); // Now we'll add a tab selected listener to set ViewPager's current item mCurrentVpSelectedListener = new ViewPagerOnTabSelectedListener(viewPager); addOnTabSelectedListener(mCurrentVpSelectedListener);//这里给你添加了一个OnTabSelectedListener final PagerAdapter adapter = viewPager.getAdapter(); if (adapter != null) { // Now we'll populate ourselves from the pager adapter, adding an observer if // autoRefresh is enabled setPagerAdapter(adapter, autoRefresh); } // Add a listener so that we're notified of any adapter changes if (mAdapterChangeListener == null) { mAdapterChangeListener = new AdapterChangeListener(); } mAdapterChangeListener.setAutoRefresh(autoRefresh); viewPager.addOnAdapterChangeListener(mAdapterChangeListener); // Now update the scroll position to match the ViewPager's current item setScrollPosition(viewPager.getCurrentItem(), 0f, true); } else { // We've been given a null ViewPager so we need to clear out the internal state, // listeners and observers mViewPager = null; setPagerAdapter(null, false); } mSetupViewPagerImplicitly = implicitSetup; }
看上面的源码你会发现 这个方法里 TabLayout会帮你add一个OnTabSelectedListener 就是下面这个
class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener { private final ViewPager mViewPager; public ViewPagerOnTabSelectedListener(ViewPager viewPager) { mViewPager = viewPager; } @Override public void onTabSelected(TabLayout.Tab tab) { mViewPager.setCurrentItem(tab.getPosition());//强行帮你选中你不希望选中的viewPager的某个页面 } @Override public void onTabUnselected(TabLayout.Tab tab) { // No-op } @Override public void onTabReselected(TabLayout.Tab tab) { // No-op } }
然后罪魁祸首是TabLayout的这个方法 从上面可以看出来 在你addOnTabSelectedListener之前已经有一个OnTabSelectedListener了
所以 执行完你自己加的OnTabSelectedListener的onTabSelected之后 总会执行TabLayout会帮你add那个OnTabSelectedListener的onTabSelected
private void dispatchTabSelected(@NonNull final Tab tab) { for (int i = mSelectedListeners.size() - 1; i >= 0; i--) { mSelectedListeners.get(i).onTabSelected(tab); } }
所以 我想到的解决方案是强行remove掉它给你加的那个OnTabSelectedListener 可以 这很反射 当然 你要换成github上的一些TabLayout也无妨
Field fields[] = tabLayout.getClass().getDeclaredFields(); String[] name = new String[fields.length]; Object[] value = new Object[fields.length]; try { Field.setAccessible(fields, true); for (int i = 0; i < name.length; i++) { name[i] = fields[i].getName(); value[i] = fields[i].get(tabLayout); if (name[i].equals("mCurrentVpSelectedListener")) { tabLayout.removeOnTabSelectedListener((TabLayout.OnTabSelectedListener) value[i]); } } } catch (Exception e) { e.printStackTrace(); }
然后自定义自己的OnTabSelectedListener
OnTabSelectedListener mTabSelectedListener = new TabLayout.ViewPagerOnTabSelectedListener(vp) { @Override public void onTabSelected(TabLayout.Tab tab) { int position = (int) tab.getTag(); if (position == 0) { vp.setCurrentItem(tab.getPosition()); }else if (position == 1) { if (condition) {//condition:自己写的某些条件 if (tab != null) { vp.setCurrentItem(tab.getPosition());//手动调用viewPager的setCurrentItem } } else { doSomething();//可以做些其他事情 这里不用调用viewPager的setCurrentItem 就不会切到不想切换的viewPager那个页面了 } } } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { //之所以要在这里添加reslect的处理 主要是你之前点击tab的时候虽然没选中并切换Viewpager的页面 //但是 TabLayout的状态其实已经被选中了 再次点击时肯定是不会走onTabSelected方法的 //但是会走这个onTabReselected 另外 选中时一些UI上的图标、文字切换效果什么的需要自己在onTabSelected中处理 int position = (int) tab.getTag(); L.e(TAG, position + " onTabReselected"); mTabSelectedListener.onTabSelected(tab); } };
最后addOnTabSelectedListener
tabLayout.addOnTabSelectedListener(mTabSelectedListener);
release版本开了混淆的话在proguard-rules.pro加上
-keepclasseswithmembernames class android.support.design.widget.TabLayout { *; }
相关文章推荐
- Android 源码在线查看
- Android 镂空效果的遮罩层实现
- Android Can't convert to dimension: type=0x1
- Android的四大组件之ContentProvider总结
- user版本如何打开uart,让android log从串口kernel log输出
- Android GridView 滑动条设置一直显示状态(推荐)
- Android中finish()与destroy()的区别
- Android12
- Android11
- 蓝牙4.0BLE在安卓项目中的使用详解
- Android 横竖屏随意切换的两种方式
- Android Studio导入项目gradle报错,解决方案
- Android自定义控件之自定义倒计时按钮
- Android之查看手机实时电流、电压
- Android-验证手机上面是否存在其它应用接收Intent
- Android 应用的真正入口 - ZygoteInit.java
- Gradle系列第(三)篇---Android Studio与Gradle那些事儿
- android 用代码打开 gprs(流量开关) android 5.0 ROOT
- ViewGroup是如何加载布局中的view?
- Android逆向之旅---静态分析技术来破解Apk