美文网首页
MaterialDesign基本使用

MaterialDesign基本使用

作者: code希必地 | 来源:发表于2020-11-10 22:55 被阅读0次

1、ToolBar

ToolBar是为了替代ActionBar的,ActionBar被限定只能位于Activity的顶部,不能实现MaterialDesign的效果,所以Google不建议使用ActionBar,而ToolBar不仅继承了ActionBar的所有功能,而且灵活性很高,可以配合其他控件完成MaterialDesign效果。
我们新建的项目默认都会显示ActionBar的,这是根据项目中设置的主题现实的。看下AndroidManifest.xml文件中的配置。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.test.rowingview">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

可以看到上面使用了android:theme="@style/AppTheme"指定了项目的主题AppTheme,看下是它是如何定义的

<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>

可以看到这里定义了一个name为AppTheme,parent为Theme.AppCompat.Light.DarkActionBar的主题,DarkActionBar表示深色主题,那么ActionBar则为深色主题,所以ActionBar上面的元素则为浅色主题。如果我们想使用ToolBar来替代ActionBar就需要更换Theme.AppCompat.Light.DarkActionBarTheme.AppCompat.Light.NoActionBar(浅色主题)或Theme.AppCompat.NoActionBar(深色主题)。下面我们看下如何使用ToolBar

<LinearLayout 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"
    tools:context=".MainActivity">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/tool_bar"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/purple_500" />
</LinearLayout>

可以看到我们使用xmlns:app指定了一个新命名空间,这是因为MaterialDesign中属性是新系统中新增的,老系统中不存在,那么为了兼容老系统,我们不能使用android:attribute这样的写法,而是使用app:attribute。
由于我们设置了项目的主题为浅色主题,那么ToolBar的主题也为浅色主题,那么ToolBar上面的元素则为深色,如果我们想让ToolBar上的元素为浅色,就需要通过android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"设置ToolBar的主题为深色。这就会使弹出的菜单项为深色,所以为了美观通过
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"设置菜单项为浅色主题,由于app:popupTheme是新增的属性,所以为了兼容需要使用app:attribute的写法。
如果我们想让ToolBar具有和ActionBar相同的功能,就需要调用setSupportActionBar(tool_bar),我们也可以通过重写Activity的onCreateOptionsMenu在ToolBar上添加菜单项,重写Activity的onOptionsItemSelected来实现菜单项的点击事件,具体代码如下。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(tool_bar)
        //设置是否允许展示返回按钮
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        //设置自定义返回按钮的图片
        supportActionBar?.setHomeAsUpIndicator(R.mipmap.ic_arrow)
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.main_menu, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            android.R.id.home -> {
            }
            R.id.title -> {
            }
            R.id.content -> {
            }
            R.id.scroll_menu -> {
            }
        }
        return true
    }
}

上面我们通过setDisplayHomeAsUpEnabled(true)设置返回按钮展示,可以在onOptionsItemSelected中监听返回按钮的点击,其id默认为android.R.id.home。ToolBar的使用还是非常简单的。

2、滑动菜单DrawLayout

DrawerLayout中允许放两个子控件,第一个子控件表示展示的主屏幕内容,第二个子控件表示滑动菜单中的内容,使用layout_gravity来表示滑动菜单的位置。注意:DrawLayout并不是只允许放两个控件,可以放多个,只不过第一个控件为主屏内容,其他子控件可以通过layout_gravity来设置菜单展示的位置。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/purple_500"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    <androidx.drawerlayout.widget.DrawerLayout
        android:id="@+id/draw_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="主界面" />


        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@android:color/white"
            android:text="Hello World!" />

    </androidx.drawerlayout.widget.DrawerLayout>
</LinearLayout>

这样我们就通过布局文件就实现了滑动菜单,在屏幕左侧向右滑动就可以让滑动菜单显示出来。


image.png

如果我们想实现滑动菜单时和导航按钮进行联动该怎么实现呢?其实很简单,修改下MainActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(tool_bar)
        //设置是否允许展示返回按钮
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        //设置自定义返回按钮的图片
//        supportActionBar?.setHomeAsUpIndicator(R.mipmap.ic_arrow)
        val drawerToggle = ActionBarDrawerToggle(
            this,
            draw_layout,
            tool_bar,
            R.string.draw_open,
            R.string.draw_close
        )
        drawerToggle.syncState()
        draw_layout.addDrawerListener(drawerToggle)
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.main_menu, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            android.R.id.home -> {
            }
            R.id.title -> {
            }
            R.id.content -> {
            }
            R.id.scroll_menu -> {
            }
        }
        return true
    }
}

代码很简单:

  • 首先调用supportActionBar?.setDisplayHomeAsUpEnabled(true)展示导航按钮(其id为android.R.id.home);
  • 然后创建ActionBarDrawerToggle对象( DrawerLayout.DrawerListener的子类);
  • 然后draw_layout.addDrawerListene()设置监听;
  • 最后记得调用drawerToggle.syncState()进行状态同步,否则无效。
    这样就实现了滑动菜单和导航按钮的联动。

3、NavigationView

刚才我们直接通过TextView来作为滑动菜单的页面,其实Google提供了专门的控件NavigationView来实现滑动菜单。NavigationView中有两个属性app:headerLayout和app:menuapp:headerLayout是用来展示菜单的头布局的,app:menu是用来展示菜单项的。使用起来很简单,这里我们修改下activity_main的布局。

<LinearLayout 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">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/purple_500"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    <androidx.drawerlayout.widget.DrawerLayout
        android:id="@+id/draw_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="主界面" />


        <com.google.android.material.navigation.NavigationView
            android:id="@+id/navigation_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            app:headerLayout="@layout/head_navigation"
            app:menu="@menu/main_menu" />

    </androidx.drawerlayout.widget.DrawerLayout>
