why recyclerview lollipop load everything? - android

I have a list of 100 items. I'm using a recyclerview with custom adapter.
It seems that all the items are load in the same times which cause OOM because I'am loading big images.
I have no problem with listview because listview does not load everything at once.
I heard that recyclerview load everything at once on lollipop, but how can I fix that?
public class ProductAdapter extends RecyclerView.Adapter<ProductViewHolder> {
List<Produit> list;
private Context ac;
private int nbColumn;
public ProductAdapter(List<Produit> list, Context ac)
{
this.list = list;
this.ac = ac;
this.nbColumn = 2;
}
public ProductAdapter(List<Produit> list, Context ac, int nbColumn)
{
this.list = list;
this.ac = ac;
this.nbColumn = nbColumn;
}
#Override
public ProductViewHolder onCreateViewHolder(ViewGroup viewGroup, int itemType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_product,viewGroup,false);
return new ProductViewHolder(view);
}
public void setNbColumn(int nb)
{
this.nbColumn = nb;
}
#Override
public void onBindViewHolder(final ProductViewHolder myViewHolder, int position) {
if (list != null) {
System.out.println("LOAD ITEM!!!!!!!!!!!!");
final Produit myObject = list.get(position);
myViewHolder.bind(myObject);
}
}
#Override
public int getItemCount() {
return list.size();
}
}
without start scrolling the output is
I/System.out: LOAD ITEM!!!!!!!!!!!!!!!!!
X100 times
UPDATE :
this is the code of my layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="wrap_content"
>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
>
<TextView
android:id="#+id/cat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is a title"
android:padding="10dp"
android:gravity="center"
android:textColor="#color/black"
android:textStyle="bold"
android:textSize="17dp"
/>
<ImageView
android:layout_width="25dp"
android:layout_height="25dp"
android:src="#drawable/list1_unselected"
android:id="#+id/list1"
android:layout_below="#+id/cat"
android:paddingLeft="10dp"
android:clickable="true"
/>
<ImageView
android:layout_width="25dp"
android:layout_height="25dp"
android:src="#drawable/list2"
android:paddingLeft="10dp"
android:id="#+id/list2"
android:layout_below="#+id/cat"
android:layout_toRightOf="#+id/list1"
android:clickable="true"
/>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/listingGrid"
android:layout_width="match_parent"
android:nestedScrollingEnabled="false"
android:layout_below="#+id/list2"
android:layout_height="match_parent"/>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
</RelativeLayout>

I partially figured out my problem. After removing the NestedScrollView, the behavior of my Recyclerview works as expected. The thing is how can I combine both NestedScrollView and RecyclerView?
Thank you

Set android:layout_height of your RecyclerView to match_parent or some constant value.
EDIT:
Obviously it didn't help, since you have it all wrapped in NestedScrollView.
I would suggest removing NestedScrollView and combining all views from your RelativeLayout into another layout that you would use as header in your RecyclerView

Replace if (list != null) with if (myViewHolder != null) and it will work as intended

Related

Add multiple expandable cardviews to layout

