I want to use a RecyclerView(list like) below another RecyclerView(Grid like) as in flipboard
I tried two RecyclerView inside ScrollView with wrap content but nothing is showing.
I can able to see two views if it is placed in linear layout and equal weight is added to it. But that does not look like this app View.
This is my layout
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/parent_category_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minWidth="#dimen/default_small_padding"
android:gravity="center"
android:visibility="visible"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/category_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnWidth="150dp"
android:gravity="center"
android:visibility="visible"/>
</LinearLayout>
There's actually a really simple way to achieve the desired layout with just one RecyclerView!
The key is using a GridLayoutManager and its SpanSizeLookup.
First of all define your GridLayoutManager like this:
GridLayoutManager layoutManager = new GridLayoutManager(context, spanCount);
where spanCount is the maximum amount of spans/columns you want to have. In your case, spanCount should be 2;
Now you need a way to tell this layoutManager how many spans an item should span.
A simple way would be to use a viewtype/ViewHolder for items that should span just one column and another one for items that span the whole width.
Let's assume you define the viewtype for grid-items as VIEWTYPE_GRID_ITEM and the viewtype for standard listitems as VIEWTYPE_LIST_ITEM.
You can then use these viewtypes to tell the layoutManager when to use just one span:
layoutManager.setSpanSizeLookup(new SpanSizeLookup() {
#Override
public int getSpanSize(int position){
return adapter.getItemViewType(position) == VIEWTYPE_GRID_ITEM ? 1 : spanCount;
}
});
Finally, set the layoutManager to your RecyclerView:
recyclerView.setLayoutManager(layoutManager);
And that's it!
I don't think that they use two ListViews (or ListView + GridView).
I think they use a ListView ( the one in the bottom) and they add a custom Header to this list (the one in the top), which look like a GridView.
Or if they use a Recyclerview, they can achieve this by using a different layout in the adapter for the first item.
PS: it's not recommended to use two scrollable view inside each other (like Recyclerview inside ScrollView).
In android we are advise to use only one scrollable view at time , if you want to use one scrollable view inside other one refer below links.
1)Android list view inside a scroll view
2) https://stackoverflow.com/questions/6210895/listview-inside-scrollview-is-not-scrolling-on-android
Related
I'm having issues with the UI not being properly bound with the recycler view or at least not what I intend to happen. The following image is the two recycler views beside one another. Everything looks fine, but when I run the app, the children within the recycler views extend off-screen. The second image shows that.
If you are using one adapter, you can basically use GridLayoutManager for that. So, you can have 2 columns on your recycler view.
To do that with Kotlin code, just add below functionality to your recycler view reference in your fragment or activity.
recyclerView.apply {
layoutManager = GridLayoutManager(this, 2)
}
Also, there is another way to do that in XML. You can use, app:layoutManager and app:spanCount in your recycler view.
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2" />
Hello guys I would like to make my RecyclerView horizontal scroll with showing at a time 2 items.
like this, in the 3rd position, I need to show RecyclerView horizontal list and show 2 items with auto fix with screen width(which means I don't want to set item width).
It's my XML Layout code.
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerviewMyHops"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="visible"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
/>
in your .kt file set:
recyclerView?.apply{
layoutManager = GridLayoutManager(view.requireContext(), 2);
}
the second parameter is spanCount and is setting the number of columns in the grid.
So I have a RecyclerView that uses a GridLayoutManager and uses a super simple adapter that does nothing besides put text in textviews.
My issue is that I want the text to evenly fill out the entire grid (down to the buttons) while making the grid not scrollable. I just want a grid that doesn't scroll and fills up the layout.
Here is what I currently have (the grid is everything between the "you win" and the buttons at the bottom):
val numberOfColumns = 3
resultsRecyclerView.layoutManager = GridLayoutManager(this, numberOfColumns)
val adapter = GridAdapter(this, gridData)
resultsRecyclerView.adapter = adapter
grid item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:padding="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="24sp"
android:textColor="#color/textColor"/>
</LinearLayout>
I was told this would be a good way of making a grid without doing each textview individually. Is there a better way of making a non-scrollable, evenly spaced grid? Any help is appreciated.
Try changing linear layout's layout_weight property.
The RecyclerView has scrolling baked in the widget. If you just need data on the screen consider the ScrollView and add these two lines of code
View.setVerticalScrollBarEnabled(false);
View.setHorizontalScrollBarEnabled(false);
Then I am guessing just put a bunch of TextViews in the ScrollView to display data
I think what you're trying to reach for a non-scroll list is:
GridLayoutManager glm = new GridLayoutManager(this, 3) {
#Override
public boolean canScrollVertically() {
return false;
}
}
It's in Java but not hard to port it to Kotlin, hope it helps.
I have a vertical recyclerview (with a GridLayoutManager) inside another recyclerview (with LinearLayoutManager). The problem I am facing right now is that, the inner recyclerview (with GridLayoutManager) binds all of it's items at the same time, even the views that are not on the screen at the moment (onBindViewHolder() gets called for all of its items).
To give you more information, in my layout file, I put height of my recycler view as wrap_content.
I think the problem is, since there are 2 nested vertically recyclerviews, when the parent RV wants to measure its children and the children is another RV, in onMeasure() it computes the size needed for the entire RV, not just the portion that it wants to bind on the screen.
Any idea how to solve this?
Here is the layout file for my outer recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/component_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
And here is the code for my inner recyclerview:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/gutter"
android:paddingBottom="#dimen/gutter">
<TextView
android:id="#+id/title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/gutter"
android:textSize="30sp"
android:textColor="#android:color/white"
android:fontFamily="sans-serif-thin"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/my_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
P.S.: I'm using this adapter delegate for my outer recyclerview:
https://github.com/sockeqwe/AdapterDelegates
I think nested recyclerviews are a very bad idea. When i try to scroll, which recyclerview has to respond the the scolling, the parrent or child.
That is why I think you are looking for the ExpandableListView? That's limited to only two levels of listings, but that sounds like it would work for your needs). It also solves the soling issue.
It would look something like this:
EDIT: even nested ExpandableListViews are possible:
EDIT: check this lib for horizontal scroling
This is a known bug.
You should not put a RecyclerView inside another RecyclerView because RecyclerView gives its children infinite space. Hence the inner RecyclerView keeps measuring till the dataset is exhausted. Try setting setAutoMeasureEnabled(false) to false on layout manager or you can solve this problem by using a wrapper adapter instead of inner recycler view.
The first thing you need to know is that, when you nest scrolling layouts, the inner ones will get infinity allowed height, effectively making them wrap_content. There is in fact a relatively easy way to fix this problem.
Say I had two nested RecyclerViews such as these, in this case vertically oriented.
<RecyclerView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical>
<View .../>
<!-- other stuff -->
<RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</RecyclerView>
The inner recyclerView here will bind all of it's children immediately every time because, from it's position, your screen will have infinite height.
The solution is to set the height of your inner recyclerview to some static value, not wrap_content or match parent, as either of those will simply fill up the outer recyclerview with one view that will all be bound at once due to it's large height. If you make the height of the inner recyclerview the same as the display's height, you should see your problem go away.
Here is an implementation that will not bind all children at once:
<RecyclerView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical>
<View .../>
<!-- other stuff -->
<RecyclerView
android:layout_width="match_parent"
android:layout_height="#dimen/screen_height"
android:orientation="vertical"/>
</RecyclerView>
Note the layout_height of the inner RecyclerView is now a fixed value pulled from the dimensions file. You yourself will have to come up with a reasonable value to put there.
Side Note: In order to make all of this work and for scrolling to work properly, you may have to play around with the parameter: NestedScrollingEnabled in your RecyclerViews - there are several known bugs relating to this that you may need to work around.
i.e.: innerRecyclerView.setHasFixedSize(true); and innerRecyclerView.setNestedScrollingEnabled(false).
so what happens here when you place a scrollview(no fixed size because of wrap content) inside another scrollview(again no fixed size because of wrap content),both nested scroll view fails to render.
So there is two solutions--
1- Either you will have to think of alternative solution for nested scrollviews
2- You can give outside recyclerview cell fixed height so that inside recycler view can get some fixed layout to render itself.
I could solve my issue by using only one Recyclerview, where it has a grid layout, and based on the component items i'm adding into it, i change the spancount for that. Basically instead of adding the inner recyclerview, i add the items that were supposed to go to the inner recyclerview, to the outer recyclerview.
I am working in android material design api & want to display some data in grid format. I tried both GridLayout and StaggeredGridlayout and both look same. For general information, i want to ask what is the difference between Gridlayout and StaggeredGridlayout?
Thank you.
Grid View : It is is a ViewGroup that displays items in a two-dimensional, scrollable grid. In this each Grid is of same size (Height and width). Grid View shows symmetric items in view.
Staggered Grid View : It is basically an extension to Grid View but in this each Grid is of varying size(Height and width). Staggered Grid View shows asymmetric items in view.
Tutorial to implement Staggered Grid View :
Staggered Grid View
Pinterest Masonry layout Staggered Grid View
My time at Oodles Technologies taught me about staggered.
I'll share that.
StaggeredGridLayout is a LayoutManager, it is just like a GridView but in this grid each view have its own size (height and width). It supports both vertical and horizontal layouts.
Below are some basic steps to create a staggered grid:
1) Create a view.
As we know StaggeredGrid is not a direct view, it is a LayoutManager that lays out children in a staggered grid formation. We use RecyclerView as a view for the staggerd grid.
Here is our RecyclerView in layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/favPlaces"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
2) Set StaggeredGridLayout LayoutManager.
Once our view is ready, let's use LayoutManager to create grids on the view:
RecyclerView favPlaces = (RecyclerView) findViewById(R.id.favPlaces);
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
favPlaces.setLayoutManager(layoutManager);
favPlaces.setHasFixedSize(true);
3) Adapter to inflate the StaggeredGrid views.
To inflate the data in form of a grid, we first need a layout which will represent that data. We are using CardView for this and the layout is:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardcornerradius="4dp"
app:cardusecompatpadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
android:orientation="vertical">
<ImageView
android:id="#+id/placePic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustviewbounds="true"
android:scaletype="fitXY" />
<TextView
android:id="#+id/placeName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textsize="16sp" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
After we setup our all the basic steps, it's time to complete our main activity. Here is the complete code of MainActivity:
public class MainActivity extends AppCompatActivity {
int placeImage[]= {R.drawable.agattia_airport_lakshadweep,R.drawable.nainital,R.drawable.goa,
R.drawable.lotus_temple,R.drawable.valley_of_flowers,R.drawable.ranikhet,R.drawable.dehradun,R.drawable.nainital1};
String placeName[]= {"Lakshadweep, India","Nainital, India","Goa, India","Lotus-Temple, India","Valley-Of-Flowers, India","Ranikhet, India",
"Dehradun, India","Nainital, India"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView favPlaces = (RecyclerView) findViewById(R.id.favPlaces);
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
favPlaces.setLayoutManager(layoutManager);
favPlaces.setHasFixedSize(true);
ArrayList<PlaceDetails> placeList = getPlaces();
StaggeredAdapter staggeredAdapter = new StaggeredAdapter(placeList);
favPlaces.setAdapter(staggeredAdapter);
}
private ArrayList<PlaceDetails> getPlaces() {
ArrayList<PlaceDetails> details = new ArrayList<>();
for (int index=0; index<placeImage.length;index++){
details.add(new PlaceDetails(placeImage[index],placeName[index]));
}
return details;
}
}
StaggeredGridlayout
This lays out children in a staggered grid formation.
It supports horizontal & vertical layout as well as an ability to layout children in reverse.
Staggered grids are likely to have gaps at the edges of the layout.
To avoid the gaps, StaggeredGridLayoutManager can offset spans independently or move items between spans. You can control this behavior via setGapStrategy(int).
GridLayout
This lays out its children in a rectangular grid.
The grid is composed of a set of infinitely thin lines that separate the viewing area into cells.
Children occupy one or more contiguous cells, as defined by their rowSpec and columnSpec layout parameters.
A staggered grid Layout includes multiple columns with multiple rows of varying sizes.
It allows for a flexible column/row view with a header and footer and looks fairly easy to implement, though Gradle users will have an easier time than those working with Eclipse and Ant. This is what the view looks like in the Etsy Github app for which it was developed.
Whereas a GridLayout is a layout that places its children in a rectangular grid.
It was introduced in API level 14, and was recently backported in the Support Library. Its main purpose is to solve alignment and performance problems in other layouts. Check out this tutorial if you want to learn more about GridLayout.