时间比较短,直接上代码了:
import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.PointF
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.ViewConfiguration
import androidx.cardview.widget.CardView
import androidx.constraintlayout.widget.ConstraintLayout
import me.frame.mvvm.utils.DisplayUtils
import kotlin.math.absclass MyConstraintLayout(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs) {private var children: CardView? = nullprivate var lastX = 0private var lastY = 0private var mOntuch = 0private var scale = 0fprivate var oldTop = 0private var oldButtom = 0private var isTopOrBottom = falseprivate var isHide = falseprivate var screenHeight = 0fun layouts(l: Int, t: Int, r: Int, b: Int) {layout(l, t, r, b)}//这个是绘制完执行的override fun onFinishInflate() {super.onFinishInflate()mOntuch = ViewConfiguration.get(context).scaledTouchSlopchildren = getChildAt(0) as CardView?Log.e("mlt", "......mOntuch............" + mOntuch)//24Log.e("mlt", "......DisplayUtils............" + DisplayUtils.displayPix(context))//1298Log.e("mlt", "......displayheightPix............" + DisplayUtils.displayheightPix(context))//1298scale = DisplayUtils.displayPix(context)screenHeight = DisplayUtils.displayheightPix(context)
//这里用了200毫秒的时间,不然会获取不到下面的值postDelayed(Runnable {oldTop = top - default.toInt()oldButtom = bottom - default.toInt()Log.e("mlt", "......top............" + top)//1848Log.e("mlt", "......bottom............" + bottom)//3648Log.e("mlt", "......height............" + height)//1800Log.e("mlt", "......width............" + width)//1080}, durationDefault)}/*** new 这里是第一种,根据view的translationY方法来上下移动整个view,而不是里面的内容
scrollTo 和scrollby 是移动view里面的内容* */private var lastNewY = 0fprivate var isNewTopOrBottom = falseprivate var isNewHide = falseprivate var transY = 0fprivate var transX= 0fprivate var downPoint = PointF()private var midden = 0fprivate var defaultNegative = -550fprivate var default = 550fprivate var durationDefault = 200Loverride fun onTouchEvent(event: MotionEvent?): Boolean {midden = measuredHeight / scalereturn if (children == null) {super.onTouchEvent(event)} else {when (event?.action) {MotionEvent.ACTION_DOWN -> {lastNewY = event.rawYdownPoint.x = event.rawXdownPoint.y = event.rawYreturn true}MotionEvent.ACTION_MOVE -> {onActionMove(event)}MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {if (isNewTopOrBottom) {if (isNewHide) {val anmi = ObjectAnimator.ofFloat(this, "translationY", 0f)anmi.duration = durationDefaultanmi.start()
// translationY = 0f} else {val anmi = ObjectAnimator.ofFloat(this, "translationY", defaultNegative)anmi.duration = durationDefaultanmi.start()
// translationY = -550f}} else {val anmi = ObjectAnimator.ofFloat(this, "translationY", -(default+midden))anmi.duration = durationDefaultanmi.start()
// translationY = -(550 + midden)}}}super.onTouchEvent(event)}}private fun onActionMove(event: MotionEvent) {val moveY = event.rawYval moveX = event.rawXtransY = moveY - downPoint.ytransX = moveX - downPoint.xif (transY <= 0) {//上if (translationY <= defaultNegative && translationY > -(midden + default) ) {translationY += transYisNewTopOrBottom = falseisNewHide = false}} else {if (translationY > defaultNegative) {translationY += transYisNewHide = true} else {translationY += transYisNewTopOrBottom = trueisNewHide = false}}downPoint.y = event.rawYdownPoint.x = event.rawX}//这个方法也可行,但是比较生硬没有动画,因为是直接绘制,用的是layou 方法也可以实现,// override fun onTouchEvent(event: MotionEvent?): Boolean {
// Log.e("mlt", "......measuredHeight............" + measuredHeight)//1500
// Log.e("mlt", "......top............" + top)//1298
// Log.e("mlt", "......bottom............" + bottom)//2798Log.e("mlt","......children............"+children?.top)//0Log.e("mlt","......children............"+children?.bottom)//1500
// return if (children == null) {
// super.onTouchEvent(event)
// } else {
// var x = event?.x
// val y = event?.y
// val tv = children?.getChildAt(0)
// val childtop = tv?.top
// val childbottom = tv?.bottom
// val childLeft = tv?.left
// val childRight = tv?.right
// var title = 0f
// when (event?.action) {
// MotionEvent.ACTION_DOWN -> {
// if (y != null) {
// if (y > childtop!! && y < childbottom!!) {
// lastX = event.rawX.toInt()
// lastY = event.rawY.toInt()
// title = lastY - yLog.e("mlt", "...........ACTION_DOWN......childtop........." + childtop)//0Log.e("mlt", "...........ACTION_DOWN......childbottom........." + childbottom)//133Log.e("mlt", "...........ACTION_DOWN......childLeft........." + childLeft)//0Log.e("mlt", "...........ACTION_DOWN......childRight........." + childRight)/1080
// Log.e("mlt", "...........ACTION_DOWN......lastX........." + lastX)
// Log.e("mlt", "...........ACTION_DOWN.......lastY........" + lastY)Log.e("mlt", "...........ACTION_DOWN.......title........" + title)//1370
// return true
// }
// }
// }
// MotionEvent.ACTION_MOVE -> {
// val dy = event.rawY - lastY
// Log.e("mlt", "...........ACTION_MOVE.........dy......" + dy)
// if (dy < 0) {//想上 measuredHeight 1500
// Log.e("mlt", ",,,,,,,,,dy < 0,,,,,,,,,,,,," + abs(dy))
// if (top >= (oldTop - measuredHeight / scale)) {
// layout(left, top - abs(dy).toInt(), right, bottom - abs(dy).toInt())
// }
// isTopOrBottom = false
// } else {
// if (top >= oldTop) {
// isHide = true
// }
// layout(left, top + abs(dy).toInt(), right, bottom + abs(dy).toInt())
// isTopOrBottom = true
// }
// lastY = event.rawY.toInt()
// }
// MotionEvent.ACTION_CANCEL -> {
//
// }
// MotionEvent.ACTION_UP -> {
// if (isTopOrBottom) {
// if (isHide) {
// val height = screenHeight - oldTop
// layout(left, screenHeight, right, bottom + height)
// } else {
// layout(left, oldTop, right, oldButtom)
// }
// isHide = false
// } else {
// isHide = false
// layout(left, oldTop - measuredHeight / scale.toInt(), right, oldButtom - measuredHeight / scale.toInt())
// }
// }
// }
// super.onTouchEvent(event)
// }
// }
}
就这点代码也花了很长的时间,主要的是对自定义view非常的不熟悉导致,以后还要多加熟悉。