最近遇到一个需求,顶部显示地图,下方是搜索页面,下方界面可以向上滑动,滑动的同时顶部地图不能遮挡,要随搜索界面向上滑动而慢慢压缩
先上效果图,如过凑巧有相同的需求可以继续往下看
首先想到的是 setOnTouchListener 去监听下方控件,根据下方控件是否上滑或者下滑去动态给上方地图控件和下方界面去设置高度
但是问题来了
首先可以通过 setOnTouchListener 去判断控件是否上滑或者下滑,MotionEvent.ACTION_UP 但是判断结果是在控件完成动作之后,做不到跟随改变大小的效果
其次 setOnTouchListener 确实有在滑动过程中的监听效果 MotionEvent.ACTION_MOVE: 在移动过程中的Y值减去 手指点击时的 Y 值 来判断是否向上(<0)或者向下(>0),但是在向上滑动过程中(<0) 会一直有 一个 向下滑动的(>0)的操作,感兴趣的小伙伴可以自己去试一试,这里我也是很懵逼,有知道的大佬可以留言一下,
所以说就会有一个问题,在滑动过程中会因为上述问题造成错乱,出现页面上下波动的效果,非常不人性化
于是经过我两天的各种面向百度操作,终于修成正果
利用 BottomSheetBehavior 可以实现上述效果,BottomSheetBehavior 不了解的 小伙伴 自行百度咯
BottomSheetBehavior 中有一个 setBottomSheetCallback 方法,该方法大体意思就是,监听底部面板是否隐藏或者全部显示,并且在 隐藏到全部显示的过程中也有个监听(0-1),那不完美了吗,根据这个监听来动态设置上方地图高度就可以了,下方是一个底部弹窗效果,高度无需自己设置,方便又省事
下面上代码
MainActivity
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
var list: ArrayList<Mycolor> = ArrayList()
var posY:Float = 0f
var curPosY:Float = 0f
@SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
for (index in 1..20){
list.add( Mycolor("颜色$index","类别$index"))
}
lv.adapter = LVAdapter(this,list)
//控件滑动监听
lv.setOnTouchListener(View.OnTouchListener { v, event ->
if (!lv.canScrollVertically(-1)) { //canScrollVertically(-1)的值表示是否能向下滚动,false表示已经滚动到顶部
lv.requestDisallowInterceptTouchEvent(false)
} else {
lv.requestDisallowInterceptTouchEvent(true)
}
false
})
//获取底部控件
val from = BottomSheetBehavior.from(tt)
/*tt.setOnClickListener {
if(from.state == BottomSheetBehavior.STATE_EXPANDED) {
Log.e(TAG, "11122")
val layoutParams = tv.layoutParams
layoutParams.height = 700
tv.layoutParams = layoutParams
}else if(from.state == BottomSheetBehavior.STATE_COLLAPSED) {
Log.e(TAG, "11133")
val layoutParams = tv.layoutParams
layoutParams.height = 1500
tv.layoutParams = layoutParams
}
}*/
//对底部控件监听
from.setBottomSheetCallback(object : BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
// Log.e(TAG, "11111-->$newState", )
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {
/**
* slideOffset从隐藏滑到全部显示时 由0-1 ,反之,根据变化来动态设置高度
* */
Log.e(TAG, "1111222->$slideOffset", )
val height = tt.height
var tt = slideOffset*600
val layoutParams = tv.layoutParams
layoutParams.height = height-tt.toInt()
tv.layoutParams = layoutParams
}
})
}
class LVAdapter : BaseAdapter {
var content: Context?=null
var my_list:ArrayList<Mycolor>?=null
constructor(context : Context, my_list:ArrayList<Mycolor> ){
this.content = context
this.my_list = my_list
}
override fun getCount(): Int {
return my_list!!.size
}
override fun getItem(position: Int): Any? {
return null
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
var inflate: View
var viewHolder:ViewHolder
if (convertView == null){
inflate = View.inflate(content, R.layout.item_lv_content, null)
viewHolder = ViewHolder()
viewHolder.textColor = inflate.findViewById(R.id.tv_color)
viewHolder.textClass = inflate.findViewById(R.id.tv_class)
inflate.tag = viewHolder
}else{
inflate = convertView
viewHolder = inflate!!.tag as ViewHolder
}
viewHolder.textColor!!.text = my_list!![position].color
viewHolder.textClass!!.text = my_list!![position].classs
return inflate
}
inner class ViewHolder{
var textColor: TextView?=null
var textClass: TextView?=null
}
}
}
activity_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textColor="@android:color/white"
android:background="@android:color/holo_green_dark"
android:text="我是上面的内容,我根据下面往上移来慢慢缩小"
android:textSize="32dp"
android:layout_marginBottom="220dp"/>
<LinearLayout
android:id="@+id/tt"
android:layout_width="match_parent"
android:layout_height="500dp"
app:behavior_hideable="false"
app:behavior_peekHeight="250dp"
android:orientation="vertical"
app:layout_behavior="@string/bottom_sheet_behavior"
android:background="@android:color/holo_orange_dark">
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:textSize="23dp"
android:text="这是搜索栏"
android:gravity="center"
android:background="@android:color/holo_blue_bright"/>
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
用到的实体类 Mycolor
class Mycolor {
var color:String?=null
var classs:String?=null
constructor(color: String?,classs:String?) {
this.color = color
this.classs = classs
}
}
ListView 子布局 item_lv_content
<?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="wrap_content">
<TextView
android:id="@+id/tv_color"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="颜色"
android:textSize="24dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textColor="@android:color/holo_red_dark"/>
<TextView
android:id="@+id/tv_class"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分类"
android:textSize="24dp"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textColor="@android:color/holo_red_dark"/>
</RelativeLayout>
上面代码是 Demo 完整代码,有问题留言即可