I am a noob in Android Development, and I was trying to build a custom sidebar today.
I used a view with 2 imageViews, and I was trying to inflate them multiple times with multiple icons, which I did using a custom class. Here is the view code:
Side_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:src="#drawable/icn"
android:layout_height="48dp"
android:tint="#afafaf"
android:id="#+id/menu_icon"
/>
<ImageView
android:layout_width="8dp"
android:layout_height="8dp"
android:id="#+id/menu_selector"
android:src="#drawable/selector"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>
Here is my custom class:
public class Item
{
private int icon, code;
private boolean isSelected;
public Item(int icon, int code)
{
this.icon = icon;
this.code = code;
}
public int getIcon()
{
return icon;
}
public void setIcon(int icon)
{
this.icon = icon;
}
public int getCode()
{
return code;
}
public void setCode(int code)
{
this.code = code;
}
public boolean isSelected()
{
return isSelected;
}
public void setSelected(boolean selected)
{
isSelected = selected;
}
public Item(int icon, int code, boolean isSelected)
{
this.icon = icon;
this.code = code;
this.isSelected = isSelected;
}
}
I used this code for assigning data to this class:
public class MenuUtils
{
public static final int HOME = 0, EDU = 1, CONTACT = 2, PROJECTS = 3;
public static List<Item> getList()
{
List<Item> list = new ArrayList<>();
list.add(new Item(R.drawable.icn1, HOME, true));
list.add(new Item(R.drawable.icn2, EDU, true));
list.add(new Item(R.drawable.icn3, CONTACT, true));
list.add(new Item(R.drawable.icn4, PROJECTS, true));
return list;
}
}
Here is the code for my adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>
{
List<Item> list;
public MyAdapter(List<Item> list)
{
this.list = list;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.side_bar, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position)
{
holder.icon.setImageResource(list.get(position).getIcon());
if (list.get(position).isSelected()) holder.selected.setVisibility(View.VISIBLE);
else holder.selected.setVisibility(View.INVISIBLE);
}
#Override
public int getItemCount()
{
Log.i("List Size", list.toString());
return list.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder
{
ImageView icon, selected;
public MyViewHolder(#NonNull View itemView)
{
super(itemView);
icon = (ImageView) itemView.findViewById(R.id.menu_icon);
selected = (ImageView) itemView.findViewById(R.id.menu_selector);
}
}
}
The method used for setting up the sidebar:
private void setMenu()
{
menu = findViewById(R.id.menu_holder);
List<Item> items = MenuUtils.getList();
MyAdapter adapter = new MyAdapter(items);
menu.setLayoutManager(new LinearLayoutManager(this));
menu.setAdapter(adapter);
}
On logging, I see that the list has 4 data items, but when inflated, only one appears.
Why so?
Please help.
I guess each item of recycle view is taking the entire screen that's why you can only see one item. Adjust the LinearLayout height and width, as-
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
......
</LinearLayout>
If you want the each item to take entire screen width use
android:layout_width="match_parent"
or vice-versa.
Happy coding !!!
Because you are using height as match_parent.
It should be wrap_content:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:src="#drawable/icn"
android:layout_height="48dp"
android:tint="#afafaf"
android:id="#+id/menu_icon"
/>
<ImageView
android:layout_width="8dp"
android:layout_height="8dp"
android:id="#+id/menu_selector"
android:src="#drawable/selector"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>
Because the first item expand full screen, therefore you can't see the others
You have to change your xml height from match_parent to wrap_content
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"> <!--change this line-->
<ImageView
android:layout_width="match_parent"
android:src="#drawable/icn"
android:layout_height="48dp"
android:tint="#afafaf"
android:id="#+id/menu_icon"
/>
<ImageView
android:layout_width="8dp"
android:layout_height="8dp"
android:id="#+id/menu_selector"
android:src="#drawable/selector"
android:layout_gravity="center_horizontal"
/>
</LinearLayout>
Related
I have 2 CardViews and a RecyclerView but i am
unable to align them vertically
unable to slide them independently (both slide if I slide any one in a bugged workaround)
I tried a few workarounds as well as different tutorials like edmt Dev and CodingWithMitch as well as searched for similar problems on stackoverflow but the problem seems to persist. So how do I align both of the cardviews vertically while still being able to slide each of them independently and horizontally.
(Code works fine for single card view)
Main Activity:
public class MainActivity extends AppCompatActivity {
List<Articles> articlesData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
articlesData = new ArrayList<>();
//Repeats
articlesData.add(new Articles("10 Necessary Gadgets","Gadgets","Gadgets You Must Carry",R.drawable.bagchaincustom));
articlesData.add(new Articles("10 Benefits of Pre-Planning the Day","Self Improvement","Benefits of Planning in Advance",R.drawable.planner1custom));
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL,false);
RecyclerView recyclerView = findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(layoutManager);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, articlesData);
recyclerView.setAdapter(adapter);
}
Here is activity_main.xml:
<?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"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recyclerview"
android:orientation="horizontal">
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>
Here is the RecyclerViewAdapter Class:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int LAYOUT_ONE= 0;
private static final int LAYOUT_TWO= 1;
#Override
public int getItemViewType(int position)
{
if(position == LAYOUT_ONE){
return LAYOUT_TWO;
}
else {
return LAYOUT_ONE;
}
}
private static final String Tag = "RecyclerViewAdapter";
private Context mContext;
private List<Articles> mData;
public RecyclerViewAdapter(Context mContext, List<Articles> mData) {
this.mContext = mContext;
this.mData = mData;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater mInflater = LayoutInflater.from(mContext);
View view;
switch (viewType) {
case 0:
ViewHolder1 viewHolder1;
view = mInflater.inflate(R.layout.layout_listitem, parent, false);
return new ViewHolder1(view);
case 1:
ViewHolder2 viewHolder2;
view = mInflater.inflate(R.layout.layout_listitem2, parent, false);
return new ViewHolder2(view);
default:
return null;
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, final int position) {
switch (holder.getItemViewType()){
case 0:
ViewHolder1 viewHolder1 = (ViewHolder1)holder;
viewHolder1.tv_article_title.setText(mData.get(position).getTitle());
viewHolder1.img_article_thumbnail.setImageResource(mData.get(position).getThumbnail());
viewHolder1.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mContext, ArticlesActivity.class);
intent.putExtra("Title", mData.get(position).getTitle());
intent.putExtra("Description", mData.get(position).getDescription());
intent.putExtra("Thumbnail", mData.get(position).getThumbnail());
intent.putExtra("Category", mData.get(position).getCategory());
mContext.startActivity(intent);
}
});
break;
case 1:
ViewHolder2 viewHolder2 = (ViewHolder2)holder;
viewHolder2.tv_article_title2.setText(mData.get(position).getTitle());
viewHolder2.img_article_thumbnail2.setImageResource(mData.get(position).getThumbnail());
viewHolder2.cardView2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mContext, ArticlesActivity.class);
intent.putExtra("Title", mData.get(position).getTitle());
intent.putExtra("Description", mData.get(position).getDescription());
intent.putExtra("Thumbnail", mData.get(position).getThumbnail());
intent.putExtra("Category", mData.get(position).getCategory());
mContext.startActivity(intent);
}
});
break;
}
}
#Override
public int getItemCount() {
return mData.size();
}
public class ViewHolder1 extends RecyclerView.ViewHolder{
TextView tv_article_title;
ImageView img_article_thumbnail;
CardView cardView;
public ViewHolder1(#NonNull View itemView) {
super(itemView);
tv_article_title = (TextView) itemView.findViewById(R.id.article_title_id);
img_article_thumbnail = (ImageView) itemView.findViewById((R.id.article_image_id));
cardView = (CardView) itemView.findViewById(R.id.cardview_id);
}
}
public class ViewHolder2 extends RecyclerView.ViewHolder{
TextView tv_article_title2;
ImageView img_article_thumbnail2;
CardView cardView2;
public ViewHolder2(#NonNull View itemView) {
super(itemView);
tv_article_title2 = (TextView) itemView.findViewById(R.id.article_title_id2);
img_article_thumbnail2 = (ImageView) itemView.findViewById((R.id.article_image_id2));
cardView2 = (CardView) itemView.findViewById(R.id.cardview_id2);
}
}
}
Here is the Articles Class:
public class Articles {
private String Title;
private String Category;
private String Description;
private int Thumbnail;
public Articles(String title, String category, String description, int thumbnail) {
Title = title;
Category = category;
Description = description;
Thumbnail = thumbnail;
}
public String getTitle() {
return Title;
}
public String getCategory() {
return Category;
}
public String getDescription() {
return Description;
}
public int getThumbnail() {
return Thumbnail;
}
And here is the CardView -> layout_listitem Layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:layout_alignParentStart="true"
android:id="#+id/rview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:id="#+id/cardview_id"
android:layout_width="120dp"
android:layout_height="220dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="0dp"
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical">
<ImageView
android:id="#+id/article_image_id"
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="#2d2d2d"
android:scaleType="centerCrop"></ImageView>
<TextView
android:id="#+id/article_title_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:text="Article Name"
android:textSize="14sp">
</TextView>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
And here is the CardView -> layout_listitem2 Layout:
<?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:card_view="http://schemas.android.com/tools"
android:layout_alignParentStart="true"
android:id="#+id/rview2"
android:layout_below="#+id/rview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="300dp">
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:id="#+id/cardview_id2"
android:layout_below="#id/cardview_id"
android:layout_width="120dp"
android:layout_height="220dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="0dp"
app:cardElevation="0dp">
<LinearLayout
android:layout_marginTop="250dp"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical">
<ImageView
android:id="#+id/article_image_id2"
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="#2d2d2d"
android:scaleType="centerCrop"></ImageView>
<TextView
android:id="#+id/article_title_id2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:text="Article Name Sec"
android:textSize="14sp">
</TextView>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
ConstraintLayout is not a scrolling parent, so it will create problem if you add a long RecyclerView inside it.
So I made a few modifications to the above code and it has solved the both problems (Independent sliding and vertical alignment)
I have added another recyclerview in main_activity.xml
<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"
tools:context=".MainActivity"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</androidx.recyclerview.widget.RecyclerView>
<androidx.recyclerview.widget.RecyclerView
android:layout_below="#+id/recyclerview_id2"
android:layout_marginTop="10dp"
android:id="#+id/recyclerview_id2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="NotSibling">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
I have also created another Adapter for the new recyclerview, seperated classes for both viewholders as well as removed the switch statements and itemViewType from RecyclerViewAdapter and RecyclerViewAdapter2 class :
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
LayoutInflater mInflater = LayoutInflater.from(mContext);
view = mInflater.inflate(R.layout.layout_listitem2,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, final int position) {
holder.tv_article_title2.setText(mData.get(position).getTitle());
holder.img_article_thumbnail2.setImageResource(mData.get(position).getThumbnail());
holder.cardView2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mContext,ArticlesActivity.class);
intent.putExtra("Title",mData.get(position).getTitle());
intent.putExtra("Description",mData.get(position).getDescription());
intent.putExtra("Thumbnail",mData.get(position).getThumbnail());
intent.putExtra("Category",mData.get(position).getCategory());
mContext.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return mData.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
TextView tv_article_title2;
ImageView img_article_thumbnail2;
CardView cardView2;
public ViewHolder(#NonNull View itemView) {
super(itemView);
tv_article_title2 = (TextView) itemView.findViewById(R.id.article_title_id2);
img_article_thumbnail2 = (ImageView) itemView.findViewById((R.id.article_image_id2));
cardView2 = (CardView) itemView.findViewById(R.id.cardview_id2);
}
}
I also edited the main_acitivty class by adding the new recyclerview and layout manager at the end:
LinearLayoutManager layoutManager2 = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL,false);
RecyclerView recyclerView2 = findViewById(R.id.recyclerview_id2);
recyclerView2.setLayoutManager(layoutManager2);
RecyclerViewAdapter2 adapter2 = new RecyclerViewAdapter2(this, articlesData);
recyclerView2.setAdapter(adapter2);
Even though this workaround fixes both problems i was facing is there any other better/more refined way of doing this (eg by using single recyclerview) and where did i made the mistake in previous approach?
I want to build a complex layout using recyclerview android. In the layout, I want to have a camera button to the top left fixed and a recyclerview wrapped around it with gallery images. I have checked flexbox layout manager for recyclerview but it doesn't seem to match my use-case.
I want the header to be non-repeating and not to scroll with other items vertically. Here's the layout for the header:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/shareLayout"
android:layout_width="185dp"
android:layout_height="135dp"
android:layout_below="#id/trendingToolbar"
android:background="#color/black">
<ImageView
android:id="#+id/cameraShareIV"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
app:srcCompat="#drawable/camera_white" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/cameraShareIV"
android:layout_centerHorizontal="true">
<TextView
android:id="#+id/infoTxt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginLeft="20dp"
android:gravity="center_horizontal"
android:text="#string/share_pic_video"
android:textColor="#android:color/white"
android:textSize="13sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/infoTxt"
android:layout_marginLeft="16dp"
android:text="#string/share_timeout_txt"
android:textColor="#color/colorPrimaryDark"
android:textSize="11sp"
android:textStyle="bold" />
</RelativeLayout>
and in my activity, here's the XML:
<RelativeLayout 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"
tools:context="base.android.com.thumbsapp.UI.Fragments.TrendingFragment">
<include layout="#layout/trending_toolbar"
android:id="#+id/trendingToolbar"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/trendingRV"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/trendingToolbar"/>
Previously, I had the header inside the activity XML but had no way to wrap a recyclerview around it. So, I have decide to use an adapter like below:
public class TrendingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = TrendingAdapter.class.getSimpleName();
private Context context;
private List<Trending> itemList;
private static final int HEADER = 0;
private static final int ITEMS = 1;
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
switch (viewType){
case HEADER:
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.trending_header, parent, false);
return new TrendingHeaderViewHolder(v);
case ITEMS:
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.trending_items_layout, parent, false);
return new TrendingItemsViewHolder(v);
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Trending tr = itemList.get(position);
if (holder instanceof TrendingHeaderViewHolder){
((TrendingHeaderViewHolder) holder).cameraShareIV.setOnClickListener( view -> {
// TODO: 4/2/2018 select image from gallery
});
} else if (holder instanceof TrendingItemsViewHolder){
// TODO: 4/2/2018 populate gallery items here with picasso
}
}
#Override
public int getItemCount() {
return itemList.size();
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
}
I'm confused how to make the header stick and also what to do for getItemViewType method.
Is this the right way to approach this?
Can anyone help out? Thanks.
For this lay out i suggest better option is use this header view
https://github.com/edubarr/header-decor
To make things simple i suggest you to look into this library
In your XML Place RecylerView into StickyHeaderView,choose horizontal or vertical orientation for your RecylerView
<tellh.com.stickyheaderview_rv.StickyHeaderView
android:id="#+id/stickyHeaderView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:scrollbars="vertical" />
</tellh.com.stickyheaderview_rv.StickyHeaderView>
Create data bean class for each item type in RecyclerView. They should extend DataBean. Override the method
public boolean shouldSticky() to decide whether the item view should be suspended on the top.
public class User extends DataBean {
private String login;
private int id;
private String avatar_url;
private boolean shouldSticky;
#Override
public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
return R.layout.item_user;
}
public void setShouldSticky(boolean shouldSticky) {
this.shouldSticky = shouldSticky;
}
// Decide whether the item view should be suspended on the top.
#Override
public boolean shouldSticky() {
return shouldSticky;
}
}
public class ItemHeader extends DataBean {
private String prefix;
#Override
public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
return R.layout.header;
}
#Override
public boolean shouldSticky() {
return true;
}
}
Create ViewBinder to bind different type views with specific data beans. As you see, provideViewHolder(View itemView) corresponds for onCreateViewHolder in RecyclerView, and bindView corresponds for onBindViewHolder in RecyclerView.
public class ItemHeaderViewBinder extends ViewBinder<ItemHeader, ItemHeaderViewBinder.ViewHolder> {
#Override
public ViewHolder provideViewHolder(View itemView) {
return new ViewHolder(itemView);
}
#Override
public void bindView(StickyHeaderViewAdapter adapter, ViewHolder holder, int position, ItemHeader entity) {
holder.tvPrefix.setText(entity.getPrefix());
}
#Override
public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
return R.layout.header;
}
static class ViewHolder extends ViewBinder.ViewHolder {
TextView tvPrefix;
public ViewHolder(View rootView) {
super(rootView);
this.tvPrefix = (TextView) rootView.findViewById(R.id.tv_prefix);
}
}
}
Instantiate StickyHeaderViewAdapter for RecyclerView and register ViewBinders for each item types.
rv = (RecyclerView) findViewById(R.id.recyclerView);
rv.setLayoutManager(new LinearLayoutManager(this));
List<DataBean> userList = new ArrayList<>();
adapter = new StickyHeaderViewAdapter(userList)
.RegisterItemType(new UserItemViewBinder())
.RegisterItemType(new ItemHeaderViewBinder());
rv.setAdapter(adapter);
I am trying to add images in a cardview from drawable and text one by one using a recyclerview. say there are 10 images in my drawable i want to use only 5 of them. So how to do that ?
here is my cardview :
<?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"
android:id="#+id/placeCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
card_view:cardCornerRadius="#dimen/card_corner_radius">
<ImageView
android:id="#+id/placeImage"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop" />
<!-- Used for the ripple effect on touch -->
<LinearLayout
android:id="#+id/mainHolder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:selectableItemBackground"
android:orientation="horizontal" />
<LinearLayout
android:id="#+id/placeNameHolder"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_gravity="bottom"
android:orientation="horizontal">
<TextView
android:id="#+id/placeName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="left"
android:paddingLeft="10dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#android:color/white" />
</LinearLayout>
</android.support.v7.widget.CardView>
here is my recyclerview adapter :
public class SubPlaceAdapter extends RecyclerView.Adapter<SubPlaceRecyclerViewHolder>{
String ImageUri;
#Override
public SubPlaceRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_places, null);
SubPlaceRecyclerViewHolder viewHolder = new SubPlaceRecyclerViewHolder(view);
}
#Override
public void onBindViewHolder(SubPlaceRecyclerViewHolder holder, int position) {
// holder.subPlaceImage
}
#Override
public int getItemCount() {
return 0;
}
}
my view holder :
public class SubPlaceRecyclerViewHolder extends RecyclerView.ViewHolder {
protected ImageView subPlaceImage;
protected TextView subPlaceTitle;
public SubPlaceRecyclerViewHolder(View view) {
super(view);
this.subPlaceImage = (ImageView) view.findViewById(R.id.placeImage);
this.subPlaceTitle = (TextView) view.findViewById(R.id.placeName);
}
}
thanks for the help :)
Step 1. First create a Model
public class ImageModel {
int imageId;
String aboutText;
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
public String getAboutText() {
return aboutText;
}
public void setAboutText(String aboutText) {
this.aboutText = aboutText;
}
}
Step 2. Create a method which return arraylist of imageModel in your fragment/activity from where you set the adapter
private ArrayList<ImageModel> setImageData(){
ArrayList<ImageModel> projectList=new ArrayList<>();
ImageModel imageModel=new ImageModel();
imageModel.setImageId(R.mipmap.ic_star_fill);
imageModel.setAboutText("RandomText");
projectList.add(imageModel);
ImageModel imageModel1=new ProjectModel();
projectModel.setImageId(R.mipmap.ic_star_fill);
projectModel.setAboutText("RandomText");
projectList.add(projectModel);
return projectList;
}
Step 3. Create constructor in your adapter which takes ArrayList as an argument
public SubPlaceAdapter(ArrayList<ImageModel> mImageList) {
this.mActivity = mActivity;
this.mImageList = mImageList);
}
Step 4. Set your adapter in your fragment/ activity.
mSubPlaceAdapter = new SubPlaceAdapter(setImageData());
Step 5. Set your item in on BindView Holder
#Override
public void onBindViewHolder(SubPlaceRecyclerViewHolder holder, int position) {
ImageModel imageModel= mImageList.get(position)
holder.subPlaceImage.setImageResource(imageModel.getImageId());
}
#Override
public int getItemCount() {
return mImageList.size();
}
This code will give you the idea how to do it.Fill free to modify this answer.
I am trying a heterogeneous Recycler view, following this tutorial. Heterogeneous Layouts All is working fine expect for the part where i scroll the Recycler view, the layouts aren't displayed properly. I have 2 layouts, one has text and other has images, on scrolling I am left with alot of blank space in the text section,giving a feel to the viewer that there was some image previously here.
I have checked links online but nothing solved the issue.Your help is needed and appreciated.
Here is my code
ComplexRecyclerViewAdapter
public class ComplexRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Object> items;
private final int STATUS = 0, IMAGE_STATUS = 1;
public ComplexRecyclerViewAdapter(List<Object> items) {
this.items = items;
}
#Override
public int getItemCount() {
return this.items.size();
}
#Override
public int getItemViewType(int position) {
if (items.get(position) instanceof ArrayFeedItem) {
return STATUS;
} else if (items.get(position) instanceof ArrayFeedItemWithImage) {
return IMAGE_STATUS;
}
return -1;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
RecyclerView.ViewHolder viewHolder;
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
if (viewType == STATUS){
View v1 = inflater.inflate(R.layout.layout_viewholder1, viewGroup, false);
viewHolder = new ViewHolder1(v1);
}
else if(viewType ==IMAGE_STATUS){
View v2 = inflater.inflate(R.layout.layout_viewholder2, viewGroup, false);
viewHolder = new ViewHolder2(v2);
}
else
viewHolder=null;
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
if (viewHolder.getItemViewType() == STATUS )
{
ViewHolder1 vh1 = (ViewHolder1) viewHolder;
configureViewHolder1(vh1, position);
vh1.setIsRecyclable(false);
}
else
{
ViewHolder2 vh2 = (ViewHolder2) viewHolder;
configureViewHolder2(vh2, position);
vh2.setIsRecyclable(false);
}
}
private void configureViewHolder1(ViewHolder1 vh1, int position) {
ArrayFeedItem item = (ArrayFeedItem) items.get(position);
if (item != null) {
vh1.getHolderImage().setImageResource(item.img);
vh1.getHolderText().setText(item.txtname);
vh1.getStatusMsg().setText(item.StatusMsg);
vh1.getTimestamp().setText(item.Timestamp);
vh1.getUrl().setText(item.URL);
}
}
private void configureViewHolder2(ViewHolder2 vh2, int position) {
ArrayFeedItemWithImage item = (ArrayFeedItemWithImage) items.get(position);
if (item != null) {
vh2.getHolderImage().setImageResource(item.img);
vh2.getHolderText().setText(item.txtname);
vh2.getStatusMsg().setText(item.StatusMsg);
vh2.getTimestamp().setText(item.Timestamp);
vh2.getUrl().setText(item.URL);
vh2.getFeedImage().setImageResource(item.feedImage1);
}
}
}
This is how I am binding the adapter to the recycle view.
Home Activity
list=(RecyclerView) findViewById(R.id.list);
adapter =new ComplexRecyclerViewAdapter(items);
list.setNestedScrollingEnabled(false);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
list.setLayoutManager(mLayoutManager);
list.setItemAnimator(new DefaultItemAnimator());
list.setAdapter(adapter);
ViewHolder1
public class ViewHolder1 extends RecyclerView.ViewHolder {
private ImageView Image;
private TextView Text,Timestamp,StatusMsg,Url;
public ViewHolder1(View itemView) {
super(itemView);
Image=(ImageView) itemView.findViewById(R.id.img);
Text=(TextView)itemView.findViewById(R.id.txt);
Timestamp=(TextView)itemView.findViewById(R.id.timestamp);
StatusMsg=(TextView)itemView.findViewById(R.id.txtStatusMsg);
Url=(TextView)itemView.findViewById(R.id.txtUrl);
}
public ImageView getHolderImage() {
return Image;
}
public void setHolderImage(ImageView image) {
this.Image = image;
}
public TextView getHolderText() {
return Text;
}
public void setHolderText(TextView text) {
this.Text = text;
}
public TextView getTimestamp() {
return Timestamp;
}
public void setTimestamp(TextView timestamp) {
this.Timestamp = timestamp;
}
public TextView getStatusMsg() {
return StatusMsg;
}
public void setStatusMsg(TextView statusmsg) {
this.StatusMsg = statusmsg;
}
public TextView getUrl() {
return Url;
}
public void setUrl(TextView url) {
this.Url = url;
}
}
layout_viewholder1
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/feed_bg"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="#dimen/feed_item_margin"
android:layout_marginRight="#dimen/feed_item_margin"
android:layout_marginTop="#dimen/feed_item_margin"
android:background="#drawable/bg_parent_rounded_corner"
android:orientation="vertical"
android:paddingBottom="#dimen/feed_item_padding_top_bottom"
android:paddingTop="#dimen/feed_item_padding_top_bottom"
android:id="#+id/layout1"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="#dimen/feed_item_padding_left_right"
android:paddingRight="#dimen/feed_item_padding_left_right" >
<ImageView
android:id="#+id/img"
android:layout_width="#dimen/feed_item_profile_pic"
android:layout_height="#dimen/feed_item_profile_pic"
android:scaleType="fitCenter" >
</ImageView>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="#dimen/feed_item_profile_info_padd" >
<TextView
android:id="#+id/txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/feed_item_profile_name"
android:textStyle="bold"
android:textColor="#color/black"/>
<TextView
android:id="#+id/timestamp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#color/timestamp"
android:textSize="#dimen/feed_item_timestamp"
/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="#+id/txtStatusMsg"
android:textColor="#color/black"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:paddingLeft="#dimen/feed_item_status_pad_left_right"
android:paddingRight="#dimen/feed_item_status_pad_left_right"
android:paddingTop="#dimen/feed_item_status_pad_top" />
<TextView
android:id="#+id/txtUrl"
android:textColor="#color/black"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:linksClickable="true"
android:paddingBottom="10dp"
android:paddingLeft="#dimen/feed_item_status_pad_left_right"
android:paddingRight="#dimen/feed_item_status_pad_left_right"
android:textColorLink="#color/link" />
</LinearLayout>
</LinearLayout>
Thanks in advance.
I have faced this issue and realised that in my case I was toggling view visibility inside
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {}
So what was happening is due to bad code on my part sometimes some of the views were getting completely hidden and hence were not getting removed or recylcled. This caused the randomness in the view. So if you have some code that changes the view visibility then remove that and test if the issue is still there.
pay attention to this point please!
if your app need remove item for any reason and you want to see removed item process in recyclerview so setISRecyclable to false is not good ,check it! so for every body wants to add this to adapter except(those that dont want to recycle some item for any reason) i have message:
please consider this point that in your adapter in onBindViewHolder for cases that need kind of toggle stuff Every call to onBindViewHolder must include either a load() call or a clear() call.
for example if you check the Boolean or 0-1 for setting some part of your RecyclerView item layout to gone or visible you should consider both of them in your If-Statement Block.
for example in this question i cant see else block inside configureViewHolder2 and 1 so messed up items happen maybe.
tnx to read patient reader
I want to create a list of items that have a background image and a TextView. Although it creates the RecyclerView normally and sets the text, the background image doesn't set.
This is my Adapter Class
public class Casino_Adapter extends RecyclerView.Adapter<Casino_Adapter.ViewHolder> {
private Data[] mDataset;
private ClickListener clickListener;
public Context context;
// Provide a suitable constructor (depends on the kind of dataset)
public Casino_Adapter(Data[] myDataset) {
this.mDataset = myDataset;
this.context = context;
}
#Override
public Casino_Adapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.casino_card_row, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private final Context context = null;
// each data item is just a string in this case
public TextView mTextView;
public ImageView mImageView;
public CardView cardView;
//Typeface tf;
public ViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.text);
mImageView = (ImageView) v.findViewById(R.id.image);
cardView = (CardView) v.findViewById(R.id.card_view);
//cardView.setPreventCornerOverlap(false);
}
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mTextView.setText(mDataset[position].getText());
holder.mImageView.setImageResource(mDataset[position].getImage());
}
public void setClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.length;
}
public interface ClickListener {
public void itemClicked(View view, int pos);
}
}
I have a Fragment Class where I want the RecyclerView to be.
public class CasinoFragment extends Fragment {
protected RecyclerView recyclerView;
protected RecyclerView.Adapter mAdapter;
protected RecyclerView.LayoutManager mLayoutManager;
public CasinoFragment() {
// Required empty public constructor
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initial();
}
private void initial() {
final Data datas[] =
{
new Data("This is an item", R.drawable.ic_home_white_36dp),
new Data("This is an item 2", R.drawable.car),
new Data("asdasd`sdads", R.drawable.car),
new Data("This is an item 3", R.drawable.car)
};
mAdapter = new Casino_Adapter(datas);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_casino, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.my_recycler_view);
mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(mAdapter);
return view;
}
}
And these are the Setters that I use.
public class Data {
int image;
String text;
public Data(String title, int backimage)
{
this.text = title;
this.image = backimage;
}
public String getText()
{
return text;
}
public int getImage()
{
return image;
}
public void setText()
{
this.text=text;
}
public void setImageID()
{
this.image = image;
}
}
Casino Row XML
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="8dp"
android:layout_margin="5dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#111111"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="#+id/image"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:background="#drawable/image_round"
android:src="#drawable/car" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignBottom="#+id/image"
android:id="#+id/rel_color"
android:background="#4c4c4c">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Μπύρα"
android:textColor="#fcfcfc"
android:textSize="30sp"
android:shadowColor="#000000"
android:shadowDx="3"
android:shadowDy="3"
android:shadowRadius="5"
android:id="#+id/text"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
The result I get is the following.
The reason why you aren't seeing your image, is because it isn't actually visible.
Your rel_color layout has the same size attributes as your ImageView.
If you want to display a layout above the ImageView, you just need to remove the background of it, otherwise the ImageView will be hidden.
Just Like that. but remember your images dimensions must be low. in my case i used 200x200
<?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"
android:id="#+id/rl_menu_item"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_margin="5dp"
android:background="#android:color/transparent"
card_view:cardCornerRadius="4dp"
card_view:cardUseCompatPadding="true">
<RelativeLayout
android:id="#+id/img_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg_blrr">
<ImageView
android:id="#+id/iv_icon"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_centerHorizontal="true"
android:layout_centerInParent="true"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"
android:background="#drawable/gray_circle"
android:padding="15dp"
android:scaleType="centerCrop"
android:src="#drawable/school" />
<TextView
android:id="#+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="#id/iv_icon"
android:layout_alignLeft="#id/iv_icon"
android:layout_alignRight="#id/iv_icon"
android:layout_alignStart="#id/iv_icon"
android:layout_below="#id/iv_icon"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:text="Your Favourite Place"
android:textColor="#android:color/black" />
</RelativeLayout>
</android.support.v7.widget.CardView>