Android学习羁绊之Material Design

Posted 姓chen的大键哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android学习羁绊之Material Design相关的知识,希望对你有一定的参考价值。

Material Design是由谷歌的设计工程师们基于传统优秀的设计原则,结合丰富的创意和科学技术所发明的一套全新的界面设计语言,包含了视觉、运动、互动效果等特性,Material Design最大的特点就是好看,它的出现使得android首次在UI方面超越了ios

Material Design是一个推荐的设计规范,主要面向UI设计人员,而不是面向开发者。Google在2015年的Google I/O大会上推出了一个Design Support库,这个库将Material Design中最具代表性的一些控件和效果进行了封装,使开发者在即使不了解Material Design的情况下也能非常轻松地将自己的应用Material化。

Design Support库中常用的控件如下:

文章目录

Toolbar

Toolbar不仅继承了ActionBar的所有功能,而且灵活性很高,可以配合其他控件来完成一些Material Design的效果

新建项目时都会默认使用ActionBar,而这个ActionBar来自项目指定的主题,要使用Toolbar,则需要指定一个不带ActionBar的主题,在 res/values/styles.xml 文件中修改:

<resources>

    <!-- Base application theme. -->
    <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>

</resources>

parent主题是Theme.AppCompat.Light.DarkActionBar,这是一个深色的ActionBar主题,将其指定成Theme.AppCompat.NoActionBar(深色主题,界面的主体颜色为深色)或Theme.AppCompat.Light.NoActionBar(淡色主题,界面的主体颜色为淡色,陪衬颜色为深色),即可获得不带ActionBar的主题。

可以通过重写属性来实现界面颜色的定制,在<style>标签中添加要重写的属性,属性值以及每个属性所指代的区域如下图所示:

colorAccent不只是用来指定这样一个按钮的颜色,而是更多表达了一个强调的意思,例如一些控件的选中状态也会使用colorAccent的颜色

向布局文件中添加如下代码即可引入Toolbar:

<!--support库-->
<android.support.v7.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" />
	
<!--androidx库-->
<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" />
  • android:theme:指定Toolbar主题
  • app:popupTheme:指定Toolbar中弹出菜单的主题

由于Material Design是在Android 5.0系统中才出现的,而很多的Material属性在5.0之前的系统
中并不存在,那么为了能够兼容之前的老系统,需要指定xmlns:app,使用app:attribute的形式进行属性设置。
在Activity中添加如下代码可以使Toolbar的外观和功能与ActionBar一致

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

可以向Toolbar中添加各种action按钮,同时,向可以通过设置app:showAsAction属性来指定按钮的显示位置

<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="@drawable/ic_backup"
		android:title="Backup"
		app:showAsAction="always" />
</menu>

app:showAsAction可选值有如下几个:

  • always:永远显示在Toolbar中,如果屏幕空间不够则不显示
  • ifRoom:屏幕空间足够的情况下显示在Toolbar中,不够的话就显示在菜单当中
  • never:永远显示在菜单当中。

Toolbar中的action按钮只会显示图标,菜单中的action按钮只会显示文字

滑动菜单

所谓的滑动菜单就是将一些菜单选项隐藏起来,而不是放置在主屏幕上,然后可以通过滑动的方式将菜单显示出来。这种方式既节省了屏幕空间,又实现了非常好的动画效果

DrawerLayout

DrawerLayout是一个布局,在布局中允许放入两个直接子控件,第一个子控件是主屏幕中显示的内容,第二个子控件是滑动菜单中显示的内容。

<!--support库-->
<android.support.v4.widget.DrawerLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res-auto"
	android:id="@+id/drawer_layout"
	android:layout_width="match_parent"
	android:layout_height="match_parent">
	<FrameLayout
		android:layout_width="match_parent"
		android:layout_height="match_parent">
		···
	</FrameLayout>
	<TextView
		android:layout_width="match_parent"
		android:layout_height="match_parent"
		android:layout_gravity="start"
		android:text="This is menu"
		android:textSize="30sp"
		android:background="#FFF" />
</android.support.v4.widget.DrawerLayout>

<!--androidx库-->
<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">

    <FrameLayout
		android:layout_width="match_parent"
		android:layout_height="match_parent">
		···
	</FrameLayout>

	<TextView
		android:layout_width="match_parent"
		android:layout_height="match_parent"
		android:layout_gravity="start"
		android:text="This is menu"
		android:textSize="30sp"
		android:background="#FFF" />

</androidx.drawerlayout.widget.DrawerLayout>

在第二个子控件中,layout_gravity 这个属性必须指定,可选值如下:

  • left:滑动菜单在左边
  • right:滑动菜单在右边
  • start:根据系统语言,决定滑动菜单位置(系统语言是从左往右的,比如英语、汉语,滑动菜单就在左边,如果系统语言是从右往左的,比如阿拉伯语,滑动菜单就在右边)

