瀏覽代碼

1. 底部tab栏方式更改

咸光金 4 年之前
父節點
當前提交
dca65c9802

+ 37 - 91
app/src/main/java/com/quansu/heifengwuliu/activity/HomeActivity.kt

@@ -1,24 +1,17 @@
 package com.quansu.heifengwuliu.activity
 
+import android.graphics.Color
 import android.os.Bundle
-import androidx.fragment.app.FragmentTransaction
-import com.flyco.tablayout.listener.CustomTabEntity
-import com.flyco.tablayout.listener.OnTabSelectListener
+import androidx.core.content.ContextCompat
 import com.quansu.heifengwuliu.R
 import com.quansu.heifengwuliu.base.MBActivity
 import com.quansu.heifengwuliu.databinding.ActivityHomeBinding
 import com.quansu.heifengwuliu.fragment.IndexFragment
 import com.quansu.heifengwuliu.fragment.MineFragment
 import com.quansu.heifengwuliu.fragment.WayBillFragment
-import com.quansu.heifengwuliu.model.bean.TabEntity
 import com.quansu.heifengwuliu.repository.HomeRepository
-import com.quansu.heifengwuliu.repository.OneLoginRepository
 import com.quansu.heifengwuliu.vmodel.HomeVModel
-import com.quansu.heifengwuliu.vmodel.OneLoginVModel
 import com.ysnows.base.base.BRepository
-import com.ysnows.base.utils.UiSwitch
-import kotlinx.android.synthetic.main.activity_home.*
-import java.util.ArrayList
 
 /**
  * 首页
@@ -27,15 +20,6 @@ import java.util.ArrayList
  */
 class HomeActivity : MBActivity<HomeVModel, ActivityHomeBinding>() {
 
-    private var mTitles = emptyArray<String>()
-    // 未被选中的图标
-    private val mIconUnSelectIds = intArrayOf(R.drawable.ic_mine_normal, R.drawable.ic_mine_normal,R.drawable.ic_mine_normal)//normal
-    // 被选中的图标
-    private val mIconSelectIds = intArrayOf(R.drawable.ic_mine_selected,R.drawable.ic_mine_selected, R.drawable.ic_mine_selected)//selected
-    private val mTabEntities = ArrayList<CustomTabEntity>()
-    private var mHomeFragment: IndexFragment? = null
-    private var mWayBillFragment: WayBillFragment?=null
-    private var mMineFragment: MineFragment? = null
     //默认为0
     private var mIndex = 0
 
@@ -49,12 +33,10 @@ class HomeActivity : MBActivity<HomeVModel, ActivityHomeBinding>() {
             mIndex = savedInstanceState.getInt("currTabIndex")
         }
         super.initCreate(savedInstanceState)
-        mTitles = arrayOf(getString(R.string.home),getString(R.string.waybill), getString(R.string.my))
-        initTab()
-        tab_layout.currentTab = mIndex
-        switchFragment(mIndex)
-        vm.getUserInfo();
+        initMainMenu()
+        binding.mainMenu.switchTab(0)
 
+        vm.getUserInfo();
     }
 
     override fun vmClass(): Class<HomeVModel> {
@@ -65,78 +47,42 @@ class HomeActivity : MBActivity<HomeVModel, ActivityHomeBinding>() {
         return HomeRepository()
     }
 
-    private fun initTab() {
-        (0 until mTitles.size)
-                .mapTo(mTabEntities) { TabEntity(mTitles[it], mIconSelectIds[it], mIconUnSelectIds[it]) }
-        //为Tab赋值
-        tab_layout.setTabData(mTabEntities)
-        tab_layout.setOnTabSelectListener(object : OnTabSelectListener {
-            override fun onTabSelect(position: Int) {
-                //切换Fragment
-                switchFragment(position)
-            }
-
-            override fun onTabReselect(position: Int) {
-            }
-        })
-    }
-
-    /**
-     * 切换Fragment
-     * @param position 下标
-     */
-    private fun switchFragment(position: Int) {
-        val transaction = supportFragmentManager.beginTransaction()
-        hideFragments(transaction)
-        when (position) {
-            0 // 货源
-            -> mHomeFragment?.let {
-                transaction.show(it)
-            } ?: IndexFragment().let {
-                mHomeFragment = it
-                transaction.add(R.id.fl_container, it, "home")
-            }
-
-            1 //我的运单
-            -> mWayBillFragment?.let {
-                transaction.show(it)
-            } ?: WayBillFragment().let {
-                mWayBillFragment = it
-                transaction.add(R.id.fl_container, it, "mine")
-            }
-
-            2 //个人中心
-            -> mMineFragment?.let {
-                transaction.show(it)
-            } ?: MineFragment().let {
-                mMineFragment = it
-                transaction.add(R.id.fl_container, it, "mine")
-            }
-            else -> {
-
-            }
-        }
-        mIndex = position
-        tab_layout.currentTab = mIndex
-        transaction.commitAllowingStateLoss()
-    }
-
-
-    /**
-     * 隐藏所有的Fragment
-     * @param transaction transaction
-     */
-    private fun hideFragments(transaction: FragmentTransaction) {
-        mHomeFragment?.let { transaction.hide(it) }
-        mWayBillFragment?.let { transaction.hide(it) }
-        mMineFragment?.let { transaction.hide(it) }
-    }
-
-
     override fun title(): String? {
         return null
     }
 
 
+    private fun initMainMenu() {
+        val oneFragment = IndexFragment()
+        val twoFragment = WayBillFragment()
+        val threeFragment = MineFragment()
+        val menuTabBuilder = binding.mainMenu.tabBuilder()
+                .setSelectColor(Color.parseColor("#2E4E71"))
+                .setNormalColor(Color.parseColor("#666666"))
+        val one = menuTabBuilder
+                .setFragment(oneFragment)
+                .setNormalDrawable(ContextCompat.getDrawable(context(), R.drawable.menu_index))
+                .setSelectedDrawable(ContextCompat.getDrawable(context(), R.drawable.menu_index_focus))
+                .setText(getString(R.string.home))
+                .build(context())
+        val two = menuTabBuilder
+                .setFragment(twoFragment)
+                .setNormalDrawable(ContextCompat.getDrawable(context(), R.drawable.menu_vehicle))
+                .setSelectedDrawable(ContextCompat.getDrawable(context(), R.drawable.menu_vehicle_focus))
+                .setText(getString(R.string.waybill))
+                .build(context())
+        val three = menuTabBuilder
+                .setFragment(threeFragment)
+                .setText(getString(R.string.my))
+                .setNormalDrawable(ContextCompat.getDrawable(context(), R.drawable.menu_tyre))
+                .setSelectedDrawable(ContextCompat.getDrawable(context(), R.drawable.menu_tyre_focus))
+                .build(context())
+        binding.mainMenu
+                .addTab(one)
+                .addTab(two)
+                .addTab(three)
+                .rendor()
+    }
+
 
 }

