TabLayoutの高度な使い方(tabのカスタマイズとインジケータ幅の変更)

7950 ワード

TabLayoutは使いやすいですが、原生の属性は正式なニーズを満たすのが難しいので、自分のtabをカスタマイズしなければなりません(単純な文字や文図の混在形式が可能です)、原生の切り替えはアニメーション効果がなく、インタラクティブな効果が良いために私たちも相応のアニメーションを追加することができます.原生のtabIndicatorは高さと背景色を設定する方法しか提供していません.幅は均一で、少し醜いです.以上の要件を達成するには、ビジネスに基づいて拡張または変更できるツールクラスを用意しました.
/**
 * @Desc:  TabLayout    
 * @Author: JiangRongtao
 * @Created by: 2018/12/21 0021 13:55
 **/

public class TabLayoutAnimUtils {
    private TabLayout mTabLayout;
    private List mTitleList;
    private Context mContext;

    public TabLayoutAnimUtils(Context context, TabLayout tabLayout, List titleList) {

        this.mContext = context;
        this.mTabLayout = tabLayout;
        this.mTitleList = titleList;
    }

    /**
     *     TabLayout    View
     *   :TabLayout Viewpager          mViewPager.setAdapter(),       ,  addOnTabSelectedListener;  adapter    mCustomViewView ,
     */
    public void setCustomViews() {
        int mSelectedTabPosition = mTabLayout.getSelectedTabPosition();
        for (int i = 0; i < this.mTitleList.size(); i++) {
            TabLayout.Tab mTab = this.mTabLayout.getTabAt(i).setCustomView(getTabView(i, mSelectedTabPosition));
            if (i == mSelectedTabPosition) {
                changeTabSelect(mTab);
            } else {
                changeTabNormal(mTab);
            }
        }
    }

    /**
     *   TabLayout View
     *   index     View
     *   :     View          
     */
    private View getTabView(int index, int mSelectedTabPosition) {
        //   View  
        View view = LayoutInflater.from(mContext).inflate(R.layout.custom_tab_item_layout, null);
        TextView title = (TextView) view.findViewById(R.id.title);
        title.setText(mTitleList.get(index));
        title.setSelected(index == mSelectedTabPosition ? true : false);
        return view;
    }

    /**
     *   TabLayout View     
     *         Tab View   
     */
    public void changeTabSelect(TabLayout.Tab tab) {
        final View view = tab.getCustomView();
        ObjectAnimator anim = ObjectAnimator
                .ofFloat(view, "", 1.0F, 1.1F)
                .setDuration(200);
        anim.start();
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cVal = (Float) animation.getAnimatedValue();
                view.setAlpha(0.5f + (cVal - 1f) * (0.5f / 0.1f));
                view.setScaleX(cVal);
                view.setScaleY(cVal);
            }
        });
    }

    /**
     *   TabLayout View      
     */
    public void changeTabNormal(TabLayout.Tab tab) {
        final View view = tab.getCustomView();
        ObjectAnimator anim = ObjectAnimator
                .ofFloat(view, "", 1.0F, 0.9F)
                .setDuration(200);
        anim.start();
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cVal = (Float) animation.getAnimatedValue();
                view.setAlpha(1f - (1f - cVal) * (0.5f / 0.1f));
                view.setScaleX(cVal);
                view.setScaleY(cVal);
            }
        });
    }

    /**
     *   tablayout      
     *
     * @param tabLayout
     * @param margin
     */
    public void changeTabIndicatorWidth(final TabLayout tabLayout, final int margin) {
        tabLayout.post(new Runnable() {
            @Override
            public void run() {
                try {
                    Field mTabStripField = tabLayout.getClass().getDeclaredField("mTabStrip");
                    mTabStripField.setAccessible(true);

                    LinearLayout mTabStrip = (LinearLayout) mTabStripField.get(tabLayout);

                    int dp10 = margin == 0 ? 50 : margin;

                    for (int i = 0; i < mTabStrip.getChildCount(); i++) {
                        View tabView = mTabStrip.getChildAt(i);

                        Field mTextViewField = tabView.getClass().getDeclaredField("mTextView");
                        mTextViewField.setAccessible(true);

                        TextView mTextView = (TextView) mTextViewField.get(tabView);

                        tabView.setPadding(0, 0, 0, 0);

                        int width = 0;
                        width = mTextView.getWidth();
                        if (width == 0) {
                            mTextView.measure(0, 0);
                            width = mTextView.getMeasuredWidth();
                        }

                        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tabView.getLayoutParams();
                        params.width = width;
                        params.leftMargin = dp10;
                        params.rightMargin = dp10;
                        tabView.setLayoutParams(params);

                        tabView.invalidate();
                    }

                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public void changeTabIndicatorWidth(TabLayout tabLayout) {
        changeTabIndicatorWidth(tabLayout, 0);
    }

    /**
     *   tablayout      
     *
     * @param tabs
     * @param leftDip
     * @param rightDip
     */
    public void setIndicatorWidth(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();
        }
    }

}

具体的な使い方の部分コードは以下の通りです.
 mViewPager.setAdapter(new TabPagerAdapter(getChildFragmentManager(), mFragmentList, mTitles));
        mTabLayout.setupWithViewPager(mViewPager);
        //       
        final TabLayoutAnimUtils mTabLayoutAnimUtils = new TabLayoutAnimUtils(mContext, mTabLayout, mTitles);
        mTabLayoutAnimUtils.changeTabIndicatorWidth(mTabLayout);
        mTabLayoutAnimUtils.setCustomViews();
        mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                mTabLayoutAnimUtils.changeTabSelect(tab);
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                mTabLayoutAnimUtils.changeTabNormal(tab);
            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
注意:TabLayoutとViewpagerを併用する場合はmViewPager.setAdapter()は、メソッドを初期化し、addOnTabSelectedListener;adapterリフレッシュはmCustomViewを空にします.つまり、あなたが設定したmCustomViewは表示されません.