Android【Toolbar、DrawerLayout 滑动菜单、 FloatingActionButton 悬浮按钮、Snackbar可交互提示、 Coordinator】

目录

1.Toolbar

1.1基本框架

1.2常用属性

1.3添加工具栏点击事件

1.4 溢出菜单

1.5 溢出菜单的点击事件

2 DrawerLayout 滑动菜单

2.1 基本框架

2.2 NavigationView

3 FloatingActionButton 悬浮按钮和可交互提示

3.1 基本框架

4 Snackbar

 4.1 基本框架

5 CoordinatorLayout

 5.1 基本框架

5.2 具体用法


1.Toolbar

还记得我们每次打开的程序的标题栏吗?那不是 toolbar 做的 , 那是 actionbar 做的 , Toolbar 可以说是 Actionbar 的升级版了。 Toolbar 不仅有 Actionbar 的所有功能 , 而且还更加灵活 .
在项目运行在虚拟机上时,都可以看见屏幕上方有一个栏目(下图红框圈出的部分),此为系统默认的
DarkActionBar ,可在 themes.xml 中查看。

去掉系统默认栏目的的方法:

以便于我们更灵活的编辑栏目内容,所以我们先将主题文件中的 DarkActionBar
改为 NoActionBar ,再次运行就可以发现顶端的栏目不见了

1.1基本框架

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/drawer"
    tools:context=".MainActivity">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/teal_200"
        app:navigationIcon="@drawable/ic_baseline_arrow_back_ios_24"
        app:title="Xisq's APP"
        app:titleTextColor="#2A91E3"
        app:subtitle="Android学习笔记"
        app:logo="@mipmap/logo"
        app:titleMarginStart="60dp"
        app:menu="@menu/toolbar_menu"/>
 
</androidx.drawerlayout.widget.DrawerLayout>
注意尖括号里不是普通的 Toolbar ,而是 androidx.appcompat.widget.Toolbar

1.2常用属性

属性
说明
app:navigationIcon
导航图标,一般情况下放回退按钮,点击退回上一个界面。
android:background
工具栏颜色
app:title
标题
app:titleTextColor
标题文字颜色
app:titleMarginStart
标题与左侧间距
app:subtitle
子标题
app:subtitleTextColor
子标题颜色
app:logo
工具栏 logo

1.3添加工具栏点击事件

Toolbar 加上 id ,我们就可以在 java 代码里获取并监听用户对工具栏图标的点击:
package com.hp.demo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;

import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.Snackbar;

public class MainActivity extends AppCompatActivity {
    private Toolbar toolbar;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        toolbar=findViewById(R.id.toolbar);
        

        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View view) {
                Toast.makeText(MainActivity.this, "返回", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

1.4溢出菜单

首先我们在 res menu 目录中创建一个 menu 资源文件 toolbar_menu.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/toolbar_user"
          android:title="用户"
          android:icon="@drawable/ic_baseline_perm_identity_24"
          app:showAsAction="never"/>
    <item android:id="@+id/toolbar_settings"
        android:title="设置"
        android:icon="@drawable/ic_baseline_settings_24"
        app:showAsAction="never"/>
    <item android:id="@+id/toolbar_add"
        android:title="其他"
        android:icon="@drawable/ic_baseline_add_24"
        app:showAsAction="never"/>
</menu>

1.5溢出菜单的点击事件

package com.hp.demo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;

import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.Snackbar;

public class MainActivity extends AppCompatActivity {
    private Toolbar toolbar;
    private DrawerLayout drawer;
    private NavigationView nv_nav;
    private FloatingActionButton fab;

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

        toolbar=findViewById(R.id.toolbar);

toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getGroupId()){
                    case 0:
                        Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                        break;
                    case 1:
                        Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                        break;
                    case 2:
                        Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                        break;
                }
                return false;
            }
        });
    }
}

2 DrawerLayout滑动菜单