二進制
app/src/main/res/drawable-xxhdpi/menu_index.webp


二進制
app/src/main/res/drawable-xxhdpi/menu_index_focus.webp


二進制
app/src/main/res/drawable-xxhdpi/menu_tyre.webp


二進制
app/src/main/res/drawable-xxhdpi/menu_tyre_focus.webp


二進制
app/src/main/res/drawable-xxhdpi/menu_vehicle.webp


二進制
app/src/main/res/drawable-xxhdpi/menu_vehicle_focus.webp


+ 16 - 25
app/src/main/res/layout/activity_home.xml

@@ -5,36 +5,27 @@
 
     </data >
 
-    <RelativeLayout
+    <LinearLayout
         android:layout_width="match_parent"
-        xmlns:app="http://schemas.android.com/apk/res-auto"
-        android:layout_height="match_parent">
+        android:layout_height="match_parent"
+        android:orientation="vertical" >
+
         <FrameLayout
-            android:id="@+id/fl_container"
+            android:id="@+id/container"
             android:layout_width="match_parent"
-            android:layout_height="match_parent" />
+            android:layout_height="0dp"
+            android:layout_weight="1" />
+
         <View
             android:layout_width="match_parent"
-            android:layout_height="0.5dp"
-            android:layout_above="@+id/tab_layout"
-            android:background="@color/color_gray" />
+            android:layout_height="0.33dp"
+            android:background="@color/divider_1" />
 
-
-        <com.flyco.tablayout.CommonTabLayout
-            android:id="@+id/tab_layout"
+        <com.ysnows.base.widget.tablayout.YTabLayout
+            android:id="@+id/main_menu"
             android:layout_width="match_parent"
-            android:layout_height="50dp"
-            android:layout_alignParentBottom="true"
-            android:background="@color/color_translucent"
-            app:tl_divider_color="@color/color_black"
-            app:tl_iconHeight="23dp"
-            app:tl_iconWidth="23dp"
-            app:tl_indicator_color="@color/colorPrimary"
-            app:tl_indicator_height="0dp"
-            app:tl_textSelectColor="@color/color_black"
-            app:tl_textUnselectColor="@color/color_gray"
-            app:tl_textsize="10sp"
-            app:tl_underline_color="#DDDDDD"
-            app:tl_underline_height="1dp" />
-    </RelativeLayout>
+            android:layout_height="@dimen/dp_48"
+            android:background="@color/color_bg" />
+
+    </LinearLayout >
 </layout >

+ 1 - 0
app/src/main/res/values/dimens.xml

@@ -175,5 +175,6 @@
     <dimen name="dp_160" >160dp</dimen >
     <dimen name="dp_25" >25dp</dimen >
     <dimen name="dp_15" >15dp</dimen >
+    <dimen name="dp_48" >48dp</dimen >
 
 </resources >

+ 24 - 0
base/src/main/java/com/ysnows/base/widget/tablayout/MainMenuAdapter.java

