i want to arrange the grid view like below image.
You need to use RecyclerView with GridLayoutManager for that. Then you can use GridLayoutManager.setSpanSizeLookup to set the column count dynamically.
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
switch (adapter.getItemViewType(position)) {
case VIEW_TYPE_1:
return 1;
case VIEW_TYPE_2:
return 2;
default:
return -1;
}
}
});
You can take RecyclerView instead of GridView and write like this
RecyclerView mRecyclerView=(RecyclerView)findViewById(R.id.card_recycler_view);
GridLayoutManager glm = new GridLayoutManager(getActivity(), 4);
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
if (position % 3 == 2) {
return 4;
} else {
return 2;
}
}
});
mRecyclerView.setLayoutManager(glm);
You need to spacify viewType in recycler adapter.
DEMO HERE
public class RVStatisticAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Statistic> mList;
public RVStatisticAdapter(List<Statistic> list) {
this.mList = list;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case CITY_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.statistic_row_one, parent, false);
return new CityViewHolder(view);
case EVENT_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.statistic_row_two, parent, false);
return new EventViewHolder(view);
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Statistic object = mList.get(position);
if (object != null) {
switch (object.getType()) {
case CITY_TYPE:
((CityViewHolder) holder).mTitle.setText(object.getTitle());
((CityViewHolder) holder).no.setText(object.getNo());
((CityViewHolder) holder).playerone.setText(object.getPlayer_one());
break;
case EVENT_TYPE:
((EventViewHolder) holder).mTitle.setText(object.getTitle());
((EventViewHolder) holder).no.setText(object.getNo());
((EventViewHolder) holder).playerone.setText(object.getName());
((EventViewHolder) holder).playertwo.setText(object.getPlayer_two());
break;
}
}
}
#Override
public int getItemCount() {
if (mList == null)
return 0;
return mList.size();
}
#Override
public int getItemViewType(int position) {
if (mList != null) {
Statistic object = mList.get(position);
if (object != null) {
return object.getType();
}
}
return 0;
}
public static class CityViewHolder extends RecyclerView.ViewHolder {
private TextView mTitle,no,playerone;
public CityViewHolder(View itemView) {
super(itemView);
mTitle = (TextView) itemView.findViewById(R.id.tv_title);
no = (TextView) itemView.findViewById(R.id.tv_no);
playerone = (TextView) itemView.findViewById(R.id.tv_player_one);
}
}
public static class EventViewHolder extends RecyclerView.ViewHolder {
private TextView mTitle,no,playerone,playertwo;
public EventViewHolder(View itemView) {
super(itemView);
mTitle = (TextView) itemView.findViewById(R.id.tv_title);
no = (TextView) itemView.findViewById(R.id.tv_no);
playerone = (TextView) itemView.findViewById(R.id.tv_player_one);
playertwo = (TextView) itemView.findViewById(R.id.tv_player_two);
}
}
}
This One will Work. Try this
RecyclerView RecyclerView=RecyclerView)findViewById(R.id.card_recycler_view);
GridLayoutManager glm = new GridLayoutManager(getActivity(), 4);
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
switch(position%3) {
case 0:
return 4;
break;
case 1:
return 2;
break;
case 2:
return 2;
break;
}
}
});
mRecyclerView.setLayoutManager(glm);
you can use StaggeredGridLayoutManager
private StaggeredGridLayoutManager gaggeredGridLayoutManager;
gaggeredGridLayoutManager = new StaggeredGridLayoutManager(2, 1);
recyclerView.setLayoutManager(gaggeredGridLayoutManager);
for more information follow this link StaggeredGridLayoutManager
for example see this image
Related
I am developing an app in which we need vertical Recyclerview inside horizontal Recyclerview. And the vertical Recyclerview have multiple view types. So the problem is, when i scroll down few items and go back up again, only the nested recyclerview is populated with wrong data. Otherwise every other data is correct.
Like in this picture you can see the correct data where recyclerview is gone
In this picture you can see the recyclerview is populated with some other object data and showing image when i scroll back up
Now i have tried everything setHasStableIds(true) , using same viewpool worsen the situation,getItemId();
But nothing seems to work.
OUTER RECYCLERVIEW ADAPTER
private ArrayList<BasePostData> basePostDataArrayList;
private Context mContext;
private RecyclerView.RecycledViewPool viewPool;
public PostFragmentListAdapter(ArrayList<BasePostData> basePostDataArrayList, Context mContext) {
this.basePostDataArrayList = basePostDataArrayList;
this.mContext = mContext;
setHasStableIds(true);
}
public static class MyviewHolder extends RecyclerView.ViewHolder{
ImageView profileImage,more;
TextView name,user_category,post_category,follow,like,comment,share,description,post_type,highlight;
RecyclerView recyclerView;
HorizontalPostRecyclerview horizontalAdapter;
public MyviewHolder(#NonNull View itemView) {
super(itemView);
Context context = itemView.getContext();
this.comment = itemView.findViewById(R.id.post_comment_textview);
this.name = itemView.findViewById(R.id.post_user_name);
this.user_category = itemView.findViewById(R.id.post_category);
this.post_category = itemView.findViewById(R.id.posts_multiple_categories);
this.follow = itemView.findViewById(R.id.post_follow_button);
this.like = itemView.findViewById(R.id.post_like_textview);
this.share = itemView.findViewById(R.id.post_whatsapp_tv);
this.profileImage = itemView.findViewById(R.id.post_profile_pic);
this.more = itemView.findViewById(R.id.post_more_tv);
this.description = itemView.findViewById(R.id.post_description_textview);
this.recyclerView =itemView.findViewById(R.id.post_content_recyclerview);
this.post_type= itemView.findViewById(R.id.post_type);
this.highlight= itemView.findViewById(R.id.post_highlighted);
// recyclerView = (RecyclerView) itemView.findViewById(R.id.horizontal_list);
}
}
#NonNull
#Override
public MyviewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.post_layout,viewGroup,false);
MyviewHolder myviewHolder = new MyviewHolder(view);
return myviewHolder;
}
#Override
public void onBindViewHolder(#NonNull MyviewHolder viewHolder, int position)
{
StringBuilder post_cat= new StringBuilder();
BasePostData basePostData = basePostDataArrayList.get(position);
viewHolder.description.setText(basePostData.getDiscription());
viewHolder.name.setText(basePostData.getUser());
viewHolder.post_type.setText(basePostData.getPost_type());
viewHolder.itemView.setTag(position);
if (basePostData.getUser_category()!=null){
viewHolder.user_category.setText("("+basePostData.getUser_parent_category()+") "+basePostData.getUser_category());
}else {
viewHolder.user_category.setText(basePostData.getUser_parent_category());
}
viewHolder.like.setText(String.valueOf(basePostData.getLike())+" Likes");
viewHolder.comment.setText(String.valueOf(basePostData.getTotal_comments())+" Comments");
for (int i = 0;i<basePostData.getPost_tag().size();i++)
{
post_cat.append(basePostData.getPost_tag().get(i).getTag()).append(" | ");
}
viewHolder.post_category.setText(post_cat.toString());
Picasso.get()
.load(basePostData.getUser_profile_pic())
.placeholder(R.drawable.profile_ic)
.error(R.drawable.profile_ic)
.into(viewHolder.profileImage);
//--------------------------------highlight answer--------------
if (basePostData.getHighlight_comment()!=null)
{
viewHolder.highlight.setVisibility(View.VISIBLE);
viewHolder.highlight.setText(basePostData.getHighlight_comment().getComment());
}
//---------------------------recyclerview for files-------------------------------
if (basePostData.getFile_type()!=null) {
viewHolder.recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
viewHolder.horizontalAdapter = new HorizontalPostRecyclerview();
viewHolder. recyclerView.setAdapter(viewHolder.horizontalAdapter);
viewHolder.horizontalAdapter.setData(basePostData.getPost_file()); // List of Strings
viewHolder.horizontalAdapter.setRowIndex(position);
viewHolder.recyclerView.setVisibility(View.VISIBLE);
/*
Log.e("item ",basePostData.getFile_type());
viewHolder. recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
*//* switch (basePostData.getFile_type()){
case "Image":
viewHolder. horizontalAdapter = new HorizontalPostRecyclerview(basePostData.getPost_file() ,mContext,ConstantsOSH.TYPE_IMAGE);
viewHolder. recyclerView.setAdapter(viewHolder.horizontalAdapter);
break;
case "Video":
viewHolder. horizontalAdapter = new HorizontalPostRecyclerview(basePostData.getPost_file() ,mContext,ConstantsOSH.TYPE_VIDEO);
viewHolder. recyclerView.setAdapter(viewHolder.horizontalAdapter);
break;
case "Document":
viewHolder. horizontalAdapter = new HorizontalPostRecyclerview(basePostData.getPost_file() ,mContext,ConstantsOSH.TYPE_DOC);
viewHolder. recyclerView.setAdapter(viewHolder.horizontalAdapter);
viewHolder.horizontalAdapter.setRowIndex(position);
break;
}*//*
if (basePostData.getFile_type().equalsIgnoreCase("image")){
viewHolder. horizontalAdapter = new HorizontalPostRecyclerview(basePostData.getPost_file() ,mContext,ConstantsOSH.TYPE_IMAGE);
}else if (basePostData.getFile_type().equalsIgnoreCase("video")){
viewHolder. horizontalAdapter = new HorizontalPostRecyclerview(basePostData.getPost_file() ,mContext,ConstantsOSH.TYPE_VIDEO);
}else if (basePostData.getFile_type().equalsIgnoreCase("document"))
viewHolder. horizontalAdapter = new HorizontalPostRecyclerview(basePostData.getPost_file() ,mContext,ConstantsOSH.TYPE_DOC);
viewHolder. recyclerView.setAdapter(viewHolder.horizontalAdapter);
viewHolder.horizontalAdapter.setRowIndex(position);
*/ }
}
#Override
public int getItemCount() {
return basePostDataArrayList.size();
}
public void add(ArrayList<BasePostData> basePostDatalist) {
basePostDataArrayList.addAll(basePostDatalist);
notifyDataSetChanged();
}
public void clear() {
basePostDataArrayList.clear();
notifyDataSetChanged();
}
#Override
public long getItemId(int position) {
BasePostData product = basePostDataArrayList.get(position);
return product.hashCode();
}
}
VERTICAL NESTED RECYCLERVIEW ADAPTER
public class HorizontalPostRecyclerview extends
RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<PostFileModel> dataset;
private Context mContext;
private int mRowIndex = -1;
private int viewType;
public HorizontalPostRecyclerview() {
setHasStableIds(true);
}
public HorizontalPostRecyclerview(ArrayList<PostFileModel> dataset, Context mContext) {
this.dataset = dataset;
this.mContext = mContext;
}
public HorizontalPostRecyclerview(ArrayList<PostFileModel> dataset, Context mContext,int viewType) {
this.dataset = dataset;
this.mContext = mContext;
this.viewType = viewType;
}
public void setRowIndex(int index) {
mRowIndex = index;
}
public void setData(ArrayList<PostFileModel> data) {
if (dataset != data) {
dataset = data;
notifyDataSetChanged();
}
}
private class ImageViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView,play_btn;
private TextView name;
public ImageViewHolder(View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.horizontal_image_layout_imageview);
// name = itemView.findViewById(R.id.post_image_gallery_name_text);
// play_btn = itemView.findViewById(R.id.post_image_gallery_play_btn);
}
}
private class VideoViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView,play_btn;
private TextView name;
public VideoViewHolder(View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.horizontal_video_layout_imageview);
// name = itemView.findViewById(R.id.post_image_gallery_name_text);
play_btn = itemView.findViewById(R.id.horizontal_video_layout_play_btn);
}
}
private class DocViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView,play_btn;
private TextView name;
public DocViewHolder(View itemView) {
super(itemView);
//imageView = itemView.findViewById(R.id.post_image_gallery_imageview);
name = itemView.findViewById(R.id.horizontal_doc_layout_textview);
play_btn = itemView.findViewById(R.id.horizontal_doc_layout_playbtn);
}
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View itemView;
// ImageViewHolder holder = new ImageViewHolder(itemView);
switch (i)
{
case ConstantsOSH.TYPE_IMAGE:
itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.horizontal_post_image_layout,viewGroup, false);
return new ImageViewHolder(itemView);
// break;
case ConstantsOSH.TYPE_DOC:
itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.horizontal_post_doc_layout,viewGroup, false);
return new DocViewHolder(itemView);
// break;
case ConstantsOSH.TYPE_VIDEO:
itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.horizontal_post_video_layout,viewGroup, false);
return new VideoViewHolder(itemView);
// break;
default:
itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.horizontal_post_image_layout,viewGroup, false);
return new ImageViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder viewHolder, int i) {
// ImageViewHolder holder = (ImageViewHolder) viewHolder;
switch (dataset.get(i).getFile_type()){
case "Image":
ImageViewHolder holder = (ImageViewHolder) viewHolder;
Picasso.get().load(dataset.get(i).getFile()).error(R.drawable.camera_ic).placeholder(R.drawable.flag_india).into(holder.imageView);
holder.itemView.setTag(i);
/* Glide.with(holder.imageView.getContext()) // Bind it with the context of the actual view used
.load(dataset.get(i).getFile()) // Load the image
.thumbnail(0.2f) // make use of the thumbnail which can display a down-sized version of the image
.into(holder.imageView);
*/
break;
case "document":
DocViewHolder holder2 = (DocViewHolder) viewHolder;
holder2.play_btn.setImageResource(R.drawable.doc_ic_new);
holder2.play_btn.setVisibility(View.VISIBLE);
String[] split = dataset.get(i).getFile().split("post_file/");
holder2.name.setText(split[1]);
holder2.name.setVisibility(View.VISIBLE);
holder2.itemView.setTag(i);
break;
case "video":
VideoViewHolder holder3 = (VideoViewHolder) viewHolder;
long interval = 2000;
RequestOptions options = new RequestOptions().frame(interval).placeholder(R.drawable.camera_ic);
Glide.with(holder3.imageView.getContext()).asBitmap()
.load(dataset.get(i).getFile())
.apply(options)
.into(holder3.imageView);
holder3.play_btn.setVisibility(View.VISIBLE);
holder3.itemView.setTag(i);
break;
}
}
#Override
public int getItemCount() {
return dataset.size();
}
#Override
public long getItemId(int position) {
PostFileModel postFileModel = dataset.get(position);
return postFileModel.hashCode();
}
#Override
public int getItemViewType(int position) {
switch (dataset.get(position).getFile_type()) {
case "Image":
return ConstantsOSH.TYPE_IMAGE;
case "video":
return ConstantsOSH.TYPE_VIDEO;
case "document":
return TYPE_DOC;
default:
return -1;
}
}
}
I need to create a recyclerView with a GridLayoutManager on two lines, and the first element to be bigger than the rest. The result should look like this:
I managed to achieve this, but in an unconventional way. In my recyclerView adapter I use a different viewHolder for the first element, a bigger one. That would have been a great solution, but the second element would have gone below the first element. So I made a trick of giving recyclerView a fixed height same as the first element, that way the first element and the second would overlap and I would simply make the visibility of the second to gone.
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case 0:
final View view = inflater.inflate(R.layout.big_item, parent, false);
return new BigViewHolder(view);
case 2:
final View view2 = inflater.inflate(R.layout.normal_item, parent, false);
return new NormalViewHolder(view2);
default:
return null;
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (position == 1) {
holder.itemView.setVisibility(View.GONE);
}}
#Override
public int getItemViewType(int position) {
if (position == 0) {
return 0;
} else return 2;
}
But I don't particularly like this approach. Does anyone have a better idea on this?
After some digging and counseling, I came to a pretty nice result. I will post it below:
First, the adapter should look like I mentioned in the question, without the hiding of the second element:
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final int TYPE_FIRST_ITEM = 0;
public static final int TYPE_ITEM = 1;
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_FIRST_ITEM:
final View view = inflater.inflate(R.layout.big_item, parent, false);
return new BigViewHolder(view);
case TYPE_ITEM:
final View view2 = inflater.inflate(R.layout.normal_item, parent, false);
return new NormalViewHolder(view2);
default:
return null;
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case TYPE_FIRST_ITEM:
BigViewHolder bigViewHolder = (BigViewHolder) holder;
// Do what you need for the first item
break;
case TYPE_ITEM:
NormalViewHolder normalViewHolder = (NormalViewHolder) holder;
// Do what you for the other items
break;
}
}
#Override
public int getItemViewType(int position) {
if (position == 0) {
return TYPE_FIRST_ITEM;
} else return TYPE_ITEM;
}
final class NormalViewHolder extends RecyclerView.ViewHolder {
public NormalViewHolder(View itemView) {
super(itemView);
}
// find your views here
}
final class BigViewHolder extends RecyclerView.ViewHolder {
public BigViewHolder(View itemView) {
super(itemView);
}
// find your views here
}
}
Second, the layout manager should implement a listener to specify how many spans (rows) should be at a specific position:
RecyclerView mRecyclerView = view.findViewById(R.id.my_recycler_view);
MyAdapter mAdapter = new MyAdapter();
GridLayoutManager mLayoutManager = new GridLayoutManager(getActivity(), 2, LinearLayoutManager.HORIZONTAL, false);
mLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
switch(mAdapter.getItemViewType(position)){
case MyAdapter.TYPE_FIRST_ITEM:
return 2;
case MyAdapter.TYPE_ITEM:
return 1;
default:
return -1;
}
}
});
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(mLayoutManager);
Hope it will help someone else too. Thank you Mike M. for your support.
I want to show 2 columns in a RecyclerView, but they show in 1 column like this photo:
How can I show my view in 2 columns?
I try it in my code with 2 columns:
rcv_pro.setLayoutManager(new GridLayoutManager(this, 2, LinearLayoutManager.VERTICAL, false));
but they don't show in 2 columns.
i find a soulotion for show in 2 culmn , i can fix it whit clear this code :
" menuList_info_models.clear(); "
but i have a new probem now , when i clear that cod , my items in recyclerview is mess , any time i scrole in recyclerview , my items change
public class MultiItem_Music_Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
ArrayList<Object> objects = new ArrayList<Object>();
Context context;
private final static int MUSIC_CAT = 1;
private final static int MUSIC_ADA = 2;
private ArrayList<MenuList_Info_Model> menuList_info_models;
private ArrayList<Cat_Model> cat_models;
private Music_Adapter adapter;
private List<MenuList_Info_Model> personList = new ArrayList<>();
private RecyclerView recyclerView;
private ListAdapter mAdapter;
private ArrayList<MenuList_Info_Model> music_data;
public GridLayoutManager manager ;
public MultiItem_Music_Adapter(ArrayList<Object> objects, Context context) {
Log.e("MyLog","farzad");
this.objects = objects;
this.context = context;
if (menuList_info_models == null)
menuList_info_models = new ArrayList<MenuList_Info_Model>();
if (cat_models == null) cat_models = new ArrayList<Cat_Model>();
adapter = new Music_Adapter(menuList_info_models, this.context);
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder ;
LayoutInflater inflater = LayoutInflater.from(context);
View view;
switch (viewType) {
case MUSIC_CAT:
view = inflater.inflate(R.layout.music_cat_item, parent, false);
viewHolder = new Music_cat_ViewHolder(view);
break;
case MUSIC_ADA:
view= inflater.inflate(R.layout.music_item_multi, parent, false);
viewHolder = new Multi_item_ViewHolder(view);
break;
default:
view = inflater.inflate(R.layout.music_item_multi, parent, false);
viewHolder = new Multi_item_ViewHolder(view);
break;
}
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Log.e("hamid_ali", "---------------------");
switch (holder.getItemViewType()) {
case MUSIC_CAT:
Cat_Config((Music_cat_ViewHolder) holder,position);
break;
case MUSIC_ADA:
item_Config((Multi_item_ViewHolder) holder,position);
break;
}
}
private void item_Config(Multi_item_ViewHolder item_viewHolder,int pos) {
MenuList_Info_Model menuList_info_model = (MenuList_Info_Model) objects.get(pos);
menuList_info_models.clear();
menuList_info_models.add(menuList_info_model);
Log.e("hamid_st",menuList_info_models.size() +"");
manager = new GridLayoutManager(this.context, 2, LinearLayoutManager.VERTICAL, false);
item_viewHolder.rcv_multi.setLayoutManager(manager);
item_viewHolder.rcv_multi.setAdapter(adapter);
}
private void Cat_Config(Music_cat_ViewHolder musicCatViewHolder,int pos) {
Cat_Model cat_model = (Cat_Model) objects.get(pos);
musicCatViewHolder.txt_cat_name.setText(cat_model.getMenu_name());
}
#Override
public int getItemCount() {
return objects.size();
}
#Override
public int getItemViewType(int position) {
if (objects.get(position) instanceof Cat_Model) {
return MUSIC_CAT;
} else {
return MUSIC_ADA;
}
}
}
you can use GridLayoutManager
set GridLayoutManager to your RecyclerView uisng below code
GridLayoutManager gridLayoutManager = new GridLayoutManager(MainActivity.this, 2);
recyclerView.setLayoutManager(gridLayoutManager);
here is link how to use GridLayoutManager with RecyclerView
RvAdapter MultiItem_Music_Adapter ;
RecyclerView rcv_pro;
MultiItem_Music_Adapter = new MultiItem_Music_Adapter (getActivity());
rcv_pro.setLayoutManager(new GridLayoutManager(getActivity(), 2));
rcv_pro.setAdapter(MultiItem_Music_Adapter );
You can try this for 2 columns :-
mRecycler.setLayoutManager(new GridLayoutManager(YourActivity.this, 2));
mRecycler.setLayoutManager(gridLayoutManager);
It is mendatory to setLayoutMangaer with your recyclerview otherwise it will not work.
You can get the two columns of an items in RecyclerView via StaggeredGridLayoutManager too.
From documentation, you can use following method:
StaggeredGridLayoutManager(int spanCount, int orientation)
StaggeredGridLayoutManager yourStaggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
yourRecyclerView.setLayoutManager(staggeredGridLayoutManager);
Or directly:
yourRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
i must be create two ViewHolder see more code
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
class ViewHolder0 extends RecyclerView.ViewHolder {
...
public ViewHolder0(View itemView){
...
}
}
class ViewHolder2 extends RecyclerView.ViewHolder {
...
public ViewHolder2(View itemView){
...
}
#Override
public int getItemViewType(int position) {
// Just as an example, return 0 or 2 depending on position
// Note that unlike in ListView adapters, types don't have to be contiguous
return position % 2 * 2;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case 0: return new ViewHolder0(...);
case 2: return new ViewHolder2(...);
...
}
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
switch (holder.getItemViewType()) {
case 0:
ViewHolder0 viewHolder0 = (ViewHolder0)holder;
...
break;
case 2:
ViewHolder2 viewHolder2 = (ViewHolder2)holder;
...
break;
}
}
}
any idea how to use Two different LayoutManager in one View? I have four cards in grid on top of the screen and bottom, and I want LinearLayout but RecyclerView showing one View at a time
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(mLayoutManager);
RecyclerView.LayoutManager lmLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(lmLayoutManager);
recyclerView.addItemDecoration(new GridSpacingDashboard(2, dpToPx(2), true));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
Is there any way I can use both Views in a single RecyclerView Or on Index O I have GridLayout and on 1 showing LinearLayout , How can achieve if there is any possibilities
Update (Card Adapter)
public class CardAdapter extends RecyclerView.Adapter<adapter.CardAdapter.CardViewHolder> {
public static final int topGridCard = 0;
public static final int bottomCards=1;
private Context mContext;
private List<CardModel> cardList;
public CardAdapter(Context mContext, List<CardModel> cardList) {
this.mContext = mContext;
this.cardList = cardList;
}
#Override
public.adapter.CardAdapter.CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
if (viewType == topGridCard) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_sec, parent, false);
return new adapter.CardAdapter.TopGridCardView(v);
}
else if (viewType == bottomCards) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view, parent, false);
return new adapter.CardAdapter.BottomCardView(v);
}
return null;
}
#Override
public void onBindViewHolder(final adapter.CardAdapter.CardViewHolder holder, final int position) {
CardModel cardModel = cardList.get(position);
if (holder.getItemViewType()==topGridCard){ adapter.CardAdapter.TopGridCardView vholder = (adapter.CardAdapter.TopGridCardView) holder;
vholder.secTitleStats.setText(cardModel.getNumStats());
vholder.secNumStats.setText(cardModel.getCardTitles());
vholder.secCardStats.setText(cardModel.getSecCartNumStats());
Glide.with(mContext).load(cardModel.getThumbnail()).into(vholder.secthumbnail);
}
else if(holder.getItemViewType()==bottomCards){
adapter.CardAdapter.BottomCardView vholder = (adapter.CardAdapter.BottomCardView) holder;
vholder.numStats.setText(cardModel.getNumStats());
vholder.image_title.setText(cardModel.getCardTitles());
Glide.with(mContext).load(cardModel.getThumbnail()).into(vholder.thumbnail);
}
}
#Override
public int getItemCount(){
return cardList.size();
}
public static class CardViewHolder extends RecyclerView.ViewHolder {
public CardViewHolder(View v) {
super(v);
}
}
public class TopGridCardView extends adapter.CardAdapter.CardViewHolder {
public TextView secTitleStats, secNumStats,secCardStats;
public ImageView secthumbnail;
public TopGridCardView(View view){
super(view);
secTitleStats = (TextView) view.findViewById(R.id.secTitleNumStats);
secNumStats = (TextView) view.findViewById(R.id.secCardNumStats);
secCardStats = (TextView) view.findViewById(R.id.sectitle);
secthumbnail = (ImageView) view.findViewById(R.id.seCthumbnail);
}
}
public class BottomCardView extends adapter.CardAdapter.CardViewHolder {
public TextView numStats,image_title;
public ImageView thumbnail;
public BottomCardView(View view) {
super(view);
numStats=(TextView)view.findViewById(R.id.numStatics);
image_title=(TextView) view.findViewById(R.id.title_overlay);
thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
}
}
#Override
public int getItemViewType(int position) {
if (isPositionHeader(position))
return topGridCard;
return bottomCards;
}
private boolean isPositionHeader(int position) {
return position == 0;
}
}
I have attached my Adapter just for more understanding , what the desired result should be
|Grid Card 1 | Grid Card 2 |
|Grid Card 3 | Grid Card 4 |
| LinearLayout Card 1 |
| LinearLayout Card 2 |
any possibilities
you can simply use gridLayout with different viewType to achieve this.
mLayoutManager = new GridLayoutManager(getActivity(), 2);
mLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
switch (adapter.getItemViewType(position)) {
case MenuAdapter.ITEM:
return 1;
case MenuAdapter.FULLSIZE:
return 2;
default:
return 1;
}
}
});
recyclerView.setLayoutManager(mLayoutManager);
Where ITEM is a grid(2x column) then return 1, otherwise FULLSIZE return 2(takes 2x grid column).
hope it helped.
I have created twoe viewHolders in my RecyclerView class, one for the contents and the other for facebook native ads, My app clash immediately after running it. How do I overcome this?
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case 0:
return new ViewHolderBoxOffice(layoutInflater.from(parent.getContext()).inflate(R.layout.custom_movie_box_office, parent, false));
case 2:
return new NativeAdViewHolder(layoutInflater.from(parent.getContext()).inflate(R.layout.custom_ads_facebook, parent, false));
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case 0:
ViewHolderBoxOffice v_holder = (ViewHolderBoxOffice) holder;
Movie currentMovie = mlistMovies.get(position);
v_holder.movieTitle.setText(currentMovie.getTitle());
Date movieReleaseDate = currentMovie.getReleaseDateTheater();
if (movieReleaseDate != null) {
String formmattedDate = dateFormat.format(movieReleaseDate);
v_holder.movieReleaseDate.setText(formmattedDate);
} else {
v_holder.movieReleaseDate.setText(Constants.NA);
}
int audienceScore = currentMovie.getAudienceScore();
if (audienceScore == -1) {
v_holder.movieAudienceScore.setRating(0.0F);
v_holder.movieAudienceScore.setAlpha(0.5F);
} else {
v_holder.movieAudienceScore.setRating(currentMovie.getAudienceScore() / 20.0F);
v_holder.movieAudienceScore.setAlpha(1.0F);
}
String urlThumbnail = currentMovie.getUrlThumbnail();
loadImages(urlThumbnail, v_holder);
case 2:
NativeAdViewHolder mHolder=(NativeAdViewHolder)holder;
// Setting the Text.
nativeAd.unregisterView();
mHolder.nativeAdCallToAction.setText(nativeAd.getAdCallToAction());
mHolder.nativeAdSocialContext.setText(nativeAd.getAdSocialContext());
mHolder.nativeAdTitle.setText(nativeAd.getAdTitle());
mHolder.nativeAdBody.setText(nativeAd.getAdBody());
// Downloading and setting the ad icon.
NativeAd.Image adIcon = nativeAd.getAdIcon();
NativeAd.downloadAndDisplayImage(adIcon, mHolder.nativeAdIcon);
// Download and setting the cover image.
NativeAd.Image adCoverImage = nativeAd.getAdCoverImage();
mHolder.nativeAdMedia.setNativeAd(nativeAd);
// Add adChoices icon
// if (adChoicesView == null)
if(! (mHolder.adview.getChildAt(0) instanceof AdChoicesView)){
AdChoicesView adChoicesView = new AdChoicesView(layoutInflater.getContext(), nativeAd, true);
mHolder.adview.addView(adChoicesView, 0);
}
nativeAd.registerViewForInteraction( mHolder.adview);
default:
break;
}
if (position > previousPosition) {
comeagain.materialdesign.anim.AnimationUtils.animate(holder, true);
} else {
comeagain.materialdesign.anim.AnimationUtils.animate(holder, false);
}
previousPosition = position;
}
private void loadImages(String urlThumbnail, final ViewHolderBoxOffice holder) {
if (urlThumbnail != null) {
imageLoader.get(urlThumbnail, new ImageLoader.ImageListener() {
#Override
public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
holder.movieThumbnail.setImageBitmap(response.getBitmap());
}
#Override
public void onErrorResponse(VolleyError error) {
}
});
}
}
#Override
public int getItemCount() {
return mlistMovies.size();
}
#Override
public void onError(Ad ad, AdError adError) {
}
#Override
public void onAdLoaded(Ad ad) {
}
#Override
public void onAdClicked(Ad ad) {
L.m("Ads is loaded, Jeez man that is good");
System.out.println("Loaded in fragment");
nativeAd = manager.nextNativeAd();
nativeAd.setAdListener(this);
}
#Override
public int getItemViewType(int position) {
int viewType = 0;
if (position % 5 == 1)
viewType = 2;
return viewType;
}
#Override
public void onAdsLoaded() {
L.m("Ads is loaded, Jeez man that is good");
System.out.println("Loaded in fragment");
nativeAd = manager.nextNativeAd();
nativeAd.setAdListener(this);
}
#Override
public void onAdError(AdError adError) {
}
class NativeAdViewHolder extends RecyclerView.ViewHolder {
private ImageView nativeAdIcon;
private TextView nativeAdTitle;
private TextView nativeAdBody;
private MediaView nativeAdMedia;
private TextView nativeAdSocialContext;
private Button nativeAdCallToAction;
private LinearLayout adview;
public NativeAdViewHolder(View itemView) {
super(itemView);
// Create native UI using the ad metadata.
nativeAdIcon = (ImageView) itemView.findViewById(R.id.native_ad_icon);
nativeAdTitle = (TextView) itemView.findViewById(R.id.native_ad_title);
nativeAdBody = (TextView) itemView.findViewById(R.id.native_ad_body);
nativeAdMedia = (MediaView) itemView.findViewById(R.id.native_ad_media);
nativeAdSocialContext = (TextView) itemView.findViewById(R.id.native_ad_social_context);
nativeAdCallToAction = (Button) itemView.findViewById(R.id.native_ad_call_to_action);
adview=(LinearLayout) itemView.findViewById(R.id.ads_unit);
}
}
class ViewHolderBoxOffice extends RecyclerView.ViewHolder implements View.OnClickListener {
private ImageView movieThumbnail;
private TextView movieTitle;
private TextView movieReleaseDate;
private RatingBar movieAudienceScore;
public ViewHolderBoxOffice(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
movieThumbnail = (ImageView) itemView.findViewById(R.id.movieThumbnail);
movieTitle = (TextView) itemView.findViewById(R.id.movieTitle);
movieReleaseDate = (TextView) itemView.findViewById(R.id.movieReleaseDate);
movieAudienceScore = (RatingBar) itemView.findViewById(R.id.movieAudienceScore);
}
Here is the error.
01-31 16:30:48.944 9429-9429/comeagain.materialdesign E/AndroidRuntime: FATAL EXCEPTION: main
Process: comeagain.materialdesign, PID: 9429
java.lang.ClassCastException: comeagain.materialdesign.adapters.AdapterBoxOffice$ViewHolderBoxOffice cannot be cast to comeagain.materialdesign.adapters.AdapterBoxOffice$NativeAdViewHolder
at comeagain.materialdesign.adapters.AdapterBoxOffice.onBindViewHolder(AdapterBoxOffice.java:148)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5217)
Error is at line
NativeAdViewHolder mHolder=(NativeAdViewHolder)holder;
I unable to determine what is the problem and how to solve this issue. Kindly help.
Terminate your Switch case with a break.
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case 0:
ViewHolderBoxOffice v_holder = (ViewHolderBoxOffice) holder;
Movie currentMovie = mlistMovies.get(position);
v_holder.movieTitle.setText(currentMovie.getTitle());
Date movieReleaseDate = currentMovie.getReleaseDateTheater();
if (movieReleaseDate != null) {
String formmattedDate = dateFormat.format(movieReleaseDate);
v_holder.movieReleaseDate.setText(formmattedDate);
} else {
v_holder.movieReleaseDate.setText(Constants.NA);
}
int audienceScore = currentMovie.getAudienceScore();
if (audienceScore == -1) {
v_holder.movieAudienceScore.setRating(0.0F);
v_holder.movieAudienceScore.setAlpha(0.5F);
} else {
v_holder.movieAudienceScore.setRating(currentMovie.getAudienceScore() / 20.0F);
v_holder.movieAudienceScore.setAlpha(1.0F);
}
String urlThumbnail = currentMovie.getUrlThumbnail();
loadImages(urlThumbnail, v_holder);
break;
case 2:
NativeAdViewHolder mHolder=(NativeAdViewHolder)holder;
// Setting the Text.
nativeAd.unregisterView();
mHolder.nativeAdCallToAction.setText(nativeAd.getAdCallToAction());
mHolder.nativeAdSocialContext.setText(nativeAd.getAdSocialContext());
mHolder.nativeAdTitle.setText(nativeAd.getAdTitle());
mHolder.nativeAdBody.setText(nativeAd.getAdBody());
// Downloading and setting the ad icon.
NativeAd.Image adIcon = nativeAd.getAdIcon();
NativeAd.downloadAndDisplayImage(adIcon, mHolder.nativeAdIcon);
// Download and setting the cover image.
NativeAd.Image adCoverImage = nativeAd.getAdCoverImage();
mHolder.nativeAdMedia.setNativeAd(nativeAd);
// Add adChoices icon
// if (adChoicesView == null)
if(! (mHolder.adview.getChildAt(0) instanceof AdChoicesView)){
AdChoicesView adChoicesView = new AdChoicesView(layoutInflater.getContext(), nativeAd, true);
mHolder.adview.addView(adChoicesView, 0);
}
nativeAd.registerViewForInteraction( mHolder.adview);
break;
default:
break;
}
if (position > previousPosition) {
comeagain.materialdesign.anim.AnimationUtils.animate(holder, true);
} else {
comeagain.materialdesign.anim.AnimationUtils.animate(holder, false);
}
previousPosition = position;
}
And next time use a debbuger to find stuff like this.