I am using AleSpero's library to create expandable cardviews for my layout. Works as expected, but now I want to add multiple cardviews in the same fragment layout, dynamically binding to some async list data that loads. How would that be possible?
Followed the demo on the library. Here is how I am adding the cards in the layout:
<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/watchlist_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="20dp"
android:orientation="vertical"
android:clipChildren="false"
android:background="#FAFAFA">
<com.alespero.expandablecardview.ExpandableCardView
android:id="#+id/main_profile_card"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:title="My Watchlist"
app:inner_view="#layout/watchlist_layout"
app:expandOnClick="true" />
</LinearLayout>
#layout/watchlist_layout is a layout I want to repeat, it contain some textView and a recyclerView to show list data. Any help or guidance would be great.
You will need to create different Adapter and Inner Row XML Layout files for each RecyclerView.
For Ex: You inflate a layout in a RecyclerView inside the MainActivity. You are using an Adapter class which is inflating the rows based on your List. Inside onBindViewHolder, you should get the object of the inner RecyclerView which is present in the row layout of the parent view. Once you have the object, create another list and initialize another adapter for the inner recyclerview. Use the new adapter to populate data inside it (similar to the first recyclerview).
Keep in mind, the process remains same, with each recyclerview
Steps:
Create recylcerview inside the layout which is going to display the list
Create a separate row_layout to be inflated in each row based on the number of list data
Crete an Adapter class, which receives data from the parent class and inflates the layout (row_ayout) in the recyclerview
Repeat these steps for N number of Nested RecyclerViews
For the demo, I am attaching sample codes with this answer to help you understand my concept.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recylcerViewParent"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
item_layout_row.xml
<RelativeLayout 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">
<com.alespero.expandablecardview.ExpandableCardView
android:id="#+id/main_profile_card"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
app:expandOnClick="true"
app:inner_view="#layout/watchlist_inner"
app:title="My Watchlist" />
</RelativeLayout>
item_recycler_view_favorite.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_with_favorites"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/favorites_count"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/margin_small"
android:layout_marginLeft="#dimen/margin_small"
android:textSize="12sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/margin_small"
android:layout_marginEnd="#dimen/margin_small"
android:orientation="horizontal"
android:weightSum="2">
<Button
android:id="#+id/btn_view_details"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:background="#android:color/transparent"
android:gravity="start|center_vertical"
android:padding="5dp"
android:text="Atish"
android:textColor="#color/colorPrimaryDark" />
<Button
android:id="#+id/btn_add_symbols"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:background="#android:color/transparent"
android:gravity="end|center_vertical"
android:padding="5dp"
android:text="Agrawal"
android:textColor="#color/colorPrimaryDark" />
</LinearLayout>
</LinearLayout>
watchlist_inner.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_with_favorites"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/favorites_count"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/margin_small"
android:layout_marginLeft="#dimen/margin_small"
android:textSize="12sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/margin_small"
android:layout_marginEnd="#dimen/margin_small"
android:orientation="horizontal"
android:weightSum="2">
<Button
android:id="#+id/btn_view_details"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:background="#android:color/transparent"
android:gravity="start|center_vertical"
android:padding="5dp"
android:text="VIEW DETAILS"
android:textColor="#color/colorPrimaryDark" />
<Button
android:id="#+id/btn_add_symbols"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:background="#android:color/transparent"
android:gravity="end|center_vertical"
android:padding="5dp"
android:text="ADD SYMBOLS"
android:textColor="#color/colorPrimaryDark" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_favorite"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="#dimen/margin_small"
android:layout_marginEnd="#dimen/margin_small"
android:layout_marginBottom="#dimen/margin_small" />
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
List<String> stringsList = new ArrayList<>();
RecyclerView recyclerViewLayout;
InnerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerViewLayout = findViewById(R.id.recylcerViewParent);
//Dummy add 10 objects in the list
for (int i = 0; i < 10; i++) {
stringsList.add(String.valueOf(i));
}
populateRecyclerView();
}
/**
* Create N items in the recycler view
*/
private void populateRecyclerView() {
//Initialize Adapter
recyclerViewLayout.setLayoutManager(new LinearLayoutManager(this));
recyclerViewLayout.setHasFixedSize(false);
adapter = new InnerAdapter(recyclerViewLayout, this);
adapter.setData(this.stringsList);
recyclerViewLayout.setAdapter(adapter);
}
}
InnerAdapter.java
public class InnerAdapter extends RecyclerView.Adapter<InnerAdapter.ViewHolder> {
private List<String> data;
private RecyclerView recyclerView;
private int i = 0;
private Context mContext;
public InnerAdapter(RecyclerView recyclerView, Context context) {
this.recyclerView = recyclerView;
this.mContext = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//Inflater creates rows from a given layout file
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View v = inflater.inflate(R.layout.item_layout_row, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
//Method to perform actions on individual row based on the position. We will get back to this later
//Change the title of the CardView
holder.main_profile_card.setTitle(String.valueOf(position));
//Creating a dummy adapter again to populate the inner recyclerview
List<String> innerData = new ArrayList<>();
for (int i = 0; i < 10; i++) {
innerData.add(String.valueOf(i));
}
//Initialize Inner Adapter
holder.recycler_view_favorite.setLayoutManager(new LinearLayoutManager(mContext));
holder.recycler_view_favorite.setHasFixedSize(false);
InnerFavAdapter adapter = new InnerFavAdapter(holder.recycler_view_favorite, mContext);
adapter.setData(innerData);
holder.recycler_view_favorite.setAdapter(adapter);
}
#Override
public int getItemCount() {
return data.size();
}
public void setData(List<String> data) {
this.data = data;
}
class ViewHolder extends RecyclerView.ViewHolder {
RecyclerView recycler_view_favorite;
ExpandableCardView main_profile_card;
ViewHolder(View itemView) {
super(itemView);
//Get the object of the views from the row layout
main_profile_card = itemView.findViewById(R.id.main_profile_card);
recycler_view_favorite = itemView.findViewById(R.id.recycler_view_favorite);
}
}
}
InnerFavAdapter.java
public class InnerFavAdapter extends RecyclerView.Adapter<InnerFavAdapter.ViewHolder> {
private List<String> data;
private RecyclerView recyclerView;
private int i = 0;
private Context mContext;
public InnerFavAdapter(RecyclerView recyclerView, Context context) {
this.recyclerView = recyclerView;
this.mContext = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
//Inflater creates rows from a given layout file
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View v = inflater.inflate(R.layout.inner_recycler_view_favorite, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
//Method to perform actions on individual row based on the position. We will get back to this later
}
#Override
public int getItemCount() {
return data.size();
}
public void setData(List<String> data) {
this.data = data;
}
class ViewHolder extends RecyclerView.ViewHolder {
ViewHolder(View itemView) {
super(itemView);
}
}
}

Android: TextView Alignment in RecyclerView [duplicate]

I have designed a layout with map fragment and recyclerView.
Each recyclerView item is cardview (I have specified give the xml layout).
The problem is RecyclerView item doesn't fill screen width.
img here
I tried to change layout_width to fill_parent, match_parent ... but it can't help
Here is the layout for each item
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:id="#+id/cardView">
<LinearLayout
android:id="#+id/locationItemView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="120px"
android:layout_height="120px"
android:id="#+id/imgIcon"
android:background="#drawable/image_bg"
android:layout_margin="5dp"
android:scaleType="fitCenter"
android:adjustViewBounds="true" />
<LinearLayout
android:id="#+id/layoutInfo"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:id="#+id/txtName"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Location Name"
android:textColor="#d5c645"
android:textStyle="bold"
android:textSize="20dp"
android:padding="3dp" />
<TextView
android:id="#+id/txtAddress"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Location Address"
android:textSize="16dp"
android:padding="3dp" />
<TextView
android:id="#+id/txtDistance"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:text="Location Distance"
android:textSize="14dp"
android:textStyle="italic"
android:padding="2dp"
android:textAlignment="viewEnd" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
and the main_layout
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:map="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
android:layout_height="0px" android:id="#+id/map" tools:context=".Main"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_weight=".6"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/locationList"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight=".4"
android:divider="#FEFFCC"
android:dividerHeight="1dp" />
</LinearLayout>
<ListView
android:id="#+id/navdrawer"
android:layout_width="250px"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="?attr/colorPrimaryDark"
android:choiceMode="singleChoice"
android:divider="#android:color/white"
android:dividerHeight="1dp"
android:drawSelectorOnTop="false"/>
</android.support.v4.widget.DrawerLayout>
Hope anyone can help me. I am stuck with it for 3 days.
Thank you.
====================================
Edit on 19/11/15
I don't thing the problem is my itemView layout because when I change it to GridLayout it still doesn't fill the width.
Here is my CustomAdapter for RecyclerView
public class LocationDetailsAdapter extends RecyclerView.Adapter<LocationDetailsViewHolder> {
Context _context;
ArrayList<LocationDetails> _data;
public LocationDetailsAdapter(Context _context, ArrayList<LocationDetails> _object) {
this._context = _context;
_data = _object;
}
#Override
public LocationDetailsViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View _v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_location,null );
LocationDetailsViewHolder _viewHolder = new LocationDetailsViewHolder(_v);
return _viewHolder;
}
#Override
public void onBindViewHolder(LocationDetailsViewHolder locationDetailsViewHolder, int i) {
LocationDetails _location = _data.get(i);
locationDetailsViewHolder._imgType.setImageResource(R.drawable.repair_img);
locationDetailsViewHolder._locationName.setText(_location.get_locationName());
locationDetailsViewHolder._locationAddress.setText(_location.get_locationAddress() + ", " + _location.get_district() + ", " + _location.get_province());
locationDetailsViewHolder._distance.setText(String.valueOf(_location.get_distance()) + " km");
locationDetailsViewHolder._locationName.setOnClickListener(clickListener);
locationDetailsViewHolder._imgType.setOnClickListener(clickListener);
locationDetailsViewHolder._locationAddress.setOnClickListener(clickListener);
locationDetailsViewHolder._locationName.setTag(locationDetailsViewHolder);
locationDetailsViewHolder._imgType.setTag(locationDetailsViewHolder);
locationDetailsViewHolder._locationAddress.setTag(locationDetailsViewHolder);
}
#Override
public int getItemCount() {
return (null != _data ? _data.size() : 0);
}
View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
LocationDetailsViewHolder _holder = (LocationDetailsViewHolder)v.getTag();
int _pos = _holder.getPosition();
int _id = _data.get(_pos).get_id();
Intent _intent = new Intent(CommonFields._context, ItemView.class);
_intent.putExtra("LocationID",_id);
_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
CommonFields._context.startActivity(_intent);
}
};
}
and here I get RecylerView in main
_locationView = (RecyclerView)findViewById(R.id.locationList);
_locationView.setLayoutManager(new LinearLayoutManager(this));
_adapter = new LocationDetailsAdapter(Main.this, CommonFields._locationData);
_locationView.setAdapter(_adapter);
When inflating a View from a LayoutInflater, you need to pass a parent parameter in order for layout_* attributes to be used. That's because these attributes need to create the correct LayoutParams class. That means that you can't use inflate(R.layout.*, null), but must instead pass a ViewGroup for the second parameter. In most cases, you also want to use the three-parameter version of the method and pass false as the third parameter. If this is omitted or true then the View is immediately added to the parent, which causes problems in places like onCreateViewHolder() because the framework is designed to perform this operation later instead. For more details, see this answer.
In your case, you have the line
View _v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_location,null );
You should change it to
View _v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_location, viewGroup, false );
You should create View like this
#Override
public CardViewDataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
// create a new view
View itemLayoutView = LayoutInflater.from(viewGroup.getContext()).inflate(
R.layout.card_view, viewGroup, false);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
Maybe my answer has a different approach, but it works to occupy the entire width of the screen and not break the elements when passing through the recycling view.
Adapter adapterBalanceInquiry = new Adapter(getActivity(), list);
recyclerView.setHasFixedSize(true);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setAdapter(adapterBalanceInquiry);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), RecyclerView.HORIZONTAL, false));
recyclerView.post(new Runnable() {
#Override
public void run() {
try {
int dx = (recyclerView.getWidth() - recyclerView.getChildAt(0).getWidth());
recyclerView.scrollBy(-dx, 0);
LinearSnapHelper snapHelper = new LinearSnapHelper();
recyclerView.setOnFlingListener(null);
snapHelper.attachToRecyclerView(recyclerView);
}catch (Exception e){
e.printStackTrace();
}
}
});

