-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
iOS - Scroll does not work at all when touch starts on a UIKitView inside eg a LazyColumn #4818
Comments
Funny, I was just about to submit this same issue. It does severely limit the use of UIKitView. Setting Here is my minimal reproducer: @OptIn(ExperimentalForeignApi::class)
fun MainViewController() = ComposeUIViewController {
Column(modifier = Modifier.verticalScroll(state = rememberScrollState())) {
UIKitView(
factory = {
UIView().apply {
backgroundColor = UIColor.redColor
}
},
modifier = Modifier.fillMaxWidth().height(400.dp)
)
repeat(100) {
Text("Item #$it")
}
}
} |
Hi, it's a known problem, and not exactly a trivial one to fix due to differences in touch processing in Compose and UIKit. We are investigating our options currently. |
Great news, thank you @elijah-semyonov . I am gonna suspend my project until than, and stay with separated UI (I am using a webview in column, which can not be done without UIKitView for iOS). |
As a workaround, you could present native |
So how that would could be part of the scrollable content? I dont get it. |
It won't be. But you don't have to reimplement entire screen natively. |
Just the column content, get it. Which is the whole screen (except top and bottom bar).:) Never mind. I started and coded the UI already separately/natively, but wanted to refactor to only maintain one UI instead of two. Took almost 2 weeks, and this was the last piece which is missing, everything else looks working, thats why its so annoying :)) But I might keep going this direction and use this screen only natively as suggested. Thanks for your help anyway, and I am looking forward to have this fixed. :) |
Flutter's UIKitView has a https://api.flutter.dev/flutter/widgets/UiKitView/gestureRecognizers.html
GestureDetector(
onVerticalDragStart: (DragStartDetails details) {},
child: const UiKitView(
viewType: 'webview',
),
) |
Well, we can do that! The problem is, there is no way that is currently apparent to us, to conditionally allow touches to slip to the interop view gesture recognisers (such as compose scroll in a native scroll, for example). The behavior in your example is possible by the usage of |
facing same issue |
same |
@elijah-semyonov could you please expand on your suggestion of "The behavior in your example is possible by the usage of Modifier.draggable and using interactable = false in UIKitView arguments.". I tried a few combinations of setting interactive = false and implementing draggable on the Modifier, without success. With interactive = false, scrolling is fine, but it doesn't register any click events as @brewin has pointed out above. My use-case is to embed a Native Ad using Google AdMob, where the UIView for the Ad is coming from Swift for iOS. In the ideal case, I want to be able to scroll on top of the Ad, but still be able to click on the Ad. |
My solution is to turn off the touch event of UIView and unify the click penetration through the click event hitTest of compose to the rect of UIView. For example, my UIView put a webview, and I need to click on the picture inside. I will first register a query of the coordinates of all pictures through js, get a set of rectangular arrays, and confirm that the picture is clicked by matching the array. |
First approach to allow touches to be processed by both Compose and nested interop views. Other UX improvements will follow. 1. `actual typealias InteropView = UIView` 2. Change `ComposeScene` API to allow hit testing specific `InteropView`. 3. Make `InteractionUIView` a `container` view of `InteropContainer` to enforce it being in the same responder chain as interop views. 4. Remove `InteractionUIView.Delegate` and replace it with callbacks to avoid `by lazy` reentry in `ComposeSceneMediator`, make `InteractionUIView` construction eager. 5. Use `event.allTouches` instead of `event.touchesForView` to avoid receiving an empty list in case `InteractionUIView` is part of responder chain but not the hit test result itself. 6. Remove `KeyboardEventHandler.uikit.kt` to avoid `by lazy` reentry, stick everything in a single lambda. Fixes some of the cases from the domain of JetBrains/compose-multiplatform#4818 ## Testing `Demo/IosBugs/UIKitRenderSync` now properly registers touches to allow LazyColumn scrolling and native view reaction. ## Release Notes ### iOS - Fixes - Touches inside interop views are not exclusive to them and are processed on Compose side as well. ### Multiple Platforms - Breaking changes - ComposeScene `fun hitTestInteropView(position: Offset): Boolean` changed to `fun hitTestInteropView(position: Offset): InteropView?` --------- Co-authored-by: Ivan Matkov <ivan.matkov@jetbrains.com>
## Description In this approach `CMPGestureRecognizer` delays `touchesBegan` until explicitly failed, and is required to fail by `UIGestureRecognizer` of children views (aka interop views). Failure happens after the first touch started and no motion above scroll slop happens within 150ms. If this happens, intercepted touches are delivered to children views (and their gesture recognisers), Compose itself gets all tracked touches as cancelled and ignores them until the touch sequence ends (imposed by UIKit). This behavior is inspired by `UIScrollView` implementation. https://github.com/JetBrains/compose-multiplatform-core/assets/4167681/1245b986-1f11-4f02-a939-c069a7797e3a ### Fixes Improves behavior of touches in [certain scenarios](JetBrains/compose-multiplatform#4818) ## Testing This should be tested by QA ## Release Notes ### iOS - Features - Improvements in touches processing to detect if touches were meant to be delivered to interop views, or should be processed by Compose. --------- Co-authored-by: Ivan Matkov <ivan.matkov@jetbrains.com>
Awaiting your feedback (and perhaps future issues) after these changes are released! |
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks. |
@elijah-semyonov I have imported 1.7.0-dev1727, But I do not experience any difference. The same lazycolumn which holds a wkwebview or a single uiview, does not scroll if the drag starts on the UIKitview (Modify.draggable also not triggered). But it does scroll with Androidview. |
I also see no difference when running 1.7.0-dev1727. In my case it's lazy column with |
@AttilaBarany @paskowski |
Nothing happens. Slow, fast, long, short, delay... ![]() |
I don’t think 1.7.0-dev1727 includes the changes. The next dev release will. |
I got it from his commit linked in this issue above. JetBrains/compose-multiplatform-core@174766b ![]() |
@AttilaBarany
Screen.Recording.2024-07-15.at.15.57.28.mov |
The logic is identical to |
I agree with #4818 (comment) that https://github.com/JetBrains/compose-multiplatform/releases/tag/v1.7.0-dev1727 does not have the changes that were supposed to fix this issue. |
@elijah-semyonov The video looks very promising, thank you for testing and showing me the error maybe is in my setup!!! I had a mistake providing the library version. I have changed the lib to 1.7.0-dev1727, but the gradle was set to use the compose.plugin which had an earlier version set. After fixed (set the plugin version to 1.7.0-dev1727), or I thought I fixed, gradle does not want to sync: |
@elijah-semyonov I got the versions sorted, I set 1.7.0-alpha01 whis is the latest, and the scroll still does not work. So @paskowski and @brewin are correct. The fix is still not included. ![]() |
That's super awkward, CI shows that it was included in 1727. Anyway, let's w8 for other dev build and see if it flies. |
|
I can confirm that both |
Affected platforms
Versions
To Reproduce
![Screenshot 2024-05-16 at 16 15 51](https://private-user-images.githubusercontent.com/40792011/331246876-5abac7f5-7468-4616-b894-52279dce0862.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjExNTMyNjUsIm5iZiI6MTcyMTE1Mjk2NSwicGF0aCI6Ii80MDc5MjAxMS8zMzEyNDY4NzYtNWFiYWM3ZjUtNzQ2OC00NjE2LWI4OTQtNTIyNzlkY2UwODYyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE2VDE4MDI0NVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTFmYzI1YTc3OTk1NjMxOGFjNjVhNzQyNTNlODU2ODRlMTQwZGM2Yjc2ZDllM2ZiMWUyMzcxMzQzNzA4YmYzNDMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.gujmWpvt7BeOjFJlXLBWVMUTCSzrqEgDzKdM7NxnhfI)
Just extend the "uikit-in-compose" example app like this:
(adding a big box after the elements inside the column, and make the column scrollable)
and try to scroll by grabbing eg the textfield
You can reproduce this with any UIKitView, eg a simple UIView(), wkwebview etc... Adding eg Androidview webview does allow us to scroll by grabbing it, but UKitView does not bubble up anything, even tried with custom nestedscrollconnection just print out pre- or post scroll, but got not a single trigger. This failure just makes useless the UIKitView, or at least very limited. You can just integrate only in static pages, without any scrolling, otherwise the user will stuck on the page with invisible contents which are below in the column.
The text was updated successfully, but these errors were encountered: