I am looking to replace the direct usage of RecyclerView.scrollBy() with an equivalent Espresso ViewAction. I found RecyclerViewActions.scrollToPosition(), but that seems to take in a target index position as opposed to a delta offset (i.e pixels). For example, I might want to scroll down by twice the height of a header.
I tried looking at the documentation in https://developer.android.com/reference/androidx/test/espresso/contrib/RecyclerViewActions but can't seem to find something that behaves like scrollBy https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/RecyclerView#scrollBy(int,int)
Related
Could anyone please explain what MotionLayout's onSwipe parameters touchAnchorId and touchAnchorSide do? This is what documentation says about touchAnchorId
View that is being moved by the swipe.
That doesn't make sense to me as swiping on MotionLayout doesn't move a single view. Swiping progresses transition between starting constraintSet and ending constraintSet. I thought initially that touchAnchorId would specify a view that user will have to drag to progress animation but this isn't a case and MotionLayout developer team introduced touchRegionId parameter for that. It's also unclear to me what touchAnchorSide is supposed to do as I don't see any difference when changing its value.
onSwipe Move progress from 0 to 1 along a
direction(dragDirection=) horizontal (dragRight/Left/StartEnd) or vertical (dragUp/Down)
If I drag my finger a 100 pixels along the screen how much does it move from 0 to 1?
That is the main question most of the other argument answer.
with out an anchor it uses the full length of the layout.
But if you are making a pull out draw that is excessive.
You could adjust it with dragScale. But how much? The pull may vary based on constraints fonts many things.
Many times you want it to act as if you are pulling a view or a side of a view. In which case you ned to the View (touchAnchorId) and the side of the view (touchAnchorSide)
Sometimes you want to limit the region in which the swipe will work
In which case you can use limitBoundsTo.
Much of the rest of the flags are bout what to do when you lift your finger.
There is much more subtly in all the use-cases it is designed to support.
I have a base layout that holds several views. I need to translate them along the x axis. Basically there are 2 types of translations happening the one that follows the finger all the way and the one that stops after certain threshold which gives a nice parallax-like effect.
So is it better to put the group of views that share same translation logic inside another container and translate the container or translate each view individually?
I know this might sound weird but Google always recommends to use flat view hierarchy because nested layouts are expensive to redraw, so does it mean that keeping just one layer of nesting and translating each view by hand is better?
Also this translation is applied to all the views in the RecyclerView, not just one.
I think you should keep a flat layout as Google recommends, and translate each view individually. I would create a custom view were you can set a threshold. And once set, you can simply pass the x position of the finger to them all, and they'll decide if they should move or not.
How to implement it requires more input or requirements before giving any suggestion. Besides performance problem, code maintainable should be considered too.
Base on my experience. With high-end phone and high API level (about >= 21), they have better hardware, effective way to manage memory and background task. The problem expensive to redraw you mentioned seems not too important with some simple animation. In this situation, code maintainability has higher priority, I will decide to have an extra FrameLayout container, wrap the View which have the same animation because you have less code => less logic. 0 or 2 FrameLayout have no noticeable difference in performance in this case
About low-end devices, if you want to target lower API users, performance becomes a top priority. Now both cases you mentioned have the effect on performance, one requires more memory to store more View and one requires more CPU to run animation. It's time for a trade-off. In your case when you have 2 translate animations run on any item in RecyclerView, I prefer to create 2 separate animations run on 2 View. This way I can save a bunch of extra containers => save memory, the animation is not run for all of the items so it only affects the CPU for a small amount of time during animation.
So to sum up, You have a different approach for each case, choose a top-priority for the case you choose, improve it, sacrifice the others that have less effect on the overall problem. No solution is 100% perfect, trade-off situation always happens when coding
Another questions about setting position of a view. If you want to move a view around then you can do setX, setTranslationX, setLeft or LayoutParam.leftMargin
Offcourse there is also overriding the onDraw method and using Matrix/Bitmap/Canvas operation.
I was wondering what's the difference. Do they all ultimetly adjust the same value which is x coordinate of the view?
It would be good to have it all in one post for future readers as well
So far I know,
LayoutParam.LeftMargin: is available for all API (specific under Api
8)
SetTranslation: Difference between original left bound of the view and the new leftbound. Though I heard maybe it is not persistent?
Anyone can shed light on the differences and if they impact different properties or the same property?
I believe that the main difference between setLeft and setX() is that setLeft() is relative to its parent view, where setX() just sets the position relative to the whole screen, which is the same as setTranslationX().
In setLeft() terms it means that the layout system can change its layout position. For example if we would use setLeft while scrolling through a RecyclerView the system would change its position accordingly, so the proper use in this case would be setX().
Without going into too much detail, I want to be able to 'slide' elements in a ListView similar to the 'slide to archive' feature in GMail. I'm fine with the onTouchListener and all that, my question is regarding the slide animation.
The first two things that come to mind are..
view.setPadding(slideOffset, 0, 0, 0);
and..
view.setX(slideOffset);
The former is very buttery, even on the emulator.
The latter is a bit janky on my Galaxy Nexus.
My questions:
* Regardless of what I've tried, what's the correct way to do this?
Why is setX less smooth than setPadding?
Does one approach conform to Android best practices more than the other?
Are tweened translation animations an option? If so, can you provide a brief example to point me in the right direction please?
Edit:
To be clear, I am attaching an image of the effect I am trying to emulate.
I'm pretty sure the setX() is slower because it affects its parents. When changing the X of a view, it calls the onLayout/onMeasure of the parent every time you update the value. That's because the X value of the child may cause other items on the parent to move, therefor the parent needs to redraw itself.
You can test this easily by extending the ViewGroup and writing to the log on those methods. Then, you can use both approaches, padding vs. setX, and see what happens.
Are you trying to animate the item? Or do you want the user to move it like on Gmail? You can use the ObjectAnimator to handle the "X" value of your item. Combined with a "hardware layer" for your item, it will create a smoother experience. You can find more details about how to do that here: http://developer.android.com/guide/topics/graphics/hardware-accel.html
Yeah, if you're targeting higher APIs, ViewPropertyAnimator is probably a great solution. If you have to support lower APIs, my thought process for implementation would be (and I haven't implemented this myself personally, but this should be good for performance) to:
In your touch handler, once you've determined that the user is "sliding", set the View's visibility to INVISIBLE, and store the drawing cache into a separate bitmap (Bitmap bmp = myView.getDrawingCache();)
Draw that bitmap in the same place as the view, and use the Canvas translate methods to shift the position according to the x-position of the user's touch point.
After the user lets go, translate back (preferably smoothly with an animation), recycle the bitmap, and set the view back to VISIBLE.
Check out the 3 devBytes posted on AndroidDev:
https://www.youtube.com/watch?v=8MIfSxgsHIs&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=12
https://www.youtube.com/watch?v=NewCSg2JKLk&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=11
https://www.youtube.com/watch?v=NewCSg2JKLk&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=11
https://www.youtube.com/watch?v=YCHNAi9kJI4&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=4
https://www.youtube.com/watch?v=PeuVuoa13S8&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=3
I'm developing an android app that User select an emoticon.
I'd like a nice swipe gesture selection with horizontal scroll.
can i create a horizontal scroll to select emotion.
this is an example
https://www.dropbox.com/s/n298h17r3fs2wvj/scrollswipe.jpg
Have you tried using GestureDetector.OnGestureListener?
http://developer.android.com/reference/android/view/GestureDetector.OnGestureListener.html
I think onScroll() is just vertical, but I might be wrong; onFling() is definitely horizontal but requires a bit of velocity.
If you haven't looked at GestureDetector, then you should write a simple demo for yourself with it in any case.
On the jpeg it looks like you are after a very specific hook like curve. If that's the case, then you need to implement detection yourself using the lower level, more flexible View.OnTouchListener.
http://developer.android.com/reference/android/view/View.OnTouchListener.html