Fix Touch events on Android

Fix Touch events on Android, using region.contains point instead of
Bitmap
This commit is contained in:
Horcrux
2017-01-13 15:54:36 +08:00
parent 0d0dd7802f
commit fc5c874a28
4 changed files with 46 additions and 63 deletions
@@ -76,13 +76,17 @@ public class GroupShadowNode extends RenderableShadowNode {
return hitSelf; return hitSelf;
} }
Matrix combinedMatrix = new Matrix(); Matrix groupMatrix = new Matrix(mMatrix);
if (matrix != null) { if (matrix != null) {
combinedMatrix.postConcat(matrix); groupMatrix.postConcat(matrix);
} }
combinedMatrix.postConcat(mMatrix); Path clipPath = getClipPath();
if (clipPath != null && !pathContainsPoint(clipPath, groupMatrix, point)) {
return -1;
}
for (int i = getChildCount() - 1; i >= 0; i--) { for (int i = getChildCount() - 1; i >= 0; i--) {
ReactShadowNode child = getChildAt(i); ReactShadowNode child = getChildAt(i);
@@ -92,9 +96,9 @@ public class GroupShadowNode extends RenderableShadowNode {
VirtualNode node = (VirtualNode) child; VirtualNode node = (VirtualNode) child;
int viewTag = node.hitTest(point, combinedMatrix); int hitChild = node.hitTest(point, groupMatrix);
if (viewTag != -1) { if (hitChild != -1) {
return (node.isResponsible() || viewTag != child.getReactTag()) ? viewTag : getReactTag(); return (node.isResponsible() || hitChild != child.getReactTag()) ? hitChild : getReactTag();
} }
} }
@@ -19,6 +19,7 @@ import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Region;
import com.facebook.common.logging.FLog; import com.facebook.common.logging.FLog;
import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Arguments;
@@ -294,62 +295,35 @@ abstract public class RenderableShadowNode extends VirtualNode {
return -1; return -1;
} }
// Bitmap bitmap = Bitmap.createBitmap( Matrix pathMatrix = new Matrix(mMatrix);
// mCanvasWidth,
// mCanvasHeight,
// Bitmap.Config.ARGB_8888);
//
// Canvas canvas = new Canvas(bitmap);
//
// if (matrix != null) {
// canvas.concat(matrix);
// }
//
// canvas.concat(mMatrix);
//
// Paint paint = new Paint();
// clip(canvas, paint);
// setHitTestFill(paint);
// canvas.drawPath(mPath, paint);
//
// if (setHitTestStroke(paint)) {
// canvas.drawPath(mPath, paint);
// }
//
// canvas.setBitmap(bitmap);
// try {
// if (bitmap.getPixel(point.x, point.y) != 0) {
// return getReactTag();
// }
// } catch (Exception e) {
//
// return -1;
// } finally {
// bitmap.recycle();
// }
return -1;
}
protected void setHitTestFill(Paint paint) { if (matrix != null) {
paint.reset(); pathMatrix.postConcat(matrix);
paint.setARGB(255, 0, 0, 0);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
}
protected boolean setHitTestStroke(Paint paint) {
if (mStrokeWidth == 0) {
return false;
} }
paint.reset(); if (pathContainsPoint(mPath, pathMatrix, point)) {
paint.setARGB(255, 0, 0, 0); Path clipPath = getClipPath();
paint.setFlags(Paint.ANTI_ALIAS_FLAG); if (clipPath != null && !pathContainsPoint(clipPath, pathMatrix, point)) {
paint.setStyle(Paint.Style.STROKE); return -1;
paint.setStrokeWidth(mStrokeWidth * mScale); }
paint.setStrokeCap(mStrokeLinecap);
paint.setStrokeJoin(mStrokeLinejoin); return getReactTag();
return true; } else{
return -1;
}
}
protected boolean pathContainsPoint(Path path, Matrix matrix, Point point) {
Path copy = new Path(path);
copy.transform(matrix);
RectF rectF = new RectF();
copy.computeBounds(rectF, true);
Region region = new Region();
region.setPath(copy, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom));
return region.contains(point.x, point.y);
} }
@Override @Override
@@ -48,6 +48,7 @@ public abstract class VirtualNode extends LayoutShadowNode {
protected String mName; protected String mName;
private SvgViewShadowNode mSvgShadowNode; private SvgViewShadowNode mSvgShadowNode;
private Path mCachedClipPath;
public VirtualNode() { public VirtualNode() {
mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density; mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density;
@@ -141,8 +142,12 @@ public abstract class VirtualNode extends LayoutShadowNode {
markUpdated(); markUpdated();
} }
protected @Nullable Path getClipPath() {
return mCachedClipPath;
}
protected @Nullable Path getClipPath(Canvas canvas, Paint paint) { protected @Nullable Path getClipPath(Canvas canvas, Paint paint) {
if (mClipPath != null) { if (mClipPath != null && mCachedClipPath == null) {
VirtualNode node = getSvgShadowNode().getDefinedClipPath(mClipPath); VirtualNode node = getSvgShadowNode().getDefinedClipPath(mClipPath);
if (node != null) { if (node != null) {
@@ -156,13 +161,13 @@ public abstract class VirtualNode extends LayoutShadowNode {
default: default:
FLog.w(ReactConstants.TAG, "RNSVG: clipRule: " + mClipRule + " unrecognized"); FLog.w(ReactConstants.TAG, "RNSVG: clipRule: " + mClipRule + " unrecognized");
} }
return clipPath; mCachedClipPath = clipPath;
} else { } else {
FLog.w(ReactConstants.TAG, "RNSVG: Undefined clipPath: " + mClipPath); FLog.w(ReactConstants.TAG, "RNSVG: Undefined clipPath: " + mClipPath);
} }
} }
return null; return getClipPath();
} }
protected void clip(Canvas canvas, Paint paint) { protected void clip(Canvas canvas, Paint paint) {
+1 -1
View File
@@ -259,7 +259,7 @@
// hitTest delagate // hitTest delagate
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{ {
return [self hitTest:point withEvent:event withTransform:CGAffineTransformMakeRotation(0)]; return [self hitTest:point withEvent:event withTransform:CGAffineTransformIdentity];
} }
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event withTransform:(CGAffineTransform)transform - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event withTransform:(CGAffineTransform)transform