Material design刚面世的时候简直是惊艳,然而这么久还是没流行起来,主要原因我觉得还是android5.0普及度还不够,当然国内设计师也是一大原因. 据我所知,很多美工都不知道material design是个什么东西。幸运的是,谷歌终于推出了material design的开发库,最低能支持到android2.1,这可是官方的库啊,此时不用,更待何时。

准备工作

『工欲善其事,必先利其器』。 环境列表:

  • Windows/Mac
  • Android Studio 1.3
  • Android SDK
  • 科学上网(开发人员还是准备一个吧)

我这里全程所用环境都是Android Studio,为什么不用eclipse呢? 因为我受够了每次 loader 0% 的痛苦。当然eclipse的adt插件已经很久不更新了,而且谷歌宣布Android Studio将取代Eclipse编译环境 中止对后者支持

刚从eclipse转到android studio,作为一个成年人,都觉得各种不适应。不过只要坚持下来,一旦习惯了这种设定,还是觉得挺带感的。原生的gradle的支持,打包、库依赖啊什么的,简直不要太轻松,尤其是现在的1.3版本,原生支持 C/C++ 开发。简直能玩上瘾。

//TODO 关于android studio的用法,伸手党可以坐等我有空再写几篇文章,有可能是有生之年系列。勤快的话,你就去谷歌找资料。

本文的实例参考了官方的demo

从标题栏开始吧

appcompat-v7 库开始提供了 Toolbar 用来取代 ActionBar。而Material Support Library库又增加了 AppBarLayout 来增强标题的设计体验。

  • AppBarLayout是什么?
    根据官网的介绍,我谷歌翻译了一下,大概意思就是用来实现标题栏手势的一个布局,通俗点就是用来做标题栏滚动效果的。举个栗子:直接看图吧。

那个title的伸缩效果就需要用到AppBarLayout。

使用方法类似这样:

 <android.support.design.widget.CoordinatorLayout
         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.support.v4.widget.NestedScrollView
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             app:layout_behavior="@string/appbar_scrolling_view_behavior">

         <!-- Your scrolling content -->

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

     <android.support.design.widget.AppBarLayout
             android:layout_height="wrap_content"
             android:layout_width="match_parent">

         <android.support.v7.widget.Toolbar
                 ...
                 app:layout_scrollFlags="scroll|enterAlways"/>

         <android.support.design.widget.TabLayout
                 ...
                 app:layout_scrollFlags="scroll|enterAlways"/>

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

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

现在大家应该对material的标题栏有个粗略的印象了。那么我们正式开始学习标题栏的使用方法。

android5.0以上原生提供了material的样式引用

@android:style/Theme.Material (dark version)
@android:style/Theme.Material.Light (light version)
@android:style/Theme.Material.Light.DarkActionBar

兼容低版本的Material标题

如果需要兼容到低版本的android,我们就需要通过v7库提供的样式来设计app。

首先创建一个新的工程,添加依赖。然后修改主题样式。

compile 'com.android.support:appcompat-v7:22.2.1'

activity需要集成** AppCompatActivity**

class MainActivity extends AppCompatActivity

values/styles.xml

<!-- Base application theme. -->
<style name="Theme.DesignDemo" parent="Base.Theme.DesignDemo">
</style>

<style name="Base.Theme.DesignDemo" parent="Theme.AppCompat.Light.NoActionBar">
  <item name="colorPrimary">#673AB7</item>
  <item name="colorPrimaryDark">#512DA8</item>
  <item name="colorAccent">#FF4081</item>
  <item name="android:windowNoTitle">true</item>
  <item name="windowActionBar">false</item>
  <item name="android:windowBackground">@color/window_background</item>
</style>

values-v21/styles.xml

<style name="Theme.DesignDemo" parent="Base.Theme.DesignDemo">
  <item name="android:windowDrawsSystemBarBackgrounds">true</item>
  <item name="android:statusBarColor">#512DA8</item>
</style>

我们使用了Theme.AppCompat.Light.NoActionBar作为父样式,并且定义了一系列颜色值,这些颜色值作用是什么呢?这里用一张官网的图片来说明。

需要注意的是android:statusBarColor这个属性只有android5.0以上才有,这个用来设置状态栏颜色。

这样我们的样式就定义好了,接下来我们完成标题栏的布局。 在activity_main.xml中添加代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/drawer_layout"
    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">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:layout_gravity="center"
                app:layout_collapseMode="parallax"
                app:layout_scrollFlags="scroll|enterAlways"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

            </android.support.v7.widget.Toolbar>


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


