Implementing a sticky section in the middle of the activity in android - android

I'm now facing quite interesting problem in develpoing android app.
So, I have 3 sections, and the order is following.
[VIEW_ON_TOP]
[TO_BE_STICKED]
[SCROLLVIEW]
Of course, scroll view has many children views, anyway it might not seem to be the problem.
What I'm trying to do is that when I scroll the [VIEW_ON_TOP] until the top of the [TO_BE_STICKED] is on the top of the screen, the [TO_BE_STICKED] section should be sticked on the top literally, then I have to move on the focus on [SCROLLVIEW] for scrolling, which means that there are exactly two sections for scrolling.
Thus, what I'm thinking is that let these 3 sections be included in the one listview, so each section is one of the listitems, then it would be nothing but the problem for 2 listitems and one sticky header problem of listview. How do you think? Is it resonable idea? Or any other suggestions, or comments?
Please note that [VIEW_ON_TOP] and [SCROLLVIEW] is independent xml file, so it is needed to make these into object for listviewitem.

I found a simple library on GitHub.
https://github.com/emilsjolander/StickyScrollViewItems
the procedure is following.
<com.emilsjolander.components.StickyScrollViewItems.StickyScrollView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/sticky_scroll">
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:weightSum="5">
<include
layout="ON_TOP"
/>
<View
THIS IS FOR SEPARATE LINE
/>
<include
layout="ON_BOTTOM"
/>
</LinearLayout>
</com.emilsjolander.components.StickyScrollViewItems.StickyScrollView>

Related

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.

Having RecyclerView inside a NestedScrollView calls onBindView for all the items

I have two RecyclerViews placed vertically in a LinearLayout. I need to make both of them scrollable and that is why I have put the LinearLayout inside NestedScrollView
This is the my layout file.
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/featured_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v7.widget.RecyclerView
android:id="#+id/all_topic_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Also, I am disabling nested scrolling in Java code.
disableNestedScrolling(findViewById(R.id.all_topic_list));
disableNestedScrolling(findViewById(R.id.featured_list));
My RecylerView library version is 26.1.0
This works fine perfectly, but then onBindViewHolder method is getting called for all the items in the list. Ideally it should only be called for the visible items in the list.
I think the issue is happening because I am giving wrap_content to the RecyclerView. A lot of answers on this question suggest that the issue is solved in v23.2.1, but I am already using v26.1.0. How to solve this issue?
I had exactly the same problem. RecyclerViews are not meant to be placed inside scroll containers with the same scroll direction. The view recycling only works when the height is set to MATCH_PARENT.
Depending on the complexity of the content inside of the NestedScrollView and the anticipated amount of RecyclerView items:
Ignore the problem. If there are only a few simple items, you may
not need view recycling at all.
When I hit the problem, I analysed the layouts of other popular apps: For example, WhatsApp only uses RecyclerViews (or ListViews with view recycling) in some parts of their app.
Particularly, this group settings screen with hundreds of possible items is made of multiple ListViews wrapped by a ScrollView, without any view recycling.
Replace the NestedScrollView with a single
ReyclerView with multiple item types and put all of your scrollable content inside of it. This is the way to go if you need view recycling.
Beware that you also have to convert all the other content in the NestedScrollView (headers and footers, spacing) to RecyclerView items with their own ViewHolders.
If the setup is rather simple, I would recommend you to implement it without additional libraries, following the link above.
There are a few different libraries available to solve your problem (all of them follow the second approach with a single RecyclerView), but most come with a lot of extra features which you may not need:
RendererRecyclerViewAdapter
It comes with a ViewRenderer/ViewModel interface, which works like a
"partial" RecyclerView for a single item type. You would create one
for every item type and then register them in a single adapter.
Epoxy
A library/framework create by airbnb and used heavily in their app.
They have a lot of scrollable content (similar to a web page) with a
lot of different item types. Epoxy also helps with the composition of
the different items on a page, and it handles animations when the
content or its order changes. Too much if you only need it for a single screen.
Litho
A complete UI framework created by Facebook which comes with it's own rendering engine, a replacement for xml layouts and much more. As far as I understand, it allows you to do to handle large amounts of items (like the Facebook timeline) and the view recycling is handled automatically. Like Epoxy, you would only use this if your app includes things like endless scrolling with a lot of different item types and you really need the performance.
I tried Epoxy and RendererRecyclerViewAdapter, but after all I created my own multiple item type adapter. It can be created in less than 100 lines of code.
Starting from RecyclerView:1.2.0-alpha04 we can use ConcatAdapter to solve this problem
https://developer.android.com/reference/androidx/recyclerview/widget/ConcatAdapter
I tried your problem by adding 20 items in each recyclerview, with NestedScrollView application called onBindViewHolder method 40 times. As you disabling nested scrolling in Java code i suggest to use Scrollview. By using ScrollView application called onBindViewHolder 33 times.
If you fix your recyclerView's height to specific size instead of "match-parent" it will reduce call to onBindViewHolder greatly.
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="false">
<android.support.v7.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.vishal.my2.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/featured_list"
android:layout_width="match_parent"
android:layout_height="300dp" />
<android.support.v7.widget.RecyclerView
android:id="#+id/all_topic_list"
android:layout_width="match_parent"
android:layout_height="300dp" />
</android.support.v7.widget.LinearLayoutCompat>
</ScrollView>
If Specifying hardcoded value to recyclerView's height does not meet your application requirement then you can try using ListView instead of recyclerView. pardon me if i am wrong, This was my first time answering any question.
Add this to nested scroll view android:fillViewport="false"

Two RecyclerViews on one screen

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.

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 >

Android scroller paging with page indicator

I am about finishing my first android app, and i have some questions to which i could not find an answer.
I would like to use a horizontal scroller in which to display several pictures. For that i need two things:
Paging enabled, so that the user can see the pictures one by one in the scroller.
Some kind of indicator to show me the index of the picture currently displayed.
If i manage to do the paging, i could probably display a text like 1/4 (2/4 and so on) if i had 4 pictures, but it is not very nice. I would like to have something more like the iPhone has with the gray/white dots. Is there anything like that, or would i have to implement it by adding content at runtime? (adding imageviews according to the number of the pictures and then changing images for them as the user scrolls to show progress)
Thank you.
Because I was already using ViewPager for the swiping UI, I used the excellent ViewPagerIndicator. It took about 5 minutes to integrate.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000000">
<include android:id="#+id/titlebar_include" layout="#layout/titlebar"/>
<include layout="#layout/menu"/>
<android.support.v4.view.ViewPager
android:layout_width="fill_parent"
android:id="#+id/product_viewpager"
android:layout_height="0dp"
android:layout_weight="1"
/>
<com.viewpagerindicator.CirclePageIndicator
android:id="#+id/indicator"
android:padding="10dip"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
/>
</LinearLayout>
I found the answer i was looking for: i used the Gallery widget and for the indicator dots i used ImageViews and wrote a couple of lines of code to update the selected image dot.
Here is the solution you can try: PageViews and PageIndicator by GreenDroid.
You can also have a look at sample market app: https://market.android.com/details?id=com.cyrilmottier.android.gdcatalog

Categories

Resources