Snackbar、CardView、FloatingActionButton、SwitchCompat使用介绍

96
奔跑吧李博
0.3 2018.10.19 23:09 字数 661

Android5.0也出来了老长一段时间了,5.0推出的MartailDesign系列确实相当高大上,颜色鲜艳像各种套壳的iphone c,老有设计范儿了。接下来,就学着写它们的用法,并写一些效果。

github代码传送门: https://github.com/18380438200/MDViews

先上效果图:

preview.gif

Snackbar

在我生命很长的一段岁月里,我用提示都是Toast,但是自从我看到微信用了这个滑溜溜地提示框后,我依然抛弃Toast了,因为普通toast太不明显。Snackbar看似简单,用法多姿多彩。
一般用法:

Snackbar.make(rootView,"弹出提示", Toast.LENGTH_SHORT).show();

第一参数需要传父容器,比如在activity中可以这样获取rootview:

rootView = getLayoutInflater().inflate(R.layout.activity_main,null);
setContentView(rootView);

setAction()带点击事件

snackbar.setAction("右边文字", new View.OnClickListener() {
@Override
public void onClick(View v) {
           Toast.makeText(MainActivity.this,"点击snackbar",Toast.LENGTH_SHORT).show();
           }
}).setCallback(new Snackbar.Callback()).show();

没有个性啊,怎么办,为了跟我app应景,我就要改背景和文字颜色,那也行。

/**
     * @hide
     *
     * Note: this class is here to provide backwards-compatible way for apps written before
     * the existence of the base {@link BaseTransientBottomBar} class.
     */
    @RestrictTo(LIBRARY_GROUP)
    public static final class SnackbarLayout extends BaseTransientBottomBar.SnackbarBaseLayout {
        public SnackbarLayout(Context context) {
            super(context);
        }

        public SnackbarLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            // Work around our backwards-compatible refactoring of Snackbar and inner content
            // being inflated against snackbar's parent (instead of against the snackbar itself).
            // Every child that is width=MATCH_PARENT is remeasured again and given the full width
            // minus the paddings.
            int childCount = getChildCount();
            int availableWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
            for (int i = 0; i < childCount; i++) {
                View child = getChildAt(i);
                if (child.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT) {
                    child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.EXACTLY),
                            MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(),
                                    MeasureSpec.EXACTLY));
                }
            }
        }
    }

SnackBar有内部类,找到布局文件

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
        android:id="@+id/snackbar_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:paddingTop="14dp"
        android:paddingBottom="14dp"
        android:paddingLeft="12dp"
        android:paddingRight="12dp"
        android:textAppearance="@style/TextAppearance.Design.Snackbar.Message"
        android:maxLines="2"
        android:layout_gravity="center_vertical|left|start"
        android:ellipsize="end"
        android:textAlignment="viewStart"/>

<Button
        android:id="@+id/snackbar_action"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="0dp"
        android:layout_marginStart="0dp"
        android:layout_gravity="center_vertical|right|end"
        android:paddingTop="14dp"
        android:paddingBottom="14dp"
        android:paddingLeft="12dp"
        android:paddingRight="12dp"
        android:visibility="gone"
        android:textColor="?attr/colorAccent"
        style="?attr/borderlessButtonStyle"/>
</merge>

所以可以通过得到子控件操纵。

                Snackbar snackbar = Snackbar.make(rootView,"弹出提示", Toast.LENGTH_SHORT);

                View snackView = snackbar.getView();
                if(snackView != null){
                    snackView.setBackgroundResource(R.color.colorAccent);
                    ((TextView)snackView.findViewById(R.id.snackbar_text)).setTextColor(Color.WHITE);
                }
                snackbar.setAction("右边文字", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this,"点击snackbar",Toast.LENGTH_SHORT).show();
                    }
                }).show();

CardView

带圆角和阴影的卡片(而且拿得起,放得下)
它继承自FrameLayout,所以不便于布局,我们使用时常常嵌套一层Relativelayout。普通的圆角可用shape来实现,但是想要更好体验效果,还是得cardview来实现,谁的项目里没有用到几处cardview呢?

整体用法:
<android.support.v7.widget.CardView
android:id="@+id/card_view"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:stateListAnimator="@animator/cardview_touchraise"
android:foreground="?android:attr/selectableItemBackground"
card_view:cardBackgroundColor="@android:color/white"
card_view:cardCornerRadius="8dp"
card_view:cardElevation="4dp"/>

它的常用属性如下:

1.cardBackgroundColor 背景色

2.cardCornerRadius 圆角半径

3.cardElevation 阴影宽度
有可能我们只需要圆角不需要阴影,cardElevation=0就可以去掉阴影。

4.lift-on-touch 触摸抬起效果
给人的感觉是真的把卡片拿起来了有没有?

使用方法:
android:stateListAnimator="@animator/cardview_touchraise"
cardview_touchraise如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="true" android:state_pressed="true">
        <objectAnimator
            android:duration="400"
            android:propertyName="translationZ"
            android:valueTo="4dp"/>
    </item>
    <item>
        <objectAnimator
            android:duration="400"
            android:propertyName="translationZ"
            android:valueTo="0dp" />
    </item>
</selector>

使用的是objectAnimator属性动画,阴影沿着Z轴从0渐变为4dp。
5.foreground 波纹效果
这里颜色选用系统自带的selectableItemBackground颜色。
自定义波纹颜色:
android:foreground="@drawable/ripple"
ripple.xml资源文件:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/colorAccent"
    android:drawable="@drawable/foreground"
    tools:ignore="NewApi" />

foreground.xml资源文件:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="#2feaea"/>
        </shape>
    </item>
    <item android:state_focused="true"
        android:state_enabled="true">
        <shape android:shape="rectangle">
            <solid android:color="#0f000000"/>
        </shape>
    </item>
</selector>

FloatingActionButton

悬浮按钮,通常见于向上回顶按钮。
用法:

<android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:borderWidth="6dp"
        android:backgroundTint="@color/colorPrimary"
        app:rippleColor="@color/colorPrimary"
        app:pressedTranslationZ="@dimen/cardview_default_elevation"
        android:background="@mipmap/display_love_pressed"/>

borderWidth 边框宽度
backgroundTint 背景色
rippleColor 按下波纹颜色
pressedTranslationZ 外环阴影

如果想给它加上按下变换图片,background就设置selector

SwitchCompat
Android里面要用到开关按钮,通常要自定义控件SwithButton之类的,但是MD包下已经有自带控件SwitchCompat,用法如下

    <android.support.v7.widget.SwitchCompat
        android:layout_width="wrap_content"
        android:layout_height="20dp"
        android:checked="true"
        android:textOn="开"
        android:textOff="关"
        app:showText="true"/>

showText属性设置是否显示文字,textOn,textOff分别设置开关的文字,setOnCheckedChangeListener设置切换监听。

Material Design系列