一般来说,用户并不知道这个滑动菜单的存在,需要Toolbar最左边加入一个导航按钮,这样就可以用两种方式来打开滑动菜单

public class MainActivity extends AppCompatActivity 
    private DrawerLayout drawerLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) 
			//让导航按钮显示
            actionBar.setDisplayHomeAsUpEnabled(true);
			//设置导航按钮图标
            actionBar.setHomeAsUpIndicator(R.mipmap.ic_launcher);
        
    

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) 
        switch (item.getItemId()) 
            case android.R.id.home:
                drawerLayout.openDrawer(GravityCompat.START);
                break;
            default:
        
        return true;
    

  • setDisplayHomeAsUpEnabled():使导航按钮显示
  • setHomeAsUpIndicator():设置导航图标的图标
  • openDrawer():显示滑动菜单,传入Gravity参数,一般设置与XML中定义一致
  • Toolbar最左侧的按钮叫做HomeAsUp按钮,默认是一个返回箭头,含义是返回上一个活动
  • HomeAsUp按钮的id为android.R.id.home

NavigationView

NavigationView(导航视图)通常与DrawerLayout(抽屉布局)结合使用,实现了良好的侧滑交互体验。

使用NavigationView需要在build.gradle文件中引入相应的库

//androidx库
dependencies 
	...
    implementation 'com.google.android.material:material:1.1.0'


//support库
dependencies 
	...
	compile 'com.android.support:design:24.2.1'

在布局文件中引入如下代码即可使用

<!--androidx库-->
<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:headerLayout="@layout/nav_header"
	app:menu="@menu/nav_menu" />

<!--support库-->
<android.support.design.widget.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 "/>
  • app:menu:向NavigationView添加菜单项布局文件
  • app:headerLayout:向NavigationView添加头部布局文件,例如头像和名称的布局

NavigationView还可以添加菜单项的点击事件

NavigationView navView = (NavigationView) findViewById(R.id.nav_view);
navView.setCheckedItem(R.id.nav_call);
navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() 
	@Override
	public boolean onNavigationItemSelected(MenuItem item) 
		//相关逻辑
	
);

悬浮按钮与可交互提示

FloatingActionButton

FloatingActionButton能够轻松实现悬浮按钮的效果
在布局文件中引入如下代码即可

<!--androidx库-->
<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"
	app:elevation="8dp"
	app:layout_anchor="@id/appBar"
	android:src="@mipmap/ic_launcher"/>

<!--support库-->
<android.support.design.widget.FloatingActionButton
	android:id="@+id/fab"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:layout_gravity="bottom|end"
	android:layout_margin="16dp"
	app:elevation="8dp"
	app:layout_anchor="@id/appBar"
	android:src="@drawable/ic_done" />
  • app:elevation:指定一个高度值,高度值越大,投影范围也越大,投影效果越淡;高度值越小,投影范围也越小,投影效果越浓
  • app:layout_anchor:指定一个锚点,表示悬浮按钮出现的区域

效果图如下:

FloatingActionButton同样可以设置监听事件,与普通按钮并没有差别

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() 
	@Override
	public void onClick(View v) 
		//相关逻辑
	
);

Snackbar

Snackbar与Toast类似,两者互为补充。两者之间有着不同的应用场景:Toast的作用是告诉用户现在发生了什么事情,用户只能被动接收这个事情;Snackbar则在这方面进行了扩展,它允许在提示当中加入一个可交互按钮,当用户点击按钮的时候可以执行一些额外的逻辑操作
Snackbar使用十分简单,与Toast类似:用静态方法make() 创建Snackbar对象,调用asetAction() 方法设置交互事件,最后用show() 方法让Snackbar显示

public static Snackbar make(@NonNull View view, @NonNull CharSequence text, @Duration int duration);
  • View view:当前界面布局的任意一个View都可以,Snackbar会使用这个View来自动查找最外层的布局,用于展示Snackbar
  • CharSequence text:要显示的文本内容
  • int duration:显示的时长,有三个内置常量可以选择:Snackbar.LENGTH_LONG 、Toast.LENGTH_SHORT和LENGTH_INDEFINITE
public Snackbar setAction(@Nullable CharSequence text, @Nullable final View.OnClickListener listener)
  • CharSequence text:交互按钮的显示名称
  • View.OnClickListener listener:点击交互按钮的监听事件

CoordinatorLayout

CoordinatorLayout是一个加强版的FrameLayout,它可以监听其所有子控件的各种事件,然后自动做出最为合理的响应,它有两个作用:

  • 用作应用的顶层布局管理器
  • 通过为子View指定 behavior 实现自定义的交互行为

可以在CoordinatorLayout中的子控件中添加app:layout_behavior属性来指定布局行为
使用以下代码引入CoordinatorLayout

<!--androidx库-->
<androidx.coordinatorlayout.widget.CoordinatorLayout
	android:layout_width="match_parent"
	android:layout_height="match_parent">

</androidx.coordinatorlayout.widget.CoordinatorLayout>

