android Material Design

282 阅读4分钟

Material Design

一、应用中的application中的style

【1】 指向了AppTheme,它的parent主题是Theme.AppCompat.Light.DarkActionBar,这是一个深色的ActionBar主题,它的界面主体颜色为深色,陪衬颜色为浅色,反之亦然

【2】 AppTheme中重写了colorPrimary,colorPrimaryDark,colorAccent中三种颜色,其中colorPrimary表示的是标题栏的颜色,colorPrimaryDark表示状态栏的颜色,colorAccent表示的是一个强调的意思,比如一些控件选中状态。还可以重写textColorPrimary更改文字的颜色,windowBackground更改背景颜色,navigationBarColor更改导航栏颜色

二、Toolbar

【1】 在布局文件中声明toolbar控件

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

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?actionBarSize"
        android:background="@color/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />


</LinearLayout>

【2】 上面的布局中使用了xmlns:app的命名空间,是因为在5.0之前都是使用xmlns:android,为了兼容5.0一下的版本,所有使用app的命名空间

【3】 如果application使用的是浅色主题,那么陪衬色为深色,那么toolbar上面的元素的颜色都是深色,这个效果看起来很差,所以为了让toolbar单独使用深色主题,这里使用了android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar",这样上面的元素颜色就是浅色,但是如果这时给toolbar指定了菜单,那么菜单也会是深色的,所以需要指定app:popupTheme="@style/ThemeOverlay.AppCompat.Light",这样弹出的菜单就是浅色的

【4】 在代码中设置setSupportAcionBar(toolbar)

【5】 给toolbar添加菜单,在res下新建menu文件夹,新建菜单文件main_menu,在代码中加载菜单

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(toolbar)
	supportActionBar?.apply {
        // 开启导航按钮
        setDisplayHomeAsUpEnabled(true)
        // 设置导航按钮图标
        setHomeAsUpIndicator(android.R.drawable.ic_dialog_map)
    }
}

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

【6】 menu文件,showAsAction用来指定按钮的位置,always表示永远显示在toolbar中,如果屏幕空间不够则不显示,ifRoom表示在屏幕空间足够的情况下,显示在toolbar上,不够则显示在菜单中,never表示显示在菜单中。toolbar中的action只会显示图标,菜单中的按钮只会显示文字。补充:可以使用反射,让菜单显示图标和文字

java:
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
	if (menu != null) {
	if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) {
	try {
	Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
	method.setAccessible(true);
	method.invoke(menu, true);
	} catch (Exception e) {
	e.printStackTrace();
	}
	}
	}
	return super.onMenuOpened(featureId, menu);
}


kotlin:
override fun onMenuOpened(featureId: Int, menu: Menu?): Boolean {
    if (menu != null) {
        if (menu.javaClass.simpleName.equals("MenuBuilder", ignoreCase = true)) {
            try {
                val method = menu.javaClass.getDeclaredMethod("setOptionalIconsVisible", java.lang.Boolean.TYPE)
                method.isAccessible = true
                method.invoke(menu, true)
            } catch (e: Exception) {
                e.printStackTrace()
            }

        }
    }
    return super.onMenuOpened(featureId, menu)
}

三、DrawLayout

【1】 允许在该控件中放两个子控件,第一个子控件是主屏幕显示的内容,第二个子控件是滑动菜单显示的内容,需要注意的是第二个子控件需要指定android:layout_gravity="start",指定菜单滑出的方向

<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    </LinearLayout>

    <TextView
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_gravity="start"
        android:text="drawableLayout" />
</android.support.v4.widget.DrawerLayout>

【2】 在activity中,设置toolbar与drawLayout开启和关闭关联,这时手动设置toolbar的导航图标将失效

val actionBarDrawerToggle = ActionBarDrawerToggle(this, drawer_layout, toolbar, 0, 0)
actionBarDrawerToggle.syncState()
drawer_layout.addDrawerListener(actionBarDrawerToggle)

【3】 也可以手动设置drawLayout的开启和关闭

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
    when (item?.itemId) {
        android.R.id.home -> {
            if (drawer_layout.isDrawerOpen(Gravity.START)) {
                drawer_layout.closeDrawer(Gravity.START)
            } else {
                drawer_layout.openDrawer(Gravity.START)
            }
        }
    }
    return true
}

四、NavigationView

【1】 布局文件

