Skip to content

Commit bc92bf9

Browse files
committed
refactor(demo): clean up accessibility bridge
1 parent 4c9a510 commit bc92bf9

3 files changed

Lines changed: 210 additions & 390 deletions

File tree

examples/demo/Assets/Plugins/Android/OneSignalConfig.androidlib/src/main/java/com/onesignal/onesignalsdk/OneSignalUnityE2EAccessibility.java

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ public void afterTextChanged(Editable s) {}
149149
if ("button".equals(role)) {
150150
view.setClickable(true);
151151
view.setOnClickListener(v -> sendToUnity(id, "click", ""));
152+
} else if ("main_scroll_view".equals(id)) {
153+
// Claim ACTION_DOWN on the scrollable's empty regions so the parent
154+
// E2EOverlay sees subsequent ACTION_MOVE events and can intercept
155+
// vertical drags. Without this, swipes on bare space fall straight
156+
// through the overlay and Appium scrollIntoView never advances.
157+
view.setClickable(true);
152158
}
153159
}
154160

@@ -211,44 +217,69 @@ private static final class Entry {
211217
}
212218

213219
private static final class E2EOverlay extends FrameLayout {
214-
private final int gutterWidth;
215220
private final int touchSlop;
216-
private boolean trackingGutterDrag;
221+
// Once a swipe is detected we hijack the gesture: the originally-targeted
222+
// child (often a button TextView) receives ACTION_CANCEL and every later
223+
// ACTION_MOVE/UP routes to this overlay's onTouchEvent.
224+
private boolean interceptingScroll;
225+
private float startX;
217226
private float startY;
218227

219228
E2EOverlay(Activity activity) {
220229
super(activity);
221-
// The test swipe lane is x=10. Keep this narrow so dialog checkboxes
222-
// near the left edge still receive normal clicks.
223-
gutterWidth = 24;
224230
touchSlop = ViewConfiguration.get(activity).getScaledTouchSlop();
225231
}
226232

227233
@Override
228-
public boolean dispatchTouchEvent(MotionEvent event) {
229-
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
230-
trackingGutterDrag = event.getX() <= gutterWidth;
231-
startY = event.getY();
232-
if (trackingGutterDrag) return true;
233-
}
234-
235-
if (!trackingGutterDrag) return super.dispatchTouchEvent(event);
236-
237-
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
238-
float deltaY = event.getY() - startY;
239-
if (Math.abs(deltaY) > touchSlop) {
240-
sendToUnity("main_scroll_view", "scroll", deltaY < 0 ? "down" : "up");
241-
}
242-
trackingGutterDrag = false;
243-
return true;
234+
public boolean onInterceptTouchEvent(MotionEvent ev) {
235+
// Unity renders into a SurfaceView, so UI Toolkit's ScrollView never
236+
// sees touches that an overlay accessibility child consumed first.
237+
// Appium's `scrollIntoView` swipes through the horizontal centre of
238+
// `main_scroll_view`, often starting on top of a clickable overlay
239+
// TextView (button) — that child eats ACTION_DOWN and the rest of the
240+
// gesture, so the ScrollView never scrolls. Catch any vertical drag
241+
// here and convert it to a real ScrollView offset change. Plain taps
242+
// stay under touchSlop and pass through unaffected.
243+
switch (ev.getActionMasked()) {
244+
case MotionEvent.ACTION_DOWN:
245+
startX = ev.getX();
246+
startY = ev.getY();
247+
interceptingScroll = false;
248+
return false;
249+
case MotionEvent.ACTION_MOVE:
250+
if (interceptingScroll) return true;
251+
float dx = ev.getX() - startX;
252+
float dy = ev.getY() - startY;
253+
if (Math.abs(dy) > touchSlop && Math.abs(dy) > Math.abs(dx)) {
254+
interceptingScroll = true;
255+
return true;
256+
}
257+
return false;
258+
default:
259+
return false;
244260
}
261+
}
245262

246-
if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
247-
trackingGutterDrag = false;
248-
return true;
263+
@Override
264+
public boolean onTouchEvent(MotionEvent ev) {
265+
if (!interceptingScroll) return false;
266+
switch (ev.getActionMasked()) {
267+
case MotionEvent.ACTION_UP:
268+
case MotionEvent.ACTION_CANCEL:
269+
float deltaY = ev.getY() - startY;
270+
interceptingScroll = false;
271+
if (Math.abs(deltaY) > touchSlop) {
272+
// Positive value = scroll forward (reveal content below),
273+
// matching a finger that travels upward on screen. Unity converts
274+
// screen pixels to UI Toolkit panel units before mutating
275+
// scrollOffset.
276+
sendToUnity(
277+
"main_scroll_view", "scrollDelta", String.valueOf(Math.round(-deltaY)));
278+
}
279+
return true;
280+
default:
281+
return true;
249282
}
250-
251-
return true;
252283
}
253284
}
254285

examples/demo/Assets/Resources/Theme.uss

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,9 @@
200200
glyph is still rendered at 18px (font-size), centered via text-align,
201201
so the button looks unchanged but absorbs small Appium tap-coord
202202
drift after ScrollView momentum / accessibility-frame settle. The
203-
transparent background keeps it visually identical. */
203+
transparent background keeps it visually identical. The negative
204+
right margin pulls the icon's visual center toward the row edge,
205+
matching the alignment used in the other SDK demos. */
204206
width: 44px;
205207
height: 44px;
206208
background-color: rgba(0, 0, 0, 0);
@@ -211,7 +213,7 @@
211213
border-width: 0;
212214
border-radius: 0;
213215
padding: 0;
214-
margin: 0;
216+
margin: 0 -11px 0 0;
215217
}
216218

217219
.card {

0 commit comments

Comments
 (0)