My layout is a bit complex.
I have a SwipeRefreshLayout in which I host a ListView. Whenever the user drags the Listview's top, the SwipeRefreshLayout performs a refresh. I also listen for the last visible item of the ListView to load next page of records (Endless scroll)
In the list's adaptor I have 2 views that I am using. The first one will only be visible in first row, the other view will remain the same for all other rows.
What I want to achieve:
On top of the row with position = 1 I want to have a sticky header. This means that when I scroll Up, the header will scroll to the top of the screen and will remain in there.
This sticky header will only be at one row
if possible I'd like to use a simple implementation as my layouts and adapters are already complex enough.
Waiting for your suggestions.
I didnt quite get your question the first time, heres the answer attempt round 2.
In your layout add an empty viewgroup (whichever you prefer, though linearlayout seems to work just great), add a scrollListener to your listView and check the position of your sticky view. If its top anchor is below (meaning its visible in the listview) the top of the screen you set the viewgroup visibility to gone, if the top anchor is either touching the top of the screen or below it, you add that view or one just like it to the viewgroup and set its visibility to visible.
You can adjust the position 2 view visibility accordingly to allow for this change to appear seamless. Can help you a bit more once you have some code and are on your way with this change.
Related
I have a list of elements in a recycler view that are generated dynamically using data binding. Each element has a bottom view that is initially set to View.GONE, however once a user clicks the element and the view is expanded, the recycler view automatically scrolls back to the top of the list. Conversely, if the view is expanded and then clicked again to collapse, the recycler view scrolls to the top of the list again. I have tried keeping track of the ID's of the elements for the adapter (again using data binding), setting focus to the child element when they expand or collapse, and using binding adapters to animate the expand/collapse itself.
My suspicion is that the adapter in the recycler view is receiving a onNotifyDataChanged() alert when the height of one of the child changes, rendering an additional view (still inside one of the children though, not a separate child in the list), and automatically scrolls to the top. Is there a way to override this? Does anyone know what else might be causing the list to snap to the top when one of the elements is clicked -> expanded/collapsed?
So I found the solution to my issue in case someone encounters something similar. I actually ended up finding this answer: RecyclerView notifyDataSetChanged scrolls to top position
and the second solution involving the staggered layout manager was the route I went with, since I want to be able to wrap the content. My suspicions were correct that it had to do with the changing height of the elements in the recycler view. The expandable item's parent wrapped content, so the recycler view was forced to recalculate the size of the item once the expandable portion appeared/disappeared (at least that's what I got out of it).
What I want to achieve: I want to have a view inside a scrollable layout (Recyclerview with GridlayoutManager) with tiles (Views) in it. Dragging and dropping an item inside of the RecyclerView should adjust the position of the icon and swap with the other elements. When a drag starts, an icon above the RecyclerView will change to a trash icon and dragging the view to this icon will delete it from this RecyclerView.
I tried this excellent tutorial, but I didn't find a way how to handle dragging outside of the Recyclerview as the ItemTouchHelper.Callback uses only Recycler.ViewHolder elements as possible targets.
The method interpolateOutOfBoundsScroll() gives feedback if the view moves out of the boundaries, but will only give back the total size that is offscreen, but no coordinates. Also, trying to drag the view out of the Recyclerview always results in cutting of the View where it passes the borders of the Recyclerview.
Does anyone have an idea how I could achieve this effect?
You can achieve this simply by set this attribute for the parent of the RecyclerView:
android:clipChildren="false"
Edit: thank Adam Katz, I don't know why but sometimes you have to add this to the RecyclerView to make it work:
android:clipToPadding="false"
You are bound by the RecyclerView boundries. You have several options:
Make the RecyclerView's layout height to match_parent and to be on top of your upper view (is it a Toolbar?) and add a sticky header of the same size and have an empty transparent layout. That way you could drag ther and see the item floating over there.
Instead of dragging an item to a garbage can icon which is located too close to a legitemate upper-right item, make a long click to select the item (and apply a signal like a check mark or a red mask) and make the garbage can appear and delete uppon click (and maybe allow multi item deleting)
I want to make the following layout in android. (Image Attached)
There is a list view and each item in the list view can has as many sub items. (One is visible in one row at a particular time), if a person wants to see further items in a particular row, then he has to use arrows provided on the left and right side of the item in the list view. (Image Attached)
On the arrow click, there should be a pager swiping type view and the next layout should come in the row.
I have tried so many approaches to do the same but have been stuck somewhere and have not been able to do the same yet:
Here I have tried all these :
1st Try
2nd Try
3rd Try
4th Try
Can anyone please tell me how to do the same functionality as shown in the figure attached and discussed above
Alright.
Try this, this should work.
Solution 1:
Have Horizontal Scroll view as child in listview, so basically you have s child now with horizontal scroll ability
Add as many as children you want to this scroll views, you can easily adjust layout of childs within scroll view to display.
Solution 2:
Have a ViewFlipper as a child withing listview
Perform the same thing as above, add as many child you want within this flipper
With flipper you get easy hastle free option like which child you want to display by default withing flipper.
Hope it help.
I have a list view in an Android (JB) app where clicking on a row replaces the list view with another view.
Pressing separate button, adds the list view back to the activity (the idea is that the parent container toggles between the list view and the contents of a single row).
The problem happens when I scroll to a row near the bottom and press it (to replace the list view). After hitting the other button to show the list view again, everything looks fine (including the row states and the scroll position). But as soon as I try to scroll again, it resets the list view to the top. Scrolling after that works normally.
The data source for the list view doesn't change at all. Weirdly, if I change the orientation of the tablet, then scrolling for the first time doesn't reset the list view to the top.
I'm guessing it has something to do with removing the view and then adding back that same view (which is done by calling removeAllViews and addView on the parent).
I'm not sure but I think when you call removeAllViews for some reason it can't save the previous state.
I'm not sure again if it is the best way to solve the problem but what you can do is to save your scroll position before remove it, and after add your views again you can set it.
Something like this:
int posX = listView.getScrollX();
//remove your view
and after:
//add your views
listView.setScrollX(posX);
I have a ListView which has overlayed on top of it another view which I call a Header. This header can be of various heights.
On ListView's dataset, I insert in a blank row, and programmatically set the height of this row to be the height of my Header view. This way when the ListView loads, the row at position 1 (the actual first row of data) is lined up to the bottom of the header. I do this so I can set the Header view as partially transparent and when the user scrolls they see the rows of data mix with the transparency of the Header view.
Now I have one use case where I can navigate to this list and a given row will be selected. What I've done is call setSelection with position X. This will automatically scroll my ListView so that the top of row X is at the top of the list. However, my Header view still obscures this. To compensate I call scrollTo. These two pieces are something as such:
listView.setSelection(selectedRowPosition);
if(hasHeadersEnabled()) {
listView.scrollTo(-headerView.getMeasuredHeight).
}
When I call these lines of code, my ListView looks as I would expect. The selected row's top is to the bottom of my HeaderView. The problem I run into is that as soon as a user touches the ListView, the scroll position jumps so that the selected row's top is at the true top of the ListView (aka the Header view's top).
My question is, after you setSelectedRow on a ListView, does the ListView always expect that row's top to be the ListView's top when it starts consuming the onTouch events for scrolling? Is there another way to accomplish what I'm hoping to do with this code? I've tried scrollTo and scrollBy and both have the same effect.
So I should have looked at the API harder. Found the answer to my question.
I need to use setSelectionFromTop instead of the combination of setSelection and scrollTo. Here is the sample code:
listView.setSelectionFromTop(rowPosition, headerView.getMeasuredHeight());