基于TabLayoutMediator实现TabLayout+ViewPager2(Fragment)封装

实现功能

1、TabLayout+ViewPager2(Fragments)

2、TabLayout

①、动态设置TabView(setTabViewResId),TextView动态设置IdseTabViewTextResId(),并获取TextView对象

②、默认全部Fragmnet预加载,可通过setOffscreenPageLimit(boolean)控制

③、UserTabConfigurationStrategy监听,获取所有TabView初始化对象

④、UserTabSelectedListener,获取TabLayout切换时候监听回调,包含切换前后上个item position

⑤、设置和更新  未读数和小红,包含是否开启初始化后立马显示未读数和小红点,也可以网络请求后设置

⑥、TabView支持选中字体加粗、字体大小、颜色,未选中字体加粗、字体大小、颜色

⑦、设置TextView,内边距和外边距。

在保留官方TabLayout和ViewPager2所有特性前提下,封装其他公共方法。

UserTabLayoutMediator代码:

public final class UserTabLayoutMediator implements TabLayout.OnTabSelectedListener {
    private static final long ATTACH_DRAWABLE_VIEW_DELAY_MILLIS = 500l;

    private TabLayout tabLayout;
    private ViewPager2 viewPager;

    private TabLayoutMediator tabLayoutMediator;

    private UserTabConfigurationStrategy userTabConfigurationStrategy;
    private UserTabSelectedListener userTabSelectedListener;
    Map<Integer, BadgeDrawable> badgeDrawableMap = new HashMap<>();
    private boolean attached = false;
    private BadgeDrawableRunnable badgeDrawableRunnable;
    private boolean attachDrawableViewAsync = false;

    private @LayoutRes
    int tabViewResId = R.layout.base_user_tab_layout_mediator_tab_view;  //user_tab_layout_mediator_tab_view
    private @IdRes
    int tabViewTextResId = R.id.base_user_tab_layout_mediator_text_view;
    private int selectTextSize;
    private int unselectedTextSize;
    private int selectTextColor;
    private int unselectedTextColor;
    private boolean fakeBoldText;
    private List<String> tabViewTextList;
    //默认设置 OffscreenPageLimit true,则ViewPager Fragment都会初始化并执行到onStart方法。当前台显示onResume->onPause
    private boolean offscreenPageLimit = true;

    private int currentItemPosition;

    private int gravity;

    private int paddingLeft;
    private int paddingTop;
    private int paddingRight;
    private int paddingBottom;

    private int marginLeft;
    private int marginTop;
    private int marginRight;
    private int marginBottom;

    private int onTabSelectPosition;

    public UserTabLayoutMediator() {

    }

    public UserTabLayoutMediator(TabLayout tabLayout, UserTabConfigurationStrategy tabConfigurationStrategy) {
        this(tabLayout, null, tabConfigurationStrategy);
    }

    public UserTabLayoutMediator(ViewPager2 viewPager, UserTabConfigurationStrategy tabConfigurationStrategy) {
        this(null, viewPager, tabConfigurationStrategy);
    }

    public UserTabLayoutMediator(TabLayout tabLayout, ViewPager2 viewPager, UserTabConfigurationStrategy tabConfigurationStrategy) {
        this.tabLayout = tabLayout;
        this.viewPager = viewPager;
        this.userTabConfigurationStrategy = tabConfigurationStrategy;
    }

    public void setTabViewText(String[] tabViewText) {
        if (tabViewText != null) {
            this.tabViewTextList = new ArrayList<>();
            Collections.addAll(this.tabViewTextList, tabViewText);
        }
    }

    public void setTabViewText(List<String> tabViewText) {
        this.tabViewTextList = tabViewText;
    }

    //设置自定义tab View resId
    public void setTabViewResId(@LayoutRes int tabViewResId) {
        this.tabViewResId = tabViewResId;
    }

    //设置自定义 tabView textViwId
    public void seTabViewTextResId(@IdRes int tabViewTextResId) {
        this.tabViewTextResId = tabViewTextResId;
    }

    public void setSelectFakeBoldText(boolean fakeBoldText) {
        this.fakeBoldText = fakeBoldText;
    }

