Android基础知识Android进阶+实战android经典收录

AndroidStudyDemo之Android5.x新控件介绍

2016-04-14  本文已影响3683人  diygreen

作者:李旺成###

时间:2016年4月14日###


Android 5新控件(一)

接上篇 AndroidStudyDemo 之 Android5.x 新 API 介绍(二)

今天主要给大家介绍下 Android 5.x 中提供的新控件(请不要纠结“控件”的定义)。

一、 RippleDrawable

简介

Android 5.x 提供了视图的水波纹效果,就是使用 RippleDrawable 实现的,看看 RippleDrawable 到底是什么。

简单使用

RippleDrawable 其实就可以当作一个 Drawable,这里主要介绍如何使用,不谈论它的实现原理之类的。

1、没有边界的 Ripple(Ripple With No Mask)
先看效果:

Ripple With No Mask

很简单,就是在 drawable 文件夹中定义一个以 <ripple> 为根控件的 xml 文件,然后作为一个控件的背景即可。
定义 ripple_blue.xml :

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="#0000cc">
</ripple>

作为 TextView 的 background:

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/ripple_blue"
    android:clickable="true"
    android:gravity="center"
    android:text="Ripple With No Mask" />

2、用颜色作为 Mask 的 Ripple(Ripple With Color Mask)
先看效果:

Ripple With White Mask Ripple With Black Mask

从上面的效果图可以看到,分别使用不同的颜色,但是好像没有看到效果;是的,用颜色作的 Mask,在这个 Mask 中颜色并没有起作用。但是可以看到与 1、 中的效果差别是很明显的,那就是这个 Mask 限定了边界。

先看代码,
ripple_blue_with_white_mask.xml:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="#0000cc" >
    <item android:id="@android:id/mask"
         android:drawable="@android:color/white" />
</ripple>

ripple_blue_with_black_mask.xml:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="#0000cc">
    <item android:id="@android:id/mask"
         android:drawable="@android:color/black" />
</ripple>

这里解释一下:如果在一个 ripple 标签中,添加一个 item,其 id 为@android:id/mask,drawable 属性为引用的颜色(color) ,则水波效果会限定在 drawable 对应的 RippleDrawable 本身矩形区域内部

3、用图片作为 Mask 的 Ripple(Ripple With Picture Mask)
先看效果:

Ripple With Picture Mask

看代码,
ripple_blue_with_pic_mask.xml:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="#0000cc" >
    <item android:id="@android:id/mask"
         android:drawable="@mipmap/icon_folder_r" />
</ripple>

这里解释一下:如果在一个 ripple 标签中,添加一个 item,其id为@android:id/mask,drawable 属性为引用的图片(png,jpg),则水波效果会限定在图片 drawable 中非透明部分对应的区域内部。

4、用设定形状作为 Mask 的 Ripple(Ripple With Shape Mask)
先看效果:

Ripple With Shape Mask

上代码
首先,要定义一个形状(shape),shape.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="rectangle">
    <solid android:color="#6666ff"/>
    <corners 
        android:bottomRightRadius="100dp"/>
</shape>

然后,在 ripple 中使用形状,ripple_blue_with_shape_mask.xml:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="#0000cc" >
    <item 
        android:id="@android:id/mask"
        android:drawable="@drawable/shape"/>
</ripple>

这里解释一下:如果在一个ripple标签中,添加一个 item,其id为@android:id/mask,drawable 属性为引用的形状(shape) ,则水波效果会限定shape 对应的区域内部。

5、搭配selector作为Ripple(Ripple With Selector)
先看效果:

Ripple With Selector

上代码,ripple_blue_with_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="#0000cc" >
    <item>
        <selector>
            <item
                android:drawable="@mipmap/icon_folder_i"
                android:state_pressed="true">
            </item>
            <item
                android:drawable="@mipmap/icon_folder_r"
                android:state_pressed="false">
            </item>
        </selector>
    </item>
</ripple>

解释一下:如果在一个 ripple 标签中,添加一个 item,在 item 的内部写上 <selector> 标签,那么这个 RippleDrawable 在按下的时候,同时具有水波效果和 selector 指定的图层。

注意事项

为了兼容可以将 <ripple> 元素定义在 drawable-v21 目录下。关于兼容,不是本文重点,以后专门讨论下。