<android.support.design.widget.NavigationView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:itemTextAppearance="@style/TextStyle1"
        app:headerLayout="@layout/navigation_header"
        app:menu="@menu/navigation_menu" />

【2】 headLayout属性是NavigationView的头布局,menu属性是NavigationView的菜单列表

<group android:checkableBehavior="single">
    <item
        android:id="@+id/sensor_light"
        android:icon="@android:drawable/ic_lock_idle_low_battery"
        android:title="光照传感器" />
    <item
        android:id="@+id/sensor_acc"
        android:icon="@android:drawable/ic_menu_agenda"
        android:title="加速传感器" />
    <item
        android:id="@+id/sensor_compass"
        android:icon="@android:drawable/ic_menu_compass"
        android:title="方向传感器" />
</group>
checkableBehavior="single"表示单选

【3】 menu点击事件

navigationView.setNavigationItemSelectedListener {
        when (it.itemId) {
            R.id.sensor_light -> {
                Toast.makeText(this, "1", Toast.LENGTH_SHORT).show()
            }
            R.id.sensor_acc -> {
                Toast.makeText(this, "2", Toast.LENGTH_SHORT).show()
            }
            R.id.sensor_compass -> {
                Toast.makeText(this, "3", Toast.LENGTH_SHORT).show()
            }
        }
        true
    }

五、FloatingActionButton

【1】 布局文件

<android.support.design.widget.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@android:drawable/ic_dialog_dialer"
            app:elevation="8dp" />
elevation:表示高度值,投影范围大

【2】 与Button点击事件一样

六、Snackbar

【1】 创建snackbar

Snackbar.make(it, "Data delete", Snackbar.LENGTH_SHORT)
                .setAction("Undo") {
                    Toast.makeText(this, "已取消", Toast.LENGTH_SHORT).show()
                }.show()

【2】 自定义snackbar颜色

val snackbar = Snackbar.make(it, "Data delete", Snackbar.LENGTH_SHORT)
                .setAction("Undo") {
                    Toast.makeText(this, "已取消", Toast.LENGTH_SHORT).show()
                }
        snackbar.setActionTextColor(resources.getColor(R.color.colorPrimaryDark))
        snackbar.view.setBackgroundColor(resources.getColor(android.R.color.holo_purple))
        val snackView = snackbar.view.findViewById<TextView>(R.id.snackbar_text)
        snackView.setTextColor(resources.getColor(android.R.color.holo_red_dark))
        snackbar.show()

七、CoordinatorLayout

【1】 此布局控件是一个加强版的FrameLayout,可以监听其所有子控件的各种事件,然后自动作出响应

八、AppLayout

【1】 在CoordinatorLayout中,同时存在toolbar,recyclerview时,recyclerview覆盖了toolbar,因为coordinatorLayout是加强版的FrameLayout

【2】 加入AppLayout布局

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

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?actionBarSize"
                android:background="@color/colorPrimary"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:layout_scrollFlags="scroll|enterAlways|snap"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
        </android.support.design.widget.AppBarLayout>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:overScrollMode="never"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>

在recyclerView中添加app:layout_behavior="@string/appbar_scrolling_view_behavior",这时就不会覆盖toolbar了

【3】 在toolbar中添加app:layout_scrollFlags属性

1.scroll:recyclerView向上滚动时,toolbar会跟着一起向上滚动并实现隐藏
2.enterAlways:recyclerView向下滚动,toolbar跟着一起向下滚动并重新显示
3.snap:toolbar还没完全隐藏或显示的时候,会根据当前滚动的距离,自动选择是隐藏还是显示
4.exitUntilCollapsed:表示CollapsingToolbarLayout随着滚动完成折叠之后就保留在界面上,不再移出屏幕

九、CollapsingToolbarLayout

【1】 作用于toolbar基础之上的布局,不能独立存在,它的设计的时候就被限定只能作为AppBarLayout的直接子布局,而AppBarLayout又必须是CoordinatorLayout的子布局

<android.support.design.widget.CollapsingToolbarLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:collapsedTitleGravity="start"
                app:contentScrim="@color/colorAccent"
                app:layout_scrollFlags="scroll|exitUntilCollapsed">

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

                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?actionBarSize"
                    android:background="@color/colorPrimary"
                    app:layout_collapseMode="pin"
                    app:layout_scrollFlags="scroll|enterAlways|snap"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
            </android.support.design.widget.CollapsingToolbarLayout>