底部导航栏是很多APP都在使用的设计,像QQ、微信、支付宝等,已经是每个Android应用必不可少的了。
本文将展示用两种方法实现。
一.BottomNavigationView+FrameLayout
实现效果如图:
思路:
做开发,在实现某些功能时不仅学习的是其实现过程,更重要的是理解其制作思路,才能举一反三。
底部导航功能的实现分为两块,一部分是底部的导航按钮,另一部分是根据底部导航更换要显示的内容部分,我们所看见的更换的内容其实是fragment。
思路:
1.使用BottomNavigationView制作其底部按钮。
2.在内容区域放上FrameLayout用于放置要添加的fragment
3.实现二者的联动
实现:
1.引入依赖
compile 'com.android.support:design:26.1.0'
2.在主界面activity_main中添加控件
<?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" android:orientation="vertical" tools:context="com.example.lenovo.bottomnavigation.MainActivity"> <!--用于切换fragment--> <FrameLayout android:id="@+id/fl_main" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@id/bnv_main"/> <android.support.design.widget.BottomNavigationView android:id="@+id/bnv_main" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true"/> </RelativeLayout>
BottomNavigationViewlai'来自于引入的design包
3.添加item
在主界面中添加了BottomNavigationView后就要为其设置item项,在item中设置按钮图标和文字
在res目录下新建menu文件夹,在该文件夹下新建menu resource file,命名navigation.xml
navigation.xml
<?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/homeb" android:title="@string/home" /> <item android:id="@+id/navigation_buy" android:icon="@drawable/shopb" android:title="@string/order" /> <item android:id="@+id/navigation_user" android:icon="@drawable/userb" android:title="@string/my" /> </menu>
要提前准备6张图片,分别表示按钮的选中和未选中状态,按钮标题提取到strings中
在此都静态设置为未选中状态的图标。
到这里如果运行的话会发现自定义的图标不会显示出来,不着急,我们会在下面解决
4.创建fragment
在此我们要创建3个不同的fragment
首页:
HeadFragment.java
public class HeadFragment extends Fragment { @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { //该View表示该碎片的主界面,最后要返回该view View view=inflater.inflate(R.layout.fragment_head,container,false); //找到主界面view后,就可以进行UI的操作了。 //注意:因为主界面现在是view,所以在找寻控件时要用view.findViewById TextView textView=view.findViewById(R.id.tv_head); //textView.setText(""); return view; } }
fragment_head.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tv_head" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="首页" android:textSize="30sp" /> </FrameLayout>
为简单起见,在fragment中只添加了一个TextView。
再按同样的方法创建其他两个fragment,
分别是OrderFragment.java+fragment_order.xml 和 UserFragment.java+fragment_user.xml
创建过程就不在此赘述,和创建HeadFragment一样
5.MainActivity.java
最后一部分也是重要的部分,直接上代码:
MainActivity.java
public class MainActivity extends AppCompatActivity { private BottomNavigationView navigationView; //创建三个Fragment和存放他们的数组 private Fragment headFragment; private Fragment orderFragment; private Fragment userFragment; public Fragment[] fragmentlist; //用于标识上一个fragment private int lastFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //fragment初始化 initFragment(); } /** * 初始化fragment,并将headFragment显示出来 */ private void initFragment() { navigationView = (BottomNavigationView) findViewById(R.id.bnv_main); //配置菜单按钮显示图标 navigationView.setItemIconTintList(null); //将三个fragment先放在数组里 headFragment = new HeadFragment(); orderFragment = new OrderFragment(); userFragment = new UserFragment(); fragmentlist = new Fragment[]{headFragment, orderFragment, userFragment}; //此时标识标识首页 //0表示首页,1表示orderFragment,2表示userFragment lastFragment = 0; //为navigationView设置点击事件 navigationView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); //设置默认页面为headFragment getSupportFragmentManager().beginTransaction().replace(R.id.fl_main, headFragment) .show(headFragment).commit(); navigationView.setSelectedItemId(R.id.navigation_home); } /** * 给BottomNavigationView添加按钮的点击事件 */ private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { //每次点击后都将所有图标重置到默认不选中图片 resetToDefaultIcon(); switch (item.getItemId()) { case R.id.navigation_home: //判断要跳转的页面是否是当前页面,若是则不做动作 if (lastFragment != 0) { switchFragment(lastFragment, 0); lastFragment = 0; } //设置按钮的 item.setIcon(R.drawable.homea); return true; case R.id.navigation_buy: if (lastFragment != 1) { switchFragment(lastFragment, 1); lastFragment = 1; } item.setIcon(R.drawable.shopa); return true; case R.id.navigation_user: if (lastFragment != 2) { switchFragment(lastFragment, 2); lastFragment = 2; } item.setIcon(R.drawable.usera); return true; } return false; } }; /** * * @param lastFragment 表示点击按钮前的页面 * @param index 表示点击按钮对应的页面 */ private void switchFragment(int lastFragment, int index) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); //隐藏上个Fragment transaction.hide(fragmentlist[lastFragment]); //判断transaction中是否加载过index对应的页面,若没加载过则加载 if (fragmentlist[index].isAdded() == false) { transaction.add(R.id.fl_main, fragmentlist[index]); } //根据角标将fragment显示出来 transaction.show(fragmentlist[index]).commitAllowingStateLoss(); } /** * 重新配置每个按钮的图标 */ private void resetToDefaultIcon() { navigationView.getMenu().findItem(R.id.navigation_home).setIcon(R.drawable.homeb); navigationView.getMenu().findItem(R.id.navigation_buy).setIcon(R.drawable.shopb); navigationView.getMenu().findItem(R.id.navigation_user).setIcon(R.drawable.userb); } }
代码中的注释都很详细,大致实现步骤是:
拿到BottomNavigationView实例-->为其设置按钮点击事件-->设置默认页面
其中,FragmentTransaction相当于是个容器,会将所有被添加的fragment保存起来,再配置把哪个显示、哪个隐藏。
刚才遗留的问题,也被解决了,因为BottomNavigationView有其默认的按钮图标,所以我们自定义的图标不会显示。我们
可以把BottomNavigationView默认icon设置为null。
navigationView.setItemIconTintList(null);
完成。
有什么问题可以在评论区留言
第二种方法链接:https://blog.csdn.net/qq_39055743/article/details/81842190