Android M 控件:Snackbar、Toolbar、TabLayout、NavigationView

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显示样子

Toolbar
Toolbar是应用的内容的标准工具栏,可以说是Actionbar的升级版,两者不是独立关系,要使用Toolbar还是得跟 ActionBar扯上关系的。相比Actionbar Toolbar最明显的一点就是变得很自由,可随处放置,因为它是作为一个ViewGroup来定义使用的,所以单纯使用ActionBar已经稍显过时 了,它的一些方法已被标注过时。

 

从左到右分别是我们前面提及到的导航栏图标,App的logo,标题和子标题,自定义控件以及ActionMenu 。

那么它怎么使用呢,首先我们一样要用到v7的支持包,然后定义程序的主题样式,在style里得先把Actionbar去掉,有点像欲想练功,必先自宫的感觉啊。如下:

/res/values/styles.xml

<style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">    

     <!-- toolbar(actionbar)颜色 -->  

        <item name="colorPrimary">#4876FF</item>  

        <!-- 状态栏颜色 -->  

        <item name="colorPrimaryDark">#3A5FCD</item>  

        <!-- 窗口的背景颜色 -->  

       <item name="android:windowBackground">@android:color/white</item>  

       <!-- SearchView -->  

       <item name="searchViewStyle">@style/MySearchViewStyle</item>  
   <!-- 底部导航栏颜色 -->  
      <item name="android:navigationBarColor">#4876FF</item> 
   </style>  

去除Actionbar最简单的方法就是直接继承NoActionBar的主题了。颜色的属性说明,还是下面这张图最清楚了: 

SearchView在AppCompat中提供了更强的可定制性和更多的样式可供设置,不过一般我们用默认的就行。
toolbar属性:


使用代码:
mToolbar = (Toolbar) findViewById(R.id.toolbar);  

// toolbar.setLogo(R.drawable.ic_launcher);  

mToolbar.setTitle("Rocko");// 标题的文字需在setSupportActionBar之前,不然会无效  

// toolbar.setSubtitle("副标题");  

setSupportActionBar(mToolbar);  

/* 这些通过ActionBar来设置也是一样的,注意要在setSupportActionBar(toolbar);之后,不然就报错了 */  

// getSupportActionBar().setTitle("标题");  

// getSupportActionBar().setSubtitle("副标题");  

// getSupportActionBar().setLogo(R.drawable.ic_launcher);  

  

/* 菜单的监听可以在toolbar里设置,也可以像ActionBar那样,通过Activity的onOptionsItemSelected回调方法来处理 */  

mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {  

    @Override  

    public boolean onMenuItemClick(MenuItem item) {  

        switch (item.getItemId()) {  

        case R.id.action_settings:  

            Toast.makeText(MainActivity.this, "action_settings", 0).show();  

            break;  

        case R.id.action_share:  

            Toast.makeText(MainActivity.this, "action_share", 0).show();  

            break;  

        default:  

            break;  

        }  

        return true;  

    }  

});  
上面关键的一点就是setSupportActionBar(mToolbar);把Toolbar当做ActionBar给设置了。menu还是可以像ActionBar一样用和处理的


有几个代码里面需要注意的地方:

· 我们在使用 Toolbar 时候需要先隐藏掉系统原先的导航栏,网上很多人都说给Activity设置一个NoActionBar的Theme。但个人觉得有点小题大做了,所以这里 我直接在BaseActivity中调用 supportRequestWindowFeature(Window.FEATURE_NO_TITLE) 去掉了默认的导航栏(注意,我的BaseActivity是继承了AppCompatActivity的,如果是继承Activity就应该调用 requestWindowFeature(Window.FEATURE_NO_TITLE))

· 如果你想修改标题和子标题的字体大小、颜色等,可以调用 setTitleTextColor setTitleTextAppearance 

    setSubtitleTextColor  setSubtitleTextAppearance 这些API;

· 自定义的View位于 title subtitle 和 actionmenu 之间,这意味着,如果 title 和 subtitle 都在,且actionmenu选项 太多的时候,留给自定义View的空间就越小;

