Created
January 10, 2015 08:36
-
-
Save emanonwzy/c72f6c0601c33810ed02 to your computer and use it in GitHub Desktop.
A simple view support delegate touch event to another view
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.graphics.Canvas; | |
import android.graphics.Rect; | |
import android.util.AttributeSet; | |
import android.view.MotionEvent; | |
import android.view.View; | |
import android.view.ViewConfiguration; | |
/** | |
* Created by zeyiwu on 1/10/15. | |
*/ | |
public class DelegateTouchSpace extends View { | |
private View mDelegateView; | |
private Rect mBoundRect; | |
private Rect mSlopBoundRect; | |
private int mSlop; | |
private boolean mDelegateTargeted; | |
public DelegateTouchSpace(Context context, AttributeSet attrs, int defStyleAttr) { | |
super(context, attrs, defStyleAttr); | |
mBoundRect = new Rect(); | |
mSlopBoundRect = new Rect(); | |
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public DelegateTouchSpace(Context context, AttributeSet attrs) { | |
this(context, attrs, 0); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public DelegateTouchSpace(Context context) { | |
//noinspection NullableProblems | |
this(context, null); | |
} | |
/** | |
* Draw nothing. | |
* | |
* @param canvas an unused parameter. | |
*/ | |
@Override | |
public void draw(Canvas canvas) { | |
} | |
/** | |
* Compare to: {@link View#getDefaultSize(int, int)} | |
* If mode is AT_MOST, return the child size instead of the parent size | |
* (unless it is too big). | |
*/ | |
private int getDefaultSize2(int size, int measureSpec) { | |
int result = size; | |
int specMode = View.MeasureSpec.getMode(measureSpec); | |
int specSize = View.MeasureSpec.getSize(measureSpec); | |
switch (specMode) { | |
case View.MeasureSpec.UNSPECIFIED: | |
result = size; | |
break; | |
case View.MeasureSpec.AT_MOST: | |
result = Math.min(size, specSize); | |
break; | |
case View.MeasureSpec.EXACTLY: | |
result = specSize; | |
break; | |
} | |
return result; | |
} | |
@Override | |
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
setMeasuredDimension( | |
getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec), | |
getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec)); | |
} | |
@Override | |
public boolean onTouchEvent(MotionEvent event) { | |
int x = (int)event.getRawX(); | |
int y = (int)event.getRawY(); | |
boolean sendToTarget = false; | |
boolean hit = true; | |
//boolean handled = false; | |
switch (event.getAction()) { | |
case MotionEvent.ACTION_DOWN: | |
calculateBounds(); | |
if (mBoundRect.contains(x, y)) { | |
mDelegateTargeted = true; | |
sendToTarget = true; | |
} | |
break; | |
case MotionEvent.ACTION_CANCEL: | |
case MotionEvent.ACTION_MOVE: | |
sendToTarget = mDelegateTargeted; | |
if (sendToTarget) { | |
if (!mSlopBoundRect.contains(x, y)) { | |
hit = false; | |
} | |
} | |
break; | |
case MotionEvent.ACTION_UP: | |
sendToTarget = mDelegateTargeted; | |
mDelegateTargeted = false; | |
break; | |
} | |
if (sendToTarget && hit) { | |
return mDelegateView.onTouchEvent(event); | |
} else { | |
return super.onTouchEvent(event); | |
} | |
} | |
/** | |
* 设置delegate view,将touch事件重定向到该view | |
* @param view delgate view | |
*/ | |
public void setDelegateView(View view) { | |
if (mDelegateView != view) { | |
mDelegateView = view; | |
} | |
} | |
private boolean calculateBounds() { | |
if (mDelegateView == null) { | |
return false; | |
} | |
Rect mHitRect = new Rect(); | |
Rect mDelegateHitRect = new Rect(); | |
int[] mLocation = new int[2]; | |
int[] mDelegateLocation = new int[2]; | |
this.getLocationOnScreen(mLocation); | |
mDelegateView.getLocationOnScreen(mDelegateLocation); | |
this.getHitRect(mHitRect); | |
mDelegateView.getHitRect(mDelegateHitRect); | |
int width = mHitRect.width(); | |
int height = mHitRect.height(); | |
mHitRect.left = mLocation[0]; | |
mHitRect.right = mLocation[0] + width; | |
mHitRect.top = mLocation[1]; | |
mHitRect.bottom = mLocation[1] + height; | |
width = mDelegateHitRect.width(); | |
height = mDelegateHitRect.height(); | |
mDelegateHitRect.left = mDelegateLocation[0]; | |
mDelegateHitRect.right = mDelegateLocation[0] + width; | |
mDelegateHitRect.top = mDelegateLocation[1]; | |
mDelegateHitRect.bottom = mDelegateLocation[1] + height; | |
if (mHitRect.intersect(mDelegateHitRect)) { | |
mBoundRect.left = mHitRect.left; | |
mBoundRect.right = mHitRect.right; | |
mBoundRect.top = mHitRect.top; | |
mBoundRect.bottom = mHitRect.bottom; | |
mSlopBoundRect.inset(-mSlop, -mSlop); | |
return true; | |
} else { | |
mBoundRect.left = 0; | |
mBoundRect.right = 0; | |
mBoundRect.top = 0; | |
mBoundRect.bottom = 0; | |
mSlopBoundRect.left = 0; | |
mSlopBoundRect.right = 0; | |
mSlopBoundRect.top = 0; | |
mSlopBoundRect.bottom = 0; | |
return false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment