时间比较短,直接上代码了:
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.abs
class MyConstraintLayout(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs) {
private var children: CardView? = null
private var lastX = 0
private var lastY = 0
private var mOntuch = 0
private var scale = 0f
private var oldTop = 0
private var oldButtom = 0
private var isTopOrBottom = false
private var isHide = false
private var screenHeight = 0
fun layouts(l: Int, t: Int, r: Int, b: Int) {
layout(l, t, r, b)
}
//这个是绘制完执行的
override fun onFinishInflate() {
super.onFinishInflate()
mOntuch = ViewConfiguration.get(context).scaledTouchSlop
children = getChildAt(0) as CardView?
Log.e("mlt", "......mOntuch............" + mOntuch)//24
Log.e("mlt", "......DisplayUtils............" + DisplayUtils.displayPix(context))//1298
Log.e("mlt", "......displayheightPix............" + DisplayUtils.displayheightPix(context))//1298
scale = DisplayUtils.displayPix(context)
screenHeight = DisplayUtils.displayheightPix(context)
//这里用了200毫秒的时间,不然会获取不到下面的值
postDelayed(Runnable {
oldTop = top - default.toInt()
oldButtom = bottom - default.toInt()
Log.e("mlt", "......top............" + top)//1848
Log.e("mlt", "......bottom............" + bottom)//3648
Log.e("mlt", "......height............" + height)//1800
Log.e("mlt", "......width............" + width)//1080
}, durationDefault)
}
/**
* new 这里是第一种,根据view的translationY方法来上下移动整个view,而不是里面的内容
scrollTo 和scrollby 是移动view里面的内容
* */
private var lastNewY = 0f
private var isNewTopOrBottom = false
private var isNewHide = false
private var transY = 0f
private var transX= 0f
private var downPoint = PointF()
private var midden = 0f
private var defaultNegative = -550f
private var default = 550f
private var durationDefault = 200L
override fun onTouchEvent(event: MotionEvent?): Boolean {
midden = measuredHeight / scale
return if (children == null) {
super.onTouchEvent(event)
} else {
when (event?.action) {
MotionEvent.ACTION_DOWN -> {
lastNewY = event.rawY
downPoint.x = event.rawX
downPoint.y = event.rawY
return 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 = durationDefault
anmi.start()
// translationY = 0f
} else {
val anmi = ObjectAnimator.ofFloat(this, "translationY", defaultNegative)
anmi.duration = durationDefault
anmi.start()
// translationY = -550f
}
} else {
val anmi = ObjectAnimator.ofFloat(this, "translationY", -(default+midden))
anmi.duration = durationDefault
anmi.start()
// translationY = -(550 + midden)
}
}
}
super.onTouchEvent(event)
}
}
private fun onActionMove(event: MotionEvent) {
val moveY = event.rawY
val moveX = event.rawX
transY = moveY - downPoint.y
transX = moveX - downPoint.x
if (transY <= 0) {//上
if (translationY <= defaultNegative && translationY > -(midden + default) ) {
translationY += transY
isNewTopOrBottom = false
isNewHide = false
}
} else {
if (translationY > defaultNegative) {
translationY += transY
isNewHide = true
} else {
translationY += transY
isNewTopOrBottom = true
isNewHide = false
}
}
downPoint.y = event.rawY
downPoint.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)//2798
Log.e("mlt","......children............"+children?.top)//0
Log.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 - y
Log.e("mlt", "...........ACTION_DOWN......childtop........." + childtop)//0
Log.e("mlt", "...........ACTION_DOWN......childbottom........." + childbottom)//133
Log.e("mlt", "...........ACTION_DOWN......childLeft........." + childLeft)//0
Log.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非常的不熟悉导致,以后还要多加熟悉。