Android实战开发--底部导航(Fragment)篇

安卓实战开发之底部导航

提示:本篇文中对基本的操作不做细节讲解,后续会通过链接方式跳转到对应的知识点。



前言

本片文章将使用Fragment来构建底部导航。底部导航栏我们使用矢量图标(png/jpg等也可以,其中优劣自行体会),这里我们通过Android Stdio 自带的矢量图标下载功能进行下载。


一、准备


1、矢量图标准备

  • 通过New——>Vector Asset,点击Clip Art打开图标的搜索界面。注意搜索时是需要联网的,且通过英文搜索。比如像常用的首页图标,我们这里输入“home”。
  • 选择完之后,点击OK,设置图片属性,Next选择资源文件位置(main),最终会保存到res资源目录的drawable目录下
    图标生成
  • 下载后是一个xml文件,我们可以更改它的颜色和宽高。这里我们将同一个图标设置拷贝成两份颜色不同的图标,用作选中(蓝色)和未选中(灰色)使用
  • 这里我们总共准备了五个选中图标、五个未选中图标

    在这里插入图片描述

2、文件准备

  • 有五个图标我们就需要五个Fragment文件>
    在这里插入图片描述
  • 最后再准备一个底部导航的布局文件,这里的底部导航是一个独立的布局,我们是通过include(包含)来引入这个底部导航的布局的。(布局自行构建这里不做讲解)
    在这里插入图片描述

注意:这里需要设置默认图标,和默认文字颜色都设为未选中的颜色(第一个图标和文字控件设置为选中状态)


二、使用步骤

1.在fragment中动态加载布局

  • 继承Fragment

代码如下(示例):

public class HomeFragment extends Fragment {

}
  • 通过快捷键(CTRL + O)快速生成onCreateView和onViewCreate方法。

代码如下(示例):

	//onCreateView的意思是:创建视图。
	//我们在这个方法里来动态加载布局
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		
	    return inflater.inflate(R.layout.fragment_home, container, false);
	}
	//onViewCreate的意思是:视图创建
	//我们在这个方法里面操作视图控件、逻辑方法就像是Activity的onCreate方法。
	//但是要注意我们操作的控件的时候使用的是:onCreateView返回view,通过传递实参到onViewCreated方法的形参View中,所以在初始化控件的时候是view.findViewById();
	//最后要注意如果有些方法使用不了,大概是因为那些方法实在Actiivty中(未作具体了解),所以需要先调用getActivity()方法。
	@Override
	public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
	    super.onViewCreated(view, savedInstanceState);
}

onCreateView方法分析:

一、首先我们可以看到这个方法的返回值类型为View(视图),所以我们需要创建View对象加载视图然后返回
    1、动态加载视图的写法:首先需要实例化LayoutInflater对象
    	LayoutInflater layoutInflater = getLayoutInflater();
    	View view = layoutInflater.inflate(R.layout.fragment,container,false);
    2、我们可以通过快捷键(CTRL + P)来查看inflate的参数列表(@LayoutRes int resource,ViewGroup root,boolean attachToRoot)
    	从字面意思来分析:
    	a.@LayoutRes int resource
    		第一个参数是一个@LayoutRes int类型的参数,通多CTRL + 左击查看@LayoutRes注解,我们可以通过注释知道这个整数参数返回的是一个布局资源引用(即R.layout.资源名)
    	b.ViewGroup root
    		第二个参数是一个ViewGroup(视图组),相当于一个容器,我们可以将若干个控件或布局放进去组成一个大的布局。root(根,底部的意思)看到这个单词我们通常会联想到权限,我们也可以理解为:我们引入的布局只在这个视图组内生效。
    	c.boolean attachToRoot
    		第三个参数是布尔类型,attachToRoot(附加到根),这里我们不附加到根(false),如果填的是附加(true)就会报错。原因和方案可以参考这个博主的文章:https://blog.csdn.net/yaolingrui/article/details/7339913

二、这里我们可以看到在onCreateView方法里面有LayoutInflater对象和ViewGroup对象,所以既然有意思和明显就是要你使用参数列表里面传过来的实参
三、最完整的写法是:View view = layoutInflater.inflate(R.layout.fragment,container,false);		这里我们就简写了


2.构建导航框架

  • 在activity_main.xml中引入导航的布局

代码如下(示例):

	<!--通过layout这个属性来添加写好的底部导航布局-->
	<include
	    android:id="@+id/include"
	    layout="@layout/navigation"
	    android:layout_width="match_parent"
	    android:layout_height="50dp"
	    app:layout_constraintBottom_toBottomOf="parent"
	    app:layout_constraintEnd_toEndOf="parent" />
  • 添加FrameLayout布局管理器

代码如下(示例):

	<FrameLayout
	   android:id="@+id/framelayout"
	   android:layout_width="match_parent"
	   android:layout_height="wrap_content"
	   tools:ignore="MissingConstraints" />
  • 我们可以嵌套一个滑动组件ScrollView包裹FrameLayout,注意引入的导航布局include不要嵌套进去,不然底部导航也会被滑动(那就不能算是底部导航了,懂我意思吧)

代码如下(示例):

<ScrollView
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent">

    <FrameLayout
        android:id="@+id/framelayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:ignore="MissingConstraints" />

</ScrollView>
  • 效果

    在这里插入图片描述

3、初始化控件

  • 在MainActivity.java中初始化控件

代码如下(示例):

//全局变量

//底部导航图片控件声明
 private ImageView[] imageViews;
    private int[] imageViewsId = {
            R.id.imageView01,
            R.id.imageView02,
            R.id.imageView03,
            R.id.imageView04,
            R.id.imageView05,
    };
//底部导航文字控件声明
    private TextView[] textViews;
    private int[] textViewsId = {
            R.id.textView01,
            R.id.textView02,
            R.id.textView03,
            R.id.textView04,
            R.id.textView05
    };
    
    //五个Fragment布局声明
    private Fragment[] fragments = {
      new HomeFragment(),
      new ServiceFragment(),
      new PartyFragment(),
      new NewsFragment(),
      new PersionFragment()
    };
  • 我们使用数组的方式声明,所有可以通过数组遍历来赋值:
//声明数组
imageViews = new ImageView[imageViewsId.length];
textViews = new TextView[textViewsId.length];

//初始化
for (int i = 0; i < imageViewsId.length; i++) {
    imageViews[i] = findViewById(imageViewsId[i]);
    textViews[i] = findViewById(textViewsId[i]);
}

4、 给FrameLayout添加默认布局

//这里需要注意的是getSupportFragment()方法
//还有一个getFragment()方法,这两方法等效
//区别在一所属包不同。第一个是在androidx中,第二个是在android中。
//所以要注意这里的我们之前准备的Fragment是继承自哪个包的Fragment,根据那个包选择方法,否则会报错
getSupportFragmentManager().beginTransaction().replace(R.id.framelayout,new HomeFragment()).commit();

5、实例化一个View.OnClickListener对象来写一个点击事件

        View.OnClickListener onClickListener = new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                for (int i = 0; i < 5; i++) {
                    if(view.getId() == imageViewsId[i]) {
                        //替换布局
                        getSupportFragmentManager().beginTransaction().replace(R.id.framelayout, fragments[i]).commitAllowingStateLoss();
                        //设置图标文字状态
                        imageViews[i].setImageDrawable(getDrawable(drawablesTrue[i]));
                        textViews[i].setTextColor(getResources().getColor(R.color.text_true));
                    }else{
                        imageViews[i].setImageDrawable(getDrawable(drawablesFalse[i]));
                        textViews[i].setTextColor(getResources().getColor(R.color.text_false));
                    }
                }

            }
        };

注意:这里在调用图标资源的时候使用getDrawable()方法,但是在调用颜色资源的时候得先调用getResources()再调用getColor()方法,否则会报错。

分析:这个View.OnClickListener对象需要重写onClick方法,在onClick方法里会传入一个View对象的实参,这个对象实质上就是设置点击事件的控件。所以view.getId()方法实质上就是获取这个控件的id值,就是R.id.imageView01。

R.id.imageView01是一个@IdRes int类型的数据,本质上就是一串特定的数字。

6、给控件设置写好的点击事件

 for (int i = 0,j = 0; i < imageViewsId.length; i++,j++) {
            imageViews[i].setOnClickListener(onClickListener);
            textView[i].setOnClickListener(onClickListener);
        }

三、 总结

至此,底部导航完成。如有问题欢迎留言评论~

  • 4
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微冷i1104

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值