Android实现控件压缩效果,上方控件随下方的移动而相应的动态改变大小

最近遇到一个需求,顶部显示地图,下方是搜索页面,下方界面可以向上滑动,滑动的同时顶部地图不能遮挡,要随搜索界面向上滑动而慢慢压缩
先上效果图,如过凑巧有相同的需求可以继续往下看
在这里插入图片描述
在这里插入图片描述

首先想到的是 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 完整代码,有问题留言即可

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值