[Android] UI进阶笔记:从 Toolbar 到可折叠标题栏的完整实战

学习 Android 开发的过程中,UI 控件往往是最直观也最容易踩坑的部分。本文整理了我在学习《第一行代码》后的实践笔记,涵盖 Toolbar、自定义标题栏、菜单、Snackbar、CoordinatorLayout、可折叠标题栏、SwipeRefreshLayout 下拉刷新、FloatingActionButton 悬浮按钮 等常见控件的使用方法和心得体会。通过这些总结,希望能帮助你快速掌握 Android 界面开发的核心知识点,让界面更灵活、更具交互感eve~

Toolbar

Toolbar是什么?

  • Toolbar 是 Android 5.0)后引入的新控件,用来替代以前的 ActionBar,可以自由控制位置、样式
  • 因为是可自定义的,所以比 ActionBar 灵活得多

Toolbar 的常见功能

  1. 应用标题
    默认显示 App 名称,你可以改成自定义标题
  2. 导航按钮(返回键 / 菜单按钮)
    可以添加返回箭头、菜单按钮,或者换成你想要的图标
  3. 菜单
    可以在右上角加"搜索""更多"等按钮
  4. 完全自定义布局
    Toolbar 内部可以放 TextView、ImageView,甚至自定义控件

Toolbar的使用(配合菜单)

  • 可以直接在layout布局文件中使用:
Android 复制代码
<Toolbar
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:id = "@+id/toolbar"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    app:popupTheme = "@style/ThemeOverlay.AppCompat.Dark"
    app:layout_constraintTop_toTopOf="parent"
    android:title="你好"
    >

</Toolbar>

以上代码中有两个较为陌生的属性:

  • android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"代表顶部导航栏的主题颜色

@style/ThemeOverlay.AppCompat.Dark.ActionBar代表白色字体图标;@style/ThemeOverlay.AppCompat.Light表示深色字体图标

  • app:popupTheme = "@style/ThemeOverlay.AppCompat.Dark" 表示菜单的主体颜色

@style/ThemeOverlay.AppCompat.Light→ 白色弹窗 @style/ThemeOverlay.AppCompat.Dark → 深色弹窗

  • app:navigationIcon 设置左上角的导航图标(常见是返回箭头)

菜单项这样来写:

Android 复制代码
   <item
       android:id="@+id/it1"
       android:icon="@drawable/ic_launcher_background"
       android:title="TODO"
       app:showAsAction = "always">

   </item>
<item
    android:id="@+id/it2"
    android:icon="@drawable/ic_launcher_foreground"
    android:title="TOD1"
    app:showAsAction = "ifRoom">

</item>
<item
    android:id="@+id/it3"
    android:title="TOD2"
    android:icon="@drawable/ic_launcher_foreground"
    app:showAsAction = "never">

</item>

app:showAsAction = "always" 代表表现的方式:

always代表一定要显示在顶部导航栏,否则不显示

ifRoom代表如果能显示显示,不能显示就去菜单项

never一定在菜单项

最后把菜单项膨胀到视图,一定要使用这个方法,因为有菜单时,系统会回调这个方法;

Android 复制代码
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.toolbai,menu);
    return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.action_search) {
        Toast.makeText(this, "点击了搜索", Toast.LENGTH_SHORT).show();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

设置toolbar

Android 复制代码
Toolbar toolbars = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbars);

设置导航按钮(返回箭头)

Android 复制代码
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbars.setNavigationOnClickListener(v -> finish());

注意:toolbar最好使用androidx

Android 复制代码
androidx.appcompat.widget.Toolbar

使用Androidx的toolbar时需要添加依赖,依赖如下:

Android 复制代码
implementation 'androidx.appcompat:appcompat:1.6.1'

当然我们也可以自定义toolbar,在toolbar中自定义控件:

