Android开发项目实战:实现折叠式布局,android组件化开发与sdk
android:layout_width=“match_parent”
android:layout_height=“200dp”>
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width=“match_parent”
android:layout_height=“match_parent”
app:layout_scrollFlags=“scroll|exitUntilCollapsed”
app:titleEnabled=“false”>
<ImageView
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:scaleType=“centerCrop”
android:src="@mipmap/homepage_pic_banner"
app:layout_collapseMode=“parallax” />
<android.support.v7.widget.Toolbar
android:id="@+id/view_toolbar"
android:layout_width=“match_parent”
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode=“pin”
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<TextView
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:layout_gravity=“center”
android:text=“新闻详情” />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width=“match_parent”
android:layout_height=“match_parent”
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:orientation=“vertical”>
<TextView
android:layout_width=“match_parent”
android:layout_height=“50dp”
android:text=“hello world” />
…
…
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
以上就是实现一个折叠式布局的典型模板布局代码,一个简简单单的布局就实现了这样的效果,但是必须要注意在AndroidMnifest.xml必须要给Activity指定它的theme为NoActionBar的样式代码如下:
<activity
android:name=".test.CoordinatorLayoutTestActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
否则会出现ActionBar和ToolBar共存的情况,的显示效果如下:
另外还需要把自己自定义的ToolBar告诉给系统,即第9行的setSupportActionBar(toolbar),否则我们的ToolBar会作为一个普通的View而存在
public class CoordinatorLayoutTestActivity extends AppCompatActivity {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coordinator_layout_test);
Toolbar toolbar = findViewById(R.id.view_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
toolbar.setNavigationIcon(R.mipmap.callback_white_icon);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
}
}
如果只指定了 setSupportActionBar(toolbar),没有AndroidMnifest.xml在指定Activity的theme为NoActionBar,那就运行就直接崩溃了,会报错如下:
Caused by: java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.
at android.support.v7.app.AppCompatDelegateImpl.setSupportActionBar(AppCompatDelegateImpl.java:345)
at android.support.v7.app.AppCompatActivity.setSupportActionBar(AppCompatActivity.java:130)
意思是说Activity已经有一个ActionBar了,请在你的样式中使用ToolBar替代
在上面的布局文件代码中,根布局CoordinatorLayout 就是用来协调AppBarLayout和NestedScrollView之间滚动的,40行的NestedScrollView是我们要滚动的内容,在11行的CollapsingToolbarLayout标签的内部就是要折叠的内容
- 其中43行的 app:layout_behavior不配置的效果:
![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy8xNTM0MjU0MS0wODNjNDhmMWM5OWRkNTk2LmdpZj9pbWFnZU1vZ3IyL2F1dG8tb3JpZW50L3N0c
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
mlwfGltYWdlVmlldzIvMi93LzM2MC9mb3JtYXQvd2VicA)
NestedScrollView的内容在ToolBar之上滚动
- 其中13行app:layout_scrollFlags="scroll|exitUntilCollapsed"如果不配置效果图如下:
如果没有配置则CollapsingToolbarLayout包裹内容内容就会固定在顶部,不会滚动
- 28行 app:layout_collapseMode="pin"不配置,效果图:
ToolBar会跟随NestedScrollView的滚动而滚动,而不会固定在布局顶部位置
- 14行app:titleEnabled="false"不配置,效果图:
即使33行的TextView配置了android:layout_gravity=“center”,title也不会居中显示
我们感觉折叠式布局就是给我们的View设置相关的属性配置,不需要进行任何编码就能完成我们的折叠效果,我们不得的赞叹android 5.0给我们提供这一强大的功能
我们来总结一下:
CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout结合起来才能产生这么神奇的效果,不要幻想使用其中的一个控件就能完成这样的效果
ToolBar的设置
系统默认使用的就是系统自带的ActionBar,如果我们要使用自定义的ToolBar,就必须明确的告诉Activity不需要使用系统自带的ActionBar即要给activity设置NoActionBar的样式,另外必须调用setSupportActionBar(toolbar)将自己定义的ToolBar设置给Activity。
CoordinatorLayout下可滑动控件的设置
CoordinatorLayout作为整个布局的父布局容器。给你的可以滑动的控件例如RecyclerView设置如下属性:app:layout_behavior=@string/appbar_scrolling_view_behavior
CoordinatorLayout还提供了layout_anchor 和 layout_anchorGravity属性一起配合使用,可以用于设置FloatingActionButton的位置,此处我是放在appBar的右下角。
app:layout_anchor="@id/appbar"
app:layout_anchorGravity=“bottom|right|end”
CollapsingToolbarLayout的layout_scrollFlags属性
AppBarLayout里面定义的子view只要设置了app:layout_scrollFlags属性,就可以在RecyclerView滚动事件发生的时候被触发某种行为
例如我给CollapsingToolbarLayout控件设置了 app:layout_scrollFlags="scroll|exitUntilCollapsed"此刻如果没有这个属性,CollapsingToolbarLayout是不会折叠的那么问题来了,layout_scrollFlags中的属性值除了可以触发折叠的行为,还有其它的属性值吗?并且各个属性的意义是什么?scroll至少有一个scroll,即可滚动。
| 属性 | 作用 |
| — | — |
| scroll | 必须要给其至少有设置一个scroll,即可滚动 |
| enterAlways | 向下滚动即可见。例如下拉时,立即显示Toolbar |
| exitUntilCollapsed | 这个flag是定义何时收缩。当你定义了一个minHeight,这个view将在滚动到达这个最小高度的时候消失 |
| enterAlwaysCollapsed | 这个flag是定义何时展开。当你定义了一个最小高度minHeight, 同时enterAlways也定义了,那么view将在到达这个最小高度的时候开始展示 |
| snap | 当一个滚动事件结束,它将根据显示百分比的大小自动滚动到收缩或展开。 |
如果不设置该属性,则该布局不能滑动
CollapsingToolbarLayout的其他属性
另外还可以给CollapsingToolbarLayout设置以下属性:
| 属性 | 作用 |
| — | — |
| contentScrim | 设置当完全折叠(收缩)后的背景颜色。 |
| expandedTitleMarginEnd | 没有扩张的时候标题显示的位置 |
| expandedTitleMarginStart | 扩张的时候标题向左填充的距离。 |
| statusBarScrim | 设置折叠时状态栏的颜色 |
CollapsingToolbarLayout下的view的layout_collapseMode属性
CollapsingToolbarLayout里面定义的view只要设置了app:layout_collapseMode属性,就可以控制子视图的折叠模式。
折叠模式分为两种:
| 属性 | 作用 |
| — | — |
| pin | 固定模式。在收缩的时候最后固定在顶端(例如向上滚动的时候就固定toolBar) |
| parallax | 视差模式,在折叠的时候会有个视差折叠的效果。(例如向下滚动的时候就展开ImageView) |
CoordinatorLayout 的fitsSystemWindows属性
fitsSystemWindows属性可以让view根据系统窗口来调整自己的布局,简单点说就是我们在设置应用布局时是否考虑系统窗口布局,这里系统窗口包括系统状态栏、导航栏、输入法等,包括一些手机系统带有的底部虚拟按键。android:fitsSystemWindows=”true” (触发View的padding属性来给系统窗口留出空间) 这个属性可以给任何view设置,只要设置了这个属性此view的其他所有padding属性失效,同时该属性的生效条件是只有在设置了透明状态栏(StatusBar)或者导航栏(NavigationBar)此属性才会生效
如何监听CollapsingToolbarLayout的展开与折叠
使用官方提供的 AppBarLayout.OnOffsetChangedListener就能实现了,不过要封装一下才好用,自定义一个继承了 AppBarLayout.OnOffsetChangedListener的类这里命名为AppBarStateChangeListener
public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {
public enum State {
EXPANDED,
COLLAPSED,
IDLE
}
private State mCurrentState = State.IDLE;
@Override
public final void onOffsetChanged(AppBarLayout appBarLayout, int i) {
if (i == 0) {
if (mCurrentState != State.EXPANDED) {
onStateChanged(appBarLayout, State.EXPANDED);
}
mCurrentState = State.EXPANDED;
} else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
if (mCurrentState != State.COLLAPSED) {
onStateChanged(appBarLayout, State.COLLAPSED);
}
mCurrentState = State.COLLAPSED;
} else {
if (mCurrentState != State.IDLE) {
onStateChanged(appBarLayout, State.IDLE);
}
mCurrentState = State.IDLE;
}
}
public abstract void onStateChanged(AppBarLayout appBarLayout, State state);
}
然后我们这样使用它:
mAppBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() {
@Override
public void onStateChanged(AppBarLayout appBarLayout, State state) {
Log.d(“STATE”, state.name());
if( state == State.EXPANDED ) {
//展开状态
}else if(state == State.COLLAPSED){
//折叠状态
}else {
//中间状态
}
}
});
这样就可以在不同的状态下根据自己的业务需求去实现相关的逻辑了
StickyLayout自定折叠式布局的实现
好了,上面就是关于通过CoordinateLayout实现的折叠式布局所有的知识点,如果说前面只是开胃菜,现在我们就开始上主菜了,我们能不能自己实现这样一个折叠式的布局,利用上一篇我们所讲的头部固定的ExpandedListView,把它作为具有滑动功能的主View,在它的顶部添加具有背景图片Header,随着ExpandedListView的滑动header实现扩展和收缩的效果,效果如下:
功能分析
其实这个效果图在文章的一开始就展示过了,整个布局分为上下两部分:上分部分为可折叠的Header,下半部分就是我们头部固定的ExpandedListView,他们公共父view就是今天我们要实现的折叠式布局StickyLayout,ExpandedListView是自身所具备滑动功能的,而我们在整个屏幕上,往上滑动的时候如果header处于展开状态则Header慢慢的要折叠起来,往下滑动的时候如果ExpandedListView顶部数据都显示出来的情况下再往下拉的时候Header就慢慢的展开,其他的状态就是我们的ExpandedListView在上下滑动,也就是说我们的Header在折叠和展开的状态下的这些事件被StickyLayout拦截了,其他的事件就交给ExpandedListView进行处理从而实现了他的上下滑动,这就属于典型的滑动冲突问题,简言之就是我们在上下滑动的过程中的有些事件需要被StickyLayout拦截消掉来实现Header的折叠和展开效果,其他的事件就交给ExpandedListView来实现它的滑动效果
现在我们要思考的是哪些情况下被拦截:
左右滑动的不需要处理,只处理上下滑动的事件
在展开的状态下,上滑事件需要拦截
ExpandedListView的第0个元素处于可见状态,此时的下滑事件需要拦截
在事件拦截方法中处理滑动冲突
public class StickyLayout extends LinearLayout {
…
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false;
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
mLastInterceptX = x;
mLastInterceptY = y;
intercept = false;
break;
case MotionEvent.ACTION_MOVE:
int dx = x - mLastInterceptX;
int dy = y - mLastInterceptY;
if(y <= mCurrHeaderHeight){
intercept = false;
}else if(Math.abs(dx) > Math.abs(dy)){
intercept = false;
}else if(mState == mStateExpand && dy <= - mScaledTouchSlop){
//上滑
intercept = true;
}else if(mGiveUpTouchEventListener.giveUpTouchEvent() && dy > mScaledTouchSlop){
//下滑
intercept = true;
}else{
intercept = false;
}
break;
case MotionEvent.ACTION_UP:
mLastInterceptX = 0;
mLastInterceptY = 0;
intercept = false;
break;
}
return intercept;
}
…
}
Android开发项目实战:实现折叠式布局,android组件化开发与sdk相关推荐
- 组件化开发之-我们有什么必要使用组件化开发?
原创 2016-05-19 背景介绍: 首先简单说一下为什我会写这篇文章呢? 源于今天讨论,提到这个组件化开发和以前没有多大区别,都需要合作编码,共同开发某些相同模块,本来之前都是按照模块划分来开发的 ...
- 组件化开发和模块化开发
组件化开发和模块化开发实际上是两种编程思想,也可以被认为是两种解决方案.组件化开发注重重用,可以用作实现基础架构的技术方案.举个例子:加入现在我需要实现一个几何图形库,包括图形的生成.修改.删除等基本 ...
- 美团前端组件化开发实践
随着前端开发复杂度的日益提升,组件化开发应运而生,并随着 FIS.React 等优秀框架的出现遍地开花.这一过程同样发生在美团,面临业务规模的快速发展和工程师团队的不断扩张,美团历经引入组件化解决资源 ...
- cocos creator组件化开发 对比 cocos studio +cocos2dx开发
相对于使用cocos studio + cocos2dx开发模式,使用cocos creator的组件化开发更为高效和简洁 以按钮myButton节点的点击音效为例: 1:cocos studio + ...
- C# Xamarin For Android移动开发项目实战篇
一.课程介绍 在前面阿笨的<C# Xamarin移动开发基础进修篇>课程中,大家已经熟悉和了解了Xamarin移动App开发的基础知识和原理.本次分享课<C# Xamarin移动开发 ...
- Android组件化与插件化开发项目实战整理分享(含支付宝、360、美团、滴滴等大厂项目实战)
小公司不说,但是在大公司的项目发展到一定程度,就必须进行模块的拆分.模块化是一种指导理念,其核心思想就是分而治之.降低耦合.而在 Android 开发的实践,目前有两种途径来实现,一个是组件化,一个是 ...
- Android游戏开发项目实战
Android游戏开发项目实战: 手机游戏开发工程师培训教程(Android4.3.Cocos2d-x.Untity2D/3D.跨平台引擎技术) 课程讲师:厉风行 课程分类:游戏开发 适合人群:初级 ...
- android下拉刷新动画效果代码_vue项目实录:下拉刷新组件的开发及slot的使用
"下拉刷新"和"上滑加载更多"功能在前端.尤其是移动端项目中非常重要,这里笔者由曾经做过的vue项目中的"blink"功能和各位探讨下[下拉 ...
- python h5开发_从零搭建移动H5开发项目实战
从零搭建移动H5开发项目实战 前端H5的前世今身 在Pc的时代,前端技术无疑统治了大多数用户的交互界面!而在移动为王的今天,NA开发在早期占领了大多数用户的交互界面,后来逐渐的前端H5开发找到了自己的 ...
- 从零搭建移动H5开发项目实战
从零搭建移动H5开发项目实战 前端H5的前世今身 在Pc的时代,前端技术无疑统治了大多数用户的交互界面!而在移动为王的今天,NA开发在早期占领了大多数用户的交互界面,后来逐渐的前端H5开发找到了自己的 ...
最新文章
- mysql 1455_关于Oracle 11g导出数据时 报 ORA-1455错误的处理
- 2019年十二周总结
- 早起5件事,让你年轻10岁
- GDCM:dicom文件的SHA1测试程序
- 【caffe-Windows】微软官方caffe之 Python接口配置及图片生成实例
- 述职答辩提问环节一般可以问些什么_论文答辩一般会问什么问题?需要注意什么事项?...
- 事务对性能影响_MySQL数据库性能优化史诗级大总结
- Django模板层:模板继承 extends标签和block标签,csrf_token标签
- 地理信息考c语言,南师地理信息系统专业01方向真题C语言
- [渝粤教育] 西安交通大学 光通信器件及系统 参考 资料
- 应用java编写 按键小脚本_一个使用JAVA编写的类似按键精灵的程序,支持脚本文件编写(含源代码) | 学步园...
- 【[中文直播] 第21期 | UE4数据驱动开发 | Epic 大钊】课程笔记
- 如何开搓饵不掉钩_为什么你开的搓饵总是无鱼咬钩?记住这4点,搓饵比拉饵效果更好...
- 关于移动硬盘突然变成RAW格式数据该怎么恢复
- Python第三方库matplotlib(2D绘图库)入门与进阶
- 【AMD】【Win11】安卓虚拟机开启VT无效的问题
- 支付宝微信等第三方支付机构备付金下月上交央行
- spring security (BCryptPasswordEncoder)加密及判断密码是否相同
- bluestacks 内部文件与电脑 Windows 互通的方法
- 数学建模 - 椅子放在不平整的地上能否站稳(长方形)
热门文章
- 使用尖刺触发死亡,并使猫里奥脸的朝向会随之发生改变
- js+css制作导航栏下划线跟随动画,App+H5点击效果
- 土壤基因组dna提取试剂盒
- 河工大邮箱申请,jetbrains学生邮箱申请,ideaIU版本下载、激活
- MFC技术内幕系列之(一)---MFC应用程序“生死因果”内幕
- orc识别较慢_提高OCR识别效率的诀窍
- python ocr高精度识别_OCR识别-python版(一)
- Android第三方登录详解2
- 炫酷的生日快乐网页 【附带源码】
- 关闭启动最新Photoshop 2021自动同步预设提示方法(临时)