    public void setTextSize(int selectTextSize, int unselectedTextSize) {
        this.selectTextSize = selectTextSize;
        this.unselectedTextSize = unselectedTextSize;
    }

    public void setTextColor(@ColorRes int selectTextColor, @ColorRes int unselectedTextColor) {
        this.selectTextColor = selectTextColor;
        this.unselectedTextColor = unselectedTextColor;
    }

    /**
     * 设置显示的ViewPager item position,未绑定,初始化设置setCurrentItem,当初始化后,直接调用ViewPager.setCurrentItem()
     *
     * @param itemPosition
     */
    public void setCurrentItemPosition(int itemPosition) {
        this.currentItemPosition = itemPosition;
        if (attached) {
            setCurrentItem(itemPosition);
        }
    }

    public void setCurrentItem(int item) {
        setCurrentItem(item, true);
    }

    public void setCurrentItem(int item, boolean smoothScroll) {
        if (viewPager != null)
            viewPager.setCurrentItem(item, smoothScroll);
    }

    public void setAttachDrawableViewAsync(boolean attachDrawableViewAsync) {
        this.attachDrawableViewAsync = attachDrawableViewAsync;
    }

    public void setOffscreenPageLimit(boolean limit) {
        this.offscreenPageLimit = limit;
    }

    public void setGravity(int gravity) {
        this.gravity = gravity;
    }

    public void setPadding(int left, int top, int right, int bottom) {
        this.paddingLeft = left;
        this.paddingTop = top;
        this.paddingRight = right;
        this.paddingBottom = bottom;
    }

    public void setMargins(int left, int top, int right, int bottom) {
        this.marginLeft = left;
        this.marginTop = top;
        this.marginRight = right;
        this.marginBottom = bottom;
    }


    //------设置监听----------------
    public void addUserTabConfigurationStrategy(UserTabConfigurationStrategy tabConfigurationStrategy) {
        this.userTabConfigurationStrategy = tabConfigurationStrategy;
    }

    public void addTabSelectedListener(UserTabSelectedListener userTabSelectedListener) {
        this.userTabSelectedListener = userTabSelectedListener;
    }


    public void attach() {
        attached = true;
        if (tabLayout != null && viewPager != null) {
            viewPager.setCurrentItem(currentItemPosition);
            tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager, new TabLayoutMediator.TabConfigurationStrategy() {
                @Override
                public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
                    if (tabViewResId != View.NO_ID) {
                        View customView = tab.setCustomView(tabViewResId).getCustomView();
                        setTabViewGravity(customView);
                        TextView textView = customView.findViewById(tabViewTextResId);
                        setTabViewText(null, textView, position);
                        setTabViewTextViewPadding(textView);
                        setTabViewTextViewMargins(textView);


                    } else {
                        setTabViewText(tab, null, position);
                    }
                    if (userTabConfigurationStrategy != null) {
                        userTabConfigurationStrategy.onConfigureTab(tab, position);
                    }
                }
            });