</LinearLayout>

效果如下:

image.png
可以通过navigation_view.setNavigationItemSelectedListener()监听菜单中item的点击事件。

4、CoordinatorLayout

CoordinatorLayout是一个加强版的FrameLayout,可以监听所有子控件的事件,并自动帮我们实现最合理的响应。先看个效果


image.png

可以看到FloatingActionButton被Snackbar遮住了,如果能让CoordinatorLayout监听到Snackbar的弹出事件,那么它会自动将FloatingActionButton上移。看下使用CoordinatorLayout之后的布局文件

<LinearLayout 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">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/purple_500"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    <androidx.drawerlayout.widget.DrawerLayout
        android:id="@+id/draw_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

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

            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="主界面" />

            <com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/float_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|end"
                android:layout_margin="16dp"
                android:src="@mipmap/ic_arrow" />

        </androidx.coordinatorlayout.widget.CoordinatorLayout>

        <com.google.android.material.navigation.NavigationView
            android:id="@+id/navigation_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            app:headerLayout="@layout/head_navigation"
            app:menu="@menu/main_menu" />

    </androidx.drawerlayout.widget.DrawerLayout>
</LinearLayout>

再次看下实现的效果:

image.png
可以看到FloatingActionButton不再被Snackbar遮住了,并且FloatingActionButton会根据SnackBar的弹出和消失上下移动位置,SnackBar并不是CoordinatorLayout的子控件,它是如何监听弹出和消失的呢?从Snackbar的用法不难看出:
 Snackbar.make(float_button, text, duration).show()

第一个参数我们传入就是FloatingActionButton,而FloatingActionButton是CoordinatorLayout的子类,因此可以监听到弹出事件。如果我们传入的不是
FloatingActionButton而是DrawLayout则无法监听到SnackBar的弹出和隐藏。

5、AppBarLayout

先看个效果

9101961-bdfbefd3c06302ea.gif
从上面效果可以看出,当滑动控件向上滑动时,隐藏ToolBar,向下滑动时展示ToolBar。实现这个效果就需要使用AppBarLayout,它是一个垂直方向的LinearLayout。实现步骤如下:
  • 1、使用AppBarLayout包裹ToolBar
  • 2、给滑动控件指定app:layout_behavior="@string/appbar_scrolling_view_behavior"
    将滑动控件的滚动事件告诉AppBarLayout
  • 3、在AppBarLayout接收到滚动事件时,通过app:layout_scrollFlags="scroll|enterAlways|snap"设置其子控件如何去响应滚动事件。
    其中scroll表示当滑动控件向上滑动时,ToolBar会跟着向上滑动并隐藏;enterAlways表示滑动控件向下滑动时,ToolBar会跟着向下滑动并显示;
    snap表示ToolBar还未完全显示或隐藏时,会根据当前滚动的距离,自动选择显示还是隐藏;
    具体代码如下:
<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:id="@+id/tool_bar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:background="@color/purple_500"
                    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                    app:layout_scrollFlags="enterAlways|scroll|snap"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
            </com.google.android.material.appbar.AppBarLayout>

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

        </androidx.coordinatorlayout.widget.CoordinatorLayout>

6、可折叠式标题栏

先来看个效果:

9833282-31a22c4230401c35.gif
要实现这个效果就需要使用可折叠式标题栏CollapsingToolbarLayout,它是作用在ToolBar基础上的布局,使用它可以让ToolBar实现的效果更加丰富。它被限定作为AppBarLayout的子布局,而AppBarLayout又必须是CoordinatorLayout的子布局,直接上代码:
<androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

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

            <com.google.android.material.appbar.CollapsingToolbarLayout
                android:id="@+id/collapsing_toolbar"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:contentScrim="@color/purple_200"
                app:layout_scrollFlags="scroll|exitUntilCollapsed">

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:scaleType="centerCrop"
                    android:src="@mipmap/ic_pager1"
                    app:layout_collapseMode="parallax" />

                <androidx.appcompat.widget.Toolbar
                    android:id="@+id/toolBar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:layout_collapseMode="pin" />


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

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

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

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:src="@mipmap/ic_arrow"
            app:layout_anchor="@id/app_bar"
            app:layout_anchorGravity="bottom|end" />
    </androidx.coordinatorlayout.widget.CoordinatorLayout>

可以看到给CollapsingToolbarLayout设置了属性app:contentScrim="@color/purple_200"表示CollapsingToolbarLayout在趋于折叠或折叠之后的颜色,其中app:layout_scrollFlags之前我们使用过,只不过之前是设置在ToolBar上的,现在设置给了CollapsingToolbarLayout,其中exitUntilCollapsed表示CollapsingToolbarLayout随着滚动折叠之后保留在屏幕上不再移出屏幕。
我们在CollapsingToolbarLayout中定义了一个ImageView和一个ToolBar。很简单,只不过app:layout_collapseMode比较陌生,它是用于指定CollapsingToolbarLayout在折叠过程中,子控件的折叠形式,给ToolBar设置成了pin表示折叠过程中位置保持始终不变,给ImageView设置成parallax随着折叠产生一定的位移。

充分利用系统状态栏空间

如果我们想使用系统状态栏的空间可以使用如下代码:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.decorView.systemUiVisibility=View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            window.statusBarColor=ContextCompat.getColor(this,android.R.color.transparent)
        }else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        }

但是对于CoordinatorLayout、AppBarLayout、CollapsingToolbarLayout这种嵌套结构的布局好像并不奏效,对于这种布局我们只需要将ImageView以及其所有父控件都增加android:fitsSystemWindows="true"才有效。

相关文章

网友评论

      本文标题:MaterialDesign基本使用

      本文链接:https://www.haomeiwen.com/subject/etkjbktx.html