I am using FirebaseRecyclerViewAdapter with CardView in my application and want to load video on one card and images on another, but I dont know how to separate them. Everytime I add a videoView in CardView layout it gets added on the top of ImageView in same card and also gets repeated in all the RecyclerView. Its like same thing is coming again and again with number of posts I have. I want that VideoView should play video on different post and ImageView shows images on different, I have searched many options but did not find anything useful, please help.
I am using Android Studio
CardView xml file:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/CardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.youtube.player.YouTubePlayerView
android:id="#+id/youtube"
android:layout_width="match_parent"
android:layout_height="200dp"/>
<ImageView
android:id="#+id/po_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />
<TextView
android:id="#+id/ti_cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="18sp"
android:textStyle="bold"/>
<TextView
android:id="#+id/de_cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp" />
<TextView
android:id="#+id/so_cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textColor="#color/SoColor"/>
</LinearLayout>
</android.support.v7.widget.CardView>
FirebaseRecyclerView Adapter class:
FirebaseRecyclerAdapter <post, postViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<post, postViewHolder>(
post.class,
R.layout.post_row_recycle_home,
postViewHolder.class,
mDatabaseReference
) {
#Override
protected void populateViewHolder(postViewHolder viewHolder, post model, int position) {
viewHolder.setTi(model.getTi());
viewHolder.setde(model.getDe());
}
};
mrecyclerView.setAdapter(firebaseRecyclerAdapter);
}
public static class postViewHolder extends RecyclerViewPager.ViewHolder{
View mView;
public postViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setTi(String ti){
TextView post_ti = (TextView)mView.findViewById(R.id.ti_cardView);
post_ti.setText(ti);
}
public void setde(String de){
TextView post_de = (TextView)mView.findViewById(R.id.de_cardView);
post_de.setText(de);
}
set visibility of both gone at first and then depending on its video url or image url. manipulate Visibility of each view
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/CardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.youtube.player.YouTubePlayerView
android:visibility="gone"
android:id="#+id/youtube"
android:layout_width="match_parent"
android:layout_height="200dp"/>
<ImageView
android:visibility="gone"
android:id="#+id/po_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />
<TextView
android:id="#+id/ti_cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="18sp"
android:textStyle="bold"/>
<TextView
android:id="#+id/de_cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp" />
<TextView
android:id="#+id/so_cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textColor="#color/SoColor"/>
</LinearLayout>
</android.support.v7.widget.CardView>
As you are using RecyclerView, don't put the VideoPlayer and the ImageView in the same xml layout, you can create two different layouts and use the getItemViewType() to choose the right layout to inflate.
The questions on how to use differente layouts on the same RecyclerView has been answered here
Sample code:
image_item_layout.xml
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/CardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:visibility="gone"
android:id="#+id/po_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />
<...>
</LinearLayout>
</android.support.v7.widget.CardView>
video_item_layout.xml
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/CardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.youtube.player.YouTubePlayerView
android:visibility="gone"
android:id="#+id/youtube"
android:layout_width="match_parent"
android:layout_height="
<...>
</LinearLayout>
</android.support.v7.widget.CardView>
On the ImageOrVideoAdapter.java you can use something like:
public class ImageOrVideoAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<ImageOrVideoItem> dataSource;
private final int VIDEO_VIEW = 0;
private final int IMAGE_VIEW = 1;
class VideoItemViewHolder extends RecyclerView.ViewHolder {
// Do your stuff with the video here
public VideoItemViewHolder(View itemView) {
}
}
class ImageItemViewHolder extends RecyclerView.ViewHolder {
// Do your stuff with the image here
public ImageItemViewHolder(View itemView) {
}
}
#Override
public int getItemViewType(int position) {
return dataSource.get(position).isVideoItem() ? VIDEO_VIEW : IMAGE_VIEW;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case VIDEO_VIEW:
return new VideoItemViewHolder(inflater.inflate(R.layout.video_item_layout, parent, false));
case IMAGE_VIEW:
return new ImageItemViewHolder(inflater.inflate(R.layout.image_item_layout, parent, false));
}
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
switch (holder.getItemViewType()) {
case VIDEO_VIEW:
VideoItemViewHolder viewHolder0 = (VideoItemViewHolder) holder;
break;
case IMAGE_VIEW:
ImageItemViewHolder viewHolder2 = (ImageItemViewHolder) holder;
break;
}
}
}
There are many posts all around StackOverflow about handling diferent layouts for the same RecyclerView, look around, you will find them.
EDIT
Take a look on this example using FireBase and see if it can adapted to fit your needs: Here
Related
I want to show a popup menu for each item of a RecyclerView when a button is clicked.
My Adapter:
public class SearchResultRecyclerViewAdapter extends RecyclerView.Adapter<SearchResultRecyclerViewAdapter.ViewHolder> {
public SearchResultRecyclerViewAdapter(ArrayList<BookModel> bookModels, Context context) {
this.bookModels = bookModels;
this.context = context;
}
ArrayList<BookModel> bookModels;
Context context;
#NonNull
#NotNull
#Override
public ViewHolder onCreateViewHolder(#NonNull #NotNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_book,parent,false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Log.d("aa", bookModels.get(position).getThumbnailLink());
Glide.with(context)
.asBitmap()
.load(bookModels.get(position).getThumbnailLink())
.into(holder.coverImage);
holder.name.setText(bookModels.get(position).getName());
holder.author.setText(bookModels.get(position).getAuthor());
holder.category.setText(bookModels.get(position).getCategories().toString());
holder.maturity.setText(bookModels.get(position).getMaturityRating());
holder.desc.setText(bookModels.get(position).getDesc());
holder.option.setOnClickListener(new View.OnClickListener() { ///////////// here
#Override
public void onClick(View v) {
//show popup
Log.d("ItemOption","Clicked");
}
});
if (position+1 == bookModels.size()){
holder.divider.setVisibility(View.GONE);
}
}
#Override
public int getItemCount() {
return bookModels.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
RoundedImageView coverImage;
TextView name;
TextView author;
TextView desc;
TextView category;
TextView maturity;
ImageView divider;
Button option;
RelativeLayout root;
public ViewHolder(#NonNull #NotNull View itemView) {
super(itemView);
coverImage = itemView.findViewById(R.id.cover_book_item_imageview);
name = itemView.findViewById(R.id.name_book_item_textview);
author = itemView.findViewById(R.id.author_book_item_textview);
desc = itemView.findViewById(R.id.desc_book_item_textview);
category = itemView.findViewById(R.id.category_book_item_textview);
maturity = itemView.findViewById(R.id.maturity_book_item_textview);
divider = itemView.findViewById(R.id.divider_book_item_imageview);
option = itemView.findViewById(R.id.option_book_item_button);
root = itemView.findViewById(R.id.root);
}
}
}
My item Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:id="#+id/cover_book_item_cardview"
android:layout_width="#dimen/_81sdp"
android:layout_height="#dimen/_124sdp"
android:layout_margin="#dimen/_15sdp"
app:cardCornerRadius="#dimen/_8sdp"
android:elevation="#dimen/_5sdp">
<com.makeramen.roundedimageview.RoundedImageView
android:id="#+id/cover_book_item_imageview"
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:src="#drawable/testcover"
android:scaleType="fitXY"
app:riv_corner_radius="#dimen/_5sdp"/>
</androidx.cardview.widget.CardView>
<TextView
android:id="#+id/name_book_item_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="name"
android:layout_marginTop="#dimen/_20sdp"
android:layout_alignStart="#id/cover_book_item_cardview"
android:layout_marginStart="#dimen/_90sdp"
android:fontFamily="#font/yanonekaffeesatz_medium"
android:layout_alignLeft="#id/cover_book_item_cardview"
android:layout_marginLeft="#dimen/_90sdp"
android:textSize="#dimen/_18sdp"
android:textColor="#color/light_black"
/>
<TextView
android:id="#+id/author_book_item_textview"
android:textSize="#dimen/_13sdp"
android:fontFamily="#font/yanonekaffeesatz_medium"
android:layout_marginTop="#dimen/_1sdp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/name_book_item_textview"
android:text="author"
android:layout_alignLeft="#id/cover_book_item_cardview"
android:layout_marginLeft="#dimen/_90sdp"
android:layout_alignStart="#id/cover_book_item_cardview"
android:layout_marginStart="#dimen/_90sdp"/>
<TextView
android:id="#+id/desc_book_item_textview"
android:layout_width="#dimen/_190sdp"
android:layout_height="#dimen/_40sdp"
android:layout_below="#id/name_book_item_textview"
android:width="#dimen/_60sdp"
android:layout_alignLeft="#id/cover_book_item_cardview"
android:layout_marginLeft="#dimen/_90sdp"
android:layout_alignStart="#id/cover_book_item_cardview"
android:layout_marginStart="#dimen/_90sdp"
android:layout_marginTop="#dimen/_30sdp"
android:textColor="#color/light_black"
android:text="desc"
android:fontFamily="#font/yanonekaffeesatz_medium"/>
<LinearLayout
android:id="#+id/holder_book_item_linearlayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="#id/name_book_item_textview"
android:layout_alignLeft="#id/cover_book_item_cardview"
android:layout_marginLeft="#dimen/_90sdp"
android:layout_alignStart="#id/cover_book_item_cardview"
android:layout_marginStart="#dimen/_90sdp">
<TextView
android:id="#+id/category_book_item_textview"
android:textColor="#color/white"
android:fontFamily="#font/yanonekaffeesatz_medium"
android:background="#drawable/rounded_rectangle_90"
android:backgroundTint="#color/yellow"
android:padding="#dimen/_3sdp"
android:layout_marginTop="#dimen/_72sdp"
android:text="category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="#+id/maturity_book_item_textview"
android:textColor="#color/white"
android:fontFamily="#font/yanonekaffeesatz_medium"
android:background="#drawable/rounded_rectangle_90"
android:backgroundTint="#color/light_black"
android:padding="#dimen/_3sdp"
android:layout_marginTop="#dimen/_72sdp"
android:text="maturity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_5sdp"/>
</LinearLayout>
<androidx.appcompat.widget.AppCompatButton
android:id="#+id/option_book_item_button"
android:layout_width="#dimen/_20sdp"
android:layout_height="#dimen/_20sdp"
android:background="#drawable/ic_more"
android:backgroundTint="#color/light_black"
android:layout_alignLeft="#id/cover_book_item_cardview"
android:layout_marginLeft="#dimen/_260sdp"
android:layout_alignStart="#id/cover_book_item_cardview"
android:layout_marginStart="#dimen/_260sdp"
android:layout_marginTop="#dimen/_23sdp"/>
<ImageView
android:id="#+id/divider_book_item_imageview"
android:layout_width="#dimen/_200sdp"
android:layout_height="1dp"
android:background="#DFDFDF"
android:layout_below="#id/holder_book_item_linearlayout"
android:layout_marginTop="#dimen/_15sdp"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
Initializing RecyclerView:
recyclerView = findViewById(R.id.search_result_recyclerview);
recyclerView.scheduleLayoutAnimation();
recyclerView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("CheckRecyclerView","clicked");
}
});
searchResultRecyclerViewAdapter = new SearchResultRecyclerViewAdapter(bookModels,SearchActivity.this);
recyclerView.setAdapter(searchResultRecyclerViewAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(SearchActivity.this));
}
XML Layout of Activity:
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawerlayout"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:layout_width="match_parent">
<RelativeLayout
android:layout_width="wrap_content"
android:gravity="center"
android:animateLayoutChanges="true"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--
Views
-->
<androidx.recyclerview.widget.RecyclerView
android:layout_centerHorizontal="true"
android:layout_below="#id/appbar_cardview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/search_result_recyclerview"
android:layoutAnimation="#anim/search_result_recyclerview_anim"
android:visibility="gone"/> <!-- will become visible later-->
<!--
Views
-->
</RelativeLayout>
<com.google.android.material.navigation.NavigationView
app:itemTextColor="#color/white"
app:itemIconTint="#color/white"
android:background="#color/black"
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header"
app:menu="#menu/menu_main" />
</androidx.drawerlayout.widget.DrawerLayout>
when the item's view is clicked nothing happens. I've done the same exact thing before with no problem I don't know what I'm missing here.
EDIT:
as #anemomylos mentioned this might be a click issue. in this layout there is a lot of Views that will be Gone in order to RecyclerView shows up. RecyclerViews don't register any clicks themselves so I'm not sure if it's being blocked by another view or not, is there any way to know what is blocking the click? I don't have any android:clickable="true" and I made sure that all Views before RecyclerView are Gone and not Invisible
I'm facing a problem with two RecyclerView inside the same ScrollView (I also tried the same with a NestestScrollView). Inside the ScrollView, I have also some other View objects that form a kind of "header section" of the fragment. Then, I would like to show a horizontal list of RecyclerView, and finally, above the horizontal list, a vertical list of other RecyclerView. However, only the horizontal one is correctly visualized. Even though the Adapter of the vertical one is correctly initialized with some objects, when I run the application, the vertical list is empty. I think it is a problem related to my layout.
This is my .xml file:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
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:id="#+id/profile_coordinator"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".HomeFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="20dp">
<!-- Here I have some other views (ImageView, TextView, etc.) -->
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/active_promos"
android:textStyle="bold"
android:textColor="#color/colorPrimary"
android:textSize="18sp"
android:layout_marginBottom="10sp"/>
<!-- Horizontal List of RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/promo_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_marginBottom="20sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/news"
android:textStyle="bold"
android:textColor="#color/colorPrimary"
android:textSize="18sp"
android:layout_marginBottom="10sp"/>
<!-- Vertical List of RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/news_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</ScrollView>
Since the objects to show are the same (but the semantics is different), I'm using the same Adapter class that loads two different xml layout according to the type of object to show.
This is the Adapter.java:
public class NewsAdapter extends RecyclerView.Adapter {
private List<NewsPromotion> newsPromotions;
private boolean promos;
public NewsAdapter(List<NewsPromotion> newsPromotions, boolean promos) {
this.newsPromotions = newsPromotions;
this.promos = promos;
}
public void setData(List<NewsPromotion> newsPromotions){
this.newsPromotions = newsPromotions;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder;
if(promos) {
View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.promo_recyclerview_item,
parent, false);
viewHolder = new PromoViewHolder(mView);
}else {
View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item_row,
parent, false);
viewHolder = new NewsViewHolder(mView);
}
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Log.d("Adapter", newsPromotions.get(position).title);
if(promos){
PromoViewHolder viewHolder = (PromoViewHolder) holder;
Picasso.get().load(RestClient.BASE_IMAGE_URL + newsPromotions.get(position).image).into(viewHolder.mImage);
}else {
NewsViewHolder viewHolder = (NewsViewHolder) holder;
Picasso.get().load(RestClient.BASE_IMAGE_URL + newsPromotions.get(position).image).into(viewHolder.mImage);
viewHolder.mTitle.setText(newsPromotions.get(position).title);
viewHolder.mDescription.setText(newsPromotions.get(position).content);
}
}
#Override
public int getItemCount() {
return newsPromotions.size();
}
public class NewsViewHolder extends RecyclerView.ViewHolder {
ImageView mImage;
TextView mTitle;
TextView mDescription;
private NewsViewHolder(View itemView) {
super(itemView);
mImage = itemView.findViewById(R.id.ivImage);
mTitle = itemView.findViewById(R.id.tvTitle);
mDescription = itemView.findViewById(R.id.tvDescription);
}
}
public class PromoViewHolder extends RecyclerView.ViewHolder {
ImageView mImage;
private PromoViewHolder(View itemView) {
super(itemView);
mImage = itemView.findViewById(R.id.ivImage);
}
}
}
And the following is how I initialize the two adapters in the Fragment:
RecyclerView promoRecycleView = activity.findViewById(R.id.promo_recyclerview);
promoAdapter = new NewsAdapter(new ArrayList<NewsPromotion>(), true);
promoRecycleView.setAdapter(promoAdapter);
RecyclerView newsRecycleView = activity.findViewById(R.id.news_recyclerview);
newsAdapter = new NewsAdapter(new ArrayList<NewsPromotion>(), false);
newsRecycleView.setAdapter(newsAdapter);
Finally, this is how I send the object to the adapters:
promoAdapter.setData(promos);
promoAdapter.notifyDataSetChanged();
newsAdapter.setData(news);
newsAdapter.notifyDataSetChanged();
Please post your adapter and item_layout. Because your given layout is working perfectly for me.
No issue with your layout i have run in myAppliaction, some issue in Adapter, please post/paste your activity and adapter code.
If you would check documentation on the RecyclerView, you will see that you need to specify size of the list. There is no wrap content for RecyclerView, because it's dynamic widget. So you would need to align your implementation for something like next.
<?xml version="1.0" encoding="utf-8"?>
<NestedScrollView
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:id="#+id/profile_coordinator"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".HomeFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="20dp">
<!-- Here I have some other views (ImageView, TextView, etc.) -->
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/active_promos"
android:textStyle="bold"
android:textColor="#color/colorPrimary"
android:textSize="18sp"
android:layout_marginBottom="10sp"/>
<!-- Horizontal List of RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/promo_recyclerview"
android:layout_width="match_parent"
android:layout_height="200dp"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_marginBottom="20sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/news"
android:textStyle="bold"
android:textColor="#color/colorPrimary"
android:textSize="18sp"
android:layout_marginBottom="10sp"/>
<!-- Vertical List of RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/news_recyclerview"
android:layout_width="match_parent"
android:layout_height="500dp" />
</LinearLayout>
</LinearLayout>
</ScrollView>
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">
I have a problem. I got an Stackoverflow Error. I tried reduced the Layout and so on. But nothing worked.
I have a view pager and in the fragments are recyclerviews 4 times. (one in each). The inflater Code
View root = inflater.inflate(R.layout.content_main, container, false);
One Layout in Fragment for example:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
android:id="#+id/list_view"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:layout_marginTop="15dp"
android:layout_height="wrap_content" />
And this is the Layout for the ReclerView Item
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
android:id="#+id/cv"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_margin="20dp"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center|left"
android:padding="10dp"
android:clickable="true"
android:background="?attr/selectableItemBackground"
>
<ImageView
android:id="#+id/album_cover"
android:layout_width="33dp"
android:layout_height="50dp"
android:layout_marginRight="16dp"
android:src="#drawable/ic_supervisor_account_black_24dp" />
<TextView
android:id="#+id/album_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Artistname"
android:textColor="#000000"
android:textSize="15sp" />
</LinearLayout>
</android.support.v7.widget.CardView>
One Layout has a Relative Layout but it works before I made some changes:
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/cv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:background="?attr/selectableItemBackground"
android:layout_margin="10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:clickable="true"
android:longClickable="true"
android:background="?attr/selectableItemBackground"
>
<ImageView
android:id="#+id/album_cover"
android:layout_width="66dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp"
android:src="#drawable/spring_276014_640" />
<TextView
android:id="#+id/album_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/album_cover"
android:text="Albumtitel"
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:id="#+id/album_artist"
android:layout_width="wrap_content"
android:layout_marginTop="5dp"
android:layout_height="wrap_content"
android:layout_below="#+id/album_name"
android:layout_toRightOf="#+id/album_cover"
android:text="von Artist xy" />
</RelativeLayout>
</android.support.v7.widget.CardView>
Captureing View Table is not possible because app is going down before it changes the layout.
Bitmaps are scaled.
Here is my Adapter:
public class DefaultAdapter extends RecyclerView.Adapter<DefaultAdapter.SongViewHolder> {
private Context con;
private List<String> names;
boolean useplaylist;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class SongViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView title;
SongViewHolder(View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cv);
title = (TextView)itemView.findViewById(R.id.album_name);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public DefaultAdapter(Context context,List<String> names,boolean playlist) {
con = context;
this.names = names;
useplaylist = playlist;
}
// Create new views (invoked by the layout manager)
#Override
public SongViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.playlist_item, viewGroup, false);
SongViewHolder pvh = new SongViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(SongViewHolder personViewHolder, int i) {
personViewHolder.title.setText(names.get(i));
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return names.size();
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
}
Log:
java.lang.StackOverflowError: stack size 8MB\n
at android.view.ViewGroup.jumpDrawablesToCurrentState(ViewGroup.java:6108)
at android.view.ViewGroup.jumpDrawablesToCurrentState(ViewGroup.java:6112)
at android.view.ViewGroup.jumpDrawablesToCurrentState(ViewGroup.java:6112)
at android.view.ViewGroup.jumpDrawablesToCurrentState(ViewGroup.java:6112)
at android.view.ViewGroup.jumpDrawablesToCurrentState(ViewGroup.java:6112)
at android.view.ViewGroup.jumpDrawablesToCurrentState(ViewGroup.java:6112)
Can somebody help me?
Problem solved.
I don't know where the Error was but maby it was an empty list or the ImageAssets wich I replaced with vector assets and activate the Libary in the Gradle.
For thoos who have the same problem in a viewpage: Deactivate all fragments and enable them single, to test where the error is.
I want to develop List like this picture
I had used to RecylerView ItemDecorator for overlap. But it's overlapping without shadow. the screen & decorator code is below
public class OverlapDecoration extends RecyclerView.ItemDecoration {
private final static int vertOverlap = -50;
#Override
public void getItemOffsets (Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(0, 0, 0, vertOverlap);
}
}
card_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:tag="cards main container">
<android.support.v7.widget.CardView
android:id="#+id/card_view"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="#color/color_white"
card_view:cardElevation="5dp"
card_view:cardUseCompatPadding="true">
<TextView
android:id="#+id/textViewName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:layout_marginBottom="30dp"
android:text="Android Name"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</android.support.v7.widget.CardView>
</LinearLayout>
try this code
card_layout.xml
<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="wrap_content"
android:orientation="vertical"
android:tag="cards main container">
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:clipToPadding="false"
android:elevation="0dp"
card_view:cardUseCompatPadding="false"
card_view:paddingEnd="0dp"
card_view:paddingStart="0dp">
<TextView
android:id="#+id/textViewName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp"
android:layout_marginTop="30dp"
android:gravity="center"
android:text="Android Name"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_above="#id/textViewName"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="#drawable/card_shadow" />
</android.support.v7.widget.CardView>
</RelativeLayout>
for card shadow
card_shadow
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="90"
android:endColor="#77111111"
android:startColor="#android:color/transparent" />
</shape>
This is example of your problem solution for static CardView , here you every time decrease your card_view:cardElevationby 2dp or 5dp. But if you done this with recyclerview and want to dynamic CardView then you have to add elevation in your RecyclerView Adapterdynamically. And its decrease with its position increase. Set card elevation holder.cardView.setCardElevation()
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:tag="cards main container">
<android.support.v7.widget.CardView
android:id="#+id/card_view"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardElevation="20dp"
card_view:cardUseCompatPadding="false">
<TextView
android:id="#+id/textViewName1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:layout_marginBottom="30dp"
android:text="Android Name"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="#+id/card_view2"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardElevation="18dp"
card_view:cardUseCompatPadding="false">
<TextView
android:id="#+id/textViewName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:layout_marginBottom="30dp"
android:text="Android Name"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="#+id/card_view3"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardUseCompatPadding="false">
<TextView
android:id="#+id/textViewName3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:layout_marginBottom="30dp"
android:text="Android Name"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</android.support.v7.widget.CardView>
</LinearLayout>
Hope it will help you. Thanks.
Try this.
In RecyclerView Adapter- on OnBindViewHolder method add the following code:
CardView cardView = ((MyViewHolder) holder).cardView;
float elevation = cardView.getCardElevation();
float value = elevation-Float.parseFloat((position*0.5)+"");
cardView.setCardElevation(value);
See the output here:
Note: depend on your code modify the above code and use it in right place.
For reference here is my sample adaptor code.
public class CustomAdapter extends RecyclerView.Adapter {
public static final String Name = "Name";
public static final String Author = "Author";
public static final String Description = "Description";
private List<Book> dataSet;
private Context context;
public CustomAdapter(List<Book> data, Context context) {
this.dataSet = data;
this.context = context;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
ImageView profile;
TextView name, author,description;
CardView cardView;
public MyViewHolder(View itemView) {
super(itemView);
profile = (ImageView) itemView.findViewById(R.id.profile_image);
name = (TextView) itemView.findViewById(R.id.name);
author = (TextView) itemView.findViewById(R.id.author);
description = (TextView) itemView.findViewById(R.id.description);
cardView = (CardView) itemView.findViewById(R.id.cardview);
}
}
#Override
public int getItemCount() {
return dataSet.size();
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder vh;
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.book_layout_sample, parent, false);
vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof MyViewHolder) {
Book book = dataSet.get(position);
((MyViewHolder) holder).profile.setImageDrawable(getResources().getDrawable(R.drawable.blank_user,this.context.getTheme()));
((MyViewHolder) holder).name.setText(book.title);
((MyViewHolder) holder).author.setText(book.author);
((MyViewHolder) holder).description.setText(book.description);
CardView cardView = ((MyViewHolder) holder).cardView;
float ele = cardView.getCardElevation();
float val = ele-Float.parseFloat((position*0.5)+"");
cardView.setCardElevation(val);
if(position==0)
{
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)cardView.getLayoutParams();
params.setMargins(0,0,0,0);
cardView.setLayoutParams(params);
}
}
}
}