最佳的UI体验—— Material Design
1 什么是 Material Design
Material Design是由谷歌的设计工程师基于优秀的设计原则,结合丰富的创意和科学技术所发明的一套全新的界面设计语言,包含了视觉、运动、互动效果等特性。
2 Toolbar
虽然对于Toolbar你暂时应该还是比较陌生的,但是对于ActionBar,你就应该有点熟悉了,由于其设计的原因,被限定只能位于活动的顶部,从而不能实现一些 Material Design 的效果,因此官方已不建议使用 ActionBar 了,而推荐使用 Toolbar。
ActionBar来自哪里?其实这是根据项目中指定的主题来显示的,打开 AndroidManifest.xml文件
可以看到android:theme属性制定了一个AppTheme的主题
这个主题定义在哪里呢?
打开res/values/styles.xml文件,代码如下所示:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
这里定义了一个叫AppTheme的主题,然后指定它的parent主题是Theme.AppCompat.Light.DarkActionBar
。这个DarkActionBar是一个深色的ActionBar主题,之前所有项目中自带的ActionBar就是因为制定了这个主题才出现的。而我们现在准备使用Toolbar来替代ActionBar,需要指定一个不带ActionBar的主题。通常有Theme.AppCompat.Light.NoActionBar
和 Theme.AppCompat.NoActionBar这两个主题可选,其中没有light的表示为深色主题,它会将界面的主题颜色设成深色,陪衬颜色设成淡色。而含有light的表示为淡色主题,它会将界面的主题颜色设成淡色,陪衬颜色设置成深色。修改res/values/styles.xml文件:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
理解见图:
除了以上三个属性,我们还可以通过textColorPrimary、windowBackground和navigationBarColor等属性来控制更多位置的颜色。不过唯独colorAccent这个属性不只是用来指定这样一个按钮的颜色,而更多表达了一个强调的意思,比如一些控件的选中状态也会使用colorAccent的颜色。
接下来修改activity_main.xml文件的代码:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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">
<!-- 第2行使用xmlns:app指定一个新的命名空间
正式由于每个布局文件都使用xmlns:android来指定命名空间,我们才能一直使用android:id等写法
这里指定了xmlns:app,也就是说现在可以使用app:attribute这样的写法了
为了能让Toolbar单独使用深色主题,这里我们是用android:theme属性
为了能让弹出的菜单项指定为淡色主题,使用app:属性popupTheme
-->
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
/>
</FrameLayout>
接下来,学习Toolbar的一些常用功能,修改标题栏上显示的文字,AndroidManifest.xml文件中
添加一些action按钮,右击 res 目录→New→Directory,提前准备几张图片作为按钮的图标,并将他们放在drawable-xxhdpi目录下。创建一个 menu 文件夹。然后右击 menu 文件夹→New→Menu resource file,创建一个toolbar.xml 文件:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/backup"
android:icon="@mipmap/ic_backup"
android:title="Backup"
app:showAsAction="always"
/>
<item
android:id="@+id/delete"
android:icon="@mipmap/ic_delete"
android:title="Delete"
app:showAsAction="ifRoom"
/>
<item
android:id="@+id/settings"
android:icon="@mipmap/ic_setting"
android:title="Settings"
app:showAsAction="never"
/>
</menu>
通过标签定义action按钮,android:id 用于指定按钮的id;android:icon 用于指定按钮的图标;android:title 用于指定按钮上的文字
app:showAsAction来设置按钮的显示i位 置:always表示永远显示在Toolbar中,如果屏幕空间不够则不显示;idfRoom表示屏幕空间足够的情况下显示在Toolbar中,不够则显示在菜单栏;never表示永远显示在菜单当中
注意: Toolbar中的action按钮只会显示图标,菜单中的action按钮只会显示文字
修改MainActivity中的代码:
package com.example.wanghui.materialtest;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar1 = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar1);
}
/**
* 在onCreateOptionsMenu()方法中加载toolbar.xml文件
* */
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar,menu);
return true;
}
/**
* 在onOptionsItemSelected()方法中处理各个按钮的点击事件
* */
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.backup:
Toast.makeText(this,"You clicked Backup",Toast.LENGTH_SHORT).show();
break;
case R.id.delete:
Toast.makeText(this,"You clicked Delete",Toast.LENGTH_SHORT).show();
break;
case R.id.settings:
Toast.makeText(this,"You clicked Settings",Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
}
测试结果:
3 滑动菜单
3.1 DrawerLayout
借助DrawerLayout控件实现滑动菜单,首先它是一个布局,在布局中允许放入两个直接子控件,第一个子控件施主屏幕中显示的内容,第二个子控件是滑动菜单中显示的内容。修改activity_main.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start"
tools:context=".MainActivity"
>
<FrameLayout 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">
<!-- 第2行使用xmlns:app指定一个新的命名空间
正式由于每个布局文件都使用xmlns:android来指定命名空间,我们才能一直使用android:id等写法
这里指定了xmlns:app,也就是说现在可以使用app:attribute这样的写法了
为了能让Toolbar单独使用深色主题,这里我们是用android:theme属性
为了能让弹出的菜单项指定为淡色主题,使用app:属性popupTheme
-->
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
/>
</FrameLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:text="This is menu"
android:background="#FFF"
/>
</androidx.drawerlayout.widget.DrawerLayout>
最外层的控件使用DrawerLayout,DrawerLayout放置了两个直接子控件,一个是TextView,用于作为滑动菜单中显示的内容,其中需要注意的是layout_gravity属性必须指定,因为我们需要告诉DrawerLayout滑动菜单是在屏幕的左边还是右边,left左,right右,这里我们指定了start表示会根据系统语言进行判断;另一个是FrameLayout,用于作为主屏幕中显示的内容。
防止一些用户不知道屏幕的左侧边缘是可以拖动的,准备一张ic_menu.png,放在drawable-xxhdpi目录下,修改MainActivity中的代码,如下所示:
public class MainActivity extends AppCompatActivity {
private DrawerLayout drawerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar1 = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar1);
//获得DrawerLayout实例
drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
//调用getSupportActionBar()方法,获得ActionBar实例
ActionBar actionBar = getSupportActionBar();
if(actionBar!=null){
//设置导航键
actionBar.setDisplayHomeAsUpEnabled(true);
//设置导航键的图片
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
}
}
/**
* 在onCreateOptionsMenu()方法中加载toolbar.xml文件
* */
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar,menu);
return true;
}
/**
* 在onOptionsItemSelected()方法中处理各个按钮的点击事件
* */
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
//HomeAsUp按钮id永远是android.R.id.home
case android.R.id.home:
Toast.makeText(this,"You clicked Home",Toast.LENGTH_SHORT).show();
//调用DrawerLayout的openDrawer()方法将滑动菜单显示出来
drawerLayout.openDrawer(GravityCompat.START);
break;
case R.id.backup:
Toast.makeText(this,"You clicked Backup",Toast.LENGTH_SHORT).show();
// drawerLayout.openDrawer(GravityCompat.START);
break;
case R.id.delete:
Toast.makeText(this,"You clicked Delete",Toast.LENGTH_SHORT).show();
break;
case R.id.settings:
Toast.makeText(this,"You clicked Settings",Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
}
3.2 NavigationView
在滑动菜单页面定制任意布局,NavigationView是Design Support库中提供的一个控件。
①首先,引入依赖库app/build.gradle文件中:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
......
implementation 'com.google.android.material:material:1.0.0'
//circleimageview开源项目,可以轻松实现图片圆形化的功能
implementation 'de.hdodenhof:circleimageview:3.0.0'
}
②准备menu和headerLayout:menu是用来在NavigationView中显示具体菜单项的,headerLayout是用来NavigationView中显示头部布局的。
准备menu:将事先找好的图标放在drawable-xxhdpi目录下,右击menu文件夹/New/Menu resource file,创建一个nav_menu.xml文件
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_call"
android:icon="@drawable/nav_call"
android:title="Call"
/>
<item
android:id="@+id/nav_friends"
android:icon="@drawable/nav_friends"
android:title="Friends"
/>
<item
android:id="@+id/nav_location"
android:icon="@drawable/nav_location"
android:title="Location"
/>
<item
android:id="@+id/nav_mail"
android:icon="@drawable/nav_mail"
android:title="Mail"
/>
<item
android:id="@+id/nav_task"
android:icon="@drawable/nav_task"
android:title="Tasks"
/>
</group>
</menu>
首先在
准备headerLayout: 这是一个可随意定制的布局,在此,我们就在headerLayout中放置头像,用户名和邮箱地址3项内容
准备一个图片(最好正方形),放在drawable-xxhdpi目录下,右击layout文件夹/New/Layout resource file,创建一个nav_header.xml文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="180dp"
android:padding="10dp"
android:background="?attr/colorPrimary">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/icon_image"
android:layout_width="70dp"
android:layout_height="70dp"
android:src="@drawable/icon_image"
android:layout_centerInParent="true"
/>
<TextView
android:id="@+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="heretoforeu@163.com"
android:textColor="#FFF"
android:textSize="14sp"
/>
<TextView
android:id="@+id/mail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/username"
android:text="Wang Hui"
android:textColor="#FFF"
android:textSize="14sp"
/>
</RelativeLayout>
布局文件的最外层是一个RelativeLayout
,将它的宽度设为match_parent,高度设为180dp,这是NavigationView比较适合的高度,然后指定它的背景色为colorPrimary。
RelativeLayout放置3个控件,CircleImageView是一个用于将图片图形化的控件,基本用法和ImageView大同小异,这里指定了一个而图片作为头像,然后设置为居中显示,另外两个TextView分别用于显示用户名和邮箱地址。android:layout_above="@id/username" --将控件置于给定ID控件之上
android:layout_alignParentBottom=“true” --将控件的底边缘和父控件的底边缘对齐
③修改activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start"
tools:context=".MainActivity"
>
<FrameLayout 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">
<!-- 第2行使用xmlns:app指定一个新的命名空间
正式由于每个布局文件都使用xmlns:android来指定命名空间,我们才能一直使用android:id等写法
这里指定了xmlns:app,也就是说现在可以使用app:attribute这样的写法了
为了能让Toolbar单独使用深色主题,这里我们是用android:theme属性
为了能让弹出的菜单项指定为淡色主题,使用app:属性popupTheme
-->
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
/>
</FrameLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/nav_menu"
app:headerLayout="@layout/nav_header"
/>
</androidx.drawerlayout.widget.DrawerLayout>
这里将之前的TextView换成了NavigationView。app:menu和app:headerLayout属性将我们准备好的menu和headerLayout设置进去,这样NavigationView就定义完成了。
④修改MainActivity.java文件
在这里插入代码片
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar1 = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar1);
drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
//获取NavigationView的实例
NavigationView navigationView = (NavigationView)findViewById(R.id.nav_view);
ActionBar actionBar = getSupportActionBar();
if(actionBar!=null){
//设置导航键
actionBar.setDisplayHomeAsUpEnabled(true);
//设置导航键的图片
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
}
//调用setCheckedItem()方法将Call菜单设置为默认选中
navigationView.setCheckedItem(R.id.nav_call);
//调用setNavigationItemSelectedListener()方法来设置一个菜单项选中事件的监听器
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
//当用户点击任意菜单项时,就会回调onNavigationItemSelected()方法中
//我们可以在这个方法中写相应的逻辑处理
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
//这里仅仅调用drawerLayout.closeDrawers()方法将滑动菜单关闭
drawerLayout.closeDrawers();
return true;
}
});
}
测试结果:
4 悬浮按钮和可交互提示
立体设计是 Material Design 中一条非常重要的思想,也就是说,按照Material Design的理念,应用程序的界面不仅仅是一个平面,而应该是有立体效果的。
4.1 FloatingActionButton
FloatingActionButton 是 Design Support 库中提供的一个控件,可以比较轻松地实现悬浮按钮地效果。它默认使用 colorAccent 作为按钮的颜色。
下面开始具体实现。首先仍需要准备一个图标,放在drawable-xxhdpi目录下,然后修改activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start"
tools:context=".MainActivity"
>
<FrameLayout 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">
<!-- 第2行使用xmlns:app指定一个新的命名空间
正式由于每个布局文件都使用xmlns:android来指定命名空间,我们才能一直使用android:id等写法
这里指定了xmlns:app,也就是说现在可以使用app:attribute这样的写法了
为了能让Toolbar单独使用深色主题,这里我们是用android:theme属性
为了能让弹出的菜单项指定为淡色主题,使用app:属性popupTheme
-->
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/ic_done"
/>
</FrameLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/nav_menu"
app:headerLayout="@layout/nav_header"
/>
</androidx.drawerlayout.widget.DrawerLayout>
可以看到,这里在主屏幕布局中加入FloatingActionButton。layout_gravity="bottom|end"表示指定该控件放置于屏幕的右下角
ayout_margin="16dp"表示给控件四周留点边距。
我们仔细观察,会发现悬浮按钮得下面有一点点阴影,说到悬浮,我们可以指定悬浮高度:
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/ic_done"
app:elevation="8dp"
/>
接下来,我们来处理FloatingActionButton得点击事件,修改MainActivity.java文件
public class MainActivity extends AppCompatActivity {
private DrawerLayout drawerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar1 = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar1);
drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
//获取NavigationView的实例
NavigationView navigationView = (NavigationView)findViewById(R.id.nav_view);
ActionBar actionBar = getSupportActionBar();
if(actionBar!=null){
//设置导航键
actionBar.setDisplayHomeAsUpEnabled(true);
//设置导航键的图片
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
}
//调用setCheckedItem()方法将Call菜单设置为默认选中
navigationView.setCheckedItem(R.id.nav_call);
//调用setNavigationItemSelectedListener()方法来设置一个菜单项选中事件的监听器
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
//当用户点击任意菜单项时,就会回调onNavigationItemSelected()方法中
//我们可以在这个方法中写相应的逻辑处理
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
//这里仅仅调用drawerLayout.closeDrawers()方法将滑动菜单关闭
drawerLayout.closeDrawers();
return true;
}
});
//获取FloatingActionButton实例
FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"Fab clicked ",Toast.LENGTH_SHORT).show();
}
});
}
测试结果:
4.2 Snackbar
Snackbar 并不是Toast的替代品,它们两者之间有着不同的应用场景。Toast的作用是告诉用户现在发生了什么事情,但同时用户只能被动接受这个事情,因为没有什么办法能让用户进行选择。而Snackbar则在这方面进行了扩展,它允许在提示当中加入一个可交互按钮,当用户点击按钮的时候可以执行一些额外的逻辑操作。
Snackbar的用法与Toast类似,只不过可以额外增加一个按钮的点击事件,修改MainActivity中的代码:
public class MainActivity extends AppCompatActivity {
private DrawerLayout drawerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar1 = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar1);
drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
//获取NavigationView的实例
NavigationView navigationView = (NavigationView)findViewById(R.id.nav_view);
ActionBar actionBar = getSupportActionBar();
if(actionBar!=null){
//设置导航键
actionBar.setDisplayHomeAsUpEnabled(true);
//设置导航键的图片
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
}
//调用setCheckedItem()方法将Call菜单设置为默认选中
navigationView.setCheckedItem(R.id.nav_call);
//调用setNavigationItemSelectedListener()方法来设置一个菜单项选中事件的监听器
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
//当用户点击任意菜单项时,就会回调onNavigationItemSelected()方法中
//我们可以在这个方法中写相应的逻辑处理
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
//这里仅仅调用drawerLayout.closeDrawers()方法将滑动菜单关闭
drawerLayout.closeDrawers();
return true;
}
});
//获取FloatingActionButton实例
FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/**
* 调用了 Snackbar.make()方法来创建一个 Snackbar对象
* make()方法的第一个参数需传入一个View,只要是当前界面布局的任意一个View都可以
* Snackbar会使用这个View来自动查找最外层布局,用于展示 Snackbar
* make()方法的第二个参数就是Snackbar中显示的内容,第三个参数时Snackbar显示的时长
*
* 接着调用了setAction()方法来设置一个动作,使得Snackbar不仅仅是一个提示,而是可以和用户进行交互的
* 简单起见,这里弹出一个Toast
*/
Snackbar.make(v,"Data delete",Snackbar.LENGTH_SHORT)
.setAction("Undo", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"Fab clicked ",Toast.LENGTH_SHORT).show();
}
}).show();
}
});
}
测试结果:
4.3 CoordinatorLayout
CoordinatorLayout 是 Design Support 库提供的一个加强版的 FrameLayout 布局,它可以监听其所有子控件的各种事件,然后自动帮我们做出最为合理的响应。
修改布局如下:
把第一个主页布局控件FrameLayout 替换成 androidx.coordinatorlayout.widget.CoordinatorLayout
可以看到悬浮按钮自动向上偏移Snackbar的同等高度,确保不会被遮挡