· 导航图标和 app logo 的区别在哪?如果你只设置 导航图标(or app logo)和 title subtitle,会发现 app logo 和 title subtitle 的间距比较小,看起来不如 导航图标 与 它们两搭配美观;

· Toolbar和其他控件一样,很多属性设置方法既支持代码设置,也支持在xml中设置(这里也是最最最最最坑爹的地方,如何坑爹法,请接着往下看);

Action Menu Item 的文字颜色设置无效

系统默设置了ActionMenu每个Item的文字颜色和大小,像ToolbarActivity在Google原生5.1系统下默认效果就是下面这样的

此时,如果我有需求要改变一下item文字颜色,应该怎么破?我按照网上比较普遍的解决方案,做了如下两步的修改操作:

在styles.xml中自定义一个Theme,并设置 actionMenuTextColor 属性(注意:不是 android:actionMenuTextColor )

<style name="Theme.ToolBar.Base" parent="Theme.AppCompat.Light.NoActionBar">

    <item name="actionMenuTextColor">@color/color_red</item>

</style>

在布局文件的Toolbar中设置popupTheme(注意:是toolbar:xxx,不是android:xxx)

    <android.support.v7.widget.Toolbar

        android:id="@+id/toolbar"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:background="@color/color_0176da"

        toolbar:popupTheme="@style/Theme.ToolBar.Base">

 

        <!--自定义控件-->

        <TextView

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Clock" />

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

运行之后,文字的颜色的并没有发生任何改变。说好的改变颜色呢…..找来找去,最后再 StackOverflow 找到一个还不错的解决方案,就是把上面的的 actionMenuTextColor 属性换成 android:textColorPrimary 即可解决,最终得到下面的运行效果。


成功修改 actionmenu item 文字的颜色
这种方法也有一个小缺点,如果我把自定义控件换成Button,你会发现Button默认的文字颜色也变成了红色。所以,此处如果有朋友有更好的解决方案,请留言赐教。

如果你想要修改 ActionMenu Item 的文字大小,也可以在theme中设置加上如下设置

<item name="android:textSize">20sp</item>

以上就是目前使用 Toolbar 一些比较折腾的坑,感觉 Google 对 Toolbar 这些坑,还可以进一步优化优化

TabLayout

应用中通过Tab在不同视图中间切换对于材料设计而言并非一个新的概念,他们等同于主页的顶级导航模式或者在应用内组织不同群组的内容如图

 

TabLayout既实现了固定的选项卡 - view的宽度平均分配,也实现了可滚动的选项卡 - view宽度不固定同时可以横向滚动。

选项卡可以在程序中动态添加:
    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);

tabLayout.setupWithViewPager(mViewPager);

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

可以调整两个属性来显示 TabLayout:

  app:tabMode - 如果你想在屏幕上显示出每个单独的 tab,就设置 tab 为 fixed 的, 。它适合只有少数 tab 的时候,但是如果有很多的 tab 的时候这是一个完全错误的选择。在这种情况下你是不确定所有的 tab 是否能很好的在同一时间显示出来的。所以,你可以设置这个属性为 scrollable 让用户去滚动 tab,就像 Google Play Store 那样。

  app:tabGravity - 如果你想要分配所有的可用空间给每个 tab,就设置这个属性为 fill。如果你想要所有的 tab 在屏幕的中间,就设置这个属性为 center。请注意,如果 tabMode 是设置成 scrollable 的,则这个属性将会被忽略。

如下图

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

之前Google在V4包中推出自己的 DrawerLayout作为抽屉侧滑菜单,标准使用方法可以参考 google 原生态 抽屉式侧滑菜单 Android DrawerLayout 布局的使用介绍。
当时的官方布局是这样的:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"  

    android:id="@+id/drawer_layout"  

    android:layout_width="match_parent"  

    android:layout_height="match_parent" > 

    <!-- the main content view --> 

    <FrameLayout  

        android:id="@+id/frame_content"  

        android:layout_width="match_parent"  

        android:layout_height="match_parent" >  

    </FrameLayout>  

    <!-- the navigetion view -->  

    <ListView  

        android:id="@+id/drawer_list"  

        android:layout_width="240dp"  

        android:layout_height="match_parent"  

        android:layout_gravity="start"  

        android:background="#9999cc"  

        android:choiceMode="singleChoice"  

        android:divider="@android:color/transparent"  

        android:dividerHeight="0dp" >  

    </ListView>  

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