Horizontal and Vertical RecyclerView under the same scroll

I have to do something like Instagram does. I have a horizontal RecyclerView for stories, and, below, a vertical RecyclerView for feed. I want to accomplish the same scroll behavior(the stories should go with feed at scroll, not stay on top as fixed). The only solution I found is NestedScrollView but it makes extremely bad performance for RecyclerViews, my screen freezes almost forever. I tried a lot of tricks found here like nestedScrollEnabled, autoLayoutMeasure etc. but nothing worked. Thanks.
Sorry if this explanation is too abstract. Let me know if you need me to be more explicit.
public class VerticalAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private static final int TYPE_HEADER = 0;
private static final int TYPE_POST = 1;
List<Post> posts;
List<FeedItems> feedItems; //this array is going to populate the horizontal recycler view. Notice that is passed it on the adapter constructor
public VerticalAdapter(List<Post> posts,List<FeedItems> feedItems) {
this.posts = posts;
this.feedItems = feedItems;
}
public void notifyFeedChanged(List<FeedItems> newFeedItems){
this.feedItems.clear();
this.feedItems = newFeedItems; //set the new feed items in the array
notifyItemChanged(0); //tell the main recycler view "Hey, update your first position". This will cause the onBindViewHolder to be called again an thus, the new items will be set into the horizontal recycler view
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER)
return new HeaderViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.your_header_layout, false));
else if (viewType == TYPE_POST)
return new PostViewHolder (LayoutInflater.from(parent.getContext()).inflate(R.layout.your_post_layout, false));
throw new RuntimeException("Don't know this type");
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof HeaderViewHolder){
//set adapter for the horizontal recycler view
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(((HeaderViewHolder) holder).recyclerView.getContext(),LinearLayoutManager.HORIZONTAL, false)
((HeaderViewHolder) holder).recyclerView.setLayoutManager(linearLayoutManager);
if (((HeaderViewHolder) holder).recyclerView.getAdapter() == null){ //only create the adapter the first time. the following times update the values
AnotherAdaterYouNeedToCreateForTheHorizontalRecyclerView adapter = new AnotherAdaterYouNeedToCreateForTheHorizontalRecyclerView(feedItems);
((HeaderViewHolder) holder).recyclerView.setAdapter(adapter);
}else {
((HeaderViewHolder) holder).recyclerView.getAdapter().notifyDataSetChanged();
}
}else if (holder instanceof PostViewHolder){
//just do the normal post binding
}
}
#Override
public int getItemCount() {
return posts.size() + 1; // +1 because of the header
}
#Override
public int getItemViewType(int position) {
return position == 0 ? TYPE_HEADER : TYPE_POST;
}
private class HeaderViewHolder extends RecyclerView.ViewHolder{
RecyclerView recyclerView;
public HeaderViewHolder(View itemView) {
super(itemView);
recyclerView = itemView.findViewById(R.id.the_recycler_view_id_on_the_heaedr_layout_file);
}
}
private class PostViewHolder extends RecyclerView.ViewHolder{
ImageView imageView;
public PostViewHolder(View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.post_image_view_or_whatever);
}
}}
So, your vertical recyclerview has the Post items (or whatever your post class is) drawn vertically, that's the easy thing to achieve. Now, for the horizontal view, you should implement a recyclerview header (check my Adapter example). The header layout will have another horizontal recyclerview.
In your XML Layout try keeping both the "header" recycler view and "Post" recycler view in a nested scroll view. It works for me.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:background="#FFFFFF">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:text="Welcome"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
android:textColor="#000000"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="#+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:textAppearance="#style/TextAppearance.AppCompat.Body1"
android:textColor="#color/black_80" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