</LinearLayout>

MainActivity.java 中添加代码

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.drawerlayout = (LinearLayout) findViewById(R.id.drawer_layout);
        this.appbar = (AppBarLayout) findViewById(R.id.appbar);
        this.toolbar = (Toolbar) findViewById(R.id.toolbar);

        toolbar.setTitle("呵呵哒么么哒");

    }

运行效果:

这样material风格的title效果就出来了。

标题如何居中?

Title居中,这是国内很多设计师喜欢的干的事情,非常常见。Android开发中标题设计基本走进了死循环,很少有app去使用系统自带的标题栏工具,基本都是自定义一个布局来替代,但是这样却失去很多Android原生能带来的优秀设计。当然也可能与曾经的ActionBar缺少灵活的自定义功能有关,ToolBar明显是考虑到了这个问题,所以允许我们自定义每一个部分。

修改activity_main.xml代码:

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:layout_gravity="center"
                app:layout_collapseMode="parallax"
                app:layout_scrollFlags="scroll|enterAlways"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:layout_gravity="center"
                    android:textColor="@android:color/white"
                    android:textSize="20sp"
                    android:text="呵呵哒"/>

            </android.support.v7.widget.Toolbar>

只需要在toolbar布局中包含一个textview,使其居中显示即可。看效果。

关联菜单

menu的关联和以前的ActionBar是一样的,只需要加一句代码

setSupportActionBar(toolbar);

如果我们自定义了toolbar的标题,千万记住要添加一句

getSupportActionBar().setDisplayShowTitleEnabled(false);

否则原本左侧的标题也会显示出来。 详细代码如下:

public class MainActivity extends AppCompatActivity {


    private android.support.v7.widget.Toolbar toolbar;
    private android.support.design.widget.TabLayout tabs;
    private android.support.design.widget.AppBarLayout appbar;
    private android.support.design.widget.CoordinatorLayout snackbarPosition;
    private android.widget.LinearLayout drawerlayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.drawerlayout = (LinearLayout) findViewById(R.id.drawer_layout);
        this.appbar = (AppBarLayout) findViewById(R.id.appbar);
        this.toolbar = (Toolbar) findViewById(R.id.toolbar);
//        toolbar.setNavigationIcon(R.mipmap.ic_launcher);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowTitleEnabled(false);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

}

显示效果如下:

我们还可以设置左侧导航的图标

toolbar.setNavigationIcon(R.mipmap.ic_launcher);

效果图:

标题的基本使用方式就是这样。更多的大家可以自行去挖掘。

Snackbar

这个东西官网的说法是为操作提供一个轻量级的反馈。通俗点讲,这东西就是用来取代Toast的。

这个控件是在material库里面加入的,使用之前需要先加入依赖

compile 'com.android.support:design:22.2.1'

使用方法很简单。一句代码搞定
我们修改一下前面那部分代码的菜单点击事件,使它点击后弹出Snackbar

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            Snackbar.make(toolbar, "这是一个学习用的snackbar", Snackbar.LENGTH_LONG)
            .setAction("取消", new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {

                        }
                    })
                    .show();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

语法:

Snackbar.make(View view, CharSequence text, int duration).show()

可以看到和Toast使用方法基本一致,但是第一个参数是一个view,这个view是用来定位用的,因为Snackbar默认显示在布局的底部。**这个view不需要特别构建,只要是当前布局的任何一个view都可以。**我可以把传入的 toolbar 替换为 appbardrawerlayout等等只要是当前这个布局中的任意view。

点击右上角的菜单后,效果图如下:

如何显示Snackbar在顶部?

Snackbar是没有API直接去设置它显示在顶部的,但是stackoverflow上面有大神给出了解决方案,我们代码修改如下:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            Snackbar snack = Snackbar
                    .make(drawerlayout, "这是一个学习用的snackbar", Snackbar.LENGTH_LONG)
                    .setAction("取消", new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {

                        }
                    });
            View view = snack.getView();
            FrameLayout.LayoutParams params =(FrameLayout.LayoutParams)view.getLayoutParams();
            params.gravity = Gravity.TOP;
            view.setLayoutParams(params);
            snack.show();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

再次运行,效果如下:

本篇文章先介绍这些,之后我会通过其他文章继续介绍Material的其他控件使用方法,敬请观看。谢谢。文章为原创,转载请注明出处。

您可以继续阅读android material design学习(二)