其实这次谷歌只是将上面的ListView布局替换成NavigationView了。简化了之前ListView写适配器的繁琐。

如今布局改成如下:

<android.support.v4.widget.DrawerLayout 

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'>

<!-- your content layout -->

<android.support.design.widget.NavigationView

android:layout_width='wrap_content'

android:layout_height='match_parent'

android:layout_gravity='start'

app:headerLayout='@layout/drawer_header'

app:menu='@menu/drawer'/>

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

 

其中最重要的就是这两个属性:
app:headerLayout //给NavigationView添加头部布局 
app:menu //给NavigationView添加menu菜单布局
通过这两个属性,我们可以非常方便的指定导航界面的头布局和菜单布局:

其中NavigationView 中的 android:layout_gravity=”start” 属性来控制抽屉菜单从哪边滑出,一般“start ”从左边滑出,“end”从右边滑出。

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="200dp"

    android:background="@drawable/img1"

    android:gravity="center"

    android:orientation="vertical">

    <ImageView

        android:layout_width="125dp"

        android:layout_height="125dp"

        android:scaleType="centerCrop"

        android:src="@drawable/image" />

    <TextView

        android:layout_marginTop="15dp"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="CSDN废墟的树博客"

        android:textColor="@android:color/white" />

</LinearLayout>

app:menu 布局如下:

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

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

    android:layout_width="match_parent"

    android:layout_height="match_parent">

    <group

        android:checkableBehavior="single"

        android:title="Home items">

        <item

            android:id="@+id/nav_blog"

            android:icon="@drawable/ic_account_balance_black_24dp"

            android:title="博客地址" />

        <item

            android:id="@+id/nav_ver"

            android:icon="@drawable/ic_error_outline_black_36dp"

            android:title="版本信息" />

        <item

            android:id="@+id/nav_about"

            android:icon="@drawable/ic_error_outline_black_36dp"

            android:title="关于我" />

    </group>

    <item android:title="Sub items">

        <menu>

            <item

                android:id="@+id/sub_exit"

                android:icon="@drawable/ic_power_settings_new_black_36dp"

                android:title="退出应用" />

            <item

                android:id="@+id/sub_switch"

                android:icon="@drawable/ic_settings_applications_black_36dp"

                android:title="切换主题" />

        </menu>

    </item>

</menu>

代码中控制NavigationView

private void initNavigationView(){

        navigationView = (NavigationView) findViewById(R.id.navigationView);

        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

        //设置侧滑菜单选择监听事件

        navigationView.setNavigationItemSelectedListener(new  NavigationView.OnNavigationItemSelectedListener() {

            @Override

            public boolean onNavigationItemSelected(MenuItem menuItem) {

                menuItem.setChecked(true);

                //关闭抽屉侧滑菜单

                drawerLayout.closeDrawers();

                return true;

            }

        });

    }

 

    @Override

    public boolean onOptionsItemSelected(MenuItem item) {

        if (item.getItemId() == android.R.id.home){

            //打开抽屉侧滑菜单

            drawerLayout.openDrawer(GravityCompat.START);

        }

        return super.onOptionsItemSelected(item);

    }

关于NavigationView中item的字体颜色和icon选中状态颜色是去当前主题theme中的

<--正常状态下字体颜色和icon颜色-->

<item name="android:textColorPrimary">@android:color/darker_gray</item>

<--选中状态icon的颜色和字体颜色-->

 <item name="colorPrimary">@color/accent_material_light</item>





原文地址:https://www.cnblogs.com/ut2016-progam/p/5379603.html