<!--support库-->
<android.support.design.widget.CoordinatorLayout
	android:layout_width="match_parent"
	android:layout_height="match_parent">

</android.support.design.widget.CoordinatorLayout>

卡片式布局

CardView

CardView是用于实现卡片式布局效果的重要控件,是一个FrameLayout,但额外提供了圆角和阴影等效果,看上去会有立体的感觉

<!--androidx库-->
<androidx.cardview.widget.CardView
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
	android:layout_margin="5dp"
	app:cardCornerRadius="4dp">

</androidx.cardview.widget.CardView>

<!--support库-->
<android.support.v7.widget.CardView
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
	app:cardCornerRadius="4dp"
	app:elevation="5dp">

</android.support.v7.widget.CardView>
  • app:cardCornerRadius:指定定卡片圆角的弧度,数值越大,圆角的弧度也越大
  • app:elevation:指定卡片的高度,高度值越大,投影范围也越大,投影效果越淡;高度值越小,投影范围也越小,投影效果越浓

CardView中的控件会显示在一张卡片上,一般CardView会配合RecyclerView一块使用,即在RecyclerView中引用CardView,呈现卡片式布局

AppBarLayout

AppBarLayout实际上是一个垂直方向的LinearLayout,它在内部做了很多滚动事件的封装,并应用了一些Material Design的设计理念。

AppBarLayout必须是CoordinatorLayout子控件。当AppBarLayout接收到滚动事件(在同一个CoordinatorLayout中的其他子控件的滚动事件)的时候,它内部的子控件其实是可以指定如何去影响这些事件的,使用app:layout_scrollFlags属性来定制,这个属性有以下几个可选值:

  • scroll:向上滚动时,控件跟着一起向上滚动并实现隐藏
  • enterAlways:向下滚动时,控件跟着一起向下滚动并重新显示
  • snap:控件还没有完全隐藏或显示的时候,会根据当前滚动的距离,自动选择是隐藏还是显示

引入AppBarLayout

<!--androix库-->
<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">

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

</androidx.coordinatorlayout.widget.CoordinatorLayout>


<!--support库-->
<android.support.design.widget.CoordinatorLayout
	android:layout_width="match_parent"
	android:layout_height="match_parent">

	<android.support.design.widget.AppBarLayout
		android:layout_width="match_parent"
		android:layout_height="wrap_content">

	</android.support.design.widget.AppBarLayout>

</android.support.design.widget.CoordinatorLayout>

下拉刷新

SwipeRefreshLayout是用于实现下拉刷新功能的核心类,把想要实现下拉刷新功能的控件放置到SwipeRefreshLayout中,就可以迅速让这个控件支持下拉刷新
向项目中引入SwipeRefreshLayout(使用androidx库时需要引入)

//androidx库
dependencies 
	...
    implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'

在布局文件中引入SwipeRefreshLayout

<!--androidx库-->
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
	android:id="@+id/swipe_refresh"
	android:layout_width="match_parent"
	android:layout_height="match_parent">

</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

<!--support库-->
<android.support.v4.widget.SwipeRefreshLayout
	android:id="@+id/swipe_refresh"
	android:layout_width="match_parent"
	android:layout_height="match_parent">

</android.support.v4.widget.SwipeRefreshLayout>

引入SwipeRefreshLayout还需要添加相关的刷新逻辑:

SwipeRefreshLayout swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
//设置刷新进度条颜色
swipeRefresh.setColorSchemeResources(R.color.colorPrimary);
//设置刷新监听器
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() 
	@Override
	public void onRefresh() 
		//刷新逻辑
	
);
//用于表示刷新事件结束,并隐藏进度条
swipeRefresh.setRefreshing(false);

可折叠式标题栏

CollapsingToolbarLayout是一个作用于Toolbar基础之上的布局,它可以让Toolbar的效果变得更加丰富,不仅仅是展示一个标题栏,而是能够实现非常华丽的效果。

CollapsingToolbarLayout是不能独立存在的,它在设计的时候就被限定只能作为AppBarLayout的直接子布局来使用。

在布局文件中引用:

<!--androidx库-->
<androidx.coordinatorlayout.widget.CoordinatorLayout
	android:layout_width="match_parent"
	android:layout_height="match_parent">

	<com.google.android.material.appbar.AppBarLayout
		android:id="@+id/appBar"
		android:layout_width="match_parent"
		android:layout_height="250dp">

		<com.google.android.material.appbar.CollapsingToolbarLayout
			android:id="@+id/collapsing_toolbar"
			androi

以上是关于Android学习羁绊之Material Design的主要内容,如果未能解决你的问题,请参考以下文章

Android学习羁绊之Service

Android学习羁绊之多媒体开发

Android :安卓第一行代码学习笔记之 material design简单理解和使用

简记那些羁绊我们学习技术热情的英文词汇

Android Material Design之CollapsingToolbarLayout使用

Android Material Design 系列之 SnackBar详解