Android studio:顶部导航栏Toolbar
主流APP在顶部都配有导航栏,在 Android 中,ActionBar 是默认启用的,它是位于屏幕顶部的一个工具栏,用来放置应用的标题、导航和操纵菜单。假如你想使用自界说的 Toolbar 来更换 ActionBar,应该先关闭它。可以通过设置 NoActionBar 主题或者在代码中手动潜伏 ActionBar 来实现。
一、关闭ActionBar
在 styles.xml 中,继承 Theme.AppCompat.Light.NoActionBar 或Theme.MaterialComponents.DayNight.NoActionBar 来关闭默认的 ActionBar。
https://i-blog.csdnimg.cn/direct/41e7dc5af3ae4291bcedf77d32b9c8f0.png
<resources>
<style name="AppCompatTheme" parent="Theme.AppCompat.Light.NoActionBar">
</style>
</resources>
然后,在 AndroidManifest.xml 中应用该主题。
假设你想应用这个主题到整个应用,你可以在 AndroidManifest.xml 中设置它:
<application
android:theme="@style/AppCompatTheme">
...
</application>
或者你也可以在单个活动(Activity)中使用:
<activity
android:name=".MainActivity"
android:theme="@style/AppCompatTheme">
</activity>
二、创建活动页面的XML文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/tl_head"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="17sp"
android:text="该页面演示工具栏功能" />
</LinearLayout>
</LinearLayout> 在 Android 中,ToolBar 是一个继承自 ViewGroup 的类。ViewGroup 是一个视图容器,它可以包含其他视图(包罗其他 View 或 ViewGroup),而 ToolBar 作为一个 ViewGroup,也具有这种容器的特性。ToolBar 本质上是一个布局容器,它可以包含多个视图组件(比如按钮、文本、图标等)。这些组件可以通过布局参数举行管理和分列。
三、创建活动页面
public class ToolbarActivity extends AppCompatActivity {
private final static String TAG = "ToolbarActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_toolbar);
Toolbar tl_head = findViewById(R.id.tl_head); // 从布局文件中获取名叫tl_head的工具栏
tl_head.setTitle("工具栏页面"); // 设置工具栏的标题文本
setSupportActionBar(tl_head); // 使用tl_head替换系统自带的ActionBar
tl_head.setTitleTextColor(Color.RED); // 设置工具栏的标题文字颜色
tl_head.setLogo(R.drawable.ic_app); // 设置工具栏的标志图片
tl_head.setSubtitle("Toolbar"); // 设置工具栏的副标题文本
tl_head.setSubtitleTextColor(Color.YELLOW); // 设置工具栏的副标题文字颜色
tl_head.setBackgroundResource(R.color.blue_light); // 设置工具栏的背景
tl_head.setNavigationIcon(R.drawable.ic_back); // 设置工具栏左边的导航图标
// 给tl_head设置导航图标的点击监听器
// setNavigationOnClickListener必须放到setSupportActionBar之后,不然不起作用
tl_head.setNavigationOnClickListener(view -> {
finish(); // 结束当前页面
});
}
}
此中setSupportActionBar是用自界说工具栏代替系统自带的顶部导航栏ActionBar,之后可以为顶部导航栏设置诸多属性。
https://i-blog.csdnimg.cn/direct/5ca2818ce32a4aa085f4bbd1d6160623.png
下面这段代码是在设置 ToolBar 的导航按钮点击事件监听器。具体来看,代码的作用是:当用户点击 ToolBar 上的导航按钮(通常是左上角的返回按钮)时,执行 finish() 方法来结束当前活动(即关闭当前页面)。
tl_head.setNavigationOnClickListener(view -> {
finish();
}); 半屏效果图如下:
https://i-blog.csdnimg.cn/direct/47fe46aac6084eb08d007dfb5b7c621a.png
四、溢出菜单
当导航栏的内容不敷放,就需要设置溢出菜单,比方下面的三个点图标,点击之后弹出窗口。
https://i-blog.csdnimg.cn/direct/0dff80573b134e159eaee6a0b9df6f4c.png
1.活动页面XML代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/tl_head"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/blue_light"
app:navigationIcon="@drawable/ic_back" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="17sp"
android:text="该页面演示溢出菜单功能" />
</LinearLayout>
</LinearLayout> app:navigationIcon="@drawable/ic_back" 这一属性的作用是为 ToolBar 设置一个导航按钮的图标,通常位于 ToolBar 左侧,常见用途是返回按钮。
https://i-blog.csdnimg.cn/direct/f7ef516e78e74c478ee9d60d728e3874.png
2.创建菜单文件:
https://i-blog.csdnimg.cn/direct/41160f956588492296678c8a2c1e7967.png
下面是包含3个菜单项的溢出菜单XML:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/menu_refresh"
android:icon="@drawable/ic_refresh"
app:showAsAction="ifRoom"
android:title="刷新"/>
<item
android:id="@+id/menu_about"
android:icon="@drawable/ic_about"
app:showAsAction="never"
android:title="关于"/>
<item
android:id="@+id/menu_quit"
android:icon="@drawable/ic_quit"
app:showAsAction="never"
android:title="退出"/>
</menu>
<menu> 标签在 Android 开辟中主要用于创建菜单,常用于 ToolBar、PopupMenu、ContextMenu、BottomNavigationView 等。
xmlns:app="http://schemas.android.com/apk/res-auto" 是 XML 命名空间声明,它的作用是支持 Android 自界说属性(比如 app:showAsAction、app:navigationIcon 等)。
在 Android XML 布局文件中,某些自界说属性不是尺度的 Android 属性(即 android: 开头的),这些自界说属性通常来自 AndroidX 组件、Material Design 组件或第三方库,xmlns:app="http://schemas.android.com/apk/res-auto" 答应你在 XML 中使用这些库提供的属性。
这里的app:showAsAction有多种取值,比方取never,则该菜单项肯定不在导航栏表现。
https://i-blog.csdnimg.cn/direct/ac08d5d19b3e4cb6b1fbce4fd039d072.png
https://i-blog.csdnimg.cn/direct/a38358ab4a3c424583371d87c72b535e.png
因此刷新这个选项会表现在导航栏上,而关于、推出则会放入溢出菜单列表。
3.下面是在活动代码中增加对菜单的处置处罚逻辑。
@SuppressLint("SetTextI18n")
public class OverflowMenuActivity extends AppCompatActivity {
private TextView tv_desc; // 声明一个文本视图对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_overflow_menu);
Toolbar tl_head = findViewById(R.id.tl_head); // 从布局文件中获取名叫tl_head的工具栏
tl_head.setTitle("溢出菜单页面"); // 设置工具栏的标题文字
setSupportActionBar(tl_head); // 使用tl_head替换系统自带的ActionBar
tv_desc = findViewById(R.id.tv_desc);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// 从menu_overflow.xml中构建菜单界面布局
getMenuInflater().inflate(R.menu.menu_overflow, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId(); // 获取菜单项的编号
if (id == android.R.id.home) { // 点击了工具栏左边的返回箭头
finish(); // 结束当前页面
} else if (id == R.id.menu_refresh) { // 点击了刷新图标
tv_desc.setText("当前刷新时间: " + DateUtil.getNowTime());
} else if (id == R.id.menu_about) { // 点击了关于菜单项
Toast.makeText(this, "这个是工具栏的演示demo", Toast.LENGTH_LONG).show();
} else if (id == R.id.menu_quit) { // 点击了退出菜单项
finish(); // 结束当前页面
}
return super.onOptionsItemSelected(item);
}
} @SuppressLint("SetTextI18n") 是 Android Lint 的一个注解,用于抑制 SetTextI18n 干系的 Lint 查抄警告。在 Android 开辟中,TextView.setText() 直接拼接字符串时,Lint 会警告你应该使用国际化(i18n)资源,而不是硬编码的字符串。假如你确定这个警告可以忽略,就可以使用 @SuppressLint("SetTextI18n") 来关闭它。
比方:textView.setText("用户名:" + username);Lint 会报 "Hardcoded text should use @StringRes instead"(硬编码文本应该使用 strings.xml) 的警告:警告缘故原由:
直接使用 "用户名:" 如许的硬编码字符串,不利于国际化(i18n),应该使用 strings.xml 界说文本。
onCreate中的代码就是上面提到的用自界说的顶部导航栏代替系统自有的导航栏。
着重看下面的代码:它的主要功能是加载 XML 菜单文件并将其表现在 Toolbar 或 ActionBar 上。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// 从menu_overflow.xml中构建菜单界面布局
getMenuInflater().inflate(R.menu.menu_overflow, menu);
return true;
}
onCreateOptionsMenu(Menu menu) 方法原本属于 Activity 类,它是 Android Activity 生命周期的一部门,用于创建选项菜单(Options Menu)。
你需要重写(@Override)这个方法,因为:
[*]默认的 onCreateOptionsMenu() 方法是空实现的,假如你不重写它,菜单不会表现。
[*]你需要告诉系统如何创建菜单,并指定菜单的内容(即加载 menu.xml)。
3.1为什么要使用 Menu 而不是直接在 XML 里写按钮?
Menu 是 专门用于 Toolbar 或 ActionBar 的菜单项,系统会主动管理它们:
[*]菜单项会主动适应设备屏幕大小(小屏幕时会潜伏到 ... 溢出菜单)。
[*]可以动态管理菜单项(比如在不同页面表现不同的菜单)。
[*]有同一的交互逻辑(长按、点击、图标表现规则)。
假如你直接在 activity_main.xml 里写 <Button>,它只是普通按钮,不会主动适配 Toolbar,体验很糟糕。
https://i-blog.csdnimg.cn/direct/e14c5dd661944554acc7718ef2f654e2.png
3.2 如何确保菜单项表现在顶部导航栏:
setSupportActionBar(tl_head) 方法的作用是设置自界说的 Toolbar 作为该 Activity 的操纵栏(ActionBar)。在设置了自界说的 Toolbar 后,onCreateOptionsMenu 方法中的菜单项(通过 getMenuInflater().inflate(R.menu.menu_overflow, menu) 加载)会主动表现在这个 Toolbar 上,而不是其他地方。
这个举动是由 AppCompatActivity 提供的,它会在 Toolbar 上表现菜单项,前提是调用了 setSupportActionBar(tl_head) 来更换默认的 ActionBar。
因此,确保菜单项表现在顶部导航栏的关键步骤是:
[*]使用 Toolbar 更换默认的 ActionBar:setSupportActionBar(tl_head)。
[*]在 onCreateOptionsMenu 中加载菜单项:getMenuInflater().inflate(R.menu.menu_overflow, menu)。
3.3 点击事件
int id = item.getItemId(); // 获取菜单项的编号。item.getItemId() 返回的是被点击的菜单项的ID。通过这个ID,后续的 if 语句可以判断是哪一个菜单项被点击了。
最后,调用 super.onOptionsItemSelected(item),如许可以让父类继承处置处罚其他未被处置处罚的菜单项,确保系统的其他举动不会受到影响。
3.4 为什么没有写监听器,仍然能通过点击事件判断 ID:
onOptionsItemSelected 方法是用于处置处罚用户点击菜单项时的事件处置处罚。当用户点击菜单项时,系统会主动调用 onOptionsItemSelected 方法,并传递一个 MenuItem 对象。在 onOptionsItemSelected 方法中,你可以通过 item.getItemId() 获取到被点击的菜单项的 ID,从而判断用户点击了哪个菜单项,并执行对应的操纵。
不需要显式地为每个菜单项写监听器,因为:
[*]onOptionsItemSelected 方法已经充当了菜单项的事件监听器。
[*]系统会主动辨认哪个菜单项被点击,并通过 item.getItemId() 将菜单项的 ID 传递给 onOptionsItemSelected 方法。
所以,你在 onOptionsItemSelected 中通过判断 item.getItemId() 来执行特定操纵,系统已经为你处置处罚了菜单项的点击事件,免去了为每个菜单项单独添加监听器的需求。
代码流程概述:
[*] 在 onCreate 中:
[*]获取并设置工具栏。
[*]使用 setSupportActionBar(tl_head) 来更换默认的 ActionBar,如许就会表现你自界说的工具栏。
[*] 在 onCreateOptionsMenu 中:
[*]通过 getMenuInflater().inflate(R.menu.menu_overflow, menu) 将 menu_overflow.xml 中的菜单项加载到工具栏上,确保菜单项表现在顶部。
[*] 在 onOptionsItemSelected 中:
[*]监听菜单项的点击事件,通过 item.getItemId() 判断点击了哪个菜单项,然后执行相应操纵。
效果:
https://i-blog.csdnimg.cn/direct/60ad9184bce04c2e80d96df16985f677.png
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]