Views with attached OnClickListeners slows down ScrollView. What can be done?
So, basically, I have a ScrollView with lots of various ViewGroups and Views added inside it and my Activity should respond to clicks on those Views. Unfortunately, OnClickListeners I set to them slows down ScrollViews reaction 开发者_如何学Pythontime to faster scroll or fling gestures (when they start on Views in question).
Is there any way to do this right or workaround this issue?
Yeah, I'm not sure that reducing the complexity of your layout will help you. Which API version is your device/emulator running? Because I've noticed a change from 2.1 to 2.2 around starting a scroll event on a clickable view, as you have described.
In my case, I'm enabling nested scrolling by using the requestDisallowInterceptTouchEvent()
method. Normally, this would allow me to place a ScrollView or ListView inside another ScrollView and still have it scroll correctly. However, starting with API level 8, this 'nested scrolling' no longer works if the touch event starts on a 'clickable' control! Augh! I haven't looked at the source to determine exactly why it happens, but it sounds like it's related to your problem.
So it seems like there was a recent change with how clickable controls consume touch events, which adversely affects their parents in some cases. I doubt there is a solution.
Edit:
If you'd like to implement "clicks" another way, that's certainly possible. I wouldn't normally recommend it, but then I don't know how bad your scrolling performance is. Up to you.
If you want to do it, you could add an OnTouchListener to your ScrollView, but I think that would be the harder way to do it. You'd have to listen for ACTION_UP
events, but only consume the events if the corresponding ACTION_DOWN
event was less than touchSlop
far away in the y direction (touchSlop
is the minimum distance a touch has to travel before a ListView
will begin scrolling... it gets this value from the ViewConfiguration
). Then, when you consume the event, you'll have to add ListView.getScrollX()
and ListView.getScrollY()
to the coordinates of the event in order to compare it to the positions of your clickable controls. And if you want "long clicks," you'll have to do more work to implement those. And all that is only for touch events... you also need to add a key listener so your users could use the trackball to click it.
I think instead you might be able to add an OnTouchListener to each one of your controls, instead of the OnClickListener. Check the View source code to see how clicks are registered. If you don't need to be able to register "long clicks" then it will be much easier for you. Then you'll be able to treat pretty much any ACTION_UP
event as a click. You'll still also need a key listener to handle trackball clicks.
Seems like a lot of work for a minor scrolling hiccup. I wonder if I didn't understand the question correctly, if it's really a more serious problem than I think it is?
I don't know specifics of the Android platform, but a typical recommendation is to do as little as possible in your event handler. Quickly check if it is an event that you are interested in and put a task in a queue. Use another thread to pull tasks from the queue, aggregate and execute them.
Try and reduce the number of ViewGroups and Views, possibly by using a RelativeLayout for each item in the scrollview. Use the HierarchyViewer tool to examin the depth of your views and possibly try Romain Guy's tips on layout improvements:
http://www.curious-creature.org/2009/03/01/android-layout-tricks-3-optimize-part-1/
Why do you think it's the OnClickListeners that make it slow?
Set all click listeners to null and try to use the app. Is it fast now?
Otherwise, profile your app to find out whats slow.
http://www.jpct.net/wiki/index.php/Profiling_Android_Applications
精彩评论