JetPack Material Design 组件简单介绍

基于最新的 com.google.android.material:material:1.4.0-alpha01。因为没有release,所以只是介绍了解,以后release了可以直接使用

1.BadgeDrawable

未读消息数和右上角小红点

        findViewById<TextView>(R.id.txt).post {
            val badgeDrawable = BadgeDrawable.create(this)
            badgeDrawable.number = 15
            badgeDrawable.badgeTextColor = Color.BLACK
            badgeDrawable.badgeGravity = BadgeDrawable.BOTTOM_END
            badgeDrawable.isVisible = true
            badgeDrawable.horizontalOffset = 100//如果没有下面两句,BadgeDrawable 会在右下角
            badgeDrawable.verticalOffset = 100
            BadgeUtils.attachBadgeDrawable(badgeDrawable, findViewById(R.id.txt));
        }

注意点:

    1. attachBadgeDrawable 需要 UnsafeExperimentalUsageError 注释,这也是没有release的锅
    1. attachBadgeDrawable方法都必须在anchor创建以后才能用,也就是不能在onCreate里调用这些方法,或者你要view.post调用,保证anchor已经绘制好了


      BadgeDrawable.png

2.FloatingActionButton && ExtendedFloatingActionButton

这个应该比较眼熟了,但是和support库还是有区别的

<androidx.coordinatorlayout.widget.CoordinatorLayout 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/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:src="@android:drawable/ic_btn_speak_now"
        app:backgroundTint="@color/design_default_color_error"
        app:fabCustomSize="50dp" />

    <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginLeft="100dp"
        android:text="12131"
        app:icon="@android:drawable/ic_btn_speak_now"/>

    <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="200dp"
        android:text="12131"
        app:icon="@android:drawable/ic_btn_speak_now"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

注意

FloatingActionButton

  • backgroundTint 前面必须是app,不然不会生效,具体看代码,里面是空的
  • android:src 设置的icon,如果没有 fabCustomSize 会导致位置偏移。而且 fabCustomSize 属性值必须和 width,height 一致

ExtendedFloatingActionButton

  • app:icon 设置图标而不是 android:src
  • 设置 wrap_content 会让text icon全部显示出来。但是如果不设置 wrap_content,比如固定值,会导致 icon 出现细小的偏移
FloatingActionButton & ExtendedFloatingActionButton.png

3.BottomAppBar

其实就是个底部的 ToolBar,但是搭配 FloatingActionButton 可以有别样的效果

        val mBottomAppBar = findViewById<BottomAppBar>(R.id.bottomappbar)
        val size = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 32f, resources.displayMetrics)
        val triangleEdgeTreatment = TriangleEdgeTreatment(size, true)
        val builder = ShapeAppearanceModel().toBuilder()
        builder.setTopEdge(triangleEdgeTreatment)//添加倒三角
        val materialShapeDrawable = MaterialShapeDrawable(builder.build())
        mBottomAppBar?.background = materialShapeDrawable

layout代码

<androidx.coordinatorlayout.widget.CoordinatorLayout 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/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.bottomappbar.BottomAppBar
        android:id="@+id/bottomappbar"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        app:fabAlignmentMode="center"
        app:fabCradleMargin="10dp"
        android:layout_gravity="bottom"/>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:layout_anchor="@id/bottomappbar" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

展示样子

BottomAppBar.png

PS:BottomAppBarCutCornersTopEdge 这个类可以将 FloatingActionButton 变成菱形,但是 getEdgePath 里面的 getFabDiameter 返回是 0,而且对应的 set 方法是 RestrictedApi。暂时无法处理。最终的理想效果在【译】Android材质组件的动手实践:Bottom App Bar 这篇文章最下面

4.BottomNavigationView

用法和之前的 NavigationBarView 基本一致。主要是要注意涉及到小红点

        val mBnv = findViewById<BottomNavigationView>(R.id.bnv)
        val badgeDrawable = mBnv.getOrCreateBadge(R.id.action_favorites)
        badgeDrawable.number = 5
        // mBnv.removeBadge(R.id.action_favorites)

示例如下


BottomNavigationView.png

5.BottomSheetBehavior

