Android - 自定義Tablayout + ViewPager(設定可滑動)

2020-09-27 08:00:49

Android - 自定義Tablayout + ViewPager(設定可滑動)

1、建立TabFragment主要把Viepager新增進去但是這裡是否需要Viewpager滑動要去重寫ViewPager去控制(程式碼下面)

/*
 * 自定義 首頁切換
 */
public class TabFragment extends RelativeLayout {

    //當前上線文物件
    public Context context;

    //當前基礎設定資料
    private BasicConfiguration basicConfiguration;

    public TabFragment(Context context) {
        super(context);
    }

    public TabFragment(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    //設定設定資料
    public void setData(BasicConfiguration basicConfiguration) {
        this.basicConfiguration = basicConfiguration;
        initView(basicConfiguration);
    }

    //獲取當前設定資料
    public BasicConfiguration getData() {
        if (basicConfiguration == null) {
            basicConfiguration = new BasicConfiguration();
        }
        return basicConfiguration;
    }

    private void initView(BasicConfiguration basicConfiguration) {
        View tabFragment = LayoutInflater.from(context).inflate(R.layout.layout_tabfragment, this, false);
        //viewPage
        CustomViewPager tabFragment_viewpager = tabFragment.findViewById(R.id.tabFragment_viewpager);
        //取消滑動陰影
        tabFragment_viewpager.setOverScrollMode(OVER_SCROLL_NEVER);
        //底部導航欄
        LinearLayout tabFragment_bottomRoot = tabFragment.findViewById(R.id.tabFragment_bottomRoot);
        //設定Viewpager 是否可滑動
        tabFragment_viewpager.setViewPagerState(basicConfiguration.isViewPagerIsScroll());
        PagerAdapter pagerAdapter = new PagerAdapter();
        tabFragment_viewpager.setAdapter(pagerAdapter);
        //設定Viewpager 最少載入條目數
        if (basicConfiguration.getLimitPage() != -1){
            tabFragment_viewpager.setOffscreenPageLimit(basicConfiguration.getLimitPage());
        }
        //設定底部tab高度
        if (basicConfiguration.getTabHeight() != -1) {
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) tabFragment_bottomRoot.getLayoutParams();
            layoutParams.height = Dp2Px(basicConfiguration.getTabHeight());
            tabFragment_bottomRoot.setLayoutParams(layoutParams);
        }
        //設定底部tab背景顏色
        if (basicConfiguration.getTabBgColor() != -1) {
            tabFragment_bottomRoot.setBackgroundResource(basicConfiguration.getTabBgColor());
        }
        //新增tab條目
        if (basicConfiguration.getPageData().size() > 0) {
            for (BasicConfiguration.TabPageData page : basicConfiguration.getPageData()) {
                View tabItem = LayoutInflater.from(context).inflate(R.layout.layout_tabitem, tabFragment_bottomRoot, false);
                ImageView tabImage = tabItem.findViewById(R.id.tabImage);
                TextView tabTitle = tabItem.findViewById(R.id.tabTitle);
                //設定圖片的寬高
                if (basicConfiguration.getImageDimension() != -1) {
                    tabImage.setLayoutParams(new LinearLayout.LayoutParams(Dp2Px(basicConfiguration.getImageDimension()),Dp2Px(basicConfiguration.getImageDimension())));
                }
                //設定文字字型
                tabTitle.setText(TextUtils.isEmpty(page.getTabTitle()) ? "" : page.getTabTitle());
                //設定當前顯示圖片 字型
                if (page.isShowCurrentPage()) {
                    tabImage.setImageResource(page.getSelectImage());
                    tabTitle.setTextColor(basicConfiguration.getTitleSelectColor());
                } else {
                    tabImage.setImageResource(page.getUnSelectImage());
                    tabTitle.setTextColor(basicConfiguration.getTitleUnSelectColor());
                }
                //設定當前view的標記
                tabItem.setTag(page.getTabTitle());
                tabFragment_bottomRoot.addView(tabItem);
            }
        }
        //建立監聽
        this.initListener(tabFragment_viewpager,tabFragment_bottomRoot);
        //新增到主佈局中
        super.addView(tabFragment);
    }