@@ -0,0 +1,24 @@
+package com.ysnows.base.widget.tablayout;
+
+import com.chad.library.adapter.base.viewholder.BaseDataBindingHolder;
+import com.ysnows.base.R;
+import com.ysnows.base.base.BAdapter;
+import com.ysnows.base.databinding.WidgetMemuItemBinding;
+
+import org.jetbrains.annotations.NotNull;
+
+
+public class MainMenuAdapter extends BAdapter<YTab, BaseDataBindingHolder<WidgetMemuItemBinding>> {
+
+    public MainMenuAdapter() {
+        super(R.layout.widget_memu_item);
+    }
+
+    @Override
+    protected void convert(@NotNull BaseDataBindingHolder<WidgetMemuItemBinding> helper, YTab tab) {
+        WidgetMemuItemBinding binding = helper.getDataBinding();
+        if (binding != null) {
+            binding.setTab(tab);
+        }
+    }
+}

+ 371 - 0
base/src/main/java/com/ysnows/base/widget/tablayout/MenuTabBuilder.java

@@ -0,0 +1,371 @@
+/*
+ * Tencent is pleased to support the open source community by making QMUI_Android available.
+ *
+ * Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the MIT License (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://opensource.org/licenses/MIT
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.ysnows.base.widget.tablayout;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.view.Gravity;
+
+import com.qmuiteam.qmui.util.QMUIDisplayHelper;
+import com.qmuiteam.qmui.widget.tab.QMUITabIcon;
+import com.qmuiteam.qmui.widget.tab.QMUITabSegment;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+
+/**
+ * use {@link QMUITabSegment#tabBuilder()} to get a instance
+ */
+public class MenuTabBuilder {
+    /**
+     * icon in normal state
+     */
+    private int normalDrawableAttr = 0;
+
+    private @Nullable
+    Drawable normalDrawable;
+    private @Nullable
+    Drawable selectedDrawable;
+    /**
+     * icon in selected state
+     */
+    private int selectedDrawableAttr = 0;
+    /**
+     * change icon by tint color, if true, selectedDrawable will not work
+     */
+    private boolean dynamicChangeIconColor = false;
+
+    /**
+     * for skin change. if true, then normalDrawableAttr and selectedDrawableAttr will not work.
+     * otherwise, icon will be replaced by normalDrawableAttr and selectedDrawable
+     */
+    private boolean skinChangeWithTintColor = true;
+
+    /**
+     * text size in normal state
+     */
+    private int normalTextSize;
+    /**
+     * text size in selected state
+     */
+    private int selectTextSize;
+
+    /**
+     * text color(icon color in if dynamicChangeIconColor == true) in  normal state
+     */
+    private int normalColorAttr = com.qmuiteam.qmui.R.attr.qmui_skin_support_tab_normal_color;
+    /**
+     * text color(icon color in if dynamicChangeIconColor == true) in  selected state
+     */
+    private int selectedColorAttr = com.qmuiteam.qmui.R.attr.qmui_skin_support_tab_selected_color;
+
+    /**
+     * text color with no skin support
+     */
+    private int normalColor = 0;
+
+    /**
+     * text color with no skin support
+     */
+    private int selectColor = 0;
+
+    /**
+     * icon position(left/top/right/bottom)
+     */
+    private @YTab.IconPosition
+    int iconPosition = YTab.ICON_POSITION_TOP;
+    /**
+     * gravity of text
+     */
+    private int gravity = Gravity.CENTER;
+    /**
+     * text
+     */
+    private CharSequence text;
+
+    /**
+     * text typeface in normal state
+     */
+    private Typeface normalTypeface;
+
+    /**
+     * text typeface in selected state
+     */
+    private Typeface selectedTypeface;
+
+    /**
+     * width of tab icon in normal state
+     */
+    private int normalTabIconWidth = QMUITabIcon.TAB_ICON_INTRINSIC;
+    /**
+     * height of tab icon in normal state
+     */
+    int normalTabIconHeight = QMUITabIcon.TAB_ICON_INTRINSIC;
+    /**
+     * scale of tab icon in selected state
+     */
+    float selectedTabIconScale = 1f;
+
+    /**
+     * signCount or redPoint
+     */
+    private int signCount = YTab.NO_SIGN_COUNT_AND_RED_POINT;
+
+    /**
+     * max signCount digits, if the number is over the digits, use 'xx+' to present
+     * if signCountDigits == 2 and number is 110, then component will show '99+'
+     */
+    private int signCountDigits = 2;
+    /**
+     * the margin left of signCount(redPoint) view
+     */
+    private int signCountLeftMarginWithIconOrText;
+    /**
+     * the margin top of signCount(redPoint) view
+     */
+    private int signCountBottomMarginWithIconOrText;
+
+    /**
+     * the gap between icon and text
+     */
+    private int iconTextGap;
+    private Fragment fragment;
+
+    /**
+     * allow icon draw outside of tab view
+     */
+    private boolean allowIconDrawOutside = true;
+
+
+    MenuTabBuilder(Context context) {
+        iconTextGap = QMUIDisplayHelper.dp2px(context, 2);
+        normalTextSize = selectTextSize = QMUIDisplayHelper.dp2px(context, 12);
+        signCountLeftMarginWithIconOrText = QMUIDisplayHelper.dp2px(context, 3);
+        signCountBottomMarginWithIconOrText = signCountLeftMarginWithIconOrText;
+    }
+
+    MenuTabBuilder(MenuTabBuilder other) {
+        this.normalDrawableAttr = other.normalDrawableAttr;
+        this.selectedDrawableAttr = other.selectedDrawableAttr;
+        this.normalDrawable = other.normalDrawable;
+        this.selectedDrawable = other.selectedDrawable;
+        this.dynamicChangeIconColor = other.dynamicChangeIconColor;
+        this.normalTextSize = other.normalTextSize;
+        this.selectTextSize = other.selectTextSize;
+        this.normalColorAttr = other.normalColorAttr;
+        this.selectedColorAttr = other.selectedColorAttr;
+        this.iconPosition = other.iconPosition;
+        this.gravity = other.gravity;
+        this.text = other.text;
+        this.signCount = other.signCount;
+        this.signCountDigits = other.signCountDigits;
+        this.signCountLeftMarginWithIconOrText = other.signCountLeftMarginWithIconOrText;
+        this.signCountBottomMarginWithIconOrText = other.signCountBottomMarginWithIconOrText;
+        this.normalTypeface = other.normalTypeface;
+        this.selectedTypeface = other.selectedTypeface;
+        this.normalTabIconWidth = other.normalTabIconWidth;
+        this.normalTabIconHeight = other.normalTabIconHeight;
+        this.selectedTabIconScale = other.selectedTabIconScale;
+        this.iconTextGap = other.iconTextGap;
+        this.allowIconDrawOutside = other.allowIconDrawOutside;
+    }
+
+    public MenuTabBuilder setAllowIconDrawOutside(boolean allowIconDrawOutside) {
+        this.allowIconDrawOutside = allowIconDrawOutside;
+        return this;
+    }
+
+    public MenuTabBuilder setNormalDrawable(Drawable normalDrawable) {
+        this.normalDrawable = normalDrawable;
+        return this;
+    }
+
+    public MenuTabBuilder setSelectedDrawable(Drawable selectedDrawable) {
+        this.selectedDrawable = selectedDrawable;
+        return this;
+    }
+
+
+    public MenuTabBuilder setNormalDrawableAttr(int normalDrawableAttr) {
+        this.normalDrawableAttr = normalDrawableAttr;
+        return this;
+    }
+
+
+    public MenuTabBuilder setSelectedDrawableAttr(int selectedDrawableAttr) {
+        this.selectedDrawableAttr = selectedDrawableAttr;
+        return this;
+    }
+
+    public MenuTabBuilder skinChangeWithTintColor(boolean skinChangeWithTintColor) {
+        this.skinChangeWithTintColor = skinChangeWithTintColor;
+        return this;
+    }
+
+    public MenuTabBuilder setFragment(Fragment fragment) {
+        this.fragment = fragment;
+        return this;
+    }
+
+
+    public MenuTabBuilder setTextSize(int normalTextSize, int selectedTextSize) {
+        this.normalTextSize = normalTextSize;
+        this.selectTextSize = selectedTextSize;
+        return this;
+    }
+
+    public MenuTabBuilder setTypeface(Typeface normalTypeface, Typeface selectedTypeface) {
+        this.normalTypeface = normalTypeface;
+        this.selectedTypeface = selectedTypeface;
+        return this;
+    }
+
+    public MenuTabBuilder setNormalIconSizeInfo(int normalWidth, int normalHeight) {
+        this.normalTabIconWidth = normalWidth;
+        this.normalTabIconHeight = normalHeight;
+        return this;
+    }
+
+    public MenuTabBuilder setSelectedIconScale(float selectedScale) {
+        this.selectedTabIconScale = selectedScale;
+        return this;
+    }
+
+    public MenuTabBuilder setIconTextGap(int iconTextGap) {
+        this.iconTextGap = iconTextGap;
+        return this;
+    }
+
+    public MenuTabBuilder setSignCount(int signCount) {
+        this.signCount = signCount;
+        return this;
+    }
+
+    public MenuTabBuilder setSignCountMarginInfo(int digit,
+                                                 int leftMarginWithIconOrText, int bottomMarginWithIconOrText) {
+        this.signCountDigits = digit;
+        this.signCountLeftMarginWithIconOrText = leftMarginWithIconOrText;
+        this.signCountBottomMarginWithIconOrText = bottomMarginWithIconOrText;
+        return this;
+    }
+
+    public MenuTabBuilder setColorAttr(int normalColorAttr, int selectedColorAttr) {
+        this.normalColorAttr = normalColorAttr;
+        this.selectedColorAttr = selectedColorAttr;
+        return this;
+    }
+
+    public MenuTabBuilder setNormalColorAttr(int normalColorAttr) {
+        this.normalColorAttr = normalColorAttr;
+        return this;
+    }
+
+    public MenuTabBuilder setSelectedColorAttr(int selectedColorAttr) {
+        this.selectedColorAttr = selectedColorAttr;
+        return this;
+    }
+
+    public MenuTabBuilder setColor(int normalColor, int selectColor) {
+        this.normalColorAttr = 0;
+        this.selectedColorAttr = 0;
+        this.normalColor = normalColor;
+        this.selectColor = selectColor;
+        return this;
+    }
+
+    public MenuTabBuilder setNormalColor(int normalColor) {
+        this.normalColorAttr = 0;
+        this.normalColor = normalColor;
+        return this;
+    }
+
+    public MenuTabBuilder setSelectColor(int selectColor) {
+        this.selectedColorAttr = 0;
+        this.selectColor = selectColor;
+        return this;
+    }
+
+    public MenuTabBuilder setDynamicChangeIconColor(boolean dynamicChangeIconColor) {
+        this.dynamicChangeIconColor = dynamicChangeIconColor;
+        return this;
+    }
+
+    public MenuTabBuilder setGravity(int gravity) {
+        this.gravity = gravity;
+        return this;
+    }
+
+    public MenuTabBuilder setIconPosition(@YTab.IconPosition int iconPosition) {
+        this.iconPosition = iconPosition;
+        return this;
+    }
+
+    public MenuTabBuilder setText(CharSequence text) {
+        this.text = text;
+        return this;
+    }
+
+    public YTab build(Context context) {
+        YTab tab = new YTab(this.text);
+//        if (!skinChangeWithTintColor) {
+//            if (normalDrawableAttr != 0) {
+//                normalDrawable = QMUIResHelper.getAttrDrawable(context, normalDrawableAttr);
+//            }
+//
+//            if (selectedDrawableAttr != 0) {
+//                selectedDrawable = QMUIResHelper.getAttrDrawable(context, selectedDrawableAttr);
+//            }
+//        }
+
+//        if (normalDrawable != null) {
+//            if (dynamicChangeIconColor || selectedDrawable == null) {
+//                tab.tabIcon = new QMUITabIcon(normalDrawable, null, dynamicChangeIconColor);
+//            } else {
+//                tab.tabIcon = new QMUITabIcon(normalDrawable, selectedDrawable, false);
+//            }
+//            tab.tabIcon.setBounds(0, 0, normalTabIconWidth, normalTabIconHeight);
+//        }
+
+        tab.skinChangeWithTintColor = this.skinChangeWithTintColor;
+        tab.normalIconAttr = this.normalDrawableAttr;
+        tab.selectedIconAttr = this.selectedDrawableAttr;
+        tab.normalTabIconWidth = this.normalTabIconWidth;
+        tab.normalTabIconHeight = this.normalTabIconHeight;
+        tab.selectedTabIconScale = this.selectedTabIconScale;
+        tab.gravity = this.gravity;
+        tab.iconPosition = this.iconPosition;
+        tab.normalTextSize = this.normalTextSize;
+        tab.selectedTextSize = this.selectTextSize;
+        tab.normalTypeface = this.normalTypeface;
+        tab.selectedTypeface = this.selectedTypeface;
+        tab.normalColorAttr = this.normalColorAttr;
+        tab.selectedColorAttr = this.selectedColorAttr;
+        tab.normalColor = this.normalColor;
+        tab.selectColor = this.selectColor;
+        tab.signCount = this.signCount;
+        tab.signCountDigits = this.signCountDigits;
+        tab.signCountLeftMarginWithIconOrText = this.signCountLeftMarginWithIconOrText;
+        tab.signCountBottomMarginWithIconOrText = this.signCountBottomMarginWithIconOrText;
+        tab.iconTextGap = this.iconTextGap;
+        tab.fragment = this.fragment;
+
+        tab.normalDrawable = this.normalDrawable;
+        tab.selectedDrawable = this.selectedDrawable;
+        return tab;
+    }
+}

+ 63 - 0
base/src/main/java/com/ysnows/base/widget/tablayout/MenuTabView.java

@@ -0,0 +1,63 @@
+package com.ysnows.base.widget.tablayout;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.ysnows.base.R;
+import com.ysnows.base.databinding.WidgetMemuItemBinding;
+import com.ysnows.base.view.BView;
+
+import androidx.databinding.DataBindingUtil;
+
+
+/**
+ * Created by xianguangjin on 16/6/1.
+ * 自定义
+ */
+
+public class MenuTabView extends LinearLayout {
+
+
+    private BView view;
+    private WidgetMemuItemBinding binding;
+
+
+    public MenuTabView(Context context) {
+        this(context, null);
+
+    }
+
+    public MenuTabView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+
+
+    }
+
+    public MenuTabView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init(context, attrs, defStyleAttr);
+
+    }
+
+    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
+        if (context instanceof BView) {
+            this.view = (BView) context;
+        }
+
+        binding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.widget_memu_item, this, true);
+        setLayoutParams(new LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1));
+    }
+
+    public void setTab(YTab yTab) {
+        if (yTab != null) {
+            binding.setTab(yTab);
+        }
+    }
+
+    public void select(Boolean selected) {
+        binding.getTab().setSelected(selected);
+    }
+}

+ 297 - 0
base/src/main/java/com/ysnows/base/widget/tablayout/YTab.java

@@ -0,0 +1,297 @@
+/*
+ * Tencent is pleased to support the open source community by making QMUI_Android available.
+ *
+ * Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the MIT License (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://opensource.org/licenses/MIT
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.ysnows.base.widget.tablayout;
+
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.view.Gravity;
+import android.view.View;
+
+import com.qmuiteam.qmui.skin.QMUISkinHelper;
+import com.qmuiteam.qmui.widget.tab.QMUITabIcon;
+import com.ysnows.base.BR;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.databinding.BaseObservable;
+import androidx.databinding.Bindable;
+import androidx.fragment.app.Fragment;
+
+public class YTab extends BaseObservable {
+    public static final int ICON_POSITION_LEFT = 0;
+    public static final int ICON_POSITION_TOP = 1;
+    public static final int ICON_POSITION_RIGHT = 2;
+    public static final int ICON_POSITION_BOTTOM = 3;
+
+
+    public static final int NO_SIGN_COUNT_AND_RED_POINT = 0;
+    public static final int RED_POINT_SIGN_COUNT = -1;
+
+    public static final int SIGN_COUNT_VIEW_LAYOUT_VERTICAL_CENTER = Integer.MIN_VALUE;
+
+    @IntDef(value = {
+            ICON_POSITION_LEFT,
+            ICON_POSITION_TOP,
+            ICON_POSITION_RIGHT,
+            ICON_POSITION_BOTTOM})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface IconPosition {
+    }
+
+
+    boolean allowIconDrawOutside;
+    boolean selected;
+    int iconTextGap;
+    int normalTextSize;
+    int selectedTextSize;
+    Typeface normalTypeface;
+    Typeface selectedTypeface;
+    int normalColor;
+    int selectColor;
+    int normalColorAttr;
+    int selectedColorAttr;
+    int normalTabIconWidth = QMUITabIcon.TAB_ICON_INTRINSIC;
+    int normalTabIconHeight = QMUITabIcon.TAB_ICON_INTRINSIC;
+    float selectedTabIconScale = 1f;
+    Drawable tabIcon = null;
+
+    @DrawableRes
+    int normalDrawableRes;
+
+    @DrawableRes
+    int selectedDrawableRes;
+
+    Drawable normalDrawable;
+    Drawable selectedDrawable;
+
+    public Drawable getNormalDrawable() {
+        return normalDrawable;
+    }
+
+    public YTab setNormalDrawable(Drawable normalDrawable) {
+        this.normalDrawable = normalDrawable;
+        return this;
+    }
+
+    public Drawable getSelectedDrawable() {
+        return selectedDrawable;
+    }
+
+    public YTab setSelectedDrawable(Drawable selectedDrawable) {
+        this.selectedDrawable = selectedDrawable;
+        return this;
+    }
+
+    boolean skinChangeWithTintColor;
+    int normalIconAttr;
+    int selectedIconAttr;
+    int contentWidth = 0;
+    int contentLeft = 0;
+    @IconPosition
+    int iconPosition = ICON_POSITION_TOP;
+    int gravity = Gravity.CENTER;
+    private CharSequence text;
+    int signCountDigits = 2;
+    int signCountLeftMarginWithIconOrText = 0;
+    int signCountBottomMarginWithIconOrText = 0;
+    int signCount = NO_SIGN_COUNT_AND_RED_POINT;
+
+    float rightSpaceWeight = 0f;
+    float leftSpaceWeight = 0f;
+    int leftAddonMargin = 0;
+    int rightAddonMargin = 0;
+
+    Fragment fragment = null;
+
+    public void setFragment(Fragment fragment) {
+        this.fragment = fragment;
+    }
+
+    YTab(CharSequence text) {
+        this.text = text;
+    }
+
+
+    @Bindable
+    public CharSequence getText() {
+        return text;
+    }
+
+    public void setText(CharSequence text) {
+        this.text = text;
+        notifyPropertyChanged(BR.text);
+    }
+
+    public int getIconPosition() {
+        return iconPosition;
+    }
+
+    public void setIconPosition(@IconPosition int iconPosition) {
+        this.iconPosition = iconPosition;
+    }
+
+    public void setSpaceWeight(float leftWeight, float rightWeight) {
+        leftSpaceWeight = leftWeight;
+        rightSpaceWeight = rightWeight;
+    }
+
+
+    public int getGravity() {
+        return gravity;
+    }
+
+    public void setGravity(int gravity) {
+        this.gravity = gravity;
+    }
+
+    public void setSignCount(int signCount) {
+        this.signCount = signCount;
+    }
+
+    public void setRedPoint() {
+        this.signCount = RED_POINT_SIGN_COUNT;
+    }
+
+    public int getSignCount() {
+        return this.signCount;
+    }
+
+    public boolean isRedPointShowing() {
+        return this.signCount == RED_POINT_SIGN_COUNT;
+    }
+
+    public void clearSignCountOrRedPoint() {
+        this.signCount = NO_SIGN_COUNT_AND_RED_POINT;
+    }
+
+    public int getNormalColor(@NonNull View skinFollowView) {
+        if (normalColorAttr == 0) {
+            return normalColor;
+        }
+        return QMUISkinHelper.getSkinColor(skinFollowView, normalColorAttr);
+    }
+
+    public int getNormalColor() {
+        return normalColor;
+    }
+
+    public int getSelectColor(@NonNull View skinFollowView) {
+        if (selectedColorAttr == 0) {
+            return selectColor;
+        }
+        return QMUISkinHelper.getSkinColor(skinFollowView, selectedColorAttr);
+    }
+
+    public int getSelectColor() {
+        return selectColor;
+    }
+
+    public int getNormalColorAttr() {
+        return normalColorAttr;
+    }
+
+    public int getSelectedColorAttr() {
+        return selectedColorAttr;
+    }
+
+    public int getNormalIconAttr() {
+        return normalIconAttr;
+    }
+
+    public int getSelectedIconAttr() {
+        return selectedIconAttr;
+    }
+
+    public int getNormalTextSize() {
+        return normalTextSize;
+    }
+
+    public int getSelectedTextSize() {
+        return selectedTextSize;
+    }
+
+    public Drawable getTabIcon() {
+        return tabIcon;
+    }
+
+    public Typeface getNormalTypeface() {
+        return normalTypeface;
+    }
+
+    public Typeface getSelectedTypeface() {
+        return selectedTypeface;
+    }
+
+    public int getNormalTabIconWidth() {
+        if (normalTabIconWidth == QMUITabIcon.TAB_ICON_INTRINSIC && tabIcon != null) {
+            return tabIcon.getIntrinsicWidth();
+        }
+        return normalTabIconWidth;
+    }
+
+    public int getNormalTabIconHeight() {
+        if (normalTabIconHeight == QMUITabIcon.TAB_ICON_INTRINSIC && tabIcon != null) {
+            return tabIcon.getIntrinsicWidth();
+        }
+        return normalTabIconHeight;
+    }
+
+    public float getSelectedTabIconScale() {
+        return selectedTabIconScale;
+    }
+
+    public int getIconTextGap() {
+        return iconTextGap;
+    }
+
+    public boolean isAllowIconDrawOutside() {
+        return allowIconDrawOutside;
+    }
+
+
+    @Bindable
+    public boolean isSelected() {
+        return selected;
+    }
+
+    public void setSelected(boolean selected) {
+        this.selected = selected;
+        notifyPropertyChanged(BR.selected);
+    }
+
+    public int getNormalDrawableRes() {
+        return normalDrawableRes;
+    }
+
+    public YTab setNormalDrawableRes(int normalDrawableRes) {
+        this.normalDrawableRes = normalDrawableRes;
+        return this;
+    }
+
+    public int getSelectedDrawableRes() {
+        return selectedDrawableRes;
+    }
+
+    public YTab setSelectedDrawableRes(int selectedDrawableRes) {
+        this.selectedDrawableRes = selectedDrawableRes;
+        return this;
+    }
+}

+ 143 - 0
base/src/main/java/com/ysnows/base/widget/tablayout/YTabLayout.java

@@ -0,0 +1,143 @@
+package com.ysnows.base.widget.tablayout;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.listener.OnItemClickListener;
+import com.qmuiteam.qmui.widget.tab.QMUITab;
+import com.ysnows.base.R;
+
+import java.util.ArrayList;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * Created by xianguangjin on 16/5/20.
+ */
+public class YTabLayout extends RecyclerView implements OnItemClickListener {
+    private ArrayList<YTab> tabs = new ArrayList<>();
+
+    private int curTab = 0;
+    private int preTab = 0;
+    private MenuTabBuilder mTabBuilder;
+    private MainMenuAdapter adapter;
+    private GridLayoutManager layoutManager;
+
+    public YTabLayout(Context context) {
+        super(context);
+        init(context, null, 0);
+    }
+
+    public YTabLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context, attrs, 0);
+    }
+
+    public YTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init(context, attrs, defStyleAttr);
+    }
+
+    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
+        setHasFixedSize(true);
+        TypedArray array = context.obtainStyledAttributes(attrs,
+                R.styleable.YTabLayout, defStyleAttr, 0);
+
+        // tabBuilder
+        int normalTextSize = array.getDimensionPixelSize(
+                R.styleable.YTabLayout_android_textSize,
+                getResources().getDimensionPixelSize(R.dimen.qmui_tab_segment_text_size));
+
+        normalTextSize = array.getDimensionPixelSize(
+                R.styleable.YTabLayout_normal_text_size, normalTextSize);
+        int selectedTextSize = normalTextSize;
+        selectedTextSize = array.getDimensionPixelSize(
+                R.styleable.YTabLayout_selected_text_size, selectedTextSize);
+
+        mTabBuilder = new MenuTabBuilder(context)
+                .setTextSize(normalTextSize, selectedTextSize)
+                .setIconPosition(array.getInt(R.styleable.YTabLayout_icon_position,
+                        QMUITab.ICON_POSITION_LEFT));
+
+        array.recycle();
+
+        adapter = new MainMenuAdapter();
+        setAdapter(adapter);
+        adapter.setOnItemClickListener(this);
+        adapter.setAnimationEnable(true);
+        adapter.setAnimationFirstOnly(false);
+        adapter.setAnimationWithDefault(BaseQuickAdapter.AnimationType.ScaleIn);
+    }
+
+
+    public void rendor() {
+        layoutManager = new GridLayoutManager(getContext(), tabs.size());
+        //setLayoutManager(new LinearLayoutManager(getContext(), HORIZONTAL, false));
+        setLayoutManager(layoutManager);
+        adapter.setList(tabs);
+    }
+
+    public YTabLayout addTab(YTab tab) {
+        tabs.add(tab);
+        return this;
+    }
+
+
+    public MenuTabBuilder tabBuilder() {
+        // do not change mTabBuilder to keep common config not changed
+        return new MenuTabBuilder(mTabBuilder);
+    }
+
+
+    public void switchTab(int tabIndex) {
+        preTab = curTab;
+        curTab = tabIndex;
+
+        //超出index,不做处理
+        if (tabIndex >= tabs.size()) {
+            return;
+        }
+
+        FragmentManager manager = ((FragmentActivity) getContext()).getSupportFragmentManager();
+        FragmentTransaction transaction = manager.beginTransaction();
+
+        Fragment fragment;
+        for (int i = 0; i < tabs.size(); i++) {
+            YTab yTab = tabs.get(i);
+            fragment = manager.findFragmentByTag("tab_" + i);
+
+            if (tabIndex == i) {
+                yTab.setSelected(true);
+                if (fragment == null) {
+                    fragment = yTab.fragment;
+                    transaction.add(R.id.container, fragment, "tab_" + tabIndex);
+                } else {
+                    transaction.show(fragment);
+                }
+            } else {
+                yTab.setSelected(false);
+                if (fragment == null) {
+                    continue;
+                }
+                transaction.hide(fragment);
+            }
+        }
+
+        transaction.addToBackStack(getClass().getCanonicalName());
+        transaction.commitAllowingStateLoss();
+    }
+
+    @Override
+    public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
+        switchTab(position);
+    }
+}