底页是包含补充屏幕内容的表面组件。它们固定在屏幕底部(使它们在移动/平板电脑设备上符合人体工程学),并且类似于Dialogs,它们位于主屏幕内容上方。在大多数情况下,可以通过向上/向下拖动手势来扩展/关闭它们。

        val llBottomSheet = findViewById<LinearLayout>(R.id.bottom_sheet)
        val bottomSheetBehavior: BottomSheetBehavior<LinearLayout> = BottomSheetBehavior.from(llBottomSheet)
        //默认的折叠状态, bottom sheets只在底部显示一部分布局。显示高度可以通过 app:behavior_peekHeight 设置(默认是0)
        bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
        //不折叠,全部展开内容
        // bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        bottomSheetBehavior.isHideable = false//一般是false。如果设为true,当 state == STATE_COLLAPSED,然后用户继续往下滑的话会导致整个view彻底消失再也无法滑动出现
        bottomSheetBehavior.addBottomSheetCallback(object : BottomSheetCallback() {
            override fun onStateChanged(bottomSheet: View, newState: Int) {
            }
            override fun onSlide(bottomSheet: View, slideOffset: Float) {
            }
        })

layout文件在这里

<androidx.coordinatorlayout.widget.CoordinatorLayout 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/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="7300dp"
        android:background="@android:color/darker_gray"
        android:orientation="vertical"
        app:behavior_hideable="true"
        app:behavior_peekHeight="80dp"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:text="测试第一行"
            android:textColor="@android:color/white" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:gravity="center"
            android:text="测试第二行"
            android:textColor="@android:color/white" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:text="测试第三行"
            android:textColor="@android:color/white" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:gravity="center"
            android:text="测试第四行"
            android:textColor="@android:color/white" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:text="测试第五行"
            android:textColor="@android:color/white" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:gravity="center"
            android:text="测试第六行"
            android:textColor="@android:color/white" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:text="测试第七行"
            android:textColor="@android:color/white" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:gravity="center"
            android:text="测试第八行"
            android:textColor="@android:color/white" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@color/colorAccent"
            android:gravity="center"
            android:text="测试第九行"
            android:textColor="@android:color/white" />
    </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

示意图


BottomSheetBehavior.gif

6.BottomSheetDialog

IOS的很多菜单都是从底部弹出的,这种展示方式还是很好看的,而丑爆的Android默认弹框一直都是大家一定要摒弃的,那么我们Android如何做出相应效果的弹框(其实这个类已经没啥意义了,一般的老项目肯定存在类似的控件)

    private fun initDialog() {
        val bottomSheetDialog = BottomSheetDialog(this)
        bottomSheetDialog.setContentView(R.layout.dialog_layout)
        bottomSheetDialog.show();
    }

dialog_layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:alpha="0.8"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:text="item1"
        android:textColor="@android:color/white"
        tools:ignore="HardcodedText" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:text="item2"
        android:textColor="@android:color/white"
        tools:ignore="HardcodedText" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="item3"
        android:textColor="@android:color/white"
        tools:ignore="HardcodedText" />
</LinearLayout>

示意图


BottomSheetDialog.gif

7.MaterialButton

这个相对简单,没啥介绍的,唯一有亮点的地方就是含有icon的button,但其实这些一般都会在项目里面有,而且也用不到那么多的功能

8.MaterialCardView

这个和CardView差别也不大,主要是背景色的设置有区别,是app开头的属性

9.MaterialCheckBox

这个和CheckBox可以说完全没有区别,继承自AppCompatCheckBox,基本没加方法

10.Chip && ChipGroup

其实就是我们熟悉的流式布局FlowLayout。ChipGroup 可以设置横向和纵向间距。Chip 就是布局中的每个item。下面这段代码就来展示常用的属性

    <com.google.android.material.chip.ChipGroup
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.chip.Chip
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="背景色"
            app:chipBackgroundColor="@color/colorPrimary" />

        <com.google.android.material.chip.Chip
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="5dp圆弧"
            app:chipCornerRadius="5dp" />

        <com.google.android.material.chip.Chip
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="搜索icon"
            app:chipIcon="@android:drawable/ic_menu_search" />

        <com.google.android.material.chip.Chip
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="stroke"
            app:chipStrokeWidth="2dp"
            app:chipStrokeColor="@color/colorPrimaryDark"/>

        <com.google.android.material.chip.Chip
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="close icon"
            app:closeIconVisible="true"
            app:closeIcon="@android:drawable/ic_menu_close_clear_cancel"/>

    </com.google.android.material.chip.ChipGroup>

