什么叫一站式
那还用问,就是一学就会呗。啦啦啦啦啦啦啦啦啦啦啦啦啦!
主要是我看别人的介绍的东西看得头大,一大堆重要细节都没有,漏了一点细节的话很多效果都没有。总得来说一站式就是吹牛皮。
文章比较长耐心看完就会用
一、撸代码前要了解的东西
Google在2015的IO大会,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个support库里面,Google给我们提供了更加规范的MD设计风格的控件。最重要的是,Android Design Support Library的兼容性更广,直接可以向下兼容到Android 2.2。(敲黑板,这是重点拿笔记下来)
上面提到了Design Support Library
,要使用这个库当然是要引入到项目中咯,在Gradle中引入:
compile 'com.android.support:design:24.1.0'
CoordinatorLayout
等一些控件就是Material Design设计风格的控件,具体有哪些控件可以搜一下。望文生义这个控件就是协调控件:
- 扩展或者缩小Toolbar或者头部,让主内容区域有更多的空间。
- 控制哪个view应该扩展还是收缩,以及其显示大小比例,包括视差滚动效果动画。
看一下效果图呗(颜色不协调是为了更好的区分不同区域):
控制哪个view应该扩展还是收缩,以及其显示大小比例,包括视差滚动效果动画。
扩展或者缩小Toolbar或者头部,让主内容区域有更多的空间。
这三种效果主要都是根据xml来决定,当然还可以通过自定义Behavior来完成这个或者完成更复杂的效果,这些都不管,现在只用xml来完成。
如果效果还尽人意请往下看看呗。
二、CoordinatorLayout与CollapsingToolbar控制View的伸展与收缩
大致的效果在上图1所示。一下分解各个实现的步骤。
- 首先咱们要使用ToolBar一般都是要先隐藏原来的ActionBar,隐藏ActionBar有几种方法,这里我们就只在Manifest.xml里面进行配置。创建一个
activity
命名CoorCollapsingToolbarAct
然后在xml中进行注册并设置Theme
:
<activity android:name=".CoorToolViewPagerAct"
android:theme="@style/coordinatorTheme"/>
coordinatorTheme
是在res\values\styles.xml
中的自定义样式,父样式parent就是去掉ActionBar的样式如下:
<!--colorPrimaryDark设置透明色的原因是为了通过后面对状态栏的颜色改变起效果(可以试着改变一下看效果)-->
<style name="coordinatorTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:colorPrimary">@color/colorPrimary</item>
<item name="android:colorPrimaryDark">@android:color/transparent</item>
</style>
-
要实现这些效果需结合
AppBarLayout
来共同完成:
-
AppBarLayout
必须作为CoordinatorLayout
的直接子View
,否则它的大部分功能将不会生效,如layout_scrollFlags
等。 -
AppBarLayout
它可以让你定制当某个可滚动View
的滚动手势发生变化时,其内部的子View
实现何种动作。 - 内部的子
View
通过在布局中加app:layout_scrollFlags
设置执行的动作,具体往下看。
- 知道什么是CollapsingToolBarLayout
- CollapsingToolbarLayout你可以像魔术一样让
Toolbar
折叠起来- 用 CollapsingToolbarLayout 包裹 Toolbar,但仍然在 AppBarLayout 中
- 从 Toolbar 不设置
layout_scrollFlags
- 为 CollapsingToolbarLayout 声明
layout_scrollFlags
,并且将layout_scrollFlags
设置成scroll|exitUntilCollapsed|snap
- 改变 AppBarLayout 扩张状态时的布局高度大小。在这个例子中,我用 250dp
app:layout_scrollFlags属性值
scroll: 所有想滚动出屏幕的view都需要设置这个flag, 没有设置这个flag的view将被固定在屏幕顶部。
snap: 在滚动结束后,如果view只是部分可见,它将滑动到最近的边界。
exitUntilCollapsed: 滚动退出屏幕,最后折叠在顶端。
还有enterAlways,enterAlwaysCollapsed等属性可以逐一试试看。
-
xml编写
使用CoordinatorLayout往往是将他直接作为根布局来操作。创建activity_coor_collapsing.xml.
<?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"
>
<!--app:elevation="0dp" TabLayout与AppBarLayout结合使用TabLayout下面会出现阴影 设置此属性可去除-->
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:layout_width="match_parent"
android:layout_height="300dp"
android:fitsSystemWindows="true"
android:elevation="0dp">
<!--
1、statusBarScrim 折叠时状态栏的颜色(设置为透明色时,状态栏会展示contentScrim背景色的效果)
contentScrim:折叠之后的背景色(不包括状态栏)
2、注意:暂时发现 5.x与4.x的系统不设置折叠样式时,折叠时会将title默认隐藏,具体效果可以试试,不知道是不是机型问题,有待考察
collapsedTitleTextAppearance 折叠字体样式 expandedTitleMarginStart 展开字体样式-->
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/main_collapsing"
android:layout_width="match_parent"
android:layout_height="250dp"
android:fitsSystemWindows="true"
app:collapsedTitleTextAppearance="@style/collapsedTitleTextAppearance_white"
app:contentScrim="@color/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:expandedTitleTextAppearance="@style/collapsedTitleTextAppearance_green"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:statusBarScrim="#fff000">
<!--layout_collapseMode (折叠模式) - 有两个值:
pin - 设置为这个模式时,当CollapsingToolbarLayout完全收缩后,Toolbar还可以保留在屏幕上。
parallax - 设置为这个模式时,在内容滚动时,CollapsingToolbarLayout中的View(比如ImageView)也可以同时滚动,实现视差滚动效果,通常和layout_collapseParallaxMultiplier(设置视差因子)搭配使用。
layout_collapseParallaxMultiplier(视差因子) - 设置视差滚动因子,值为:0-1。-->
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@drawable/jjy_bg"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="1"
/>
<!--app:popupTheme,这个属性就是用来自定义我们弹出的菜单的样式,在之前的Actionbar的溢出菜单,
我们是不能自定义他的样式的,只能根据你的theme来选择黑白两种,不能自己定义,现在我们可以定义弹出菜单的样式。
暂时使用系统定义好的样式-->
<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/ThemeOverlay.AppCompat.Light"/>
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/colorPrimary"
app:tabIndicatorColor="@color/colorAccent"
app:tabSelectedTextColor="#000"
app:tabTextColor="#fff"/>
</android.support.design.widget.AppBarLayout>
<!--layout_behavior=”@string/appbar_scrolling_view_behavior”标志位(该Behavior系统以及帮我们实现),
那么当带有这个标志位的控件滑动的时候会触发带有scroll_flags标志位的另一个控件进行滑动,
此时imageview的layout_collapseMode是parallax,所以它会以有视差的方式来相对滑动,而toolbar设置了pin的标记位,
所以在收缩后会固定在屏幕顶部。
可在VIewPager中放置Recyclerview,ScrollView等滑动的布局(ListView与GridView不行)可进行联动-->
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v4.view.ViewPager>
<!--没有渐变效果一直显示不隐藏 原因时上面使用了TabLayout 感觉是不能在AppBarLayout添加TabLayout来一起使用-->
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:clickable="true"
android:src="@android:drawable/ic_menu_add"
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"/>
</android.support.design.widget.CoordinatorLayout>
分析+解密[吹牛皮](敲黑板,文件中的注释是重点记下来要考)
- CollapsingToolbarLayout中的
statusBarScrim
:折叠时状态栏的颜色。前面在Activity的Theme
中将状态栏设置为透明色,所以当折叠ToolBar时会显示我们在这里设置的色值。如果在Theme
中不设置为透明这里将不起作用。 - 根布局CoordinatorLayout与AppBarLayout都要设置
android:fitsSystemWindows="true"
,如对此属性不懂可参考fitsystemwindows简单使用 - layout_behavior=”@string/appbar_scrolling_view_behavior”标志位(该Behavior系统以及帮我们实现),那么当带有这个标志位的控件滑动的时候会触发带有scroll_flags标志位的另一个控件进行滑动,此时imageview的layout_collapseMode是parallax,所以它会以有视差的方式来相对滑动,而toolbar设置了pin的标记位,所以在收缩后会固定在屏幕顶部。可在VIewPager中放置Recyclerview,ScrollView等滑动的布局(ListView与GridView不行)可进行联动.
比较奇葩的发现
暂时发现,如果你想实现title(图一的LOGO)的的效果,需设置CollapsingToolbarLayout的title值,然而5.x与4.x的系统不设置折叠样式
collapsedTitleTextAppearance
时,折叠时会将title默认隐藏,具体效果可以试试,不知道是不是机型问题,有待考察,6.x的系统不设置折叠时也会展示出来。
三、撸代码(图一效果)
因为用上了ViewPager
,所以顺带也用上了TabLayout
,不了解可以看看TabLayout高端用法,所以也结合了Fragment
实现。
- 大致创建一个简单的
Fragment
的基类BaseFragment:
/**
* Created by Leogh on 2017/8/28.
*/
public abstract class BaseFragment extends Fragment {
//这个title不用管 弄着玩的
public TextView tv_title;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = getLayoutView(inflater, container);
tv_title = (TextView) view.findViewById(R.id.tv_title);
init();
return view;
}
public abstract View getLayoutView(LayoutInflater inflater, ViewGroup container);
public abstract void init();
}
在创建三个Fragment,分别为Fragment1,Fragment2,Fragment3
简单粗暴嘛,这里只贴一个Fragment1的
代码,其它两个类似改一下就OK。
/**
* Created by Leogh on 2017/8/28.
*/
public class Fragment1 extends BaseFragment {
private View view;
private RecyclerView rv_page1;
private List<String> mDatas = new ArrayList<String>();
@Override
public View getLayoutView(LayoutInflater inflater, ViewGroup container) {
view = inflater.inflate(R.layout.fragment_page1, container, false);
return view;
}
@Override
public void init() {
initData();
tv_title.setText("one");
rv_page1 = (RecyclerView) view.findViewById(R.id.rv_page1);
rv_page1.setLayoutManager(new LinearLayoutManager(getActivity()));
rv_page1.setAdapter(new CoorAdapter(getActivity(), mDatas));
}
private void initData() {
for (int i = 0; i < 20; i++) {
mDatas.add("老腊肉" + i);
}
}
}
差点漏了Recyclerview的Adapter了CoorAdapter
:
/**
* Created by Leogh on 2017/8/29.
*/
public class CoorAdapter extends RecyclerView.Adapter<CoorAdapter.MyViewHolder> {
private Context mContext;
private List<String> mDatas;
public CoorAdapter(Context mContext, List<String> mDatas) {
this.mContext = mContext;
this.mDatas = mDatas;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.main_list_item, parent, false);
return new MyViewHolder(v);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.textView.setText(mDatas.get(position));
}
@Override
public int getItemCount() {
return mDatas.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public MyViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.textview);
}
}
}
Fragment1的布局文件fragment_page1.xml
:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="one"
android:textSize="20sp"
android:layout_centerInParent="true"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_page1"
android:background="#efffff"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"/>
</RelativeLayout>
最后主Activity上场CoorCollapsingToolbarAct
:
/**
* Created by Leogh on 2017/8/28.
* 图片渐变效果与CollapsingToolBarLayout(折叠ToolBar)
* <p>
* 要实现此效果 需要使用 CoorinatorLayout (协调布局) AppBarLayout(导航布局) + 一个可以滑动的布局
* (注意 不支持 listView和GirdView)
*/
public class CoorCollapsingToolbarAct extends AppCompatActivity {
private Toolbar mToolBar;
private ViewPager mViewPager;
private TabLayout mTabLayout;
private CollapsingToolbarLayout main_collapsing;
private List<Fragment> mFragments;
private String[] mTitles = new String[]{"你", "我", "他"};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coordinator);
mToolBar = (Toolbar) findViewById(R.id.toolbar);
mToolBar.setLogo(android.R.drawable.ic_menu_add);
main_collapsing = (CollapsingToolbarLayout) findViewById(R.id.main_collapsing);
//手动设置title
// 注意:目前测试用的是5.1系统 发现不在xml中设置折叠字体样式,折叠时title也会直接隐藏,同时也试了4.4系统也是一样,6.0系统不会
//我也没有专门去测试,也不能直接得出结论说5.x与4.x的系统一定要设置 具体情况具体分析哈 多试试
main_collapsing.setTitle("LOGO");
setSupportActionBar(mToolBar);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mTabLayout = (TabLayout) findViewById(R.id.tabs);
setupViewPager();
}
private void setupViewPager() {
mFragments = new ArrayList<Fragment>();
mFragments.add(new Fragment1());
mFragments.add(new Fragment2());
mFragments.add(new Fragment3());
FragmentPagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mTitles[position];
}
};
mViewPager.setAdapter(adapter);
//ViewPager与TabLayout联动
mTabLayout.setupWithViewPager(mViewPager);
}
/**
* 如果有Menu,创建完后,系统会自动添加到ToolBar上
* 此方法用于初始化菜单,其中menu参数就是即将要显示的Menu实例。 返回true则显示该menu,false 则不显示;
* (只会在第一次初始化菜单时调用)
*
* @param menu
* @return
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
}
到此就可以看到图一的效果了,有很多属性可能没有分析,但是多试试才知道有什么效果。
四、撸代码(图2效果)
这里就只上xml文件了,代码都差不多 只是改了一下xml文件,将CollapsingToolBarLayout
去掉直接换成了ToolBar
来实现效果:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap"/>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:background="@color/colorPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
android:src="@android:drawable/ic_input_add" />
</android.support.design.widget.CoordinatorLayout>
这样,滑动列表的时候就可以直接展示与折叠ToolBar了,不需要拉扯到列表顶部才能对ToolBar进行联动,如果非要以图一的形式来实现就需要自定义Behavior了(暂时没有发现其他方法)。
五、撸代码(图3效果)
注意:图三效果就是那个图标(FloatingActionButton)有渐变最后消失的一个过程的效果,图一中我们也对FloatingActionButton
做了同样的处理,可是并没有达到预期的效果:
- 暂时得出来的结论就是, 原因是图一中使用了TabLayout,去掉TabLayout就有渐变效果, 感觉是不能在AppBarLayout添加TabLayout来一起使用。所以这里只要把TabLayout去掉就可以了。
xml如下:
<?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:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:layout_width="match_parent"
android:layout_height="300dp"
android:fitsSystemWindows="true"
android:elevation="0dp">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/main_collapsing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:collapsedTitleTextAppearance="@style/collapsedTitleTextAppearance_white"
app:contentScrim="@color/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:expandedTitleTextAppearance="@style/collapsedTitleTextAppearance_green"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:statusBarScrim="#fff000">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@drawable/jjy_bg"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="1"
/>
<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/ThemeOverlay.AppCompat.Light"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<!--有渐变效果 layout_anchor指定参照物为AppBarLayout-->
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:src="@mipmap/ic_launcher"
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"/>
</android.support.design.widget.CoordinatorLayout>
这个Activity的话就直接加载布局就行:
/**
* Created by Leogh on 2017/8/29.
* FloatingActionButton渐变效果
*/
public class CoorFloatingActionButtonAct extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.testfloatbutton);
}
}
可能有些细节漏了,但注释写的很详细,多留意注释。
最后提供一下官方Demo:点我点我点我
网友评论