Android Design Support Library使用详解(一)

Design Support Library是在Google I/O 2015上发布的一个全新兼容函数库,它使得开发者可以在Android2.1(API = 7)及以上的设备中实现Material Design效果,这个函数库提供了一系列的控件,主要包括:Snackbar,Navigation View、FloatActionButton、CoordinatorLayout、CollapsingToolbarLayout等。

在使用Design Support Library 之前,首先需要添加如下依赖:

dependencies {
    compile 'com.android.support:design:25.2.0'
}

Snackbar

Snackbar提供了一个介于Toast和AlertDialog之间轻量级控件,它可以很方便的提供消息的提示和动作反馈。
Snackbar的使用与Toast的使用基本相同:

Snackbar.make(view, "Snackbar comes out", Snackbar.LENGTH_LONG)
                        .setAction("Action", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Toast.makeText(
                                        MainActivity.this,
                                        "Toast comes out",
                                        Toast.LENGTH_SHORT).show();
                            }
                        }).show();

需要注意的是,这里我们把第一个参数作为Snackbar显示的基准元素,而设置的Action也可以设置多个。

显示的效果就类似如下:
这里写图片描述

Snackbar在出现一定时间后,就会消失,这与Toast一模一样。

TextInputLayout

TextInputLayout的主要作用是作为EditText的容器,从而为EditText默认生成一个浮动的Label,当用户点击EditText之后,EditText中设置的hint字符串会自动移动到EditText的左上角。TextInputLayout的使用很简单,语句如下,将它作为EditText的父容器即可。同时,如果给EditText增加监听,还可以给它增加更多的floating label。

下面我们来看这与一个TextInputLayout:

<android.support.design.widget.TextInputLayout
        android:id="@+id/til_pwd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

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

一定要注意,他是把EditText包含起来的,不能单独使用。

在代码中,我们给它设置监听:

        //TextInputLayout
        textInputLayout = (TextInputLayout) findViewById(R.id.til_pwd);
        EditText editText = textInputLayout.getEditText();
        textInputLayout.setHint("Password");

        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (s.length() > 4) {
                    textInputLayout.setError("Password error");
                    textInputLayout.setErrorEnabled(true);
                } else {
                    textInputLayout.setErrorEnabled(false);
                }
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

这样:显示效果如下:

这里写图片描述

当输入时:

这里写图片描述

这里需要注意的是,TextInputLayout的颜色来自style中的colorAccent的颜色:

<item name="colorAccent">#1743b7</item>

TabLayout

Tablayout控件用于在应用中轻松添加Tab分组功能,总共有两种类型可供选择。

  • 固定Tabs:对应xml配置中的app:tabMode=”fixed”。
  • 可滑动的Tabs:对应xml配置中的app:tabMode=”scrollable”。

选项卡可以在程序中动态添加:

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.addTab(tabLayout.newTab().setText("tab1"));
        tabLayout.addTab(tabLayout.newTab().setText("tab2"));
        tabLayout.addTab(tabLayout.newTab().setText("tab3"));

但大部分时间我们都不会这样用,通常滑动布局都会和ViewPager配合起来使用,所以,我们需要ViewPager来帮忙:

        mViewPager = (ViewPager) findViewById(R.id.viewpager);
        // 设置ViewPager的数据等
        setupViewPager();
        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        // 非常重要,将ViewPager和TabLayout结合了起来
        tabLayout.setupWithViewPager(mViewPager);

通过一句话setupWithViewPager,我们就把ViewPager和TabLayout结合了起来。

这里写图片描述

NavigationView在MD设计中非常重要,之前Google也提出了使用DrawerLayout来实现导航抽屉。这次,在support library中,Google提供了NavigationView来实现导航菜单界面,所以,新的导航界面可以这样写了:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    android:id="@+id/dl_main_drawer"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- 你的内容布局-->
    <include layout="@layout/navigation_content"/>

    <android.support.design.widget.NavigationView
        android:id="@+id/nv_main_navigation"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/navigation_header"
        app:menu="@menu/drawer_view"/>

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

其中最重要的就是这两个属性:

app:headerLayout
app:menu

通过这两个属性,我们可以非常方便的指定导航界面的头布局和菜单布局:

这里写图片描述

其中最上面的布局就是app:headerLayout所指定的头布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="192dp"
    android:background="?attr/colorPrimaryDark"
    android:gravity="center|left"
    android:orientation="vertical"
    android:paddingTop="30dp"
    android:paddingLeft="16dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:id="@+id/avatar"
        android:layout_width="72dp"
        android:layout_height="72dp"
        android:scaleType="centerCrop"
        android:background="@drawable/ic_user"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="JiaMengfei"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="不负韶华,砥砺前行!"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

</LinearLayout>

而下面的菜单布局,我们可以直接通过menu内容自动生成,而不需要我们来指定布局:

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_home"
            android:icon="@drawable/customerservice"
            android:title="Home"/>
        <item
            android:id="@+id/nav_messages"
            android:icon="@drawable/my_library"
            android:title="Messages"/>
        <item
            android:id="@+id/nav_friends"
            android:icon="@drawable/my_delegation"
            android:title="Friends"/>
        <item
            android:id="@+id/nav_discussion"
            android:icon="@drawable/buy"
            android:title="Discussion"/>
    </group>

    <item android:title="Version">
        <menu>
            <item
                android:icon="@drawable/financecenter"
                android:title="Android"/>
            <item
                android:icon="@drawable/financecenter"
                android:title="iOS"/>
        </menu>
    </item>