    //動態設定tab的切換
    private void switchTab(LinearLayout tabFragment_bottomRoot,int position){
        //所有的狀態置為 false
        for (BasicConfiguration.TabPageData page : basicConfiguration.getPageData()){
            page.setShowCurrentPage(false);
        }
        //把所需要的的position 為 true
        basicConfiguration.getPageData().get(position).setShowCurrentPage(true);
        //遍歷根據狀態去修改圖片 和文字顏色
        for (int i = 0; i < basicConfiguration.getPageData().size(); i++){
            View tabItem = tabFragment_bottomRoot.getChildAt(i);
            ImageView tabImage = tabItem.findViewById(R.id.tabImage);
            TextView tabTitle = tabItem.findViewById(R.id.tabTitle);
            //設定當前顯示圖片 字型
            if (basicConfiguration.getPageData().get(i).isShowCurrentPage()) {
                tabImage.setImageResource(basicConfiguration.getPageData().get(i).getSelectImage());
                tabTitle.setTextColor(basicConfiguration.getTitleSelectColor());
            } else {
                tabImage.setImageResource(basicConfiguration.getPageData().get(i).getUnSelectImage());
                tabTitle.setTextColor(basicConfiguration.getTitleUnSelectColor());
            }
        }
    }

    //設定監聽
    private void initListener(CustomViewPager tabFragment_viewpager,LinearLayout tabFragment_bottomRoot) {
        //設定viewPager滑動監聽
        if (basicConfiguration.isViewPagerIsScroll()){
            tabFragment_viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                @Override
                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                    switchTab(tabFragment_bottomRoot,position);
                }

                @Override
                public void onPageSelected(int position) {

                }

                @Override
                public void onPageScrollStateChanged(int state) {

                }
            });
        }
        //設定tab點選監聽
        for (int i = 0; i < basicConfiguration.getPageData().size(); i++) {
            //獲取裡面所有的view監聽
            View childAt = tabFragment_bottomRoot.getChildAt(i);
            childAt.setOnClickListener(view -> {
                //根據view標記去判斷當前點選的那個view
                int tagIndex = -1;
                for (int j = 0; j < basicConfiguration.getPageData().size(); j++) {
                    if (basicConfiguration.getPageData().get(j).getTabTitle().equals(view.getTag())){
                        tagIndex = j;
                        break;
                    }
                }
                //拿到標記去切換tab
                switchTab(tabFragment_bottomRoot, tagIndex);
                //去切換Fragment
                tabFragment_viewpager.setCurrentItem(tagIndex);
            });
        }
    }


    class PagerAdapter extends FragmentStatePagerAdapter{
        public PagerAdapter() {
            super(((FragmentActivity)context).getSupportFragmentManager(),BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
        }
        @NonNull
        @Override
        public Fragment getItem(int position) {
            return basicConfiguration.getPageData().get(position).getFragment();
        }

        @Override
        public int getCount() {
            return basicConfiguration.getPageData().size();
        }
    }


    private int Dp2Px(float dp) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
    }


}

2.重寫ViewPager 設定是否需要滑動

/*
 * 可控制滑動 viewpager
 */
public class CustomViewPager extends ViewPager {
    //滑動開關控制常數
    private boolean enable = false;

    //重寫構造
    public CustomViewPager(Context context) {
        super(context);
    }

    //重寫構造
    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    //觸碰事件
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (this.enable) {
            //開關開啟,事件不進行攔截
            return super.onTouchEvent(ev);
        }
        //預設攔截狀態
        return false;
    }

    //攔截事件監聽
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (this.enable) {
            //開關開啟,即處理攔截下來的touch事件
            return super.onInterceptTouchEvent(ev);
        }
        //預設狀態不處理來接下來的事件
        return false;
    }


    //傳遞觸控事件
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        //處理事件的分發,將攔截到的事件分發到viewpager下的子view中去
        //這個攔截了就沒有後續事件發生了,到viewpager為止
        if (this.enable) {
            return super.dispatchTouchEvent(ev);
        }
        //一般都不攔的
        return super.dispatchTouchEvent(ev);
    }

    //留一個方法修改開關的開啟關閉狀態
    public void setViewPagerState(Boolean scrollEnable) {
        this.enable = scrollEnable;
    }

}