说明:上面的示例 Demo 和描述参考自 Android L Ripple 的使用

这个 Demo 已经将简单的使用场景覆盖,当然可以组合出各种更丰富的效果,发挥你的想象力去试试吧。

二、 Toolbar

Toolbar 简介

Toolbar 示意图

Toolbar 是应用程序内容中使用的标准工具栏,可以说是** ActionBar 的升级版**。

Toolbar 与 ActionBar 并不是相互独立的,要使用 Toolbar 还是得跟 ActionBar 扯上关系的。相比 Actionbar,Toolbar 最明显的一点就是变得很自由,可随处放置。因为它是作为一个 ViewGroup 来定义使用的,所以单纯使用 ActionBar 已经稍显过时了,它的一些方法已被标注过时。

看一下官方文档上对 Toolbar 的介绍:

Toolbar 简介

如上图所示,Toolbar 继承自 ViewGroup,这个熟悉。再来看看 ActionBar:

ActionBar 简介

ActionBar 继承的是 Object,就只从继承结构来看,我都会觉得 Toolbar 会更灵活(或者说强大),确实如此。来,瞄一眼 Toolbar 提供的一些方法:

Toolbar 类的主要方法

Toolbar 的简单使用

先看看 Toolbar 的使用效果:

Toolbar 演示

Toolbar 的使用很简单,我没用过 ActionBar,很多人都说用过 ActionBar 再来使用 Toolbar 就很容易了。哈哈,我想告诉你,如果没用过 ActionBar 就不用去看 ActionBar 了,直接使用 Toolbar 即可,这个使用也很简单。

Toolbar 的使用可以采用如下步骤:
1、定义使用 Toolbar 的主题(Theme)
将 res/values/styles.xml 中原来新建项目时所生成的默认主题,修改为继承自 Theme.AppCompat(可以直接继承 Theme.AppCompat.Light.NoActionBar,这样就需要再去除 ActionBar 了,当然也可以手动去除),然后,设置相关属性。

这里只是为了演示如何使用 Toolbar,所以先把原本的 ActionBar 隐藏起来。

看代码:

<!-- 去掉 ActionBar,使用 Toolbar 的主题 -->
<style name="AppTheme.DIYToolbar" parent="Theme.AppCompat">
    <!-- toolbar(actionbar)颜色 -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <!-- 状态栏颜色 -->
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <!-- 各控制元件(如:check box、switch 或是 radoi) 被勾选 (checked) 或是选定 (selected) 的颜色 -->
    <item name="colorAccent">#003300</item>
    <!-- 各控制元件的预设颜色 -->
    <item name="colorControlNormal">#6600ff</item>
    <!-- 导航栏的背景色 -->
    <item name="android:navigationBarColor">#330099</item>
</style>

调整 Menu 位置

<!-- Toolbar 定制菜单的样式 -->
<style name="AppTheme.DIYToolbar2" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- toolbar(actionbar)颜色 -->
    <!-- App bar 上的标题与更多菜单中的文字颜色 -->
    <item name="colorPrimary">#ff6600</item>
    <!-- 状态栏颜色 -->
    <item name="colorPrimaryDark">#ff9900</item>
    <!-- 窗口的背景颜色 -->
    <item name="android:windowBackground">@android:color/white</item>
    <!-- 溢出菜单 -->
    <!-- Required for Lollipop. -->
    <item name="android:actionOverflowMenuStyle">@style/DIYMenuStyle</item>
</style>

<!-- 溢出菜单样式 -->
<style name="DIYMenuStyle" parent="@style/Widget.AppCompat.Light.PopupMenu.Overflow">
    <!-- Required for Lollipop. -->
    <item name="android:overlapAnchor">false</item>
    <item name="android:dropDownVerticalOffset">10dp</item>
    <item name="android:popupBackground">#ff6600</item>
</style>

注意:在设置 style 时使用兼容库中的 Toolbar 与使用 Android 5.x 中提供的 Toolbar还是稍有区别的,我这里演示的是 Android 5.x 中的 Toolbar。如果你自己尝试的时候和我演示的效果不一致时,请确认你使用的是哪个 Toolbar,以及自定义 Theme 下的 item 的 name 与我演示使用的是否是一致的。

