ToolBar


  • 改变主题
    项目中默认使用的为ActionBar,需要使用ToolBar替代ActionBar
    指定主题为NoActionBar的,在values/styles.xml中修改
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

Theme.AppCompat.Light.NoActionBar为淡色主题,另外一种Theme.AppCompat.NoActionBar为深色主题,字会为黑色。

关于style、theme、attrs的关系可参考这篇文章
Android中Styles、Themes、attrs介绍

颜色分布代表下图的各个位置

找不到getSystemService 安卓 android中找不到design_ico

  • 修改activity_main.xml的代码
<android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        />

将高度设置为actionbar的高度

找不到getSystemService 安卓 android中找不到design_android_02


可以看到文字仍然我深色的,,因为Toolbar上面的元素会自动使用深色,但是这样很难看啊。

1.让Toolbar单独使用深色的主题

android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"

2.使弹出的菜单也变成浅色

app:popupTheme="@style/ThemeOverlay.AppCompat.Light"

找不到getSystemService 安卓 android中找不到design_ico_03

  • MainActivity中
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
        setSupportActionBar(toolbar);
    }
  • 设置按钮图标
    在res/menu下创建一个toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/find"
        android:icon="@drawable/find"
        android:title="find"
        app:showAsAction="always"
        />

    <item
        android:id="@+id/news"
        android:icon="@drawable/news"
        android:title="news"
        app:showAsAction="always"
        />

    <item
        android:id="@+id/settings"
        android:title="settings"
        app:showAsAction="never"
        />

    <item
        android:id="@+id/home"
        android:title="home"
        app:showAsAction="never"
        />
</menu>

app:showAsAction有三个值,always表示永远显示,ifRoom在屏幕空间不够的时候不显示,never则表示显示在菜单栏中

找不到getSystemService 安卓 android中找不到design_android_04

  • 添加其他的控件

找不到getSystemService 安卓 android中找不到design_xml_05

在MainActivity中添加

toolbar.setNavigationIcon(R.mipmap.ic_launcher);

找不到getSystemService 安卓 android中找不到design_xml_06

DrawerLayout+NavigationView


实现一个侧滑菜单的功能

  • 添加依赖
compile 'com.android.support:design:25.0.1'

DrawerLayout是一个布局,允许放入两个子控件,一个现实主屏幕中的内容,另一个为滑动菜单中的内容。

NavigationView用来实现滑动菜单的页面,分为headerLayout和menu。

  • 创建nav_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/item_collect"
        android:icon="@drawable/item_collect"
        android:title="Collect"/>
    <item
        android:id="@+id/item_draft"
        android:icon="@drawable/item_draft"
        android:title="draft" />
    <item
        android:id="@+id/item_find"
        android:icon="@drawable/item_find"
        android:title="find"/>
    <item
        android:id="@+id/focus"
        android:icon="@drawable/item_focus"
        android:title="focus"/>
    <item
        android:id="@+id/home"
        android:icon="@drawable/item_home"
        android:title="home" />
</menu>

android:icon设定显示的图标

  • 创建nav_header.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:background="?attr/colorPrimary"
    android:padding="10dp">

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/user_image"
        android:src="@drawable/user"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_centerInParent="true"/>

    <TextView
        android:id="@+id/user_intro"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:textColor="#FFFFFF"
        android:textSize="14sp"
        android:text="资深精分患者"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/user_intro"
        android:textColor="#FFFFFF"
        android:textSize="20sp"
        android:text="linsawako"/>

</RelativeLayout>

在这里使用了de.hdodenhof.circleimageview.CircleImageView,作用为将原本的图片变成圆形
需要添加依赖

compile 'de.hdodenhof:circleimageview:2.1.0'
  • 修改activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.Toolbar
            android:id="@+id/tool_bar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            />

    </FrameLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/nav_menu"
        app:headerLayout="@layout/nav_header"/>

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

FrameLayout为主屏幕中显示的内容,放入toolbar,滑动菜单显示navigationView,并使用刚才创建的nav_menu和nav_header.

  • activity中
public class MainActivity extends AppCompatActivity {

    private DrawerLayout mDrawerLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
        toolbar.setNavigationIcon(R.mipmap.ic_launcher);
        setSupportActionBar(toolbar);

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);

        ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.test1, R.string.test2);
        mDrawerToggle.syncState();
        mDrawerLayout.setDrawerListener(mDrawerToggle);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.toolbar, menu);
        return true;//表示允许创建的菜单显示出来
    }
}