            tabLayout.addOnTabSelectedListener(this);
            RecyclerView.Adapter adapter = viewPager.getAdapter();
            if (offscreenPageLimit && adapter != null) {
                int itemCount = adapter.getItemCount();
                if (itemCount > 1)
                    viewPager.setOffscreenPageLimit(itemCount);
            }
            tabLayoutMediator.attach();
            if (attachDrawableViewAsync)
                attachDrawableViewByAsync();
        }
    }


    public void detach() {
        attached = false;
        if (tabLayoutMediator != null) {
            tabLayoutMediator.detach();
            tabLayoutMediator = null;
        }
        if (tabLayout != null) {
            tabLayout.removeOnTabSelectedListener(this);
        }
        if (badgeDrawableMap != null) {
            badgeDrawableMap.clear();
        }
        removeDrawableViewCallbacks();
    }


    /**
     * 添加 BadgeDrawable 小红点
     *
     * @param context
     * @param position
     * @param backgroundColor
     */
    public void addBadgeDrawable(Context context, int position, @ColorRes int backgroundColor) {
        BadgeDrawable badge = BadgeDrawable.create(context);
        badge.setBackgroundColor(ContextCompat.getColor(context, backgroundColor));
        badge.setHorizontalOffset(5);
        badge.setVerticalOffset(5);
        badge.setVisible(true);
        badgeDrawableMap.put(position, badge);
    }

    /**
     * 添加 BadgeDrawable 未读数量
     *
     * @param context           上下文
     * @param position          需要添加位置
     * @param backgroundColor   背景颜色
     * @param badgeTextColor    字体颜色
     * @param number            显示未读数量
     * @param maxCharacterCount 最大位数 number 99999, max== 3 则显示:99+
     */
    public void addBadgeDrawable(Context context, int position, @ColorRes int backgroundColor, @ColorRes int badgeTextColor, int number, int maxCharacterCount) {
        BadgeDrawable badge = BadgeDrawable.create(context);
        badge.setBackgroundColor(ContextCompat.getColor(context, backgroundColor));
        badge.setBadgeTextColor(ContextCompat.getColor(context, badgeTextColor));
        badge.setHorizontalOffset(5);
        badge.setVerticalOffset(5);
        badge.setNumber(number);
        badge.setMaxCharacterCount(maxCharacterCount);
        badge.setVisible(true);
        badgeDrawableMap.put(position, badge);

    }

    /**
     * 绑定 DrawableView
     *
     * @param context
     * @param position
     * @param backgroundColor
     */
    @SuppressLint({"UnsafeExperimentalUsageError", "RestrictedApi"})
    public void attachDrawableView(Context context, int position, @ColorRes int backgroundColor) {
        addBadgeDrawable(context, position, backgroundColor);
        BadgeDrawable badgeDrawable = badgeDrawableMap.get(position);
        if (badgeDrawable != null) {
            View view = badgeDrawableView(position);
            if (view != null) {
                BadgeUtils.attachBadgeDrawable(badgeDrawable, view);
            }
        }
    }

    /**
     * 绑定 DrawableView
     *
     * @param context
     * @param position
     * @param backgroundColor
     * @param badgeTextColor
     * @param number
     * @param maxCharacterCount
     */
    @SuppressLint("UnsafeExperimentalUsageError")
    public void attachDrawableView(Context context, int position, @ColorRes int backgroundColor, @ColorRes int badgeTextColor, int number, int maxCharacterCount) {
        addBadgeDrawable(context, position, backgroundColor, badgeTextColor, number, maxCharacterCount);
        BadgeDrawable badgeDrawable = badgeDrawableMap.get(position);
        if (badgeDrawable != null) {
            View view = badgeDrawableView(position);
            if (view != null) {
                BadgeUtils.attachBadgeDrawable(badgeDrawable, view);
            }
        }
    }

    /**
     * 绑定 DrawableView  不可初始化之后,直接调用
     */
    @SuppressLint("UnsafeExperimentalUsageError")
    public void attachDrawableView() {
        if (tabLayout != null && attached && badgeDrawableMap.size() > 0) {
            for (Map.Entry<Integer, BadgeDrawable> entry : badgeDrawableMap.entrySet()) {
                TabLayout.Tab tabAt = tabLayout.getTabAt(entry.getKey());
                BadgeDrawable badgeDrawable = entry.getValue();
                if (tabAt != null && badgeDrawable != null) {
                    View customView = tabAt.getCustomView();
                    if (customView != null) {
                        View view = customView.findViewById(tabViewTextResId);
                        if (view != null) {
                            BadgeUtils.attachBadgeDrawable(badgeDrawable, view);
                        }
                    }
                }
            }
        }
    }

    /**
     * 异步绑定 DrawableView
     */
    public void attachDrawableViewByAsync() {
        if (tabLayout != null && attached && badgeDrawableMap.size() > 0) {
            badgeDrawableRunnable = new BadgeDrawableRunnable(tabLayout, badgeDrawableMap, tabViewTextResId);
            tabLayout.postDelayed(badgeDrawableRunnable, ATTACH_DRAWABLE_VIEW_DELAY_MILLIS);
        }
    }

    /**
     * 移除异步线程
     */
    private void removeDrawableViewCallbacks() {
        if (tabLayout != null && badgeDrawableRunnable != null) {
            tabLayout.removeCallbacks(badgeDrawableRunnable);
        }
    }


    /**
     * 更新 BadgeDrawable
     *
     * @param position
     * @param number
     */
    @SuppressLint("UnsafeExperimentalUsageError")
    public void updateBadgeDrawable(int position, int number) {
        if (badgeDrawableMap != null) {
            if (badgeDrawableMap.containsKey(position)) {
                BadgeDrawable badgeDrawable = badgeDrawableMap.get(position);
                if (badgeDrawable != null) {
                    badgeDrawable.setNumber(number);
                    View view = detachBadgeDrawable(position);
                    if (view != null) {
                        BadgeUtils.attachBadgeDrawable(badgeDrawable, view);
                    }
                }
            }
        }
    }

    /**
     * 移除 BadgeDrawable
     *
     * @param position
     * @return
     */
    @SuppressLint("UnsafeExperimentalUsageError")
    public View detachBadgeDrawable(int position) {
        if (badgeDrawableMap != null && position < badgeDrawableMap.size()) {
            BadgeDrawable badgeDrawable = badgeDrawableMap.get(position);
            if (badgeDrawable != null) {
                badgeDrawable.setVisible(false);
                View view = badgeDrawableView(position);
                if (view != null) {
                    BadgeUtils.detachBadgeDrawable(badgeDrawable, view);
                }
                return view;
            }
        }
        return null;
    }

    /**
     * 获取当前 badgeDrawable ---view
     *
     * @param position
     * @return
     */
    private View badgeDrawableView(int position) {
        if (tabLayout != null) {
            TabLayout.Tab tabAt = tabLayout.getTabAt(position);
            if (tabAt != null) {
                View customView = tabAt.getCustomView();
                if (customView != null) {
                    return customView.findViewById(tabViewTextResId);

                }
            }
        }
        return null;
    }

    private void setTabViewText(TabLayout.Tab tab, TextView textView, int position) {
        if (tabViewTextList != null && position < tabViewTextList.size()) {
            String text = tabViewTextList.get(position);
            if (tab != null) {
                tab.setText(text);
            }

            if (textView != null)
                textView.setText(text);

        } else {
            RecyclerView.Adapter adapter = viewPager.getAdapter();
            if (adapter instanceof BaseFragmentPagerAdapter) {
                BaseFragmentPagerAdapter pagerAdapter = (BaseFragmentPagerAdapter) adapter;
                CharSequence text = pagerAdapter.getPageTitle(position);
                if (tab != null)
                    tab.setText(text);

                if (textView != null)
                    textView.setText(text);
            }
        }
    }


    /**
     * 设置tabView textView padding
     *
     * @param view
     */
    private void setTabViewTextViewPadding(View view) {
        if (view != null && (paddingLeft != 0 || paddingTop != 0 || paddingRight != 0 || paddingBottom != 0)) {
            view.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
        }
    }

    /**
     * 设置tabView textView margin
     *
     * @param view
     */
    private void setTabViewTextViewMargins(View view) {
        if (view != null && (marginLeft != 0 || marginTop != 0 || marginRight != 0 || marginBottom != 0)) {
            ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
            if (layoutParams instanceof LinearLayout.LayoutParams) {
                LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) layoutParams;
                params.setMargins(marginLeft, marginTop, marginRight, marginBottom);
            }
        }
    }

    /**
     * 设置tabView gravity
     *
     * @param view
     */
    private void setTabViewGravity(View view) {
        if (view != null && gravity != 0 && view instanceof LinearLayout) {
            LinearLayout linearLayout = (LinearLayout) view;
            linearLayout.setGravity(gravity);
        }
    }


    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        if (viewPager != null)
            onTabSelectPosition = viewPager.getCurrentItem();
        if (tab != null) {
            View customView = tab.getCustomView();
            if (customView != null) {
                TextView textView = customView.findViewById(tabViewTextResId);
                if (textView != null) {
                    if (selectTextSize != 0 && selectTextSize != unselectedTextSize)
                        textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, selectTextSize);
                    if (selectTextColor != 0 && selectTextColor != unselectedTextColor)
                        textView.setTextColor(ContextCompat.getColor(textView.getContext(), selectTextColor));
                    if (fakeBoldText)
                        textView.getPaint().setFakeBoldText(true);
                }
            }
        }
        if (userTabSelectedListener != null) {
            userTabSelectedListener.onTabSelected(tab, onTabSelectPosition);
        }
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
        if (tab != null) {
            View customView = tab.getCustomView();
            if (customView != null) {
                TextView textView = customView.findViewById(tabViewTextResId);
                if (textView != null) {
                    if (selectTextSize != 0 && selectTextSize != unselectedTextSize)
                        textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, unselectedTextSize);
                    if (selectTextColor != 0 && selectTextColor != unselectedTextColor)
                        textView.setTextColor(ContextCompat.getColor(textView.getContext(), unselectedTextColor));
                    if (fakeBoldText)
                        textView.getPaint().setFakeBoldText(false);
                }
            }
        }

        if (userTabSelectedListener != null) {
            userTabSelectedListener.onTabUnselected(tab, onTabSelectPosition);
        }
    }

    @Override
    public void onTabReselected(TabLayout.Tab tab) {
        if (userTabSelectedListener != null) {
            userTabSelectedListener.onTabReselected(tab);
        }
    }

    /**
     * 异步 BadgeDrawableView
     */
    static class BadgeDrawableRunnable implements Runnable {
        private WeakReference<TabLayout> tabLayoutWeakReference;
        private Map<Integer, BadgeDrawable> badgeDrawableMap;
        private int tabViewTextResId;

        public BadgeDrawableRunnable(TabLayout tabLayout, Map<Integer, BadgeDrawable> badgeDrawableMap, int tabViewTextResId) {
            if (tabLayout != null)
                tabLayoutWeakReference = new WeakReference<>(tabLayout);
            this.badgeDrawableMap = badgeDrawableMap;
            this.tabViewTextResId = tabViewTextResId;
        }

        @SuppressLint("UnsafeExperimentalUsageError")
        @Override
        public void run() {
            if (tabLayoutWeakReference != null && tabLayoutWeakReference.get() != null && badgeDrawableMap != null) {
                TabLayout tabLayout = tabLayoutWeakReference.get();
                for (Map.Entry<Integer, BadgeDrawable> entry : badgeDrawableMap.entrySet()) {
                    TabLayout.Tab tabAt = tabLayout.getTabAt(entry.getKey());
                    BadgeDrawable badgeDrawable = entry.getValue();
                    if (tabAt != null && badgeDrawable != null) {
                        View customView = tabAt.getCustomView();
                        if (customView != null) {
                            View view = customView.findViewById(tabViewTextResId);
                            if (view != null) {
                                BadgeUtils.attachBadgeDrawable(badgeDrawable, view);
                            }
                        }
                    }
                }
            }
        }
    }


    public interface UserTabConfigurationStrategy {
        /**
         * Called to configure the tab for the page at the specified position. Typically calls {@link
         * TabLayout.Tab#setText(CharSequence)}, but any form of styling can be applied.
         *
         * @param tab      The Tab which should be configured to represent the title of the item at the given
         *                 position in the data set.
         * @param position The position of the item within the adapter's data set.
         */
        void onConfigureTab(@NonNull TabLayout.Tab tab, int position);
    }


    public interface UserTabSelectedListener {
        void onTabSelected(TabLayout.Tab tab, int position);

        /**
         * Called when a tab exits the selected state.
         *
         * @param tab The tab that was unselected
         */
        void onTabUnselected(TabLayout.Tab tab, int unPosition);

        /**
         * Called when a tab that is already selected is chosen again by the user. Some applications may
         * use this action to return to the top level of a category.
         *
         * @param tab The tab that was reselected.
         */
        void onTabReselected(TabLayout.Tab tab);

    }


}
tabView:base_user_tab_layout_mediator_tab_view 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="horizontal">

    <TextView
        android:id="@id/base_user_tab_layout_mediator_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />


</LinearLayout>

ids.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- tabLayout tabView id -->
    <item name="base_user_tab_layout_mediator_tab_view" type="id"></item>
    <!-- tabLayout tabView textView id -->
    <item name="base_user_tab_layout_mediator_text_view" type="id"></item>
</resources>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值