效果图


Chip && ChipGroup.png

11.MaterialDatePicker

年月日的选择器,用法

        val builder = MaterialDatePicker.Builder.datePicker()//单选
        //val builder = MaterialDatePicker.Builder.dateRangePicker()//多选,可以选择时间范围
        //val builder = MaterialDatePicker.Builder.customDatePicker()//自定义,暂时标注RestrictTo
        val picker = builder.build()
        picker.show(supportFragmentManager, "date_picker_tag")

示例图


MaterialDatePicker.gif

评价:太丑了,一般都和ios保持同步,所以一般用不到

12.ShapeableImageView

个人认为没啥意义,只是比(ImageView+自定义background)多了一个ShapeAppearanceModel属性。可以通过style来配置,也可以通过代码实现

ShapeAppearanceModel.builder()
            .setAllCorners(CornerFamily.ROUNDED,20f)
            .setTopLeftCorner(CornerFamily.CUT,RelativeCornerSize(0.3f))
            .setTopRightCorner(CornerFamily.CUT,RelativeCornerSize(0.3f))
            .setBottomRightCorner(CornerFamily.CUT,RelativeCornerSize(0.3f))
            .setBottomLeftCorner(CornerFamily.CUT,RelativeCornerSize(0.3f))
            .setAllCornerSizes(ShapeAppearanceModel.PILL)
            .setTopLeftCornerSize(20f)
            .setTopRightCornerSize(RelativeCornerSize(0.5f))
            .setBottomLeftCornerSize(10f)
            .setBottomRightCornerSize(AbsoluteCornerSize(30f))
            .build()

代码接收一个ShapeAppearanceModel,通过构建者模式实现

  • setTopLeft表示处理左上角,其他同理。
  • cornerSize表示设置的大小,有RelativeCornerSize和AbsoluteCornerSize,RelativeCornerSize构造方法接收一个百分比,范围0-1;AbsoluteCornerSize构造方法接收一个具体数值,这个数值就是圆角的数值。
  • CornerFamily,它表示处理的方式,有ROUNDED和CUT两种,ROUNDED是圆角,CUT是直接将圆角部分裁切掉.
  • setAllCornerSizes(ShapeAppearanceModel.PILL)可以直接实现圆形效果。

13. Slider

加强版的SeekBar.先上测试代码

    <com.google.android.material.slider.Slider
        android:id="@+id/slider"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:value="0.3"
        android:valueFrom="0.0"
        android:valueTo="1.0"
        android:stepSize="0.1"
        app:tickColor="@android:color/holo_orange_dark"
        app:thumbColor="@android:color/holo_green_light"
        app:haloColor="@android:color/holo_blue_bright"
        app:trackColorActive="@android:color/black"
        app:trackColorInactive="@android:color/holo_red_dark" />

说明

  • tickColor是指刻度的颜色,必须指明stepSize大于0.0f,否则不显示
  • thumbColor是指中间的进度的圆圈颜色
  • haloColor是指长按以后thumb外圈的颜色
  • trackColor整个进度条的颜色

上动图


Slider.gif

14.SwitchMaterial

加强版的Switch。从功能来讲,它还是有点丑,无法满足日常开发需求,还是要自己定制。。。。。。

15.TextInputLayout

和android 5.0的时候推出的TextInputLayout差别不大,用法在这里

16.MaterialTimePicker

google自带的时间选择器,用法如下

            val builder = MaterialTimePicker.Builder()
            builder.setInputMode(MaterialTimePicker.INPUT_MODE_CLOCK)
            //builder.setInputMode(MaterialTimePicker.INPUT_MODE_KEYBOARD)
            val picker = builder.build()
            picker.show(supportFragmentManager, "click")

示例图


MaterialTimePicker.gif

本人不推荐,主要有两方面,第一,确实挺难看的,一般还是按照ios的来做,做成底部滚轮的那种。第二,builder的可配置项太少了,做不了什么修改

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容