3.建立 需要的資料實體類,使用的時候傳過來資料便是

/*
 * 頁面基礎設定
 */
public class BasicConfiguration {

    //設定 viewPager是否允許滑動  預設不允許
    private boolean viewPagerIsScroll = false;

    //設定ViewPager最少提前載入的頁數  不設定預設
    private int limitPage = -1;

    //設定底部tab高度 預設
    private float tabHeight = -1;

    //設定底部欄 背景顏  預設白色
    private @ColorInt int tabBgColor = -1;

    //設定底部欄 圖片 寬高  預設40
    private float imageDimension = -1;

    //設定底部欄 文字字型 選中顏色
    private @ColorRes int titleSelectColor = -1;

    //設定底部欄 文字字型 未選中顏色
    private @ColorRes int titleUnSelectColor = -1;

    //設定是否顯示 tab圖片  預設顯示
    private boolean isShowTabImage = true;

    //設定 是否顯示 tab標題 預設顯示
    private boolean isShowTabTitle = true;
    //設定資料
    private List<TabPageData> pageData;

    public BasicConfiguration() {
    }

    public BasicConfiguration(int titleSelectColor, int titleUnSelectColor, List<TabPageData> pageData) {
        this.titleSelectColor = titleSelectColor;
        this.titleUnSelectColor = titleUnSelectColor;
        this.pageData = pageData;
    }

    public BasicConfiguration(int tabHeight, int tabBgColor, int titleSelectColor, int titleUnSelectColor, List<TabPageData> pageData) {
        this.tabHeight = tabHeight;
        this.tabBgColor = tabBgColor;
        this.titleSelectColor = titleSelectColor;
        this.titleUnSelectColor = titleUnSelectColor;
        this.pageData = pageData;
    }

    public BasicConfiguration(int tabHeight, int tabBgColor, int imageDimension, int titleSelectColor, int titleUnSelectColor, List<TabPageData> pageData) {
        this.tabHeight = tabHeight;
        this.tabBgColor = tabBgColor;
        this.imageDimension = imageDimension;
        this.titleSelectColor = titleSelectColor;
        this.titleUnSelectColor = titleUnSelectColor;
        this.pageData = pageData;
    }

    public boolean isViewPagerIsScroll() {
        return viewPagerIsScroll;
    }

    public void setViewPagerIsScroll(boolean viewPagerIsScroll) {
        this.viewPagerIsScroll = viewPagerIsScroll;
    }

    public int getLimitPage() {
        return limitPage;
    }

    public void setLimitPage(int limitPage) {
        this.limitPage = limitPage;
    }

    public float getTabHeight() {
        return tabHeight;
    }

    public void setTabHeight(float tabHeight) {
        this.tabHeight = tabHeight;
    }

    public int getTabBgColor() {
        return tabBgColor;
    }

    public void setTabBgColor(int tabBgColor) {
        this.tabBgColor = tabBgColor;
    }

    public float getImageDimension() {
        return imageDimension;
    }

    public void setImageDimension(float imageDimension) {
        this.imageDimension = imageDimension;
    }

    public int getTitleSelectColor() {
        return titleSelectColor;
    }

    public void setTitleSelectColor(int titleSelectColor) {
        this.titleSelectColor = titleSelectColor;
    }

    public int getTitleUnSelectColor() {
        return titleUnSelectColor;
    }

    public void setTitleUnSelectColor(int titleUnSelectColor) {
        this.titleUnSelectColor = titleUnSelectColor;
    }

    public boolean isShowTabImage() {
        return isShowTabImage;
    }

    public void setShowTabImage(boolean showTabImage) {
        isShowTabImage = showTabImage;
    }

    public boolean isShowTabTitle() {
        return isShowTabTitle;
    }