Huge gap between cards of recyclerView

I have a recylerView to show the images fetched from firebase cloud, However there is a large gap between some items and these gaps arise after i start scrolling, before scrolling, everything is placed perfectly, I have read a few articles, however not proved to be correct in my case.
The code for my MainActivity is given below
RecyclerView.LayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
Query query = firebaseDatabase.getReference().child("Products").child(Uid).orderByKey();
FirebaseRecyclerOptions options = new FirebaseRecyclerOptions.Builder<MainConstructor>().setQuery(query, MainConstructor.class).build();
mFirebaseAdapter = new FirebaseRecyclerAdapter<MainConstructor, ShowDataViewHolder>(options) {
#Override
public ShowDataViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_view, parent, false);
return new ShowDataViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull ShowDataViewHolder holder, int position, #NonNull MainConstructor model) {
holder.setImg(getApplicationContext(),model.getImageUrl());
holder.setImageText(model.getImageUrl());
holder.setCode(model.getProductCode());
progressDialog.dismiss();
}
};
recyclerView.setAdapter(mFirebaseAdapter);
}
#Override
protected void onStart() {
super.onStart();
mFirebaseAdapter.startListening();
recyclerView.setAdapter(mFirebaseAdapter);
}
#Override
protected void onStop() {
super.onStop();
mFirebaseAdapter.stopListening();
}
The code for ViewHolder class is given as
public class ShowDataViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ImageView img;
TextView imageText, codeText;
public ShowDataViewHolder(final View itemView) {
super(itemView);
itemView.setOnClickListener(this);
}
private void setImg(Context ctx, String img1) {
img = (ImageView) itemView.findViewById(R.id.List_ImageView);
Picasso.with(ctx).load(img1).placeholder(R.drawable.notification).into(img);
// progressDialog.dismiss();
}
private void setImageText(String text){
imageText = (TextView)itemView.findViewById(R.id.textView);
imageText.setText(text);
}
private void setCode(String code){
codeText = (TextView)itemView.findViewById(R.id.Code);
codeText.setText(code);
}
The large unwanted gaps can be clearly seen here:
The list_view layout code is given as:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_margin="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/List_ImageView"
android:padding="2dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textView"
android:visibility="invisible"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Code"
android:visibility="invisible"/>
</LinearLayout>
</android.support.v7.widget.CardView>
I have read someWhere that this problem arises because recyclerView continuously keeps on updating the items, so to correct that we need a ViewHolder class, however i have a viewHolder in my case then also this problem is there,
Can anyone help me with the solution and also with the exact problem why is it happening?
Thanks in advance
Your code is perfect just remove your parent node RelativeLayout which is actually not needed. That is creating issue with match_parent height.
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_margin="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="#+id/List_ImageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="2dp" />
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible" />
<TextView
android:id="#+id/Code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible" />
</LinearLayout>
</android.support.v7.widget.CardView>
Change this:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
to this:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

