I want to implement point-events for Nativescript.
Though I am facing a technical dilemma for which I might need help. Thus this issue
To achieve that feature you need UIView::hitTest or iOS and android.view.View.dispatchTouchEvent on android.
For it work well we would need this to be applied to any view, either from the framework or from a module.
This could be achieved on iOS with a category on UIView in which we would implement hitTest and inside call a method on the Nativescript View class. But is there a way to use category that way in Nativescript? Maybe in the widgets?
Now on android it s even more tricky as it is a method that need to be overridden. There I fill stuck.
I implemented this in another framework (Titanium Mobile), but there it was easier because each widget (even modules) was actually created inside a custom bounding View on which I had total control. So when you were creating a button you were actually creating a view and a button inside it.
For me this is a must have feature as I use it all the time in my apps. For example a flexible app bar under which you have a map view for example.
Any idea would be much appreciated
@farfromrefug you cannot create an Objective-C category from JavaScript/TypeScript. If you really need a new Obj-C category I would suggest you to consider creating a NativeScript plugin (maybe this point-events functionality can be part of the same plugin?).
Btw could you elaborate what exactly is point-events?
Related to https://github.com/NativeScript/ios-runtime/issues/775
@manoldonev sorry for not explaining, css 'point-events' is equivalent to a "touch pass through property".
And no this can't really be done within a plugin as it is a property that should be applicable to any view even the Nativescript ones.
Now I have been thinking about this and I think the way I could make it work would be to create (upon point-events property set to "none", thus touch pass through activated) a wrapper holder view. That view could be custom and thus we could override the necessary methods on iOS and Android.
Would such implementation would be ok with the Nativescript Team?
The trickiest thing would be the layout of all that and the separation of actions that should be applied to the "layout" holder and not to the native view.
For example if you were to do that on a button, you would have to differentiate access to nativeViewProtected. Changing width should be applied on the wrapper layout, but changing label should be applied on the actual button view. I used such a trick in this PR
@farfromrefug all NativeScript views implement the IsUserInteractionEnabled property that indicates whether the user can interact with the respective view. Have you tried it and wouldn't it accomplish the essence of css point-events you are looking for?
@manoldonev no it s not the same thing. Because with isUserInteractionEnabled any child would also be disabled. So it's not really a "touch pass through". This for example would not work for material design action bar when you can have a background "actionable" view.
@farfromrefug I am working on something (extended version of the isUserInteractionEnabled idea) that should achieve the desired functionality -- you can check the related PRs (work in progress).
@manoldonev thanks for looking into this. Great PR on the way!
2 things:
isUserInteractionEnabled will disable touch for all children. touchPassThrough only disables it for the view itself. Thus the hitTest on iOS. If you touch a child view, actual touch will be registered and pass to the child.dispatchTouchEvent to test for child touch. If child touch accepts it (enabled and not touch pass through and not sub child handled...) then you return false and the parent can handle it.Now I have a well tested implementation of that. I had many app using that. You can look at it:
https://github.com/Akylas/titanium_mobile/blob/master/android/titanium/src/java/org/appcelerator/titanium/view/TiCompositeLayout.java#L1757
https://github.com/Akylas/titanium_mobile/blob/master/iphone/Classes/TiUIView.m#L2092
PS: There are many features I already implemented there that I would love and will try to bring to Nativescript!
PS2: thinking about it I now have a doubt that onTouchEvent might actually work. But will it the way it is used in Nativescript with a gesture handler? Did you try? Could be a nifty trick!
PS3: actually I might have just re-rewritten dispatchTouchEvent in my class :D. Look at this
I am going to test your code tomorrow!
[Edit: Updated the scenarios]
@farfromrefug can you write up what you expect to happen when tapping on RED, GREEN, and BLUE elements on iOS and Android in the following use case scenarios:
Scenario 1 (inner StackLayout isUserInteractionEnabled=true and isPassThroughParentEnabled=false):
<StackLayout tap="onOuterStackTap">
<StackLayout tap="onStackTap" backgroundColor="red" height="200">
<Button isUserInteractionEnabled="false" color="white" backgroundColor="green" tap="onTap" text="WILL NOT TAP"></Button>
<Button color="white" backgroundColor="blue" tap="onTap2" text="TAP"></Button>
</StackLayout>
</StackLayout>
Scenario 2 (inner StackLayout isUserInteractionEnabled=true and isPassThroughParentEnabled=true):
<StackLayout tap="onOuterStackTap">
<StackLayout tap="onStackTap" backgroundColor="red" height="200" isPassThroughParentEnabled="true">
<Button isUserInteractionEnabled="false" color="white" backgroundColor="green" tap="onTap" text="WILL NOT TAP"></Button>
<Button color="white" backgroundColor="blue" tap="onTap2" text="TAP"></Button>
</StackLayout>
</StackLayout>
Scenario 3 (inner StackLayout isUserInteractionEnabled=false and isPassThroughParentEnabled=false):
<StackLayout tap="onOuterStackTap">
<StackLayout tap="onStackTap" backgroundColor="red" height="200" isUserInteractionEnabled="false">
<Button isUserInteractionEnabled="false" color="white" backgroundColor="green" tap="onTap" text="WILL NOT TAP"></Button>
<Button color="white" backgroundColor="blue" tap="onTap2" text="TAP"></Button>
</StackLayout>
</StackLayout>
Scenario 4 (inner StackLayout isUserInteractionEnabled=false and isPassThroughParentEnabled=true):
<StackLayout tap="onOuterStackTap">
<StackLayout tap="onStackTap" backgroundColor="red" height="200" isUserInteractionEnabled="false" isPassThroughParentEnabled="true">
<Button isUserInteractionEnabled="false" color="white" backgroundColor="green" tap="onTap" text="WILL NOT TAP"></Button>
<Button color="white" backgroundColor="blue" tap="onTap2" text="TAP"></Button>
</StackLayout>
</StackLayout>
Also, am I missing a scenario that is related to passthrough / event propagation?
btw if I understand you correctly I think I now agree that isPassThroughParentEnabled should not depend on (override) the isUserInteractionEnabled value.
@farfromrefug Maybe I initially misunderstood the feature -- could you confirm if in the following setup:
<StackLayout tap="onOuterStackTap">
<StackLayout tap="onStackTap" backgroundColor="red" height="200" isPassThroughParentEnabled="true">
<Button isUserInteractionEnabled="false" color="white" backgroundColor="green" tap="onTap" text="WILL NOT TAP"></Button>
<Button color="white" backgroundColor="blue" tap="onTap2" text="TAP"></Button>
</StackLayout>
</StackLayout>
@manoldonev you are correct we have almost exactly the same sample
Ok, then I'll have to update my implementation, will let you know when I'm done.
@manoldonev I can help you with the implementation if you want. Let me know.
About 2 comments I missed:
isUserInteractionEnabled is different from isPassThroughParentEnabledisUserInteractionEnabled=false should be combine with isPassThroughParentEnabled of the parent view.PS : you don't like pointEvents for the name? I personally don't like it but I wanted to make it "compatible" with web css.
@farfromrefug naming is not finalized but keeping pointer-events makes sense if we ultimately expose it like css property (and it behaves as the web version).
I updated my PRs and I think currently the iOS implementation fulfils the requirements of https://github.com/NativeScript/NativeScript/issues/6191#issuecomment-415082159. However, there are some problems with Android approach and the isUserInteractionEnabled / isPassThroughParentEnabled relationship. I am thinking about exploring a different approach with moving the isPassThroughParentEnabled property from View to CustomLayoutView class as we are already implementing a custom Android ViewGroup widget for it that we might be able to customize as per the feature requirements). I'll continue working on this next week.
@farfromrefug you can check the updated PRs in both NativeScript #6204 and widgets https://github.com/NativeScript/tns-core-modules-widgets/pull/135 repos
@manoldonev great! on holidays right now. will try to look at it as soon as possible. thanks again
Closing with #6204 and https://github.com/NativeScript/tns-core-modules-widgets/pull/135
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
Closing with #6204 and https://github.com/NativeScript/tns-core-modules-widgets/pull/135