Two RecyclerViews on one screen - android

I have been given the task to implement a feature on Mobile application. Previously I had no experience with Android nor Java.
What I need is one screen (one fragment) to display two lists of events with uneven number of members one after another, let's call them ListX and ListY.
I've made layout containing two RecyclerViews and two labels (one label to act as header for each of recycler views).
It is working as it is now and I have events displayed, but ListX is scrollable even though its layout_height is set to wrap_content (only 6 items displayed at the time) while ListY is not scrollable and is displaying all events in collection.
What I need is all items from ListX displayed in first RecyclerView (without scroll), and after that ListY displayed in second RecyclerView without scroll too.
Layout:
<FrameLayout
android:id="#+id/resultsView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/label_daily" />
<android.support.v7.widget.RecyclerView
android:id="#+id/list_daily"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/label_daily"
tools:listitem="#layout/fragment_timetracking_event_item" />
<TextView
android:id="#+id/label_unfinished" />
<android.support.v7.widget.RecyclerView
android:id="#+id/list_unfinished"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/label_unfinished"
tools:listitem="#layout/fragment_timetracking_event_item" />
</LinearLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>
As you can see from XML both RecyclerViews have layout_height set to wrap_content yet first RecyclerView is not obeying.
Here is sketch of how it should look like
Is there any way to put both lists in one RecyclerView and make custom separators? Or any other way to anchor beginning of one list to the end of the other and make them show all items without scroll?
I hope to get help here.

You don't need 2 recyclerViews, you can achieve using single recylcerView.
You should read about getItemViewType & using same in bindViewHolder & createViewHolder
You can specify these three types
Header
DailyItem
FinishItem
Create your list like this
add Daily HEADER
add Daily ITEMS
add Unfinished HEADER
add Unfinished ITEMS
Now you can render both lists in single recyclerview

Your problem
...other way to anchor beginning of one list to the end of the other and make them show all items without scroll?
has a simple solution without rewriting your code to the one RecycleView - just put android.support.v4.widget.NestedScrollView instead of ScrollView in your xml layout. It seems to be a bug in the ScrollView widget, which is fixed in android.support.v4.widget.NestedScrollView.
P.S. After solving this problem you will face with other problem - Android RecycleView scrolls with no momentum, which is resolved in "RecyclerView within NestedScrollView Scrolling Issue". It is fine only for short item list in RecycleView because as it is mentioned in comments to above article
This is not a good solution since disabling nested scrolling will disable cell reuse as well, therefore loading all cells at once.
which will have impact on the memory consumption of your app in the case of long item list.

Related

My listview seems to hide the bottom two entries once the entire page is full

I have a list view with a list view adapter in my kotlin project. It works perfectly fine for the first thirteen entries, once I go past that the next two entries don't show up however for every entry after those next two the entry I entered two entries before shows up and I can scroll to it (So if I put in a sixteenth entry then the fourteenth will show up). When deleting so that the whole page is no longer full the final two show up. When debugging I saw that they should be visible as the list view adapter shows the code to display them running so I think the problem is that when scrolling the listview I just cant scroll till the bottom 2. Due to this I suspect that the navigation bar is maybe covering the bottom two entries or that the list view for some reason is longer than or as long as the parent so the bottom of it is past the end of the page. However I am still not sure how to fix this problem even though I think I know what it is.
The xml code for the list is below:
<ListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/header" />
Can you try to change your constraint for ListView like this
<ListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/header" />
here i have consider that there is not other view below listview to show
that's why i have set bottom constraint to parent

Android Recyclerview not remeasuring its height

My application has a lot of nested recycler views , In one of those I have a layout which holds an image and a textview like this.
The text view is an indicator which would disappear when the user opens that specific course.
And it would become something like this :
Since the indicator is present only on some of the courses , the indicator might disappear (view.gone) and appear (view.visible) on certain conditions.
This is the recyclerview code that holds these courses.
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_video_packs"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/margin_16dp"
android:clipToPadding="false"
android:paddingEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/rv_continue_watching" />
Notice that the recycler view is a wrap content.
When there is a case of multiple courses , some courses might not contain the new video indicator. And if those courses with no indicator is present on the screen then the recyclerview would wrap its height to only hold on to the course image , something like this.
but the issue is , when we scroll horizontally , some courses might contain the indicator , meaning that the recyclerview should increase its height accordingly to accommodate the indicator as well .
Instead recyclerview fails to update its height to wrap around both the view hence resulting in this incomplete view.
This is happening because the recyclerview was unable to update its height when scrolling hence making the view cut in half.
I have tried multiple ways to fix this like ,
Setting setHasFixedSize to false etc . But didnt seem to work
This is happening only sometimes.
The only viable solution now is to fix the recycler view height to a specific height so that it holds both the views.
But I want a more scalable and optimum solution if possible for this .
Is there any way to make recyclerview recalculate its height ?
Recyclerview Item view code.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true"
android:clickable="true"
android:orientation="vertical"
>
<ImageView
android:id="#+id/iv_learn_item"
android:visibility="invisible"
android:layout_width="134dp"
android:layout_height="200dp"
android:adjustViewBounds="true"
android:layout_marginStart="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:foreground="?attr/selectableItemBackground"
/>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/video_update_tv_guideline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintGuide_begin="195dp"
android:orientation="horizontal"
/>
<TextView
android:id="#+id/video_update_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="#id/iv_learn_item"
app:layout_constraintEnd_toEndOf="#id/iv_learn_item"
app:layout_constraintTop_toBottomOf="#+id/video_update_tv_guideline"
android:layout_marginStart="#dimen/dimen_11dp"
android:layout_marginEnd="#dimen/dimen_11dp"
style="#style/content_update_pill"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
Adapter code
rvVideoPacks.layoutManager =
LinearLayoutManager(itemView.context, LinearLayoutManager.HORIZONTAL, false)
rvVideoPacks.setHasFixedSize(false)
rvVideoPacks.itemAnimator = null
rvVideoPacks.isNestedScrollingEnabled = true
rvVideoPacks.adapter = videoPackAdapter
EDIT :
I have also tried to make the indicator invisible , but that just creates an extra space at the bottom , making it look bad.
I want the recyclerview to adjust its height accordingly.
One way to fix this issue is give fix height to main ConstraintLayout if possible for your layout.

Scrollable list trailed by fixed views

This might be a very beginner question, but I'm yet unable to find myself around the android jungle.
I've already got a RecyclerView working to show a list of items (with data binding and Room database and DiffUtil.ItemCallback and all).
I'd like to put 2 links after the list: "missing something?" and "add new entry" that will lead to other fragments.
What I have:
When I put 2 buttons (I don't know yet how to put links, but this is not the point of this question) after the RecyclerView, all in a LinearLayout, they stay fixed near the screen bottom. I mean, the RecyclerView is scrollable by itself, scrolling "beneath" the two buttons, the entire LinearLayout expanding to fill the screen (match_parent).
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="top"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Missing something?"
android:onClick="#{...}" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Add new item"
android:onClick="#{...}" />
</LinearLayout>
What I want
I'd like the 2 buttons to scroll along with the list, so that they are always positioned after the last item (think as if they were items themselves, albeit an heterogeneous list with different types/RecyclerView.ViewHolder).
For a big enough list the buttons will be initially off screen; to be scrolled in if the user happen to scroll to the bottom of the list.
What I tried
I tried with ScrollView around the LinearLayout, and it works, but everywhere everybody say that one should never put a RecyclerView inside a ScrollView (maybe because it is scrollable itself).
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/routines_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<!-- buttons -->
</LinearLayout>
</ScrollView>
Being really a beginner in android programming, I'd like to know how usually this kind of layout should be done. Only main directions will be enough for me.
NB. I don't know if I really need a RecyclerView because I don't expect this list to be lengthy. Maybe usually something around 4 to 8 items, possibly 10. But I really don't expect it to be much bigger than that. For many users the two links will even be visible all the time (i.e. no scroll at all).
RecyclerView is always the most efficient to show a list especially if you are getting the data from a database or an API. Don't put your recyclerview in a scrollview. You can add two items to the bottom of the list as your links and program your recyclerview to exhibit different properties for last two items. That is the best way I can think of. Good Luck!
Also, Recyclerview is very difficult to work with when you are working with complex data. With small lists such as in your case, it can seem inconvenient to create a whole adapter class and do everything you are supposed to do. When you have grasped the concepts on xml android and have plenty experience with that. You can move to jetpack compose and lazy column will make your life easy.

Get Item when scroll in horizontal recyclerview

I have a horizontal Recyclerview with 2 elements
I would like to call a function to load into a data list when I scroll through the elements of the recyclerview.
I would like to load the data of the item located in the center of the screen / Recyclerview
I am trying with onScrolled but I cannot figure out when in the Recyclerview I change the item
the elements could perhaps become even more than 2 (for example 6) so if it were possible I would like a function that is not necessarily only for 2 elements
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list_compte"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="12dp"
android:divider="#drawable/rectangle_border_bottom"
android:paddingLeft="110dp"
android:paddingRight="110dp"
android:clipToPadding="false"
android:dividerHeight="1dp"
android:isScrollContainer="false"
android:nestedScrollingEnabled="true"
android:orientation="horizontal" />
it's possible?
Thanks
Yes, it is possible. There is a good tutorial here by Nick Rout which perfectly describes your case.

Create a RecyclerView with both horizontal and vertical scrolling

Over the past few weeks I've been learning to use the RecyclerView. I need to implement a horizontal list, ie, that by turning the device in landscape mode like so:
I found the best solution for this (how to create the horizontal displacement of RecyclerView, here), but encountered another problem. The item RecyclerView was larger than the height of the device (in landscape, horizontal), so I need to create a vertical and horizontal displacement, simultaneously.
I looked at the Android Developer methods for the LayoutManager class, but my skills are not high enough to understand most of the methods. I also tried putting a RecyclerView vertically inside another RecyclerView horizontally with all the content, but I get error:
IllegalStateException: RecyclerView has no LayoutManager
To rememedy this I removed all <View ... /> elements from the XML file, but this does not give any results.
To clarify what I am asking: is it possible to have my layout scroll both horizontally and vertically, and if you could explain how I would appreciate it.
I was so angry about all the problems that had tended with the application that had not thought about the easiest solution.
In a RecyclerView consists of two XML files, the main one where the RecyclerView is declared and another with content.
The simplest solution was to introduce the RecyclerView within a ScrollView. So I can move all items at a time thanks to ScrollView vertically and horizontally I can move the items thanks to RecyclerView in landscape mode.
activity_main.xml
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/cardIn_margin_ext">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbarStyle="outsideInset"
android:scrollbars="horizontal" />
</ScrollView>
The accepted answer did'nt work for me. I had to use the HorizontalScrollView instead of simple ScrollView.
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/cardIn_margin_ext">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbarStyle="outsideInset"
android:scrollbars="horizontal" />
</HorizontalScrollView >

Categories

Resources