Android底部導航欄的三種風格實現
一、效果圖展示
如果動圖沒有動的話,也可以看下面這個靜態圖
以下挨個分析每個的實現,這裡只做簡單的效果展示,大家可以基於目前程式碼做二次開發。
二、BottomNavigationView
這是 Google 給我們提供的一個專門用於底部導航的 View,你只需要在新建 Activity 的時候選擇 “Bottom Navigation Activity”,IDE 就會自動使用 BottomNavigationView 幫你生成好相應的程式碼了。
1. 在 xml 中使用
<android.support.design.widget.BottomNavigationView android:id="@+id/navigation" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="0dp" android:layout_marginStart="0dp" android:background="?android:attr/windowBackground" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:menu="@menu/navigation" />
這裡面唯一要注意的就是 app:menu 屬性了,它指定了你的導航欄顯示的頁面選單是怎樣的。
2. menu 的佈局檔案
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/navigation_home" android:icon="@drawable/ic_home_black_24dp" android:title="@string/title_home" /> <item android:id="@+id/navigation_dashboard" android:icon="@drawable/ic_dashboard_black_24dp" android:title="@string/title_dashboard" /> <item android:id="@+id/navigation_notifications" android:icon="@drawable/ic_notifications_black_24dp" android:title="@string/title_notifications" /> </menu>
3. 在 Activity 中呼叫
private TextView mTextMessage; private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.navigation_home: mTextMessage.setText(R.string.title_home); return true; case R.id.navigation_dashboard: mTextMessage.setText(R.string.title_dashboard); return true; case R.id.navigation_notifications: mTextMessage.setText(R.string.title_notifications); return true; } return false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_style1); mTextMessage = findViewById(R.id.message); BottomNavigationView navigation = findViewById(R.id.navigation); navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); }
這裡的演示 code 都是 IDE 自動生成的,由於 BottomNavigationView 目前我還沒有在專案中實際使用過,這裡不做過多分析,使用起來不難,以上程式碼已經足以滿足我們的基本使用要求了。
三、RadioGroup + ViewPager
這是一種比較常見了的,下面 4 個 tab 的導航按鈕,可以切換不同的頁面,這裡頁面使用了 ViewPager + Fragment 的組合,實現了滑動的頁面效果,也可以不使用 ViewPager,這個根據產品的定義來使用即可。
1. 佈局檔案
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".style2.Style2Activity"> <android.support.v4.view.ViewPager android:id="@+id/fragment_vp" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/tabs_rg" /> <RadioGroup android:id="@+id/tabs_rg" android:layout_width="match_parent" android:layout_height="56dp" android:layout_alignParentBottom="true" android:background="#dcdcdc" android:orientation="horizontal"> <RadioButton android:id="@+id/today_tab" style="@style/Custom.TabRadioButton" android:checked="true" android:drawableTop="@drawable/tab_sign_selector" android:text="今日" /> <RadioButton android:id="@+id/record_tab" style="@style/Custom.TabRadioButton" android:drawableTop="@drawable/tab_record_selector" android:text="記錄" /> <RadioButton android:id="@+id/contact_tab" style="@style/Custom.TabRadioButton" android:drawableTop="@drawable/tab_contact_selector" android:text="通訊錄" /> <RadioButton android:id="@+id/settings_tab" style="@style/Custom.TabRadioButton" android:drawableTop="@drawable/tab_setting_selector" android:text="設定" /> </RadioGroup> </RelativeLayout>
2. Activity 類
public class Style2Activity extends AppCompatActivity { private ViewPager mViewPager; private RadioGroup mTabRadioGroup; private List<Fragment> mFragments; private FragmentPagerAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_style2); initView(); } private void initView() { // find view mViewPager = findViewById(R.id.fragment_vp); mTabRadioGroup = findViewById(R.id.tabs_rg); // init fragment mFragments = new ArrayList<>(4); mFragments.add(BlankFragment.newInstance("今日")); mFragments.add(BlankFragment.newInstance("記錄")); mFragments.add(BlankFragment.newInstance("通訊錄")); mFragments.add(BlankFragment.newInstance("設定")); // init view pager mAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(),mFragments); mViewPager.setAdapter(mAdapter); // register listener mViewPager.addOnPageChangeListener(mPageChangeListener); mTabRadioGroup.setOnCheckedChangeListener(mOnCheckedChangeListener); } @Override protected void onDestroy() { super.onDestroy(); mViewPager.removeOnPageChangeListener(mPageChangeListener); } private ViewPager.OnPageChangeListener mPageChangeListener = new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position,float positionOffset,int positionOffsetPixels) { } @Override public void onPageSelected(int position) { RadioButton radioButton = (RadioButton) mTabRadioGroup.getChildAt(position); radioButton.setChecked(true); } @Override public void onPageScrollStateChanged(int state) { } }; private RadioGroup.OnCheckedChangeListener mOnCheckedChangeListener = new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group,int checkedId) { for (int i = 0; i < group.getChildCount(); i++) { if (group.getChildAt(i).getId() == checkedId) { mViewPager.setCurrentItem(i); return; } } } }; private class MyFragmentPagerAdapter extends FragmentPagerAdapter { private List<Fragment> mList; public MyFragmentPagerAdapter(FragmentManager fm,List<Fragment> list) { super(fm); this.mList = list; } @Override public Fragment getItem(int position) { return this.mList == null ? null : this.mList.get(position); } @Override public int getCount() { return this.mList == null ? 0 : this.mList.size(); } } }
這裡唯一注意點的就是兩個監聽事件,要實現底部導航按鈕和頁面的聯動。
四、帶頁面跳轉功能的底部導航
很多 APP 的底部導航欄中間有一個很大的按鈕,點選後通常是開啟一個新的頁面,這裡我們要實現的就是這種底部導航。
依舊是使用 RadioGroup 來做,只不過中間一個 tab 我們先用一個空的 View 來佔位,然後在這個 View 的位置放置一個較大的按鈕來覆蓋住。
1. 佈局檔案
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".style3.Style3Activity"> <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/tabs_rg" /> <RadioGroup android:id="@+id/tabs_rg" android:layout_width="match_parent" android:layout_height="56dp" android:layout_alignParentBottom="true" android:background="#dcdcdc" android:orientation="horizontal"> <RadioButton android:id="@+id/today_tab" style="@style/Custom.TabRadioButton" android:checked="true" android:drawableTop="@drawable/tab_sign_selector" android:text="今日" /> <RadioButton android:id="@+id/record_tab" style="@style/Custom.TabRadioButton" android:drawableTop="@drawable/tab_record_selector" android:text="記錄" /> <View style="@style/Custom.TabRadioButton" /> <RadioButton android:id="@+id/contact_tab" style="@style/Custom.TabRadioButton" android:drawableTop="@drawable/tab_contact_selector" android:text="通訊錄" /> <RadioButton android:id="@+id/settings_tab" style="@style/Custom.TabRadioButton" android:drawableTop="@drawable/tab_setting_selector" android:text="設定" /> </RadioGroup> <ImageView android:id="@+id/sign_iv" android:layout_width="80dp" android:layout_height="80dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:background="@android:color/transparent" android:src="@mipmap/sign" /> </RelativeLayout>
2. Activity 類
public class Style3Activity extends AppCompatActivity { private RadioGroup mTabRadioGroup; private SparseArray<Fragment> mFragmentSparseArray; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_style3); initView(); } private void initView() { mTabRadioGroup = findViewById(R.id.tabs_rg); mFragmentSparseArray = new SparseArray<>(); mFragmentSparseArray.append(R.id.today_tab,BlankFragment.newInstance("今日")); mFragmentSparseArray.append(R.id.record_tab,BlankFragment.newInstance("記錄")); mFragmentSparseArray.append(R.id.contact_tab,BlankFragment.newInstance("通訊錄")); mFragmentSparseArray.append(R.id.settings_tab,BlankFragment.newInstance("設定")); mTabRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group,int checkedId) { // 具體的fragment切換邏輯可以根據應用調整,例如使用show()/hide() getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,mFragmentSparseArray.get(checkedId)).commit(); } }); // 預設顯示第一個 getSupportFragmentManager().beginTransaction().add(R.id.fragment_container,mFragmentSparseArray.get(R.id.today_tab)).commit(); findViewById(R.id.sign_iv).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(Style3Activity.this,SignActivity.class)); } }); } }
注意:
如果這裡你也想使用 ViewPager 來展示 Fragment 的話,一定要注意這裡的 RadioGroup 中間有一個佔位的 View,即兩者的監聽事件裡,實現聯動時要考慮多個這個 View 的存在。
程式碼地址: https://gitee.com/afei_/BottomTabbar
到此這篇關於Android底部導航欄的三種風格實現的文章就介紹到這了,更多相關Android底部導航欄內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!