    public void setShowTabTitle(boolean showTabTitle) {
        isShowTabTitle = showTabTitle;
    }

    public List<TabPageData> getPageData() {
        return pageData;
    }

    public void setPageData(List<TabPageData> pageData) {
        this.pageData = pageData;
    }

    public static class TabPageData{
        //是否預設顯示當前頁面
        private boolean isShowCurrentPage;
        //當前頁面
        private Fragment fragment;
        //選中圖片
        private int selectImage;
        //未選中圖片
        private int unSelectImage;
        //當前tab標題
        private String tabTitle;

        public TabPageData(boolean isShowCurrentPage,Fragment fragment, int selectImage, int unSelectImage, String tabTitle) {
            this.isShowCurrentPage = isShowCurrentPage;
            this.fragment = fragment;
            this.selectImage = selectImage;
            this.unSelectImage = unSelectImage;
            this.tabTitle = tabTitle;
        }

        public boolean isShowCurrentPage() {
            return isShowCurrentPage;
        }

        public void setShowCurrentPage(boolean showCurrentPage) {
            isShowCurrentPage = showCurrentPage;
        }

        public Fragment getFragment() {
            return fragment;
        }

        public void setFragment(Fragment fragment) {
            this.fragment = fragment;
        }

        public int getSelectImage() {
            return selectImage;
        }

        public void setSelectImage(int selectImage) {
            this.selectImage = selectImage;
        }

        public int getUnSelectImage() {
            return unSelectImage;
        }

        public void setUnSelectImage(int unSelectImage) {
            this.unSelectImage = unSelectImage;
        }

        public String getTabTitle() {
            return tabTitle;
        }

        public void setTabTitle(String tabTitle) {
            this.tabTitle = tabTitle;
        }
    }
}

4.裡面用到的佈局條目

layout_tabfragment.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:id="@+id/tabFragment_root"
    android:layout_height="match_parent">
    <com.example.tabfragment.CustomViewPager
        android:id="@+id/tabFragment_viewpager"
        android:layout_width="match_parent"
        android:layout_above="@id/tabFragment_bottomRoot"
        android:layout_height="match_parent"/>
    <LinearLayout
        android:id="@+id/tabFragment_bottomRoot"
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:layout_height="52dp"
        android:layout_alignParentBottom="true"/>
</RelativeLayout>

layout_tabitem.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="0dp"
    android:layout_weight="1"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_height="match_parent">
    <ImageView
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:id="@+id/tabImage"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="標題"
        android:id="@+id/tabTitle"
        />
</LinearLayout>

5.最後的使用 方式 如下↓

public class ChipsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chips);
        initTabFragment();
    }

    private void initTabFragment() {
        TabFragment myTab = findViewById(R.id.myTab);
        List<BasicConfiguration.TabPageData> pageData = new ArrayList<>();
        pageData.add(new BasicConfiguration.TabPageData(true,new MyFragment(),
                R.mipmap.icon_tab_home_pre,R.mipmap.icon_tab_home,"首頁"));
        pageData.add(new BasicConfiguration.TabPageData(false,new CarFragment(),
                R.mipmap.icon_tab_gouwuche_pre,R.mipmap.icon_tab_gouwuche,"購物車"));
        pageData.add(new BasicConfiguration.TabPageData(false,new ModeFragment(),
                R.mipmap.icon_tab_wode_pre,R.mipmap.icon_tab_wode,"我的"));
        //建立初始化資料
        BasicConfiguration basicConfiguration = new BasicConfiguration(58,
                                                                R.color.white,
                                                                Color.parseColor("#03DAC5"),
                                                                Color.parseColor("#999999"),
                                                                pageData);
        basicConfiguration.setImageDimension(32);
        basicConfiguration.setViewPagerIsScroll(true);
        myTab.setData(basicConfiguration);
    }
}

6.最後想要的效果在這

在這裡插入圖片描述
在這裡插入圖片描述

最後 如果各位大佬覺得不好,不要噴,如果對你們有用那就拿去嫖,記得點贊收藏奧!!!!