+ 36 - 0
base/src/main/res/layout/widget_memu_item.xml

@@ -0,0 +1,36 @@
+<layout xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <data >
+
+        <variable
+            name="tab"
+            type="com.ysnows.base.widget.tablayout.YTab" />
+
+    </data >
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:orientation="vertical" >
+
+        <ImageView
+            android:id="@+id/img_icon"
+            android:layout_width="24dp"
+            android:layout_height="23.84dp"
+            android:src="@{tab.selected?tab.selectedDrawable:tab.normalDrawable}" />
+
+        <TextView
+            android:id="@+id/tv_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="2.33dp"
+            android:gravity="center_horizontal"
+            android:text="@{tab.text}"
+            android:textColor="@{tab.selected?tab.selectColor:tab.normalColor}"
+            android:textSize="@dimen/sp_12" />
+
+    </LinearLayout >
+</layout >
+
+        

+ 26 - 0
base/src/main/res/values/attrs.xml

@@ -22,4 +22,30 @@
     <declare-styleable name="TextField" >
         <attr name="isDelete" format="boolean" />
     </declare-styleable >
+
+
+
+    <!--   TabLayout -->
+    <declare-styleable name="YTabLayout" >
+        <attr name="indicator_height" format="dimension" />
+        <attr name="has_indicator" format="boolean" />
+        <attr name="indicator_top" format="boolean" />
+        <attr name="indicator_with_follow_content" format="boolean" />
+        <attr name="normal_text_size" format="dimension" />
+        <attr name="selected_text_size" format="dimension" />
+        <attr name="mode" format="enum" >
+            <enum name="scrollable" value="0" />
+            <enum name="fixed" value="1" />
+        </attr >
+        <attr name="space" format="dimension" />
+        <attr name="icon_position" format="enum" >
+            <enum name="left" value="0" />
+            <enum name="top" value="1" />
+            <enum name="right" value="2" />
+            <enum name="bottom" value="3" />
+        </attr >
+
+        <attr name="android:textSize" />
+    </declare-styleable >
+
 </resources >