Skip to content

Instantly share code, notes, and snippets.

@emanonwzy
Created January 10, 2015 08:36
Show Gist options
  • Save emanonwzy/c72f6c0601c33810ed02 to your computer and use it in GitHub Desktop.
Save emanonwzy/c72f6c0601c33810ed02 to your computer and use it in GitHub Desktop.
A simple view support delegate touch event to another view
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