Android 复制代码
Toolbar toolbar = findViewById(R.id.custom_toolbar);
setSupportActionBar(toolbar);
// 去掉系统默认标题,使用我们自己的 TextView
getSupportActionBar().setDisplayShowTitleEnabled(false);

getSupportActionBar().setDisplayShowTitleEnabled(false);核心就是设置后setSupportActionBar的这一句代码,我们就可以使用自定义控件了,那么具体怎么自定义,那就看你想要什么样子的效果啦;

不过需要注意一点,这里只是去掉了默认的标题,所以系统默认的标题不显示了,但是我们仍然可以使用其他方法,比如设置返回图标;

好了,Toolbar的简单学习先到这里;

FloatingActionButton

这是悬浮按钮 ,我们可以做点击事件

在xml文件中简单使用如下

Android 复制代码
<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|right"
    android:layout_margin="20dp"
    android:id = "@+id/fa"
    android:elevation="2dp"
    android:src = "@drawable/ic_launcher_foreground"

/>

属性解释:

android:elevation="2dp" 数值越大,阴影面积大,但浅,反之则相反;

android:src = "@drawable/ic_launcher_foreground"可用来添加图片

Snackbar

一个功能类似toast提示框,与toast不同的是,可以和用户交互

Android 复制代码
floatingActionButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Snackbar.make(view,"嘿嘿",Snackbar.LENGTH_LONG).setAction("确定", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"雪雪学安卓",Toast.LENGTH_SHORT).show();
            }
        }).show();
    }
});

Snackbar.make(view,"嘿嘿",Snackbar.LENGTH_LONG);

  • make方法是确认提示主体 ,第一个参数是界面任意 一个view,snackbar会自动选择最上层那一个,第二个参数是提示语

  • setAction方法 通过setaction方法和用户交互 ,第一个参数是按钮效果 ,第二个参数做监听

最后别忘记show()!

CoordinatorLayout布局

这个布局和帧布局差不多

但是它可以监听所有 的子控件,从而做出最佳响应:比如悬浮按钮和提示框重合问题

需要注意的是:

那前提得是子控件,所以提示框传入的view参数得是coordinatorlayout的子控件了;

glide依赖如下

Android 复制代码
    implementation 'com.github.bumptech.glide:glide:4.16.0'

Recycleview进阶版

可能照片资源过大,所以这个时候就需要它了;

依赖如下:

Android 复制代码
implementation 'com.github.bumptech.glide:glide:4.16.0'

Glide.with(mcontext).load(fruit.getImageid()).into(holder.imageView);

第一个参数是context ,第二个是把这个id加载到第三个参数的布局中

Android 复制代码
GridLayoutManager layoutManager = new GridLayoutManager(this,2);

代表两列

Android 复制代码
<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <androidx.appcompat.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:id = "@+id/toolbar"
            android:theme="@style/Widget.AppCompat.Light.ActionBar"
            app:popupTheme = "@style/ThemeOverlay.AppCompat.Light"
            app:layout_scrollFlags="scroll|enterAlways|snap"
            app:layout_constraintTop_toTopOf="parent"
            android:title="你好"
            >
        </androidx.appcompat.widget.Toolbar>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:id="@+id/recy">

    </androidx.recyclerview.widget.RecyclerView>

陌生属性介绍:

  • com.google.android.material.appbar.AppBarLayout 这个布局为了顶部导航栏的显示

  • app:layout_behavior="@string/appbar_scrolling_view_behavior" 为了顶部导航栏的显示,否则可能遮挡顶部导航栏;

  • app:layout_scrollFlags="scroll|enterAlways|snap"

scroll 作用:视图会随着内容滚动而一起滚动(向上滑时隐藏,向下滑时显示

enterAlways 作用: 向下滚动时立即显示视图(不需要滚动到顶部)

snap 作用: 滚动停止时自动"吸附"到最近的边界(要么完全显示,要么完全隐藏, 提供更流畅的用户体验

exitUntilCollapsed

作用:

  • 视图会滚动退出,但不会完全消失,而是停留在折叠状态
  • 必须scroll 标志一起使用
  • 需要定义 minHeight 属性指定折叠后的高度

我们通常是scroll和exitUntilCollapsed搭配使用!

SwipeRefreshLayout下拉刷新

依赖:

Android 复制代码
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'

xml文件:用法包在recyview外面表示刷新

implementation 复制代码
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
    android:layout_width="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    android:id = "@+id/swip"
    android:layout_height="match_parent">
    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/recy">

    </androidx.recyclerview.widget.RecyclerView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

在mainactivity

我把过程中难以理解的代码都标注出来啦

implementation 复制代码
SwipeRefreshLayout swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swip);
swipeRefreshLayout.setColorSchemeColors(R.color.black);//刷新的颜色
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
//每次刷新都会回调
    @Override
    public void onRefresh() {
    //经常得到数据之后,开始刷新,所以要在子线程中
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                //回到主线程中
                 runOnUiThread(new Runnable() {
                     @Override
                     public void run() {
                     //适配器刷新Notify
                         fruitadapots.notifyDataSetChanged();
                         //表示刷新事件结束,隐藏刷新进度条
                         swipeRefreshLayout.setRefreshing(false);
                     }
                 });

            }
        }).start();
    }
});

可折叠式表示栏

CoordinatorLayout

这是最外层的布局

然后你需要把你的用于折叠的照片,还有顶部导航栏,都设置在appbarlayout布局中

Android 复制代码
<com.google.android.material.appbar.AppBarLayout
    android:layout_height="250dp"
    android:layout_width="match_parent"
    android:id = "@+id/appbar">
    <com.google.android.material.appbar.CollapsingToolbarLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id = "@+id/coll"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:contentScrim="?attr/colorPrimary"
        app:layout_scrollFlags="snap|scroll|exitUntilCollapsed">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id = "@+id/iv"
            app:layout_collapseMode="parallax"
            android:scaleType="centerCrop"
            >

        </ImageView>
        <androidx.appcompat.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:id = "@+id/toolbar"
            app:layout_collapseMode="pin">

        </androidx.appcompat.widget.Toolbar>
    </com.google.android.material.appbar.CollapsingToolbarLayout>


 </com.google.android.material.appbar.AppBarLayout>

定义在CollapsingToolbarLayout

  • android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 代表设置一个主题

  • app:contentScrim="?attr/colorPrimary"代表这个布局在趋于折叠和折叠后的背景色

  • app:layout_scrollFlags="snap|scroll|exitUntilCollapsed"是appbarlayout中的属性

app:layout_collapseMode="parallax"表示折叠模式

有三种折叠模式:

Pin代表在折叠时永不消失,这里代表顶部导航栏,在折叠会回固定在顶部,通常和toolbar一起联合使用;

parallax模式(视差模式) 效果:控件以较慢速度 滚动,产生景深效果,我们还可以设置它的滚动的速度,更有感觉。

滚动的速度通过此来控制,数值越小,速度越慢: app:layout_collapseParallaxMultiplier="0.7"

默认模式(无模式) 效果:控件会随滚动完全消失,一般不设置,无折叠效果。

中间内容:经常是recycleview等等

Android 复制代码
<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:id = "@+id/card"
            app:cardCornerRadius="4dp"
            android:layout_margin="10dp"
            android:layout_height="wrap_content">
            <TextView
                android:layout_width="match_parent"
                android:id = "@+id/tv"
                android:layout_height="wrap_content">

            </TextView>
        </androidx.cardview.widget.CardView>
    </LinearLayout>

</androidx.core.widget.NestedScrollView>

app:layout_behavior="@string/appbar_scrolling_view_behavior" 这个属性搭配折叠效果;

NestedScrollView只能有一个直接子项布局

体会