2、使用主题
关于 Theme 的作用范围,这里不做赘述。我的 Demo 项目中为了演示不同主题的效果,以及不破坏其他的页面,是直接为单个 Activity 应用该主题,当然在实际项目中一般都是直接应用在 app 上。

看代码:

<activity
    android:name=".newwidget1.ToolbarActivity"
    android:theme="@style/AppTheme.DIYToolbar" />
<activity android:name=".newwidget1.Toolbar2Activity"
    android:theme="@style/AppTheme.DIYToolbar2"/>

3、在布局中加入 Toolbar
直接把 Toolbar 当成一个普通的 ViewGroup,它的使用很灵活,没有太多限制。这里做个简单的演示:

<Toolbar
    android:id="@+id/tb_title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:navigationIcon="@mipmap/btn_back"
    android:logo="@mipmap/ic_logo"
    android:title="@string/title_toolbar"
    android:subtitle="@string/subtitle_toolbat"/>

上面用到的属性基本上可以见名知义,这里不打算细说,去试一下即可看到效果,稍后会小结一下常用属性的设置。

4、添加 Menu
Android 上的 Menu 生命力还是很顽强的,Toolbar 上的 Menu 个人感觉效果还可以,而且不少的 App 都有使用(当然大多都是 Meterial Design 风格的 App 在用)。来看看 Toolbar 中 Menu 的基本用法。

首先,使用 xml 定义 Menu:toolbar_menu.xml
(在代码中如何定义 Menu 可以参考 AndroidStudyDemo之Android4.x介绍中 PopupMenu 的使用)

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@+id/menuitem0"
        android:title="唐三藏"/>
    <item
        android:id="@+id/menuitem1"
        android:title="孙悟空"/>
    <item
        android:id="@+id/menuitem2"
        android:title="猪八戒"/>
    <item
        android:id="@+id/menuitem3"
        android:title="沙和尚"/>
</menu>  

这里为了演示动态改变 Toolbar 还定义了一个 toolbar_menu2.xml,如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@+id/menuitem_new"
        android:title="New"/>
    <item
        android:id="@+id/menuitem_open"
        android:title="open"/>
</menu>  

然后,在 Activity 中填充 Menu:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // 使用 xml 定义的 Menu 文件,填充 Menu
    getMenuInflater().inflate(R.menu.toolbar_menu, menu);
    return true;
}

最后,为 Toolbar 的 Menu 按钮设置监听:

this.mTitleTB.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
    @Override
    public boolean onMenuItemClick(MenuItem item) {
        Toast.makeText(getApplicationContext(), item.getTitle(), Toast.LENGTH_SHORT).show();
        return false;
    }
});

5、代码中使用 Toolbar
首先,初始化 Toolbar,并将 ActionBar 替换为 Toolbar:

this.mTitleTB = (Toolbar) findViewById(R.id.tb_title);
// 使用 setActionBar() 方法,取代原来的 ActionBar
setActionBar(mTitleTB);

然后,设置 Toolbar:
(这不是必要的,你完全可以在布局文件中定义这些属性,这里仅仅是为了演示如何在代码中设置 Toolbar)

private void changeToolbar() {
    this.mTitleTB.setTitle("ChangeToolbar");
    this.mTitleTB.setSubtitle("ToolbarSubtitle");
    this.mTitleTB.setNavigationIcon(R.mipmap.btn_back_lightblue);
    this.mTitleTB.setLogo(R.mipmap.ic_launcher);
    // Menu 也可以替换
    mToolbarMenu.clear();
    getMenuInflater().inflate(R.menu.toolbar_menu2, mToolbarMenu);
}

综合使用

这里以 Toolbar+DrawerLayout 实现抽屉菜单为例,演示这两个控件的搭配,先看效果:

Toolbar 和 DrawerLayout 配合使用

在效果图中可以看到,左侧菜单滑出和收起的时候,Toolbar 左边的菜单图标带有一个挺好看的动画。这是 Toolbar 和 DrawerLayout搭配的效果,实现很简单。
实现步骤:
1、定义 Toolbar 布局:include_toolbar.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- 为了和 DrawerLayout 搭配,这里使用了兼容包中的 Toolbar -->
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:logo="@mipmap/ic_logo"
    android:title="@string/title_toolbar"
    android:subtitle="@string/subtitle_toolbat">
</android.support.v7.widget.Toolbar>

