Android常用底部导航栏实现(一)

底部导航栏是很多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

猜你喜欢

转载自blog.csdn.net/qq_39055743/article/details/81809630