android Material Design 學習之十:底部Tab的兩種實現

三少爺的鞋發表於2018-05-31

   上一篇:android Material Design 學習之九:TabLayout 基本使用 只是提到了TabLayout 作為頂部Tab 使用,其實TabLayout還可以作為底部的Tab。

TabLayout 實現底部Tab

佈局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
   >
   <include
       layout="@layout/tool_bar_layout"/>
    <com.dhl.mdstudy.NoAnimationViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        >
    </com.dhl.mdstudy.NoAnimationViewPager>
    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/white"
        app:tabIndicatorHeight="0dp"
        >
    </android.support.design.widget.TabLayout>

</LinearLayout>


NoAnimationViewPager 是為了解決Tab切換動畫閃動的問題,原始碼如下:

/**
 * 頁面切換取消動畫
 */

public class NoAnimationViewPager extends ViewPager {
    public NoAnimationViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setCurrentItem(int item) {
        super.setCurrentItem(item,false);
    }
}

自定義Tab 的佈局:

<?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="vertical">

    <ImageView
        android:id="@+id/image_menu_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/selector_menu_home"/>

    <TextView
        android:id="@+id/tv_menu_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Item"
        android:textColor="@color/selector_blue"/>

</LinearLayout>

上面是一個ImageView,下面是TextView 

這裡TextView 的selector :

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_selected="true" android:color="@color/blue"></item>
    <item android:state_checked="true" android:color="@color/blue"></item>
    <item android:color="@color/gray"></item>

</selector>

程式碼部分:

初始化Indicators:

 private void initIndicators()
    {
        tabIndicators = new ArrayList<>();
        tabIndicators.add("Tab01");
        tabIndicators.add("Tab02");
        tabIndicators.add("Tab03");
    }

核心程式碼:

private void initTab()
    {
        fragments = new ArrayList<>();
        //tabIndicators = new ArrayList<>();
        fragments.add(TabFragment.newInstance("Fragment 1"));
        fragments.add(TabFragment.newInstance("Fragment 2"));
        fragments.add(TabFragment.newInstance("Fragment 3"));
        //底部固定
        mTab_layout.setTabMode(TabLayout.MODE_FIXED);
        TabPagerAdapter tabPagerAdapter = new TabPagerAdapter(getSupportFragmentManager());
        tabPagerAdapter.setTabFragments(fragments);
        mView_pager.setAdapter(tabPagerAdapter);
        mTab_layout.setupWithViewPager(mView_pager);
        //必須放在 mTab_layout.setupWithViewPager(mView_pager); 後面,要不然 itemTab == null
        for (int i = 0; i < tabIndicators.size(); i++) {
            TabLayout.Tab itemTab = mTab_layout.getTabAt(i);
            if (itemTab!=null){
                itemTab.setCustomView(R.layout.tab_layout_custom);
                TextView itemTv = itemTab.getCustomView().findViewById(R.id.tv_menu_item);
                ImageView imageView = itemTab.getCustomView().findViewById(R.id.image_menu_item);
                imageView.setImageResource(R.drawable.selector_menu_home);
                itemTv.setText(tabIndicators.get(i));
            }
        }
        mTab_layout.getTabAt(0).getCustomView().setSelected(true);
    }

對每個Tab 自定義CustomView ,然後設定適當的Seleector 。

如下圖:


BottomNavigationView 實現底部Tab

佈局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.dhl.mdstudy.BottomNavActivity">

   <FrameLayout
       android:id="@+id/content_id"
       android:layout_width="match_parent"
       android:layout_height="match_parent"></FrameLayout>

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/bottom_nav_view"
        android:layout_width="match_parent"
        android:layout_alignParentBottom="true"
        app:itemIconTint="@color/selector_blue"
        app:itemTextColor="@color/selector_blue"
        app:menu="@menu/menu_bottom_navigation"
        android:layout_height="wrap_content">
    </android.support.design.widget.BottomNavigationView>

    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:layout_above="@id/bottom_nav_view"
        android:background="@color/gray"/>
</RelativeLayout>

Menu:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/action_home"
        android:title="首頁"
        android:icon="@drawable/ic_action_home"/>

    <item
        android:id="@+id/action_explore"
        android:title="發現"
        android:icon="@drawable/ic_action_explore"/>

    <item
        android:id="@+id/action_me"
        android:title="我"
        android:icon="@drawable/ic_action_me"/>

</menu>

底部Tab 就能正確顯示,新增Fragment ,支援正確切換:

public class BottomNavActivity extends AppCompatActivity {


    private BottomNavigationView bottomNavigationView ;
    private FragmentManager fragmentManager ;
    private FragmentTransaction transaction ;
    private TabFragment tabFragment01,tabFragment02,tabFragment03 ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bottom_nav);
        fragmentManager = getSupportFragmentManager();
        transaction = fragmentManager.beginTransaction();
        bottomNavigationView = (BottomNavigationView)findViewById(R.id.bottom_nav_view);
        transaction = fragmentManager.beginTransaction();
        tabFragment01 = TabFragment.newInstance("tab01");
        transaction.add(R.id.content_id,tabFragment01);
        transaction.commit();
        bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                transaction = fragmentManager.beginTransaction();
                hideFragment();
                //bottomNavigationView.setSelectedItemId(item.getItemId());
                switch (item.getItemId())
                {
                    case R.id.action_home :

                        if(tabFragment01 == null)
                        {
                            tabFragment01 = TabFragment.newInstance("tab01");
                            transaction.add(R.id.content_id,tabFragment01);
                        }else
                        {
                            transaction.show(tabFragment01);
                        }
                        break;

                    case R.id.action_explore :
                       // bottomNavigationView.setSelectedItemId(item.getItemId());
                        if(tabFragment02 == null)
                        {
                            tabFragment02 = TabFragment.newInstance("tab02");
                            transaction.add(R.id.content_id,tabFragment02);
                        }else
                        {
                            transaction.show(tabFragment02);
                        }
                        break;

                    case R.id.action_me :
                       // bottomNavigationView.setSelectedItemId(item.getItemId());
                        if(tabFragment03 == null)
                        {
                            tabFragment03 = TabFragment.newInstance("tab03");
                            transaction.add(R.id.content_id,tabFragment03);
                        }else
                        {
                            transaction.show(tabFragment03);
                        }
                        break;


                }
                transaction.commit();
                updateNavigationBarState(item.getItemId());
                //必須return true
                return true;
            }
        });
    }

    /**
     * 隱藏Fragment
     */
    private void hideFragment()
    {
        if(tabFragment01 != null) {
            transaction.hide(tabFragment01);
        }
        if(tabFragment02 != null)
        {
            transaction.hide(tabFragment02);
        }
        if(tabFragment03 != null)
        {
            transaction.hide(tabFragment03);
        }

    }

    /**
     * 更新Tab 選中狀態
     * @param actionId
     */
    private void updateNavigationBarState(int actionId){
        Menu menu = bottomNavigationView.getMenu();

        for (int i = 0, size = menu.size(); i < size; i++) {
            MenuItem item = menu.getItem(i);
            item.setChecked(item.getItemId() == actionId);
        }
    }
}

如下圖:


這個感覺要比TabLayout 實現要好一點。

相關文章