Android实现炫酷底部导航栏

炫酷导航栏实现

创建导航栏图标

使用系统自带的矢量图库文件,鼠标右键点击res->New->Vector Asset即可跳转到如下界面,按照下图操作:

image-20240313155429141

用使用矢量绘图icon图标,并且在Name属性栏选择图标名称;

  • 根据自己需求选择合适的icon,Select icon中图标数量并不是很多,自行选择即可,我这里选择四个icon图标;
  • baseline_person_fill / baseline_person_stroke,一般后缀名fill和stroke来区分点击前和点击后icon图标;

修改依赖

build.grade(:app)中的dependencies修改以下依赖即可:

implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta7'

创建资源文件

创建资源文件,鼠标右键点击res文件夹,依次点击New->New Resource File即可:

选择Resource typesLayout即可,File name暂定为all_icon_layout(后期根据情况修改名称)

image-20240312185642351

第一步:将all_icon_layout.xml文件转换为MotionLayout

image-20240312185921212

第二步:在母体中添加ImageView和TextView组件(选中组件后拖拽即可),位置目前任意摆放,暂无要求。将ImageView组件拖动到母版后出现图二所示界面,选择合适的Image(即之前创建的icon的xml文件)

image-20240312190718032

同理,在添加TextView组件之前,需要先添加资源文件,在string.xml资源文件中添加如下代码:

<resources>
    <string name="scanner_icon_title">扫码乘车</string>
    <string name="record_icon_title">预约记录</string>
    <string name="start_icon_title">校车预约</string>
    <string name="account_icon_title">我的</string>
</resources>

利用string.xml文件,一次设置四个TextView的text属性:

image-20240313160629007

接下来,将ImageView和TextView串联起来,让它们保持整齐。

例如:选中ImageView组件,然后白板中组件的四个白点分别连接到手机四个边即可,TextView组件同理,最后再将两个组件上下连接即可。

我们需要将两种图片进行过度,需要将图片转换为ImageFilterView

选中ImageView组件后,鼠标右键即可选择Convert view...,并且选择ImageFilterView即可

image-20240312192226787

分别进行如下操作:

  • 点击1号start模板
  • 点击2号位置的组件ImageView
  • 3号位置有一个✏️图标,点击✏️图标后选择后点击Create Constraint,分别对ImageView和TextView组件进行同样操作,直至Source属性列变换为start即可
  • 完成上述操作后,点击end模版,并且执行2和3同样的操作即可出现下方图中右侧两个效果即成功。

image-20240312192628623添加动画效果KeyCycle

image-20240312193847145

image-20240312194242630

设置选中状态的图片,在all_icon_layout.xml代码中添加如下代码,目的是为了点击icon图标后,有明显的变化:

image-20240312194453755

过渡画面

ImageView组件的过渡动画

首先设置ImageView组件的过渡动画初始状态选择ImageView组件后,点击CustomAttributes添加即可:

start模版下,Value的值为0;在end模版下,Value的值为1。

image-20240312194838028

设置颜色过渡,点击icon图标后,矢量图icon图标发生颜色变化:

image-20240312195439707

同理需要设置end模版的的颜色,同样操作,选择end板块后添加颜色即可

image-20240312195741368

到此ImageView组件调整完毕,接下来只需要调整TextView组件的颜色过渡即可,不需要设置动画过渡。

TextView组件的过渡动画

在选中TextView组件后,进行颜色过渡操作即可:

  • 设置start模版textColor属性为?attr/colorControlNormal
  • 设置end模版textColor属性为#1AFA29,变换后的颜色根据具体情况修改即可。

image-20240312200151407

上述做的只是其中一个部分,其余三个部分复制粘贴即可,我这里将之前的名字all_icon_layout修改为scanner_icon_layout;其他的部分复制粘贴后修改名称,分别是star_icon_layoutrecord_icon_layoutaccount_icon_layout

随后需要修改布局文件中的矢量图icon图标和对应的TextView组件文字;至此,所有的布局文件暂时告一段乱了。接下来设置main布局文件。

设置main布局文件

  • 设置导航栏,直接在Layouts部分,设置LinearLayout(horizontal)
  • 将创建的LinearLayout布局的左右下三个点分别连接到白板的左右下对应的位置,此时这三个点的颜色由白色填充为蓝色;
  • 将LinearLayout布局的高度设置为56dp.

image-20240312202109149

设置完上面布局文件后,设置gravity,选择center_vertical即可:

image-20240312202222490

接下来就开始放置之前创建的四个UI组件,使用Containers/include即可实现:

  • 拖动四个include到LinearLayout布局文件中
  • 选择之前创建的四个矢量图icon图标.xml文件

image-20240312202543688

为了继续美化点击icon时的效果,在四个矢量图icon图标对应的xml文件中添加水波纹:

android:background="?attr/selectableItemBackgroundBorderless"

image-20240312203238551

创建四个Fragment占位,按照如下图所示操作,选择Fragment(Blank),即可创建成功(这里已经创建成功了,不过多演示了):

image-20240313162841348

创建navigationres->New->New Resource File,并且选择Resource type为Navigation即可,点击ok后,会自动导入依赖,需要提前打开科技工具,否则时间很慢👀:

image-20240312203726537

系统依赖自动导入后,就可以导入其中的Fragment,按照导航栏的顺序导入即可,有home图标的表示是第一个Fragment(按照下面操作即可):

image-20240312205306926

在之前的布局文件中,添加NavHostFragment即可,然后设置高度,点击下拉菜单,选择0dp(match constraint)即可:

image-20240312205911434

然后将NavHostFragment添加到activity_main.xml中,直接拖动即可

image-20240312205810761

设置每个Fragment布局文件中的内容,将TextView居中,且设置文本:

image-20240312210353501

最后一件事就是将四个Fragment装在一起。

组装Fragment

打开MainActivity.java文件,参考下面的代码,修改自己的代码即可

public class MainActivity extends AppCompatActivity {

    //NavHostFragment的控制器
    NavController navController;
    //4个MotionLayout
    MotionLayout ScannerMotionLayout;
    MotionLayout StarMotionLayout;
    MotionLayout RecordMotionLayout;
    MotionLayout AccountMotionLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        // 初始化步骤,注意 NavHostFragment 控制器获取方法
        // 修改这里以确保正确设置NavController
        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
        navController = navHostFragment.getNavController();

        ScannerMotionLayout = findViewById(R.id.scannerMotionLayout);
        StarMotionLayout = findViewById(R.id.starMotionLayout);
        RecordMotionLayout = findViewById(R.id.recordMotionLayout);
        AccountMotionLayout = findViewById(R.id.accountMotionLayout);

        // 设置点击事件
        ScannerMotionLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 选中直接转换到对应页面
                navController.navigate(R.id.scannerFragment);
            }
        });

        StarMotionLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                navController.navigate(R.id.starFragment);
            }
        });

        RecordMotionLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                navController.navigate(R.id.recordFragment);
            }
        });

        AccountMotionLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                navController.navigate(R.id.accountFragment);
            }
        });

        navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(@NonNull NavController controller,
                                             @NonNull NavDestination destination,
                                             @Nullable Bundle arguments) {
                controller.popBackStack();
                AccountMotionLayout.setProgress(0f);
                RecordMotionLayout.setProgress(0f);
                StarMotionLayout.setProgress(0f);
                ScannerMotionLayout.setProgress(0f);
                switch (destination.getId()) {
                    case R.id.accountFragment:
                        AccountMotionLayout.transitionToEnd();
                        break;
                    case R.id.recordFragment:
                        RecordMotionLayout.transitionToEnd();
                        break;
                    case R.id.starFragment:
                        StarMotionLayout.transitionToEnd();
                        break;
                    case R.id.scannerFragment:
                        ScannerMotionLayout.transitionToEnd();
                        break;
                }
            }
        });
    }
}

在我提供的代码第21行,有一个组件叫做fragmentContainerView,这个组件其实就是activity_layout.xml布局文件中的导航栏的id,大家根据自己的id修改即可

image-20240313163456680

至此,所有的功能均可运行,炫酷的导航栏终于实现了。

参考教程:第57集 底部导航栏动态效果

  • 16
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

WeiComp

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

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

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

打赏作者

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

抵扣说明:

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

余额充值