2.1基本框架

布局 ---- 在这个布局中允许放入两个直接子控件
        屏幕中显示的内容
        滑动菜单中显示的内容
<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/drawer"
    tools:context=".MainActivity">
    <!--主屏幕中显示的内容-->
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/teal_200"
        app:navigationIcon="@drawable/ic_baseline_arrow_back_ios_24"
        app:title="Xisq's APP"
        app:titleTextColor="#2A91E3"
        app:subtitle="Android学习笔记"
        app:logo="@mipmap/logo"
        app:titleMarginStart="60dp"
        app:menu="@menu/toolbar_menu"/>

</FrameLayout>
    <!--滑动菜单中的内容--> <!--android:layout_gravity="start"指定了滑动菜单在屏幕的哪边
        start是指系统语言是从左到右读就在右边,反之就在左边-->
    <!--android:layout_gravity="start"必须要指定,指定了的就是滑动菜单-->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nv_nav"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/nav_item"
        app:headerLayout="@layout/nav_header"/>

</androidx.drawerlayout.widget.DrawerLayout>
点击 Toolbar 的图标弹出滑出菜单
package com.hp.demo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;

import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.Snackbar;

public class MainActivity extends AppCompatActivity {
    private Toolbar toolbar;
    private DrawerLayout drawer;

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

        toolbar=findViewById(R.id.toolbar);
        drawer=findViewById(R.id.drawer);
        
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View view) {
                drawer.openDrawer(GravityCompat.START);
            }
        });
    }
}

2.2 NavigationView

1.引入开源项目 CircleImageView, 可以轻松实现图片圆形化

dependencies {     
    ··· 
    implementation 'de.hdodenhof:circleimageview:3.0.1'     
}
2. 创建 menu ,作为滑动菜单 drawerlayout_men.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_1"
            android:title="朋友"
            android:icon="@drawable/ic_baseline_accessibility_24"/>
        <item android:id="@+id/nav_2"
            android:title="位置"
            android:icon="@drawable/ic_baseline_location_on_24"/>
        <item android:id="@+id/nav_3"
            android:title="记事本"
            android:icon="@drawable/ic_baseline_event_note_24"/>
    </group>
</menu>
3. layout 创建 headerLayout 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:background="#2196F3">
    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/civ_img"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:src="@mipmap/tou"
        android:layout_centerInParent="true"/>

    <TextView
        android:layout_below="@id/civ_img"
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="24sp"
        android:textColor="@color/white"
        android:layout_centerHorizontal="true"
        android:text="八嘎呀路" />
</RelativeLayout>
4. 修改基本框架
<com.google.android.material.navigation.NavigationView
        android:id="@+id/nv_nav"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/nav_item"
        app:headerLayout="@layout/nav_header"/>
5. 给滑动菜单设置点击事件
    private NavigationView nv_nav;
    ...
        nv_nav=findViewById(R.id.nv_nav);
     
nv_nav.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                if (item.getItemId()==R.id.nav_1){
                    Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                }else if (item.getItemId()==R.id.nav_2){
                    Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                }else if (item.getItemId()==R.id.nav_3){
                    Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                }
                return true;
            }
        });

3 FloatingActionButton悬浮按钮和可交互提示

3.1基本框架

   <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:backgroundTint="#FFEB3B"
            android:id="@+id/fab"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:elevation="8dp"
            android:src="@drawable/ic_baseline_done_outline_24"/>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>

4 Snackbar

Toast 提示是不是有点拉,可以用 Snackbar 提示。
但是 Toast 并非是不如 Snackbar ,他们有不同的应用场景。
        Toast只能告诉用户现在发生了什么事情,用户只能被动接收这件事情。
        Snackbar允许在提示中加入一个可交互按钮,当用户点击按钮的时候,就可以执行一            些额外的逻辑操作

 4.1基本框架

package com.hp.demo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;

import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.Snackbar;

