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();
            }
        }
    }
    

    完整代碼

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