Android Design Support Library使用详解(一)

来源:互联网 发布:周杰伦成名之路 知乎 编辑:程序博客网 时间:2024/06/05 02:10

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 高级进阶》

原创粉丝点击