public class MainActivity extends AppCompatActivity {

    private FloatingActionButton fab;

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

    
        fab=findViewById(R.id.fab);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view,"删除数据",Snackbar.LENGTH_SHORT).setAction("取消", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Toast.makeText(MainActivity.this, "数据已恢复", Toast.LENGTH_SHORT).show();
                    }
                }).show();
            }
        });

5 CoordinatorLayout

但是此时我们会发现 Snackbar 弹出的时候会把悬浮按钮遮住,但是这个问题我们可以用
CoordinatorLayout 解决
        CoordinatorLayout可以是一种加强版的 FrameLayout( 帧布局 )
        CoordinatorLayout会监听所有子控件的各种事件,并且自动帮助我们做出最为合理的            响应

 5.1基本框架

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/drawer"
    tools:context=".MainActivity">
    <!--主屏幕中显示的内容-->
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/teal_200"
        app:navigationIcon="@drawable/ic_baseline_arrow_back_ios_24"
        app:title="Xisq's APP"
        app:titleTextColor="#2A91E3"
        app:subtitle="Android学习笔记"
        app:logo="@mipmap/logo"
        app:titleMarginStart="60dp"
        app:menu="@menu/toolbar_menu"/>
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:backgroundTint="#FFEB3B"
            android:id="@+id/fab"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:elevation="8dp"
            android:src="@drawable/ic_baseline_done_outline_24"/>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>

</FrameLayout>
    <!--滑动菜单中的内容--> <!--android:layout_gravity="start"指定了滑动菜单在屏幕的哪边
        start是指系统语言是从左到右读就在右边,反之就在左边-->
    <!--android:layout_gravity="start"必须要指定,指定了的就是滑动菜单-->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nv_nav"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/nav_item"
        app:headerLayout="@layout/nav_header"/>

</androidx.drawerlayout.widget.DrawerLayout>

5.2具体用法

package com.hp.demo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;

import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.Snackbar;

public class MainActivity extends AppCompatActivity {
    private Toolbar toolbar;
    private DrawerLayout drawer;
    private NavigationView nv_nav;
    private FloatingActionButton fab;

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

        toolbar=findViewById(R.id.toolbar);
        drawer=findViewById(R.id.drawer);
        nv_nav=findViewById(R.id.nv_nav);
        fab=findViewById(R.id.fab);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view,"删除数据",Snackbar.LENGTH_SHORT).setAction("取消", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        Toast.makeText(MainActivity.this, "数据已恢复", Toast.LENGTH_SHORT).show();
                    }
                }).show();
            }
        });

        nv_nav.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                if (item.getItemId()==R.id.nav_1){
                    Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                }else if (item.getItemId()==R.id.nav_2){
                    Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                }else if (item.getItemId()==R.id.nav_3){
                    Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                }
                return true;
            }
        });

        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View view) {
                //Toast.makeText(MainActivity.this, "返回", Toast.LENGTH_SHORT).show();
                drawer.openDrawer(GravityCompat.START);
            }
        });
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getGroupId()){
                    case 0:
                        Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                        break;
                    case 1:
                        Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                        break;
                    case 2:
                        Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
                        break;
                }
                return false;
            }
        });
    }
}
其实就是把原本的 FrameLayout 布局改成了 androidx.coordinatorlayout.widget.CoordinatorLayout
行了
效果就是当点击悬浮按钮 Snackbar 出现的时候,悬浮按钮会上移来适应 Snackbar 是自己不会被
Snackbar 遮住
但是 Snackbar 并不是 CoordinatorLayout 的子控件,而是 DrawerLayout 的子控件 , 为什么也能成功
?
是因为 Snackbar.make() 传入了一个 view, 这是用来指定 Snackbar 是哪个 View 触发的,所以传入的是悬浮
按钮控件本身,悬浮按钮控件是 CoordinatorLayout 的子控件,所以能成功

版权声明:本文为weixin_63261150原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。