2、添加动作菜单:toolbar_menu.xml
这个,上面已经说过了,不再赘述。

3、在布局中添加 Toolbar 和 DrawerLayout:activity_toolbardrawerlayout.xml

<?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="match_parent"
    android:orientation="vertical">

    <include layout="@layout/include_toolbar"></include>

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/dl_left"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <!-- 内容界面 -->
        <FrameLayout
            android:id="@+id/fl_containor"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <!-- 菜单界面 -->
        <LinearLayout
            android:layout_width="270dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="#66ccff"
            android:orientation="vertical">
            <ListView
                android:id="@+id/lv_menu"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="10dp" />
        </LinearLayout>
    </android.support.v4.widget.DrawerLayout>

</LinearLayout>

4、设置 NoActionBar 主题,初始化 Toolbar
这个也说过了,注意一点,这里的 Toolbar 为 Support V7 中提供的,所以,要调用 setSupportActionBar() 让 Toolbar 替代 ActionBar。

5、绑定 Toolbar 与 DrawerLayout 状态

ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(
    this, 
    mDrawerLayout, 
    mToolbar, 
    R.string.open, 
    R.string.close);
drawerToggle.syncState();
mDrawerLayout.addDrawerListener(drawerToggle);

6、初始化抽屉菜单

private void initLeftMenu() {
    ListView menuList = (ListView) findViewById(R.id.lv_menu);
    menuList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1
            , new String[]{"Menu Item 1","Menu Item 2","Menu Item 3"}));
    menuList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Fragment fragment = new ContentFragment();
            Bundle bundle = new Bundle();
            bundle.putString("title", ((TextView) view).getText().toString());
            fragment.setArguments(bundle);
            mFm.beginTransaction().replace(R.id.fl_containor, fragment).commit();
            mDrawerLayout.closeDrawer(Gravity.LEFT);
        }
    });
}

7、初始化内容视图

private void initContentView() {
    Fragment fragment = new ContentFragment();
    Bundle bundle = new Bundle();
    bundle.putString("title","Menu Item 1");
    fragment.setArguments(bundle);
    mFm.beginTransaction().replace(R.id.fl_containor,fragment).commit();
}

