第一次看到这个类名,我以为能顺利的把所有的事件在被代理的那个view里面拿到。
实践了一下,确实能到事件,但是莫名其妙的 x y变成固定值了,我特么fuck了呀。
敢情这个TouchDelegate只是把事件转移到了这个view上面,但是X,Y都改的面目全非了。
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
//是否发生event事件给需要代理的view
boolean sendToDelegate = false;
//是否点击在需代理的view上,这里不好翻译,大致意思看后面
boolean hit = true;
//是否已处理
boolean handled = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Rect bounds = mBounds;
//down事件包含在rect区域里,要发event事件给需代理的view
if (bounds.contains(x, y)) {
mDelegateTargeted = true;
sendToDelegate = true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_MOVE:
sendToDelegate = mDelegateTargeted;
if (sendToDelegate) {
Rect slopBounds = mSlopBounds;
//用ScaleTouchSlop扩大的区域是否包含了event的x y坐标,hit默认为true,默认包含
if (!slopBounds.contains(x, y)) {
hit = false;
}
}
break;
case MotionEvent.ACTION_CANCEL:
sendToDelegate = mDelegateTargeted;
mDelegateTargeted = false;
break;
}
if (sendToDelegate) {
final View delegateView = mDelegateView;
if (hit) {
// Offset event coordinates to be inside the target view
//这里重设了event的坐标,改成固定左边坐标了
event.setLocation(delegateView.getWidth() / 2, delegateView.getHeight() / 2);
} else {
// Offset event coordinates to be outside the target view (in case it does
// something like tracking pressed state)
int slop = mSlop;
//上面英文解释也很清楚,是为了追踪preesed状态的,就是当move事件一直移动还没up前移出了设定的rect点击区域的时候需要重写设置event的坐标
event.setLocation(-(slop * 2), -(slop * 2));
}
handled = delegateView.dispatchTouchEvent(event);
}
return handled;
}
看最后的 event.setLocation瞬间一口老血吐出来了。照这样,只能作为扩大view的点击区域用了。并不能作为扩大view的滑动响应区域。
参考SearchView里面自定了TouchDelegate修改了一番
class UpdatableTouchDelegate(
targetBounds: Rect,
actualBounds: Rect,
delegateView: View
) : TouchDelegate(targetBounds, delegateView) {
companion object {
private const val TAG = "UpdatableTouchDelegate"
}
/**
* View that should receive forwarded touch events
*/
private val mDelegateView: View
/**
* Bounds in local coordinates of the containing view that should be mapped to the delegate
* view. This rect is used for initial hit testing.
*/
private val mTargetBounds: Rect
/**
* Bounds in local coordinates of the containing view that are actual bounds of the delegate
* view. This rect is used for event coordinate mapping.
*/
private val mActualBounds: Rect
/**
* True if the delegate had been targeted on a down event (intersected mTargetBounds).
*/
private var mDelegateTargeted = false
init {
mTargetBounds = Rect()
mActualBounds = Rect()
setBounds(targetBounds, actualBounds)
mDelegateView = delegateView
}
fun setBounds(desiredBounds: Rect, actualBounds: Rect) {
mTargetBounds.set(desiredBounds)
mActualBounds.set(actualBounds)
}
override fun onTouchEvent(event: MotionEvent): Boolean {
val x = event.x.roundToInt()
val y = event.y.roundToInt()
var sendToDelegate = false
var handled = false
when (event.action) {
MotionEvent.ACTION_DOWN -> if (mTargetBounds.contains(x, y)) {
mDelegateTargeted = true
sendToDelegate = true
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_MOVE -> {
sendToDelegate = mDelegateTargeted
}
MotionEvent.ACTION_CANCEL -> {
sendToDelegate = mDelegateTargeted
mDelegateTargeted = false
}
}
if (sendToDelegate) {
// Offset event coordinates to the target view coordinates.
event.offsetLocation(-mActualBounds.left.toFloat(), -mActualBounds.top.toFloat())
handled = mDelegateView.dispatchTouchEvent(event)
}
return handled
}
}
ennnnnnn~ 愉快的拿到了会变动的x和y了