</menu>

你可以通过设置一个OnNavigationItemSelectedListener,使用其setNavigationItemSelectedListener()来获得元素被选中的回调事件。它为你提供被点击的 菜单元素 ,让你可以处理选择事件,改变复选框状态,加载新内容,关闭导航菜单,以及其他任何你想做的操作。例如这样:

        // 图片都变为灰色的破解方法
        NavigationView navigationView = (NavigationView) findViewById(R.id.nv_main_navigation);
        navigationView.setItemIconTintList(null);
        if(navigationView != null) {
            navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
                @Override
                public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                    Snackbar.make(tablayoutContent,
                    menuItem.getTitle()+"  pressed",Snackbar.LENGTH_LONG).show();
                    menuItem.setCheckable(true);
                    mDrawerLayout.closeDrawers();
                    return true;
                }
            });
        }

这里有两个坑位需要注意:

1.设计好的彩色图标,在NavigationView中却是灰色。这里有两种办法:

  • 设置属性app:itemIconTint,将item的图标设置为统一颜色。
  • 在代码中调用setItemIconTintList()方法,传入null,如下:
// 这种可以显示图片原有的色彩
navigationView.setItemIconTintList(null);

2.头部布局不能响应点击的处理

在navigation_header 属性中 app:headerLayout=”@layout/navigation_header” 可以指定上部分的布局 app:menu=”@menu/drawer” 可以设置下部分菜单下面的菜单的点击事件 可以 用 setNavigationItemSelectedListener 来实现,而上面的部分 没有方法,想想也是,因为上面的部分 谷歌根本不知道你会布局什么,而下面的已经固定了。

此时,如果我希望点击头像产生事件,我首先要找到头像,而 head_iv 在布局 navigation_header 中,navigation_header 又在 NavigationView 中定义了。 所以首先要取消 app:headerLayout ,在逻辑代码中设置headview,再从headview找到head_iv,再设置点击事件。

View headview = navigationView.inflateHeaderView(R.layout.navigation_header);
            ImageView avatar = (ImageView) headview.findViewById(R.id.avatar);
            avatar.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Snackbar.make(tablayoutContent,"You click avatar",Snackbar.LENGTH_LONG).show();
                    mDrawerLayout.closeDrawers();
                }
            });

FloatingActionButton

floating action button 是一个负责显示界面基本操作的圆形按钮。Design library中的FloatingActionButton 实现了一个默认颜色为主题中colorAccent的悬浮操作按钮,like this:

这里写图片描述

FloatingActionButton——FAB使用非常简单,你可以指定在加强型FrameLayout里面——CoordinatorLayout,这个我们后面再将。

关于FAB的使用,你可以把它当做一个button即可。

<android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_done"/>

通过指定layout_gravity就可以指定它的位置。

自定义背景颜色:

app:backgroundTint="@color/mycolor"

自定义波浪颜色:

app:rippleColor="@android:color/white"

你也可以在代码中进行设置,不过设置backgroundTint稍微困难一点,因为它使用了颜色状态列表(StateList),需要按如下语句进行设置

fab.setBackgroundTintList(ColorStateList.valueOf("Your color"));

FAB有两个可选的尺寸,通过添加如下属性可以将FAB设置为迷你版本:

app:fabSize="mini"

点击事件:

    // fab的点击事件
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Snackbar.make(v, "Snackbar comes out", Snackbar.LENGTH_LONG)
                        .setAction("Action", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Toast.makeText(
                                        MainActivity.this,
                                        "Toast comes out",
                                        Toast.LENGTH_SHORT).show();
                            }
                        })
                        .show();
            }
        });

注意事项

虽然这些错误在将来也许会被修复,但是我们还是先介绍几个让FAB正常工作的技巧。首先,如果你运行前面的代码,你会发现根据安卓系统版本的不同,会出现很多未料到的事情。所有这些问题似乎都和一个叫做 borderWidth的属性有关, borderWidth需要设置成0:

app:borderWidth="0dp"

另外,在lollipop以前的版本上,使用这个属性会在周围产生外边距(margin),而21+以上则不会。产生的原因和CardView上所看到的是一样的:lollipop 以前阴影是使用一个drawable来渲染的,使用的是自身的空间来绘制,而Lollipop之后阴影是由系统渲染的。CardView有一个属性可以启用compat padding。

但是浮动操作按钮却没有。不过要模拟出来耶很简单。只要根据安卓版本添加一个margin就可以了。

android:layout_margin="@dimen/fab_compat_margin"

现在只需在dimen.xml文件中定义一个属性值。

values目录下:

<dimen name="fab_compat_margin">0dp</dimen>

values-v21目录下:

<dimen name="fab_compat_margin">16dp</dimen>

OK,到现在为止,已经学习了Snackbar,TextInputLayout、TabLayout、NavigationView、FloatingActionButton这四个MD新特性布局,由于篇幅关系,和CoordinatorLayout等的重要性,咱们在下一篇接着学习Android Design Support Library使用详解(二)。关于这篇有什么不懂或错误欢迎留言指出。

参考:
Android Design Support Library使用详解
《Android 高级进阶》

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值