CardView not showing content eclipse

I am using android.support.v7.widget.CardView to show ImageView with two TextView's in RecyclerView but card view not showing the content(showing only blank white cards) when the screen orientation is vertical, on the other hand it is showing content when orientation is landscape.
When I run the same project from AndroidStudio there is no problem everything works fine.
I don't understand what is problem out there, is there problem with eclipse?
Please see the code below,
PostListFragment
public class PostListFragment extends Fragment implements AppConfig {
private ArrayList<Post> mPostArrayList;
private PostRecyclerAdapter mPostRecyclerAdapter;
private RecyclerView mRecyclerView;
//other declarations
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//removed
}
private void init() {
// Set up RecyclerView
mRecyclerView = (RecyclerView) mRootView
.findViewById(R.id.mPostListRecyclerView);
// Setup layout manager for mPostArrayList and column count
final LinearLayoutManager mLayoutManager = new LinearLayoutManager(
getActivity());
// Control orientation of the mPostArrayList
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mLayoutManager.scrollToPosition(0);
// Attach layout manager
mRecyclerView.setLayoutManager(mLayoutManager);
// Listen to the item touching
mRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(
getActivity(),
new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View itemView, int position) {
//some action
}
}));
mPostArrayList = new ArrayList<>();
// Bind adapter to recycler
mPostRecyclerAdapter = new PostRecyclerAdapter(
getActivity(), mPostArrayList);
mRecyclerView.setAdapter(mPostRecyclerAdapter);
}
private void getPosts() {
// Execute async task
new AsyncPosts().execute(mPostURL);
}
public class AsyncPosts extends AsyncTask<Object, String, JSONObject> {
//no problem with this
}
}
Layout used for PostListFragment
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/mParentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/mPostListContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/mPostListSwipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<android.support.v7.widget.RecyclerView
android:id="#+id/mPostListRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>
<!-- removed -->
</LinearLayout>
Here is adapter to set the values,
PostRecyclerAdapter
public class PostRecyclerAdapter extends
RecyclerView.Adapter<PostRecyclerAdapter.SimpleItemViewHolder> {
private Context mContext;
private List<Post> post;
// Provide a suitable constructor (depends on the kind of data store)
public PostRecyclerAdapter(Context context, List<Post> items) {
this.mContext = context;
this.post = items;
}
// Return the size of your data set (invoked by the layout manager)
#Override
public int getItemCount() {
return this.post.size();
}
// Create new items (invoked by the layout manager)
// Usually involves inflating a layout from XML and returning the holder
#Override
public SimpleItemViewHolder onCreateViewHolder(ViewGroup viewGroup,
int viewType) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(
R.layout.post_list_item, viewGroup, false);
return new SimpleItemViewHolder(itemView);
}
// Replace the contents of a view (invoked by the layout manager)
// Involves populating data into the item through holder
#Override
public void onBindViewHolder(SimpleItemViewHolder viewHolder, int position) {
Glide.with(mContext).load(post.get(position).IMG_URL)
.placeholder(R.drawable.ic_placeholder).crossFade(1000)
.centerCrop().into(viewHolder.mPostListSmallThumbnail);
viewHolder.mPostListSmallTitle.setText(post.get(position).POST_TITLE);
viewHolder.mPostListSmallContent
.setText(post.get(position).POST_CONTENT);
}
// Provide a reference to the views for each data item
// Provide access to all the views for a data item in a view holder
public final static class SimpleItemViewHolder extends
RecyclerView.ViewHolder {
ImageView mPostListSmallThumbnail;
TextView mPostListSmallTitle, mPostListSmallContent;
public SimpleItemViewHolder(View itemView) {
super(itemView);
mPostListSmallThumbnail = (ImageView) itemView
.findViewById(R.id.mPostListSmallThumbnail);
mPostListSmallTitle = (TextView) itemView
.findViewById(R.id.mPostListSmallTitle);
mPostListSmallContent = (TextView) itemView
.findViewById(R.id.mPostListSmallContent);
}
}
}
post_list_item
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/mPostListSmallCard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="#drawable/card_background"
android:clickable="true"
app:cardCornerRadius="#dimen/blog_card_radius"
app:cardUseCompatPadding="true"
app:contentPadding="#dimen/blog_card_radius">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/mPostListSmallThumbnail"
android:layout_width="#dimen/blog_image_thumb_dim"
android:layout_height="#dimen/blog_image_thumb_dim"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="#drawable/ic_placeholder"
android:adjustViewBounds="true"
android:contentDescription="#string/image_thumbnail_placeholder" />
<TextView
android:id="#+id/mPostListSmallTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="#dimen/post_list_margin_left"
android:layout_marginStart="#dimen/post_list_margin_right"
android:layout_toEndOf="#+id/mPostListSmallThumbnail"
android:layout_toRightOf="#+id/mPostListSmallThumbnail"
android:ellipsize="end"
android:lines="2"
android:singleLine="false"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/mPostListSmallContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/mPostListSmallThumbnail"
android:layout_alignEnd="#+id/mPostListSmallTitle"
android:layout_alignLeft="#+id/mPostListSmallTitle"
android:layout_alignRight="#+id/mPostListSmallTitle"
android:layout_alignStart="#+id/mPostListSmallTitle"
android:layout_below="#+id/mPostListSmallTitle"
android:ellipsize="end"
android:lines="3"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
</android.support.v7.widget.CardView>
Here is post_list_item for landscape layout
land/post_list_item
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/mPostListSmallCard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginRight="#dimen/blog_card_margin_landscape"
android:layout_marginLeft="#dimen/blog_card_margin_landscape"
app:cardCornerRadius="#dimen/blog_card_radius"
app:cardUseCompatPadding="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/mPostListSmallThumbnail"
android:layout_width="#dimen/blog_image_thumb_dim"
android:layout_height="#dimen/blog_image_thumb_dim"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:adjustViewBounds="true"
android:contentDescription="#string/image_thumbnail_placeholder" />
<TextView
android:id="#+id/mPostListSmallTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="#dimen/post_list_margin_left"
android:layout_marginStart="#dimen/post_list_margin_right"
android:layout_toEndOf="#+id/mPostListSmallThumbnail"
android:layout_toRightOf="#+id/mPostListSmallThumbnail"
android:ellipsize="end"
android:lines="2"
android:singleLine="false"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/mPostListSmallContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/mPostListSmallThumbnail"
android:layout_alignEnd="#+id/mPostListSmallTitle"
android:layout_alignLeft="#+id/mPostListSmallTitle"
android:layout_alignRight="#+id/mPostListSmallTitle"
android:layout_alignStart="#+id/mPostListSmallTitle"
android:layout_below="#+id/mPostListSmallTitle"
android:ellipsize="end"
android:lines="3"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
</android.support.v7.widget.CardView>

Categories

Resources