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介绍
颜色分布代表下图的各个位置
- 修改activity_main.xml的代码
<android.support.v7.widget.Toolbar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
/>
将高度设置为actionbar的高度
可以看到文字仍然我深色的,,因为Toolbar上面的元素会自动使用深色,但是这样很难看啊。
1.让Toolbar单独使用深色的主题
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
2.使弹出的菜单也变成浅色
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
- 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则表示显示在菜单栏中
- 添加其他的控件
在MainActivity中添加
toolbar.setNavigationIcon(R.mipmap.ic_launcher);
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中定义的一致
看下效果图
悬浮按钮
悬浮按钮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);
在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中有那句话,就会检查其他控件,然后如果有上面这句对应的话,那么滑动效果就是可以实现的。