Android 仿高德地图可拉伸的BottomSheet
来源:互联网 发布:网络销售外包合同 编辑:程序博客网 时间:2024/06/05 00:30
项目上要用到类似高德地图搜索结果后的结果展示的可拉伸控件。
由于没有找到合适的软件,制作的效果有点差,将就看下。
自己的效果:
虽然说效果没有高德的好(就是在下滑的时候不能准确折叠到中间),但是基本满足了项目的需要。如果各位大神有更好的方法,欢迎留言提供方法。
刚开始以为这是抽屉效果(slidingdrawer),结果发现这个类已经被谷歌抛弃,且content也不能滑动,得自定义控件实现。但是我的自定义控件水平不高,苦思一天还是写不出来,只能各种查类似的效果,终于找到了比较接近的CoordinatorLayout。
@deprecated This class is not supported anymore. It is recommended you base your own implementation on the source code for the Android Open Source Project if you must use it in your application.
关于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:id="@+id/coordinator" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#88bbbbbb" android:gravity="center" tools:context="com.joysuch.collapseviewdemo.MainActivity"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/girl"/> <RelativeLayout android:id="@+id/design_bottom_sheet_bar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/colorAccent" app:layout_anchor="@+id/design_bottom_sheet" app:layout_anchorGravity="top" android:layout_gravity="bottom" android:visibility="invisible"> <ImageView android:layout_width="23dp" android:layout_height="23dp" android:layout_marginLeft="23dp" android:src="@mipmap/ic_launcher" android:layout_centerVertical="true"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="点击收起BottomSheet" android:textColor="#ffffff" android:layout_centerInParent="true"/> </RelativeLayout> <RelativeLayout android:id="@+id/design_bottom_sheet" android:layout_width="match_parent" android:layout_height="match_parent" android:minHeight="100dp" app:behavior_peekHeight="56dp" app:behavior_hideable="false" app:layout_behavior="@string/bottom_sheet_behavior" android:background="#ffffff"> <TextView android:id="@+id/bottom_sheet_tv" android:layout_width="wrap_content" android:layout_height="56dp" android:layout_centerHorizontal="true" android:gravity="center" android:text="这是一个BottomSheet"/> <android.support.v7.widget.RecyclerView android:id="@+id/bottom_sheet_rv" android:layout_below="@+id/bottom_sheet_tv" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" android:padding="10dp" android:minHeight="100dp" android:adjustViewBounds="true" android:scaleType="centerInside" android:layout_gravity="center"/> </RelativeLayout></android.support.design.widget.CoordinatorLayout>
最主要的一个布局就是id为design_bottom_sheet的布局,它设置了
app:layout_behavior="@string/bottom_sheet_behavior"
的属性,将布局作为底部折叠纸片。
app:behavior_hideable="false"
让这个BottomSheet不可以被手动滑动隐藏,设置为true则可以滑到屏幕最底部隐藏。
app:behavior_peekHeight
设置的是折叠状态时的高度,此时设置的折叠时的高度和子View的TextView的高度一样高,所以折叠时将显示TextView的内容。
id为design_bottom_sheet_bar的RelativeLayout是用来实现BottomSheet完全展开时的自定义顶部工具条。
app:layout_anchor="@+id/design_bottom_sheet" app:layout_anchorGravity="top" android:layout_gravity="bottom"
上面这段设置是使design_bottom_sheet_bar的位置与design_bottom_sheet锚定,锚定在design_bottom_sheet的上方.
design_bottom_sheet设置的高度是充满父布局,在展开状态下我们需要其给design_bottom_sheet_bar留出位置,所以要修改一下design_bottom_sheet的高度,代码设置放在了onWindowFocusChanged()里。
@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); //修改design_bottom_sheet的高度 让其显示总布局一半的高度 if(!setBottomSheetHeight){ CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) design_bottom_sheet.getLayoutParams(); params.height = coordinatorLayout.getHeight() / 2; design_bottom_sheet.setLayoutParams(params); setBottomSheetHeight = true ; } }
// 协调布局 coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinator); // 伸展后显示类似 ActionBar design_bottom_sheet_bar = (RelativeLayout) findViewById(R.id.design_bottom_sheet_bar); // 折叠后显示的类似handle design_bottom_sheet = (RelativeLayout) findViewById(R.id.design_bottom_sheet); bottom_sheet_tv = (TextView) findViewById(R.id.bottom_sheet_tv); // RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.bottom_sheet_rv); initRecyclerView(); final BottomSheetBehavior behavior = BottomSheetBehavior.from(design_bottom_sheet); //// 默认让其展开状态,此时design_bottom_sheet的高度是总布局高度的一半,正好显示在中间。 behavior.setState(BottomSheetBehavior.STATE_EXPANDED); bottom_sheet_tv.setVisibility(View.GONE);//点击上方的锚定条---折叠 design_bottom_sheet_bar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { behavior.setState(BottomSheetBehavior.STATE_COLLAPSED); } }); behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { //BottomSheet状态改变时的回调 @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { // collapsed. if(newState!=BottomSheetBehavior.STATE_COLLAPSED && bottom_sheet_tv.getVisibility()==View.VISIBLE){ bottom_sheet_tv.setVisibility(View.GONE); mRecyclerView.setVisibility(View.VISIBLE); }else if(newState==BottomSheetBehavior.STATE_COLLAPSED&& bottom_sheet_tv.getVisibility()==View.GONE){ bottom_sheet_tv.setVisibility(View.VISIBLE); mRecyclerView.setVisibility(View.GONE); } } //BottomSheet滑动时的回调 @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { if(bottomSheet.getTop() > coordinatorLayout.getHeight() /2){ CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) design_bottom_sheet.getLayoutParams(); params.height = coordinatorLayout.getHeight() / 2; design_bottom_sheet.setLayoutParams(params); }else { CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) design_bottom_sheet.getLayoutParams(); params.height = coordinatorLayout.getHeight() - design_bottom_sheet_bar.getHeight(); design_bottom_sheet.setLayoutParams(params); } if(bottomSheet.getTop()<2*design_bottom_sheet_bar.getHeight()){ design_bottom_sheet_bar.setVisibility(View.VISIBLE); design_bottom_sheet_bar.setAlpha(slideOffset); design_bottom_sheet_bar.setTranslationY(bottomSheet.getTop()-2*design_bottom_sheet_bar.getHeight()); } else{ design_bottom_sheet_bar.setVisibility(View.INVISIBLE); } } });
BottomSheet 的状态回调有两个方法:onStateChanged:状态改变是我们要控制控件的显示与隐藏。onSlide:滑动时:当 bottomSheet.getTop() > coordinatorLayout.getHeight() /2这个节点设置design_bottom_sheet的高度是可行的,其他情况均出现问题。滑动时设置锚定条的移动距离,让其显示出来。
根据我的coordinatorLayout.getHeight() /2这个节点我手动测试发现,在bottomSheet.getTop() >2*coordinatorLayout.getHeight() /3时是折叠区间。coordinatorLayout.getHeight() /2 ~2 * coordinatorLayout.getHeight() /3是展示在中间的区间,其他情况展示在顶部。
好吧,我就这样实现了,好像是卡了一个Bug实现了。源码实在太难理清逻辑,有点遗憾没有完美解决下滑的时候不能准确折叠到中间(像高德的那种体验),欢迎各位大神提供此控件实现方法或者改进方法。以上属于自己理解,欢迎指正!
项目下载:https://github.com/GoldenStrawberry/CollapseViewDemo
- Android 仿高德地图可拉伸的BottomSheet
- Android BottomSheet 的一些坑
- Android 自定义地图控件 可手指拉伸放大缩小拖动,指定坐标加点加线
- [Android] 带阻尼效果的可拉伸的HorizontalScrollView
- 【Android UI】CoordinatorLayout实现带图片可拉伸的Toolbar
- 制作可拉伸的UIImage
- 可拉伸图片的方法
- Android Support Library - BottomSheet
- Android弹出框BottomSheet
- Android开发-BottomSheet的使用和BottomSheetDialogFragment的封装
- Android底部对话框的实现(BottomSheet,自定义Dialog)
- Android基础之BottomSheet的介绍和使用
- android 自定义ScrollView可上下拉伸
- [Android]使用draw9patch制作可拉伸图片
- [Android]使用draw9patch制作可拉伸图片
- BottomSheet的用法
- 一个自定义的bottomsheet
- BottomSheet的使用
- 数据挖掘中的 10 大算法
- 加密连接数据库明文密码
- PAT考试乙级1031(C语言实现)重点题目
- 时间不同步导致Spring session失效的巨坑
- ADV-202 最长公共子序列
- Android 仿高德地图可拉伸的BottomSheet
- Python进阶之网络通信过程再现
- golang interface深度解析
- 从Element学习Vue的使用
- Quartz作业调度框架入门学习
- 大菲波数
- java基础2:异常
- ADS7822的使用
- this逃逸