这里有新鲜出炉的精品教程,程序狗速度看过来!
Android 是一种基于 Linux 的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由 Google 公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用 "安卓" 或 "安致"。
大家都知道 CoordinatorLayout 是一个 "加强版" 的 FrameLayout,那么下面这篇文章主要给大家分享了 Android 中关于 CoordinatorLayout 的一些布局技巧,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
介绍
CoordinatorLayout 是一个 "加强版" 的 FrameLayout,它主要有两个用途:
(1) 用作应用的顶层布局管理器
(2) 通过为子 View 指定 behavior 实现自定义的交互行为。
在我们做 Material Design 风格的 app 时通常都使用 CoordinatorLayout 作为布局的根节点,以便实现特定的 UI 交互行为。
那么现在我们来看看如何用已有的一些控件实现一些常见的布局。
Toolbar + TabLayout 实现 TabLayout 置顶效果
很常见的一种模式是 TabLayout 放在 ToolBar 布局中与其一起置顶在界面上方,而现在的效果是将 ToolBar 隐藏而 TabLayout 一直置顶在界面上方。
tablayout
如何实现呢?首先所在的 Activity 要使用 AppTheme.NoActionBar 风格主题,之后再编写布局文件。
- <android.support.design.widget.CoordinatorLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <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:layout_scrollFlags="scroll|enterAlways|snap"
- app:popupTheme="@style/AppTheme.PopupOverlay">
- <!-- toolbar内部布局文件 -->
- </android.support.v7.widget.Toolbar>
- <android.support.design.widget.TabLayout
- android:id="@+id/tab_layout"
- android:layout_width="match_parent"
- android:layout_height="@dimen/tab_height"
- app:tabIndicatorColor="@color/white"
- app:tabTextColor="@color/white_normal">
- </android.support.design.widget.TabLayout>
- </android.support.design.widget.AppBarLayout>
- <!-- 主界面布局文件 -->
- </android.support.design.widget.CoordinatorLayout>
很重要的两点:
保证 Toolbar 能随界面滑动向上隐藏。
- layout_scrollFlags="scroll|enterAlways|snap"
浸入式 + CollapsingToolbarLayout
CollapsingToolbarLayout 可以包裹 Toolbar , 当其显示完收缩动画时使 Toolbar 显示在顶端。而我们可以再加入浸入式的效果让 CollapsingToolbarLayout 的背景图突破系统的状态栏使界面更加美观同时也不影响 Toolbar 的显示效果。
浸入式布局
在实现布局文件前要赋予当前的 Activity 主题为 AppTheme.Immersive。
其样式要在 v19 与 v21 分别处理,至于 v19 之前的 android 版本那就无能为力了。
v19
- <style name="AppTheme.Immersive" parent="AppTheme.NoActionBar">
- <item name="android:windowTranslucentStatus">true</item>
- </style>
v21
- <style name="AppTheme.Immersive" parent="AppTheme.NoActionBar">
- <!--透明导航栏-->
- <item name="android:statusBarColor">@android:color/transparent</item>
- <item name="android:windowDrawsSystemBarBackgrounds">true</item>
- </style>
之后再来看布局文件,包括了 AppBarLayout,CollapsingToolbarLayout 和 Toolbar 这些控件。
同样也是要分为 v19 和 v21 两种布局
v19
- <?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.support.design.widget.AppBarLayout
- android:id="@+id/app_bar"
- android:layout_width="match_parent"
- android:layout_height="220dp"
- android:theme="@style/AppTheme.AppBarOverlay">
- <android.support.design.widget.CollapsingToolbarLayout
- android:id="@+id/collapsing_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:contentScrim="?attr/colorPrimary"
- app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
- app:statusBarScrim="@android:color/transparent"
- app:titleEnabled="false">
- <RelativeLayout
- android:id="@+id/anime_root"
- android:layout_width="match_parent"
- android:layout_height="220dp"
- app:layout_collapseMode="parallax"
- app:layout_collapseParallaxMultiplier="0.7">
- <!-- 可伸缩背景图布局文件 -->
- </RelativeLayout>
- <android.support.v7.widget.Toolbar
- android:id="@+id/toolbar"
- android:layout_width="match_parent"
- android:layout_height="?attr/actionBarSize"
- android:layout_marginTop="25dp"
- app:layout_collapseMode="pin"
- app:popupTheme="@style/AppTheme.PopupOverlay"
- app:titleMarginTop="15dp" />
- </android.support.design.widget.CollapsingToolbarLayout>
- </android.support.design.widget.AppBarLayout>
- <!-- 界面布局文件 -->
- </android.support.design.widget.CoordinatorLayout>
v21
- <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">
- <android.support.design.widget.AppBarLayout
- android:id="@+id/app_bar"
- android:layout_width="match_parent"
- android:layout_height="220dp"
- android:fitsSystemWindows="true"
- android:theme="@style/AppTheme.AppBarOverlay">
- <android.support.design.widget.CollapsingToolbarLayout
- android:id="@+id/collapsing_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true"
- app:contentScrim="?attr/colorPrimary"
- app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
- app:statusBarScrim="@android:color/transparent"
- app:titleEnabled="false">
- <RelativeLayout
- android:id="@+id/anime_root"
- android:layout_width="match_parent"
- android:layout_height="220dp"
- android:fitsSystemWindows="true"
- app:layout_collapseMode="parallax"
- app:layout_collapseParallaxMultiplier="0.7">
- <!-- 可伸缩背景图布局文件 -->
- </RelativeLayout>
- <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"
- app:titleMarginTop="15dp" />
- </android.support.design.widget.CollapsingToolbarLayout>
- </android.support.design.widget.AppBarLayout>
- <!-- 界面布局文件 -->
- </android.support.design.widget.CoordinatorLayout>
那么重点在哪里呢?
fitsSystemWindows 详解:这个一个 boolean 值的内部属性,让 view 可以根据系统窗口 (如 status bar) 来调整自己的布局,如果值为 true, 就会调整 view 的 paingding 属性来给 system windows 留出空间。
Fragment + 不同风格布局
有时候产品要求在一个 Activity 上显示不同的 Fragment 界面,且 Fragment 上的每一个头部样式都不一样,比如说一个是普通情况下的 Toolbar,另一个却是浸入式的可伸缩头部,像简书 app 的首页
额,我们先不提图中的那个 bug,图中的界面主要是两种效果,一个为普通的标题栏 + 正文,另一个则是浸入式的图片背景 + 正文。我们也可以利用浸入式的主题来仿照出简书的效果。
各个页面不同样式
第一步要做的是给 Fragment 所在的 Activity 套上 AppTheme.Immersive 浸入式主题样式,之后为 Activity 加上布局
- <?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"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <com.ashokvarma.bottomnavigation.BottomNavigationBar
- android:id="@+id/bottom_navigation_bar"
- android:layout_width="match_parent"
- android:layout_height="56dp"
- android:layout_gravity="bottom"
- android:fitsSystemWindows="true">
- </com.ashokvarma.bottomnavigation.BottomNavigationBar>
- <android.support.v4.view.ViewPager
- android:id="@+id/viewpager"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginBottom="56dp" />
- </android.support.design.widget.CoordinatorLayout>
无他,就是一个 ViewPager 容器用来加载 Fragment。
书城所在的 Fragment 布局如下:
- <?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"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true">
- <android.support.design.widget.AppBarLayout
- android:id="@+id/app_bar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:fitsSystemWindows="true"
- android:theme="@style/AppTheme.AppBarOverlay">
- <android.support.design.widget.CollapsingToolbarLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:fitsSystemWindows="true"
- app:contentScrim="?attr/colorPrimary"
- app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
- app:statusBarScrim="@android:color/transparent"
- app:titleEnabled="false">
- <!-- 背景布局 -->
- <android.support.v7.widget.Toolbar
- android:id="@+id/toolbar"
- android:layout_width="match_parent"
- android:layout_height="36dp"
- android:minHeight="36dp"
- app:layout_collapseMode="pin"
- app:popupTheme="@style/AppTheme.PopupOverlay">
- <!-- 搜索框布局 -->
- </android.support.v7.widget.Toolbar>
- </android.support.design.widget.CollapsingToolbarLayout>
- </android.support.design.widget.AppBarLayout>
- <!-- 界面主布局 -->
- </android.support.design.widget.CoordinatorLayout>
布局跟之前的浸入式布局相同,但单单这样布局是有问题的,此时的 Toolbar 会显示在系统的状态栏下。所以我们要修正 Toolbar 的摆放位置,即人为的为其设置 MarginTop 距离。
- /**
- * 修正 Toolbar 的位置
- * 在 Android 4.4 版本下无法显示内容在 StatusBar 下,所以无需修正 Toolbar 的位置
- *
- * @param toolbar
- */
- protected void fixToolbar(Toolbar toolbar) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- int statusHeight = getStatusBarHeight(getActivity());
- ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams();
- layoutParams.setMargins(0, statusHeight, 0, 0);
- }
- }
- /**
- * 获取系统状态栏高度
- *
- * @param context
- * @return
- */
- public int getStatusBarHeight(Context context) {
- Class < ?>c = null;
- Object obj = null;
- Field field = null;
- int x = 0,
- statusBarHeight = 0;
- try {
- c = Class.forName("com.android.internal.R$dimen");
- obj = c.newInstance();
- field = c.getField("status_bar_height");
- x = Integer.parseInt(field.get(obj).toString());
- statusBarHeight = context.getResources().getDimensionPixelSize(x);
- } catch(Exception e1) {
- e1.printStackTrace();
- }
- return statusBarHeight;
- }
在每个 Fragment 初始化 Toolbar 时都需要调用这个方法来修正位置。
重点又来了:
Fragment 与 Toolbar 的选项菜单问题
在 Fragment 之间切换的时候很容易遇到 Toolbar 上的菜单无法正确的显示的问题,解决方法也很简单,在 Fragment 的 onCreateView() 方法中添加一行代码:
- toolbar.setTitle("title"); ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
- fixToolbar(toolbar);
- setHasOptionsMenu(true); //重要的一行代码,防止选项菜单错乱
总结
自从 Google 出了 com.android.support:design 包之后,其多样化的定制给 App 应用带来更加酷炫的效果,布局的变化只不过是其中的一部分而已。文章的开头也说了, CoordinatorLayout 不止是带来了布局的变化,也带给了控件更多的 UI 交互动作。
来源: http://www.phperz.com/article/17/0827/337541.html