实现一个可拖动的ConstraintLayout

package com.abc.robot01.view

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.View
import android.view.ViewConfiguration
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
import androidx.constraintlayout.widget.ConstraintLayout
import kotlin.math.abs

class DraggableConstraintLayout2 @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ViewGroup(context, attrs, defStyleAttr) {

    val TAG="DraggableConstraintLayout"
    private var lastX = 0f
    private var deltaX = 0f
    private var velocityTracker: VelocityTracker? = null
    private val minFlingVelocity: Int
    private val maxFlingVelocity: Int

    init {
        val viewConfiguration = ViewConfiguration.get(context)
        minFlingVelocity = viewConfiguration.scaledMinimumFlingVelocity
        maxFlingVelocity = viewConfiguration.scaledMaximumFlingVelocity
    }

    private var root2 :View?=null
//    private  lateinit  var close :View
//    private lateinit var sp: View
    private var lastY = 0f

    private var contentVisible = true

    private lateinit var childConstraintLayout: ConstraintLayout

    override fun onFinishInflate() {
        super.onFinishInflate()
        // Assuming the child is a ConstraintLayout and there's only one child
        if (childCount == 1 && getChildAt(0) is ConstraintLayout) {
            childConstraintLayout = getChildAt(0) as ConstraintLayout
        } else {
            throw IllegalStateException("DraggableConstraintLayout2 must have a single ConstraintLayout child")
        }

//        close =  findViewById<View>(R.id.close)
//           val  toggle = findViewById<View>(R.id.toggle)
          sp = findViewById<View>(R.id.sp)
//        val  onClick = {
//            if(root2.visibility== VISIBLE){
//                Log.e(TAG,"onclick INVISIBLE")
//                root2.visibility = INVISIBLE
//                contentVisible = false
//            }
//            else{
//                root2.visibility = VISIBLE
//                contentVisible = true
//                Log.e(TAG,"onclick VISIBLE")
//            }
//        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        measureChild(childConstraintLayout, widthMeasureSpec, heightMeasureSpec)
        setMeasuredDimension(
            resolveSize(childConstraintLayout.measuredWidth, widthMeasureSpec),
            resolveSize(childConstraintLayout.measuredHeight, heightMeasureSpec)
        )
    }

    override fun onLayout(p0: Boolean, l: Int, t: Int, r: Int, b: Int) {
        // Layout the ConstraintLayout
        childConstraintLayout.layout(0, 0, childConstraintLayout.measuredWidth, childConstraintLayout.measuredHeight)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                lastX = ev.rawX
                velocityTracker = VelocityTracker.obtain()
                velocityTracker?.addMovement(ev)
            }
            MotionEvent.ACTION_MOVE -> {
                val deltaX = ev.rawX - lastX
                if (abs(deltaX) > ViewConfiguration.get(context).scaledTouchSlop) {
                    return true
                }
            }
        }
        return super.onInterceptTouchEvent(ev)
    }

    private var  injected= false;

    private var  move= false;

    override fun onTouchEvent(event: MotionEvent): Boolean {
        velocityTracker?.addMovement(event)
        when (event.action) {
            MotionEvent.ACTION_MOVE -> {
                 deltaX = event.rawX - lastX
                lastX = event.rawX
                // Move the child ConstraintLayout horizontally
                childConstraintLayout.translationX += deltaX
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                velocityTracker?.computeCurrentVelocity(1000, maxFlingVelocity.toFloat())
                val velocityX = velocityTracker?.xVelocity ?: 0f
                //向右滑动,translationX为0
                if(deltaX > 0 ){
                    val targetX = 0f
                    // Animate the translationX property using ObjectAnimator
                    ObjectAnimator.ofFloat(
                        childConstraintLayout,
                        "translationX",
                        childConstraintLayout.translationX,
                        targetX
                    ).apply {
                        duration = 1000L // Animation duration in milliseconds
                        interpolator = DecelerateInterpolator()
                        addListener(object : AnimatorListenerAdapter() {
                            override fun onAnimationEnd(animation: Animator) {
                                super.onAnimationEnd(animation)
                            }
                        })
                        start()
                    }
                }
                //向左滑动,translationX最小为它的0-width.
                if(deltaX < 0 ){
                    val targetX = -width.toFloat()
                    // Animate the translationX property using ObjectAnimator
                    ObjectAnimator.ofFloat(
                        childConstraintLayout,
                        "translationX",
                        childConstraintLayout.translationX,
                        targetX
                    ).apply {
                        duration = 1000L // Animation duration in milliseconds
                        interpolator = DecelerateInterpolator()
                        addListener(object : AnimatorListenerAdapter() {
                            override fun onAnimationEnd(animation: Animator) {
                                super.onAnimationEnd(animation)
                            }
                        })
                        start()
                    }
                }
//                else
//                if (1==1 || abs(velocityX) > minFlingVelocity) {
//                    // Fling the view out of the parent if the velocity is high enough
//                    val targetX = if (velocityX > 0) width.toFloat() else -childConstraintLayout.width.toFloat()
//                    val distanceX = (targetX - childConstraintLayout.translationX).toInt()
//                    // Calculate the scroll duration based on a speed factor
//                    val speedFactor = 0.3f // Adjust this factor to control the speed
//                    val duration = (distanceX / speedFactor).roundToInt()
//                    scroller.startScroll(
//                        childConstraintLayout.left, 0,
//                        targetX.toInt() - childConstraintLayout.left, 0
//                    )
//                    invalidate()
//                } else {
//                    // Snap back to position if the fling is not strong enough
//                    scroller.startScroll(
//                        childConstraintLayout.left, 0,
//                        -childConstraintLayout.left, 0
//                    )
//                    invalidate()
//                }
                velocityTracker?.recycle()
                velocityTracker = null
            }
        }
        return true
    }

