android锚点优化

首先看效果
在这里插入图片描述

先说关键点

  1. tabLayout选中的时候滑动到指定锚点
  2. 由scrollview主动引起的滑动,滑动的指定区域,选中那个指定tabLayout
  3. 由于上述两个步骤会引起相互调用,所以要判断scrollview滑动是主动引起的还是点击tabLayout引起的,涉及到利用反射给tabLayout的tab添加onClick点击监听

项目中的LinearLayout的子元素之间的分隔符用到了系统提供的以下属性

  1. android:showDividers="middle|end"
  2. android:divider="@drawable/divider_item"
  3. 使用方法给百度LinearLayout分隔符

部分代码

  1. 关键点1代码

    tab_layout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            int position = tab.getPosition();
            int top = 0;
            switch (position) {
                case 0:
                    top = ll_first.getTop();
                    break;
                case 1:
                    top = ll_second.getTop();
                    break;
                case 2:
                    top = ll_third.getTop();
                    break;
            }
            //关键点1:点击tab滑动页面到指定位置,利用scrollView的smoothScrollTo方法
            if (!isScroll) {//如果是点击tabLayout
                //因为用户滑动页面也会导致tab选中,这里避开这种情况
                scrollview.smoothScrollTo(0, top);
            }
        }
    
  2. 关键点2代码

    scrollview.setCallbacks(new CustomScrollView.Callbacks() {
        @Override
        public void onScrollChanged(int x, int y, int oldx, int oldy) {
            if (isScroll) {
                //关键点2:由scrollView引起的滑动后移动tabLayout高亮显示指定的tab
                if (y < ll_second.getTop()) {
                    setScrollPos(0);
                } else if (y >= ll_second.getTop() && y < ll_third.getTop()) {
                    setScrollPos(1);
                } else if (y >= ll_third.getTop()) {
                    setScrollPos(2);
                }
            }
        }
    });
    private void setScrollPos(int newPos) {
        if (lastPos != newPos) {
            //此方法可能会导致scrollview的二次滑动,所以要在onTabSelected事件中要判断是不是由scrollview主动引起的滑动
            tab_layout.getTabAt(newPos).select();
            //此方法只是从表面上选中了tab选项,实际tab_layout.getTabAt(0).isSelected()返回值仍可能是false,导致有时候点击tab页面不会滑动到指定锚点
            //            tab_layout.setScrollPosition(newPos,0,true);
        }
        lastPos = newPos;
    }
    
  3. 关键点3代码

    public static void addClick(final TabLayout tabLayout, final OnTabClickListener listener){
        for (int i = 0; i < tabLayout.getTabCount(); i++) {
            TabLayout.Tab tab = tabLayout.getTabAt(i);
            if (null == tab) return;
            // 这里使用到反射,拿到Tab对象后获取Class
            Class c = tab.getClass();
            try {
                // Filed “字段、属性”的意思,c.getDeclaredField 获取私有属性。
                // "view"是Tab的私有属性名称(可查看TabLayout源码8.0以上),类型是 TabView,TabLayout私有内部类。
                //8.0以下是mView
                Field field = null;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
                    //8.0及以上手机
                    field = c.getDeclaredField("view");
                }else {
                    field = c.getDeclaredField("mView");
                }
                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) {
                       listener.onClick(tabLayout,v);
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    完整代码

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章