I am using this youtube player (which uses iFrame Youtube API in a webview) in a jetpack compose app - via AndroidView()
DisposableEffect(
AndroidView(factory = {
youTubePlayerView
}
)
) {
onDispose { youTubePlayerView.release() }
}
Problem is, when used from a Lazy Column, on scroll up, the long press is passed along to the iFrame in the webview, which triggers this context menu to appear:
Same problem occurs in the "classic" android view system, when used with a recycler view, and is described in detail here, along with a solution given - but I cant figure out how to adopt this solution to compose - or is there any other solution? Let me recap, how to detect and stop the long press on vertical scroll from propagating to the iFrame?
public class CustomRecyclerView extends RecyclerView {
private int touchSlop;
private List<MotionEvent> touchEventTrack = new ArrayList<>();
public CustomRecyclerView(@NonNull Context context) {
super(context);
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
public CustomRecyclerView(Context context, AttributeSet attributeSet){
super(context,attributeSet);
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
public CustomRecyclerView(@NonNull Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// TODO Only intercept vertical scroll
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:{
touchEventTrack.clear();
touchEventTrack.add(MotionEvent.obtain(ev));
break;
}
case MotionEvent.ACTION_MOVE:{
touchEventTrack.add(MotionEvent.obtain(ev));
break;
}
case MotionEvent.ACTION_UP:{
touchEventTrack.add(MotionEvent.obtain(ev));
if (isClick(ev)) {
for (int i = 0; i < getChildCount();i++){
View view = getChildAt(i);
if (!isInView(ev, view)) {
continue;
}
boolean handle = false;
for (MotionEvent event : touchEventTrack) {
handle = dispatchTransformedTouchEvent(event, view);
if (!handle){
break;
}
}
if (handle) {
MotionEvent cancelEvent = MotionEvent.obtain(ev);
cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
return onTouchEvent(cancelEvent);
}
}
}
break;
}
}
return onTouchEvent(ev);
}
private boolean isInView(MotionEvent ev, View view) {
Rect rect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
return rect.contains((int)ev.getX(), (int)ev.getY());
}
private boolean isClick(MotionEvent ev) {
MotionEvent downEvent = this.touchEventTrack.get(0);
return Math.abs(downEvent.getX() - ev.getX()) < touchSlop && Math.abs(downEvent.getY() - ev.getY()) < touchSlop;
}
private boolean dispatchTransformedTouchEvent(MotionEvent event, View child) {
float offsetX = getScrollX() - child.getLeft();
float offsetY = getScaleY() - child.getTop();
event.offsetLocation(offsetX, offsetY);
boolean handle = child.dispatchTouchEvent(event);
if (!handle) {
event.offsetLocation(-offsetX, -offsetY);
}
return handle;
}
}
I did try several things suggested in other SO threads, like the one below, but none of them works, best it achieves is disabling gestures for the lazy column too (which obviously is not what i want, i want to be able to scroll but just not pass the long press on scroll to the iFrame)
Jetpack Compose: how to disable gesture detection on children
https://github.com/PierfrancescoSoffritti/android-youtube-player/issues/848