//    override fun computeScroll() {
//        if (scroller.computeScrollOffset()) {
//            childConstraintLayout.translationX = scroller.currX.toFloat()
//            invalidate()
//        }
//    }

//    override fun onTouchEvent(event: MotionEvent): Boolean {
        Log.e(TAG,"onTouchEvent:"+event)
        BaseActivity.a?.inject(event);
//        if (event.action == MotionEvent.ACTION_DOWN) {
//            if(contentVisible) {
//                val location = IntArray(2)
//                root2.getLocationOnScreen(location)
//                val imageViewX = location[0]
//                val imageViewY = location[1]
//                val imageViewWidth = root2.width
//                val imageViewHeight = root2.height
//                // Check if the touch event is within the ImageView's bounds
//                if (event.rawX >= imageViewX && event.rawX <= (imageViewX + imageViewWidth) &&
//                    event.rawY >= imageViewY && event.rawY <= (imageViewY + imageViewHeight)
//                ) {
//                    injected = false
//                    move = true
//                    // The touch event is within the ImageView
//                    // Handle the event here
//                    // Example: perform a specific action
//                } else {
//                    Log.e(TAG,"inject 1 (event):"+event)
//                    BaseActivity.a?.inject(event);
//                    injected = true
//                }
//            }
//            else{
//                Log.e(TAG,"inject 2 (event):"+event)
//                BaseActivity.a?.inject(event);
//                injected = true
//            }
//        } else{
//            if(injected){
//                Log.e(TAG,"inject 3 (event):"+event)
//                BaseActivity.a?.inject(event);
//            }
//        }
//
//        when (event.action) {
//            MotionEvent.ACTION_DOWN -> {
//                lastX = event.rawX
//                lastY = event.rawY
//            }
//            MotionEvent.ACTION_MOVE -> {
//                val dx = event.rawX - lastX
//                val dy = event.rawY - lastY
//                if(move) {
//                    if(constraintLayout.translationX+dx<=1920-409 && constraintLayout.translationX+dx >=0){
//                        constraintLayout.translationX += dx
//                        lastX = event.rawX
//                    }
//                    if(constraintLayout.translationY+dy<=1080-416 && constraintLayout.translationY+dy>=0){
//                        constraintLayout.translationY += dy
//                        lastY = event.rawY
//                    }
//
//                }
//
//
//            }
//            MotionEvent.ACTION_UP ->{
//                injected = false
//                move = false
//            }
//        }
//        return true
//    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值