编者对于在运用折叠式标题栏时有了一些新的体会

  1. 当你在某控件中设置parallax,即使折叠后仍然显示当前折叠时的背景,它不会因为折叠就直接消失显示pin模式下的控件,假如parallax设置的是背景图,那么背景图会和pin模式下的视图重叠,直接你看不到是因为通常toobar设置的是pin,toolbar的会挡住背景图,当你尝试把toolbar设置为透明时,你会发现有重合的问题qvq;
  2. 折叠后的高度由谁决定? AI中会解释道:由toolbar的高度决定,但你仔细看,你就会发现是由使用pin模式的控件 决定的,因为toolbar设置了pin,所以AI才会这样解释,当我们toolbar中的设置为100dp,那么折叠后的高度就是100dp了;此时又发现一个属性minheigh(控制 CollapsingToolbarLayout的最小可见高度),它也会影响高度,当它的高度大于PIN模式下控件的高度时,那么此时折叠后的高度就是minheight了,所以如果是minHeight比toolbar的高度要高,最后的结果就是上面是toolbar,折叠后仍然留有一部分高度是minheight的剩余高度;
  3. 可折叠模式写在coll布局的直接子view中;
  4. 当有很多空间都设置了pin模式,按照在xml文件中的排布在顶部依次显示;
  5. 可折叠式标题栏的核心:

最外层是coor的一个布局

中间套 appbarlayout负责响应滑动:android:fitsSystemWindows="true"这里这个属性true代表toolbar在状态栏下方,避免系统的窗口区域和布局重叠

里面是coll的一个布局:里面写两个重要属性:app:layout_scrollFlags,控制滚动的效果,app:contentScrim 折叠后显示的背景色(不写会出现透明/白色突兀问题);

在未折叠的布局中写属性控制折叠后的效果;

在内容区例如recycleview或者scroll中写app:layout_behavior="@string/appbar_scrolling_view_behavior"不然滑动不会带动 AppBar 折叠;

希望编者的理解对你有帮助哦!

悬浮按钮升级版

Android 复制代码
<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="16dp"
    app:layout_anchor="@id/appbar"
    app:layout_anchorGravity="bottom|end"
    >

</com.google.android.material.floatingactionbutton.FloatingActionButton>

app:layout_anchor="@id/appbar" 锚定谁

app:layout_anchorGravity="bottom|end" 锚定谁的哪里

anchor锚点

这么设置就会出现在标题栏的区域内

另外:

collapsingToolbarLayout.setTitle("i like");

这里也可以设置折叠后导航栏的标题搭配顶部导航栏的使用

本次分享到这里结束!

相关推荐
CYRUS_STUDIO21 小时前
一步步带你移植 FART 到 Android 10,实现自动化脱壳
android·java·逆向
CYRUS_STUDIO21 小时前
FART 主动调用组件深度解析:破解 ART 下函数抽取壳的终极武器
android·java·逆向
蓝倾9761 天前
淘宝/天猫店铺商品搜索API(taobao.item_search_shop)返回值详解
android·大数据·开发语言·python·开放api接口·淘宝开放平台
Propeller1 天前
【Android】LayoutInflater 控件实例化的桥梁类
android
国家二级编程爱好者1 天前
Android开机广播是有序还是无序?广播耗时原因是什么?
android
猿小蔡-Cool1 天前
Robolectric如何启动一个Activity
android·单元测试·rebolectric
Industio_触觉智能1 天前
瑞芯微RK3576开发板Android14三屏异显开发教程
android·开发板·瑞芯微·rk3576·多屏异显·rk3576j·三屏异显
AI视觉网奇1 天前
android adb调试 鸿蒙
android
NRatel1 天前
GooglePlay支付接入记录
android·游戏·unity·支付·googleplay
在下历飞雨1 天前
为啥选了Kuikly?2025“液态玻璃时代“六大跨端框架横向对比
android·harmonyos