代码很简单,其他的就不在此罗列了,具体请参考源码。(该示例参考自:android 5.X Toolbar+DrawerLayout实现抽屉菜单

注意事项

我在使用 Toolbar 的过程中遇到过一些问题,在这里列一下,希望你不要再踩同样的坑。
1、不同 Toolbar 的区别
如果你是用的是兼容包中的 Toolbar,上面的演示代码有几处需要修改。
第一,是 Theme 的修改(这里只列举一个示例,其他属性类似):

<!-- Required for pre-Lollipop. -->
<item name="overlapAnchor">false</item>
<!-- Required for Lollipop. -->
<item name="android:overlapAnchor">false</item>

注意:这里如果设置的不对,会发现 Menu 的显示位置死活改不过来。
第二,在 /res/values-v21/styles.xml 中定义同样的 Theme
第三,在 Activity 中替换 ActionBar(当然这个写错了,编译通不过)

// 使用 support v7 里的 Toolbar 替换 ActionBar
setSupportActionBar(toolbar);
// 使用 Android 5.x 的 Toolbar 替换 ActionBar
setActionBar(toolbar);

2、不同的手机(ROM)对 Toolbar 的支持稍有区别
Toolbar 的属性全部在布局中设置,在不同的手机的显示效果,如下图:

不同 ROM 对 Toolbar 的支持 Toolbar 在布局中的设置

在 MIUI 上,布局中设置的 logo 准确的展示出来了,在中兴的手机上,却没有展示出来。当然在代码中设置的话,效果都是一致的。

这里我没有去深究原因了,姑且认为是不同 ROM 对 Toolbar 的支持不同吧!

Toolbar 使用属性小结

下图总结了使用 Toolbar 中涉及到的常用属性:

Toolbar 使用属性说明

下面就上图所标示出来的做个简要说明:
在布局中设置:

在 style 的属性中设置:

进阶

也不是什么真的进阶,上面演示了 Toolbar 的基本使用,这样使用,在页面少的时候没什么问题;但是如果页面一多,就得为每个页面都拷贝一份同样的 Toolbar 设置,当然你可以使用 <include>,但总归不方便。

考虑到上述原因,就有人想到对 Toolbar 进行封装,使用模版模式把这些重复代码都封装起来。

具体实现这里就不讨论了,你要是感兴趣可以参考 Android ToolBar 的简单封装。原理和实现都比较简单,有兴趣可以自己试试。

三、Material Theme

简介

关于 Android 上的 Theme 本来是不想现在就讨论的,但是考虑到 Android 5.x 出现了个 Material 主题,所以在这里简单说一下。先看下效果:

Material Theme 示意图

官方提供的 Materal Theme

我们自定义的 Materal Theme 都需要(直接或者间接)继承自官方提供的 Materal Theme,Google 提供了如下三种:

与之对应的 Compat Theme(兼容包中提供):

分别对应上图所示的三种效果。

Material Theme 简单使用##

其实上面讲 Toolbar 的时候就已经在使用。
1、将自定义主题继承自 android:Theme.Material/Material.Light/Material.Light.DarkActionBar

说明:也可以用兼容包中提供的主题,上面介绍了 Android 5.x 与兼容包中 Materal Theme 的对应关系。

<style name="DIYMaterialTheme" parent="android:Theme.Material">
    <!-- 自定义设置 -->
</style>

2、个性化颜色基调

<style name="DIYMaterialTheme" parent="android:Theme.Material">
    <!-- 个性化颜色基调 -->
    <item name="colorPrimary">#336600</item>
    <item name="colorPrimaryDark">#339900</item>
    <item name="colorAccent">#993300</item>
</style>

说明:

3、使用自定义主题

<!-- 为 App 指定主题 --->
<application
    android:name=".DIYApp"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/DIYMaterialTheme"/>
    ...
</application>

<!-- 为 Activity 指定主题 -->
<activity android:name=".newwidget1.MaterialThemeActivity"
            android:theme="@style/DIYMaterialTheme"/>

看图吧:

Materal Theme 说明示意

与 Toolbar 的属性介绍部分重合,不要介意...

注意事项

1、不要把兼容包中的 Material Theme 使用到 Activity 上
兼容包中的 Material Theme 是提供给 AppCompatActivity 使用的

2、兼容包中与 Android 5.x 中的 Material Theme 在 style 中设置有区别
如:

<style name="DIYAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- 使用兼容包中的 Material Theme -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

<style name="DIYMaterialTheme.Base" parent="android:Theme.Material.Light"/>
<style name="DIYMaterialTheme" parent="DIYMaterialTheme.Base">
    <!-- 使用 Android 5.x 的 Material Theme -->
    <item name="android:colorPrimary">#336600</item>
    <item name="android:colorPrimaryDark">#339900</item>
    <item name="android:colorAccent">#993300</item>
    <item name="android:statusBarColor">#ccffff</item>
    <item name="android:navigationBarColor">#330099</item>
</style>

提示:用错了轻则没有效果,重则程序崩溃。

3、不同的 ROM 对 Material Theme 的支持不同
主要表现在有些 ROM 去除了虚拟 navigationBar,使用实体按键,效果如上图:左侧为 小米 Note,右侧为 中兴。

项目地址

GitHub

有同学建议思维导图的暗黑风格与 AndroidStudio 严重重合,审美疲劳了;所以,思维导图换了个风格,喜欢大家喜欢,有任何建议或意见都欢迎给我留言。
如果对你有用,那帮忙点个喜欢吧!

未完待续,下一篇将继续介绍 Android 5.x 的新控件,考虑到 RecyclerView 内容较多,会单独做一篇,所以计划中关于 Android 5.x 的新控件还有两篇。

附录

Android 5.x 思维导图

参考

Android L Ripple的使用
RippleDrawable 的简单使用
RippleDrawable
Android-Toolbar 使用
利用Toolbar替换ActionBar
深入辨析Android四大组件(九)——Activity之AppCompatActivity与toolbar的结合
android acitonbar(toolbar)自定义溢出菜单样式
android 5.X Toolbar+DrawerLayout实现抽屉菜单
Android ToolBar 的简单封装
Using the Material Theme
Android Support Library 22.1
Material design
Android 5.x Theme 与 ToolBar 实战
ANDROID L - Material Design详解(主题和布局)
Material Theme
Android Material Design-Using the Material Theme(使用Material主题)-(二)

上一篇下一篇

猜你喜欢

热点阅读