想要打开导航抽屉,需要利用DrawerLayout.DrawerListener 监听器来监听打开和关闭事件,当导航抽屉打开和关闭时分别会回调 onDrawerOpened() 和 onDrawerClosed() 方法

如果含有ActionBar,可以使用ActionBarDrawerToggle,它实现了 DrawerListener 接口,可以监听到打开和关闭事件。构造方法参数有五个,分别代表:宿主 Activity 、 DrawerLayout 、导航抽屉打开时应用图标、导航抽屉打开时描述文本、导航抽屉关闭时描述文本

另外一种方法
设置HomeAsUp按钮

ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);//让导航按钮显示出来
            actionBar.setHomeAsUpIndicator(R.drawable.back);//设定导航按钮图标
        }

设置点击时打开菜单

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                mDrawerLayout.openDrawer(GravityCompat.START);
                break;
        }
        return true;
    }

Gravity参数,为了保证行为和XML中定义的一致

看下效果图

找不到getSystemService 安卓 android中找不到design_android_07

悬浮按钮


悬浮按钮FloatingActionButton

<android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|end"
        android:src="@drawable/comments"/>

layout_anchorGravity将悬浮按钮固定在右下角

可以指定悬浮的高度

app:elevation="8dp"

处理点击事件和按钮的差不多

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setImageResource(R.drawable.add);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //do something
                });

如果想设置为不可见,可以设置

fab.setVisibility(View.INVISIBLE);

找不到getSystemService 安卓 android中找不到design_xml_08

在Android studio自动生成的代码中可以发现是这样的

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.example.linsawako.zhihu.activity.Main2Activity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

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

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

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

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

CoordinatorLayout为一个加强版的FrameLayout,可以监听所有子控件的各种事件

Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();v

指定了基于哪个View触发,传入了FloatingActionButton本身,所以能被监听到,
会自动将fab向上移动,不会被遮挡。

AppBarLayout是一个垂直方向的LinearLayout,有很多滚动事件的封装。
可以设置在其他控件设置

app:layout_behavior="@string/appbar_scrolling_view_behavior"

就会将滚动的事件通知AppBarLayout,接收后,它内部的子控件可以指定如何反应,例如,设置Toolbar实现向上滚动时隐藏,向下滚动时重新显示。

<android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways|snap"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

app:layout_scrollFlags=”scroll|enterAlways|snap”,snap表示没有完全隐藏或显示式,根据当前滚动的距离,自动选择。

CollapsingToolBarLayout


它只能是AppBarLayout的直接布局,而AppBarLayout又必须是CoordinatorLayout的子布局。

自动生成的

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.example.linsawako.zhihu.activity.ScrollingActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_bar_height"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay" />

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

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

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|end"
        app:srcCompat="@android:drawable/ic_dialog_email" />

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

分开看看

CollapsingToolbarLayout标题栏
  • app:contentScrim=”?attr/colorPrimary”设置折叠后的背景色
  • app:layout_scrollFlags=”scroll|exitUntilCollapsed” scroll表示会随着内容滚动,exitUntilCollapsed表示滚动完后保留在界面。

它有一个子控件

Toolbar
  • app:layout_collapseMode=”pin”用于指定折叠过程的折叠模式,pin表示位置始终保持不变,parallax表示产出偏移。
FloatingActionButton
  • app:layout_anchor=”@id/app_bar”设置锚点
  • app:layout_anchorGravity=”bottom|end”相对于锚点的定位

include的布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.example.linsawako.zhihu.activity.ScrollingActivity"
    tools:showIn="@layout/activity_scrolling">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:text="@string/large_text" />

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

在ScrollView的基础上增加了嵌套响应滚动事件。只允许一个直接子布局。

  • 在NestedScrollView中
    app:layout_behavior=”@string/appbar_scrolling_view_behavior指定布局行为
  • 和CollapsingToolbarLayout中
    app:layout_scrollFlags=”scroll|exitUntilCollapsed”

对应,系统一旦发现NestedScrollView中有那句话,就会检查其他控件,然后如果有上面这句对应的话,那么滑动效果就是可以实现的。