I am facing an issue in multiple view type recycler view i think the code in myadapter is lacking something which i am not able to figure out pls help. Here is the detailed description :
I have a response list from retrofit :
public class DateResponse {
#SerializedName("RecordEntryON")
#Expose
private String record_EntryOn;
#SerializedName("PatientID")
#Expose
private int Patient_ID;
#SerializedName("DiscountedAmount")
#Expose
private double discounted_Amount;
#SerializedName("ClientID")
#Expose
private int client_ID;
#SerializedName("TestType")
#Expose
private String test_Type;
#SerializedName("TestName")
#Expose
private String test_Name;
#SerializedName("FetchingTime")
#Expose
String fetching_Time;
#SerializedName("ClientTestCount")
#Expose
int clienttest_Count;
#SerializedName("CentreName")
#Expose
String center_Name;
getter and setter to follow (not writing here). I have another request model which i am passing into retrofit request here is the code for request model :
public class Date_Request {
#SerializedName("IsSuccess")
boolean is_success;
#SerializedName("Message")
String _message;
#SerializedName("ResponseData")
List<DateResponse> response_data;
code for retrofit in MyActivity :
authToken = "Basic " + Utils.getAuthToken(Dashboard.this);
restClient.getService().getByCentre(authToken, DEV_ID,defaultDate).enqueue(new
Callback<Date_Request>() {
#Override
public void onResponse(Call<Date_Request> call, Response<Date_Request> response) {
// List<DateResponse> listAll;
if (response.isSuccessful())
try {
boolean success = response.body().isIs_success();
String message = response.body().get_message();
if (success) {
listAll = response.body().getResponse_data();
List<DateResponse> centerList = new ArrayList<>();
int i;
for(i=0;i<5;i++){
String centerName = listAll.get(i).getCenter_Name();
int patientCount = listAll.get(i).getPatient_ID();
double amount = listAll.get(i).getDiscounted_Amount();
DateResponse topList = new DateResponse();
topList.setPatient_ID(patientCount);
topList.setDiscounted_Amount(amount);
centerList.add(topList);
dateViewAdapter = new DateViewAdapter(centerList, Dashboard.this);
recyclerView.setAdapter(dateViewAdapter);
dateViewAdapter.notifyDataSetChanged();
}
Procedure : I am selecting an option from Spinner there are three options: center,date,test. On select, a calendar opens user select the date and the corresponding list is shown. APIs for all three options are different with little different data. However, in model i am using only one response model and one request.
Now the issue is if I am running this code than no of item matches the for loop ie 5(or whatever i set here 10 15) and displayed in list if i remove the for loop and directly add the list wo setting getting anything here in activity than i still get list with 10 items as I fixed the list to show 10 items only using getItemCount method in adapter
whatever I use center name is not showing(blank) + TextView hardcoded text of xml layout is not showing + I am unable to concatenate anything before center name.
The data--amount and patientCount is showing but no hardcoded text or cant concatenate anything with these fields
In the test or date list in the same recycler view test name is showing but not test type(blank) instead it is showing patient count in test list and date list also
In centre list:
centre name not showing
Patient Count and Amount showing but hardcoded text in textview missing in addition cant concatenate string Patient Count
In test list:
test name and amount is showing
test type is not showing instead patient count is showing
In date list:
same as test list
Code for adapter :
public class DateViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<DateResponse> listAll;
private final int limit = 10;
private Context mContext;
private static final int CENTER_LIST = 0;
private static final int TEST_LIST = 1;
private static final int DATE_LIST = 2;
private static final int TYPE_DEFAULT = 3;
public DateViewAdapter(List<DateResponse> listAll, Context mContext) {
this.listAll = listAll;
this.mContext = mContext;
}
public void addAllItems(List<DateResponse> items) {
listAll.addAll(items);
notifyDataSetChanged();
}
//override getItemViewType method to assign the layout to each item depending on the viewtype passed
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
// view = LayoutInflater.from(parent.getContext()).inflate(R.layout.center_list, parent, false);
// return new DetailsViewHolder(view);
switch (viewType) {
case CENTER_LIST:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.center_list, parent, false);
return new CenterViewHolder(view);
case TEST_LIST:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.test_list, parent, false);
return new TestViewHolder(view);
case DATE_LIST:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.date_list, parent, false);
return new DateListViewHolder(view);
default:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.default_view, parent, false);
return new DefaultViewHolder(view);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
if (listAll.get(position).toString().contains("CentreName")) {
CenterViewHolder centerViewHolder = (CenterViewHolder) holder;
centerViewHolder.setDetails(listAll.get(position));
} else if (listAll.get(position).toString().contains("TestName")) {
TestViewHolder testViewHolder = (TestViewHolder) holder;
testViewHolder.setTestDetails(listAll.get(position));
} else if (listAll.get(position).toString().contains("Date")) {
DateListViewHolder dateListViewHolder = (DateListViewHolder) holder;
dateListViewHolder.setDateListDetails(listAll.get(position));
} else if (listAll.get(position).toString().contains("PatientID")) {
DefaultViewHolder defaultViewHolder = (DefaultViewHolder) holder;
defaultViewHolder.setDefaultDetails(listAll.get(position));
// throw new RuntimeException("problem in logic");
} else {
throw new RuntimeException("problem in logic");
}
}
public int getItemViewType(int position) {
DateResponse dateResponse = new DateResponse();
dateResponse = listAll.get(position);
if(listAll.get(position).toString().contains("CentreName"))
{
return CENTER_LIST;
} else if (listAll.get(position).toString().contains("TestName")) {
return TEST_LIST;
} else if (listAll.get(position).toString().contains("Date")) {
return DATE_LIST;
} else if (listAll.get(position).toString().contains("PatientID")) return TYPE_DEFAULT;
return position;
}
#Override
public int getItemCount() {
if (listAll.size() > limit) {
return limit;
} else {
return listAll.size();
}
}
class CenterViewHolder extends RecyclerView.ViewHolder {
private TextView tvCenterName, tvPatientCount, tvAmount;
public CenterViewHolder(#NonNull View itemView) {
super(itemView);
tvCenterName = itemView.findViewById(R.id.cn_name);
tvPatientCount = itemView.findViewById(R.id.pt_count);
tvAmount = itemView.findViewById(R.id.amount);
}
void setDetails(DateResponse centerDetails) {
tvCenterName.setText("Centre Name : " + centerDetails.getCenter_Name());
tvPatientCount.setText("Patient Count : " + centerDetails.getPatient_ID());
tvAmount.setText("Amount : " + centerDetails.getDiscounted_Amount());
}
}
class TestViewHolder extends RecyclerView.ViewHolder {
private TextView tvTestName, tvTestType, tvTestAmount;
public TestViewHolder(#NonNull View itemView) {
super(itemView);
tvTestAmount = itemView.findViewById(R.id.test_amount);
tvTestName = itemView.findViewById(R.id.test_name);
tvTestType = itemView.findViewById(R.id.test_type);
}
void setTestDetails(DateResponse testDetails) {
tvTestType.setText("Test Name : " + testDetails.getTest_Type());
tvTestName.setText(testDetails.getTest_Name());
tvTestAmount.setText(String.valueOf(testDetails.getDiscounted_Amount()));
}
}
class DateListViewHolder extends RecyclerView.ViewHolder {
private TextView tvClientCount, tvPatCount, tvDateAmount;
public DateListViewHolder(#NonNull View itemView) {
super(itemView);
tvClientCount = itemView.findViewById(R.id.client_name);
tvPatCount = itemView.findViewById(R.id.patient_count);
tvDateAmount = itemView.findViewById(R.id.date_test_amount);
}
void setDateListDetails(DateResponse dateListDetails) {
tvDateAmount.setText(String.valueOf(dateListDetails.getDiscounted_Amount()));
tvPatCount.setText(String.valueOf(dateListDetails.getPatient_ID()));
tvClientCount.setText(dateListDetails.getTest_Name());
}
}
class DefaultViewHolder extends RecyclerView.ViewHolder {
private TextView tvdefaultCenter, tvdefaultCount, tvdefaultAmount;
public DefaultViewHolder(#NonNull View itemView) {
super(itemView);
tvdefaultCenter = itemView.findViewById(R.id.default_center);
tvdefaultCount = itemView.findViewById(R.id.default_pt_count);
tvdefaultAmount = itemView.findViewById(R.id.default_amount);
}
void setDefaultDetails(DateResponse defaultDetails) {
tvdefaultCenter.setText(defaultDetails.getCenter_Name());
tvdefaultCount.setText(String.valueOf(defaultDetails.getPatient_ID()));
tvdefaultAmount.setText(String.valueOf(defaultDetails.getDiscounted_Amount()));
}
}
}
layout for centre_list view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/parent_linear"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:id="#+id/parent_matrix"
app:cardCornerRadius="3dp"
app:cardElevation="2dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/cp_info"
android:layout_width="wrap_content"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:id="#+id/cn_name"
android:padding="1dp"
android:layout_marginStart="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="Centre Name : "
android:textColor="#color/purple_200">
</TextView>
<TextView
android:padding="1dp"
android:text="Patient Count : "
android:id="#+id/pt_count"
android:textColor="#color/black"
android:layout_marginStart="5dp"
android:paddingBottom="1dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentEnd="true">
<TextView
android:id="#+id/amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="#dimen/text_margin"
android:layout_marginEnd="25dp"
android:padding="2dp"
android:text="Amount"
android:textColor="#color/black"
android:textStyle="bold" />
</LinearLayout>
</RelativeLayout>
</androidx.cardview.widget.CardView>
Related
I am trying to have 2 layout in one RecyclerView
I have a recycler view list which is called Bookmark and it is parsed from an xml and this is all working , but I wanna in this recyclerview to put another layout which contains a button and that can be clickable.
Like in the photo the icons are from recyclerview and the plus button need to be compatible with the list, if the list is larger or smaller the button will be compatible with the space of list.
This is my new code for the Adapter which depends on the answer #LluisFelisart
And this is the error
ViewHolder views must not be attached when created. Ensure that you are not passing 'true' to the attachToRoot parameter of LayoutInflater.inflate(..., boolean attachToRoot)
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
ArrayList<Bookmark> arrayList = new ArrayList<>();
public MyAdapter(Context context, ArrayList<Bookmark> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
public class ViewHolder0 extends RecyclerView.ViewHolder {
TextView tvName,tvId,tvSearchUrl,tvNativeUrl;
ImageView tvIcon;
public ViewHolder0(#NonNull View itemView) {
super(itemView);
tvName=itemView.findViewById(R.id.textView);
tvIcon = itemView.findViewById(R.id.image_view);
/* tvId=itemView.findViewById(R.id.tvId);
tvSearchUrl=itemView.findViewById(R.id.tvSearchUrl);
tvNativeUrl=itemView.findViewById(R.id.tvNativeUrl);*/
}
}
public class ViewHolder2 extends RecyclerView.ViewHolder {
ImageView tvAddBookmark;
public ViewHolder2(#NonNull View itemView) {
super(itemView);
tvAddBookmark = itemView.findViewById(R.id.image_button_add);
}
}
#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;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.grid_item, viewGroup, false);
switch (i) {
case 0: return new ViewHolder0(viewGroup);
case 2: return new ViewHolder2(viewGroup);
}
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case 0:
ViewHolder0 viewHolder0 = (ViewHolder0) holder;
((ViewHolder0) holder).tvName.setText(arrayList.get(position).getName());
((ViewHolder0) holder).tvIcon.setImageResource(arrayList.get(position).getIcon());
break;
case 2:
ViewHolder2 viewHolder2 = (ViewHolder2) holder;
}
((ViewHolder0) holder).tvIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent;
intent = new Intent(context, BookmarkActivity.class);
v.getContext().startActivity(intent);
}
});
((ViewHolder0) holder).tvIcon.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Intent intent = new Intent(context, ActivityBookmarksFavorites.class);
v.getContext().startActivity(intent);
return false;
}
});
}
#Override
public int getItemCount() {
return arrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tvName,tvId,tvSearchUrl,tvNativeUrl;
ImageView tvIcon;
public ViewHolder(#NonNull View itemView) {
super(itemView);
tvName=itemView.findViewById(R.id.textView);
tvIcon = itemView.findViewById(R.id.image_view);
/* tvId=itemView.findViewById(R.id.tvId);
tvSearchUrl=itemView.findViewById(R.id.tvSearchUrl);
tvNativeUrl=itemView.findViewById(R.id.tvNativeUrl);*/
}
}
}
This is the grid item layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:orientation="vertical"
android:visibility="visible"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="#+id/image_view"
style="#style/BookmarkIconIv" />
<TextView android:id="#+id/textView"
android:layout_marginTop="1.0dip"
style="#style/BookmarkTextTv" />
</LinearLayout>
This is the layout of button which I want to be in the recycler view
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="#+id/image_button_add"
android:layout_width="45dp"
android:layout_height="45dp"
android:src="#drawable/ic_add_black_24dp"
android:background="#color/transparent" />
</android.support.constraint.ConstraintLayout>
This is the Fragment which the recycler view it is shown
public class FragmentBookmark extends Fragment {
ArrayList<Bookmark> arrayList = new ArrayList<>();
XmlPullParser pullParser;
MyAdapter myAdapter;
View paramView;
RecyclerView myRecyclerView;
private Context mContext;
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
}
#Nullable
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
paramView = inflater.inflate(R.layout.bookmark, container, false);
myRecyclerView = paramView.findViewById(R.id.myRecyclerView);
myRecyclerView.setLayoutManager(new GridLayoutManager(mContext, 4));
myRecyclerView.setHasFixedSize(true);
myAdapter = new MyAdapter(mContext, arrayList);
myRecyclerView.setAdapter(myAdapter);
try {
XmlPullParser xpp = getResources().getXml(R.xml.bookmarks);
while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
if (xpp.getEventType() == XmlPullParser.START_TAG) {
if (xpp.getName().equals("Bookmark")) {
Bookmark bookmark = new Bookmark();
bookmark.setName(xpp.getAttributeValue(null, "name"));
int drawableResourceId = getResources().getIdentifier(xpp.getAttributeValue(null, "icon"),"drawable", mContext.getPackageName());
bookmark.setIcon(drawableResourceId);
arrayList.add(bookmark);
}
}
xpp.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
myAdapter.notifyDataSetChanged();
return paramView;
}
}
This is the layout bookmark which contains recyclerview
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/myRecyclerView"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:fillViewport="false">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
Here is the answer
Follow this steps
First Create a two layout for your Multiple viewType
SAMPLE CODE
layout.layout_one
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:cardCornerRadius="15dp"
app:cardElevation="5dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Name : " />
<TextView
android:id="#+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Icon : " />
<ImageView
android:id="#+id/tvIcon"
android:layout_width="20dp"
android:layout_height="20dp"
android:padding="10dp"
android:text="" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Id : " />
<TextView
android:id="#+id/tvId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="SearchUrl : " />
<TextView
android:id="#+id/tvSearchUrl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="NativeUrl : " />
<TextView
android:id="#+id/tvNativeUrl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
layout.button_two
<?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">
<ImageView
android:id="#+id/imgButton"
android:layout_width="50dp"
android:layout_height="50dp" />
</LinearLayout>
Now you need to create two RecyclerView.ViewHolder for your both viewType
Now you need to Override getItemViewType()
it Return the viewType of the item at position for the purposes of view recycling.
Now in your onCreateViewHolder() method you need to return your instance of your ViewHolder based on your viewType which you will get using getItemViewType() method
Than in your onBindViewHolder() method based your viewType set your view property
here is the sample code of RecyclerView.Adapter with multiple view types
DataAdapter
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class DataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
ArrayList<Bookmark> arrayList = new ArrayList<>();
public static final int ITEM_TYPE_ONE = 0;
public static final int ITEM_TYPE_TWO = 1;
public DataAdapter(Context context, ArrayList<Bookmark> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = null;
// check here the viewType and return RecyclerView.ViewHolder based on view type
if (viewType == ITEM_TYPE_ONE) {
view = LayoutInflater.from(context).inflate(R.layout.layout_one, parent, false);
return new ViewHolder(view);
} else if (viewType == ITEM_TYPE_TWO) {
view = LayoutInflater.from(context).inflate(R.layout.button_two, parent, false);
return new ButtonViewHolder(view);
}else {
return null;
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
final int itemType = getItemViewType(position);
// First check here the View Type
// than set data based on View Type to your recyclerview item
if (itemType == ITEM_TYPE_ONE) {
ViewHolder viewHolder = (ViewHolder) holder;
viewHolder.tvName.setText(arrayList.get(position).getName());
viewHolder.tvIcon.setImageResource(arrayList.get(position).getIcon());
viewHolder.tvSearchUrl.setText(arrayList.get(position).getSearchUrl());
viewHolder.tvNativeUrl.setText(arrayList.get(position).getNativeUrl());
} else if (itemType == ITEM_TYPE_TWO) {
ButtonViewHolder buttonViewHolder = (ButtonViewHolder) holder;
buttonViewHolder.imgButton.setImageResource(arrayList.get(position).getIcon());
}
}
#Override
public int getItemViewType(int position) {
// based on you list you will return the ViewType
if (arrayList.get(position).getViewType() == 0) {
return ITEM_TYPE_ONE;
} else {
return ITEM_TYPE_TWO;
}
}
#Override
public int getItemCount() {
return arrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tvName, tvId, tvSearchUrl, tvNativeUrl;
ImageView tvIcon;
public ViewHolder(#NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tvName);
tvIcon = itemView.findViewById(R.id.tvIcon);
tvId = itemView.findViewById(R.id.tvId);
tvSearchUrl = itemView.findViewById(R.id.tvSearchUrl);
tvNativeUrl = itemView.findViewById(R.id.tvNativeUrl);
}
}
public class ButtonViewHolder extends RecyclerView.ViewHolder {
ImageView imgButton;
public ButtonViewHolder(#NonNull View itemView) {
super(itemView);
imgButton = itemView.findViewById(R.id.imgButton);
}
}
}
When you adding data in your list you need to provide the viewtype in list
Make some changes in your Bookmark POJO class
Bookmark POJO class
public class Bookmark
{
String name,id,nativeUrl,searchUrl;
int icon;
int viewType;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getIcon() {
return icon;
}
public void setIcon(int icon) {
this.icon = icon;
}
public String getNativeUrl() {
return nativeUrl;
}
public void setNativeUrl(String nativeUrl) {
this.nativeUrl = nativeUrl;
}
public String getSearchUrl() {
return searchUrl;
}
public void setSearchUrl(String searchUrl) {
this.searchUrl = searchUrl;
}
public int getViewType() {
return viewType;
}
public void setViewType(int viewType) {
this.viewType = viewType;
}
#Override
public String toString() {
return "Bookmark{" +
"name='" + name + '\'' +
", icon='" + icon + '\'' +
", id='" + id + '\'' +
", nativeUrl='" + nativeUrl + '\'' +
", searchUrl='" + searchUrl + '\'' +
'}';
}
}
Sample activity code
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private Context mContext;
ArrayList<Bookmark> arrayList = new ArrayList<>();
RecyclerView myRecyclerView;
DataAdapter dataAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
myRecyclerView = findViewById(R.id.myRecyclerView);
myRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
myRecyclerView.setHasFixedSize(true);
dataAdapter = new DataAdapter(mContext, arrayList);
myRecyclerView.setAdapter(dataAdapter);
try {
XmlPullParser xpp = getResources().getXml(R.xml.bookmarks);
while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
if (xpp.getEventType() == XmlPullParser.START_TAG) {
if (xpp.getName().equals("Bookmark")) {
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(0) + " * ");
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(1) + " * ");
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(5) + " * ");
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(2) + " * ");
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(3) + " * ");
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(4) + " * ");
Bookmark bookmark = new Bookmark();
bookmark.setName(xpp.getAttributeValue(0));
int drawableResourceId = this.getResources().getIdentifier(xpp.getAttributeValue(1), "drawable", mContext.getPackageName());
bookmark.setIcon(drawableResourceId);
bookmark.setId(xpp.getAttributeValue(2));
bookmark.setSearchUrl(xpp.getAttributeValue(3));
bookmark.setNativeUrl(xpp.getAttributeValue(4));
// here you need to set view type
bookmark.setViewType(0);
arrayList.add(bookmark);
}
}
xpp.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// here i have added second viewType
// you need to set as per your requirement
Bookmark bookmark = new Bookmark();
bookmark.setViewType(1);
bookmark.setIcon(R.drawable.dishu);
arrayList.add(bookmark);
dataAdapter.notifyDataSetChanged();
}
}
NOTE
In the below code i have set second viewType at the last index of Arraylist
you need to set viewType as per your requirement
For more information you can check below articles
Working with RecyclerView and multiple view types
A RecyclerView with multiple item types
Android RecyclerView with Different Child Layouts
Android Pagination Tutorial—Handling Multiple View Types
Heterogenous Layouts inside RecyclerView
Android RecyclerView Example – Multiple ViewTypes
How to create RecyclerView with multiple view type?
Android Multiple row layout using RecyclerView
You can use different layouts on the same RecyclerView , just override adapter getItemViewType() method and return a different int value for the button layout, in your example you should return for example 1 for the normal item and 2 for the button item.
The view type is passed as argument to onCreateViewHolder() method and depending of the viewType value you inflate the normal layout or the button layout.
It seems that you need also make getItemCount() to return one more than the array size
Hope it will help
Here an example:
How to create RecyclerView with multiple view type?
Do this operations in your Activity.
ArrayList<Bookmark> data = new ArrayList<>();
//data.addAll(your array list bookmark); uncomment this line add your all array list of bookmark
Bookmark d = new Bookmark(0);
data.add(d);
mList.setAdapter(new BookMarkAdapter(activity, data));
Try This adapter
public class BookMarkAdapter extends RecyclerView.Adapter {
private Context context;
private ArrayList<Bookmark> data;
public BookMarkAdapter(Context context, ArrayList<Bookmark> data) {
this.context = context;
this.data = data;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == 1)
return new ViewBookmarkHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_with_normal_image_and_textview, parent, false));
else
return new AddBookmarkHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_with_image, parent, false));
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Bookmark d = data.get(position);
if (d.getType()==1) {
ViewBookmarkHolder viewBookmarkHolder =(ViewBookmarkHolder) holder;
// do your show image and textview operation here
} else {
AddBookmarkHolder addBookmarkHolder =(AddBookmarkHolder) holder;
// do your on click operation here. Like adding new bookmark and update your arraylist and notify data changed for adapter.
}
}
#Override
public int getItemViewType(int position) {
return data.get(position).getType();
}
#Override
public int getItemCount() {
return data.size();
}
}
Update this methods and variables in your Bookmark Pojo
public class Bookmark {
private Integer type;
public Bookmark(Integer type) {
this.type = type;
}
public void setType(Integer type) {
this.type = type;
}
public Integer getType() {
if(type==null)
return 1;
return type;
}
}
That is when the sender from one device sends message,it should appear on the right hand side and when the other device gets the message it should appear on the left hand side.
My java class: This is the function I am calling
private void chatRowStyling(boolean isItMe, ViewHolder holder){
if (isItMe){
holder.layoutParams.gravity = Gravity.END;
holder.chatBody.setTextColor(Color.BLUE);
holder.senderName.setBackgroundResource(R.drawable.speech_bubble_green);
}else{
holder.layoutParams.gravity = Gravity.START;
holder.chatBody.setTextColor(Color.GREEN);
holder.senderName.setBackgroundResource(R.drawable.speech_bubble_orange);
}
Log.i("TAG","error :" + mySnapShot);
holder.senderName.setLayoutParams(holder.layoutParams);
holder.chatBody.setLayoutParams(holder.layoutParams);
}
In the Screenshot, all the messages appear on the right side, whereas I want one to be on right and another to be on left from different users.
This is my XML code :
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/singleMessageContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:text="#string/sender"
android:textColor="#2980b9"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="#+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_margin="5dip"
android:padding="12dp"
android:text="#string/author"
android:textColor="#2c3e50" />
</LinearLayout>
The best way to do it would be to implement RecyclerView with separate view types, that way you could adjust layout however you want without some shady workaround. Here is example to do it.
Reference : How to create RecyclerView with multiple view type?
EDIT:
Convinced by comments I decided to add some more explanation.
You could create two separate layouts, one for your messages:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tvAuthor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"/>
<TextView
android:id="#+id/tvMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/tvAuthor"
android:layout_alignParentRight="true"/>
</RelativeLayout>
and the other one for messages from friend:
<?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="wrap_content">
<TextView
android:id="#+id/tvAuthor"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/tvMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/tvAuthor" />
</RelativeLayout>
Then you can create a class for your messages:
public class Message {
private String message;
private String author;
public Message(String message, String author) {
this.message = message;
this.author = author;
}
public String getMessage() {
return message;
}
public String getAuthor() {
return author;
}
}
Next step would be to create adapter for your RecyclerView that will use two seperate ViewHolders, one for your messages and the other for messages from your friend. Inside OnCreateViewHolder you can choose which layout you want to display for each message. Then in OnBindViewHolder, you can fill TextViews with correct message data.
public class MessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<Message> messages;
private final static int TYPE_FROM_FRIEND = 1;
private final static int TYPE_TO_FRIEND = 2;
public MessageAdapter(ArrayList<Message> messages) {
this.messages = messages;
}
public int getItemViewType(int position) {
if (messages.get(position).getAuthor().equals("Me")) {
return TYPE_TO_FRIEND;
} else {
return TYPE_FROM_FRIEND;
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int layout = 0;
RecyclerView.ViewHolder viewHolder;
switch (viewType){
case TYPE_TO_FRIEND:
layout = R.layout.view_message_to_friend;
View toFriendView = LayoutInflater
.from(parent.getContext())
.inflate(layout, parent, false);
viewHolder=new ToFriendViewHolder(toFriendView);
break;
case TYPE_FROM_FRIEND:
layout = R.layout.view_message_from_friend;
View fromFriendView = LayoutInflater
.from(parent.getContext())
.inflate(layout, parent, false);
viewHolder = new FromFriendViewHolder(fromFriendView);
break;
default:
viewHolder = null;
break;
}
return viewHolder;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
int viewType=holder.getItemViewType();
switch (viewType){
case TYPE_TO_FRIEND:
((ToFriendViewHolder)holder).tvMessage.setText(messages.get(position).getMessage());
((ToFriendViewHolder)holder).tvAuthor.setText(messages.get(position).getAuthor());
break;
case TYPE_FROM_FRIEND:
((FromFriendViewHolder)holder).tvMessage.setText(messages.get(position).getMessage());
((FromFriendViewHolder)holder).tvAuthor.setText(messages.get(position).getAuthor());
break;
}
}
private class ToFriendViewHolder extends RecyclerView.ViewHolder {
private TextView tvAuthor;
private TextView tvMessage;
public ToFriendViewHolder(View view) {
super(view);
tvAuthor = (TextView) view.findViewById(R.id.tvAuthor);
tvMessage = (TextView) view.findViewById(R.id.tvMessage);
}
}
private class FromFriendViewHolder extends RecyclerView.ViewHolder {
private TextView tvAuthor;
private TextView tvMessage;
public FromFriendViewHolder(View view) {
super(view);
tvAuthor = (TextView) view.findViewById(R.id.tvAuthor);
tvMessage = (TextView) view.findViewById(R.id.tvMessage);
}
}
#Override
public int getItemCount() {
return messages.size();
}
}
Finally you can set RecyclerView's adapter in your activity:
public class MainActivity extends AppCompatActivity {
private RecyclerView rvMain;
private ArrayList<Message> messages = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvMain = (RecyclerView) findViewById(R.id.rvMain);
rvMain.setLayoutManager(new LinearLayoutManager(this));
messages.add(new Message("Hello", "Me"));
messages.add(new Message("Hi", "Friend"));
messages.add(new Message("How are you?", "Me"));
messages.add(new Message("I'm fine and you?", "Friend"));
MessageAdapter adapter = new MessageAdapter(messages);
rvMain.setAdapter(adapter);
}
}
You can achieve it by setting the view gravity not the LayoutParams with something like this:
if(isIfMe) {
holder.linearLayout.setGravity(Gravity.END);
holder.tvAuthor.setGravity(Gravity.END);
} else {
holder.linearLayout.setGravity(Gravity.END);
holder.tvAuthor.setGravity(Gravity.END);
}
I have this working perfectly with a ListView, but decided to update my code to use RecyclerView.
I see there is no default implementation, and the responses to similar questions are quite old.
Is using a sort of cursor the best way to go, or is there a better option?
These are my code snippets for a working RecyclerView with hard-coded values:
MainActivity
recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
mLayoutmanager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLayoutmanager);
mAdapter = new recyclerViewDataAdapter();
recyclerView.setAdapter(mAdapter);
recyclerViewDataAdapter
public class recyclerViewDataAdapter extends RecyclerView.Adapter {
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//lets populate our recyler view with the item created;
//get the view from the layout inflator
// third parameter is set to false to prevent viewgroup to attach to root
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item,parent,false);
// as this method need to return the viewHolder type
// need to convert our view to the view holder
RecyclerView.ViewHolder viewHolder = new RecyclerView.ViewHolder(view) {
#Override
public String toString() {
return super.toString();
}
};
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return 3000;
}
}
activity_main
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
recycler_item
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="vertical">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hii "
android:textSize="30sp" />
</LinearLayout>
Here is my DatabaseAdapter which worked perfectly with a ListView:
public class DatabaseHelper extends SQLiteAssetHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "database9.db";
private static final String BOOKS = "books";
private static final String AUTHORS = "authors";
public DatabaseHelper (Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// setForcedUpgrade();
}
// Getting all books
public ArrayList<Author> getAllAuthors() {
ArrayList<Author> authorList = new ArrayList<>();
// Select all query
String selectQuery = "SELECT id, name FROM " + AUTHORS + " ORDER BY name_alphabetic";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
// create new author object
Author author = new Author();
// set ID and name of author object
author.setID(Integer.parseInt(cursor.getString(0)));
author.setName(cursor.getString(1));
// pass author object to authorList array
authorList.add(author);
} while (cursor.moveToNext());
}
// return author list
return authorList;
}
}
Your can try
In your activity
ArrayList<Author> authors = dbHandler. getAllAuthors();
recyclerView.setHasFixedSize(true);
// ListView
recyclerView.setLayoutManager(new LinearLayoutManager(youractivity.this));
// create an Object for Adapter
CardViewDataAdapter1 mAdapter = new CardViewDataAdapter1(authors);
// set the adapter object to the Recyclerview
recyclerView.setAdapter(mAdapter);
Your adapter is look like
class CardViewDataAdapter1 extends RecyclerView.Adapter<CardViewDataAdapter1.ViewHolder> {
private ArrayList<Author> dataSet;
public CardViewDataAdapter1(ArrayList<Author> os_versions) {
dataSet = os_versions;
}
#Override
public CardViewDataAdapter1.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
// create a new view
View itemLayoutView = LayoutInflater.from(viewGroup.getContext()).inflate(
R.layout.recycler_item, null);
itemLayoutView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));
// create ViewHolder
CardViewDataAdapter1.ViewHolder viewHolder = new CardViewDataAdapter1.ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(CardViewDataAdapter1.ViewHolder viewHolder, int i) {
Author fp = dataSet.get(i);
viewHolder.tv_name.setText(fp.getName());
viewHolder.menu = fp;
}
#Override
public int getItemCount() {
return dataSet.size();
}
public void updateList(List<Author> temp) {
dataSet = (ArrayList<Author>) temp;
notifyDataSetChanged();
}
// inner class to hold a reference to each item of RecyclerView
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView tv_name;
public Author menu;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
tv_name = (TextView) itemLayoutView .findViewById(R.id.tv_name);
}
}
}
Your recycler_item.xml
<?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:layout_width="match_parent"
android:layout_height="match_parent"
card_view:cardCornerRadius="5dp"
card_view:cardBackgroundColor="#FFFFFF"
card_view:cardUseCompatPadding="true"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Enamul"/>
</LinearLayout>
</android.support.v7.widget.CardView>
I've got a RecyclerView which populates from an ArrayList. The output is a CardView layout.
In the Cardview, there are 2 buttons amongst other Views.
They only have to read the current value of a TextView, which by default is 1, and increase or decrease it.
The Arraylist contains 8 items.
When I run the app the UI works fine. Trouble is when I try to modify the value of the TextView.
The value is correctly increased and decreased on the CardView I'm working on, but ALSO the value is modified on another CardView. And in that second CardView, modifying its TextView value, also modifies the first one.
So, what am I doing wrong?
This is my Fragment:
public class Fragment_rosas extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_rosas,container,false);
RecyclerView recyclerview_rosas;
RecyclerView.Adapter adaptador_rv_rosas;
RecyclerView.LayoutManager lm_rosas;
List rosas = new ArrayList();
rosas.add(new Tropa(1,R.drawable.minibarbaro, getResources().getString(R.string.barbaro),7,1));
recyclerview_rosas = (RecyclerView) view.findViewById(R.id.recyclerView_tropasRosas);
recyclerview_rosas.setHasFixedSize(true);
lm_rosas = new LinearLayoutManager(getContext());
recyclerview_rosas.setLayoutManager(lm_rosas);
adaptador_rv_rosas = new AdaptadorTropa(rosas);
recyclerview_rosas.setAdapter(adaptador_rv_rosas);
return view;
}
}
And here the part of code on my Adapter:
#Override
public void onBindViewHolder(final TropaViewHolder viewHolder, int i) {
viewHolder.imagen.setImageResource(items.get(i).getImagen());
viewHolder.nombre.setText(items.get(i).getNombre());
viewHolder.maxnivel.setText(String.valueOf(items.get(i).getNivelMax()));
viewHolder.espacioencamp.setText((String.valueOf(items.get(i).getEspacioEnCamp())));
final String nombre = items.get(i).getNombre();
final int maxnivel = items.get(i).getNivelMax();
viewHolder.nivelmas.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String niveltemp = viewHolder.nivel.getText().toString();
String nivelmaxtemp = viewHolder.maxnivel.getText().toString();
int nivel = Integer.parseInt(niveltemp);
int maxxnivel = Integer.parseInt(nivelmaxtemp);
int nuevonivel = nivel+1 ;
if (nuevonivel<=maxxnivel) {
viewHolder.txtv_nivel.setText(String.valueOf(nuevonivel));
}
}
});
My OnCreateViewHolder (nothing really happens here):
#Override
public TropaViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.cardview, viewGroup, false);
return new TropaViewHolder(v);
}
Here is the solution, as mentioned in the comment above, it addresses two problems:
1. positiontoValueMap - saves current value for each position
2. onclicklistener is passed to the ViewHolder in onCreateViewHolder
Adapter Class
public class MyAdapter extends RecyclerView.Adapter {
private Context context;
private List<String> dataList;
private Map<Integer, Integer> positionToValueMap = new HashMap<>();
public MyAdapter(Context context, List<String> dataList) {
this.context = context;
this.dataList = dataList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_item, null, false);
return new MyViewHolder(view, new OnRecyclerItemClickListener());
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((MyViewHolder) holder).onRecyclerItemClickListener.updatePosition(position);
((MyViewHolder) holder).position.setText("" + position);
((MyViewHolder) holder).title.setText(dataList.get(position));
int valueToDisplay = 1;
if(positionToValueMap.containsKey(position)) {
valueToDisplay = positionToValueMap.get(position);
} else {
positionToValueMap.put(position, valueToDisplay);
}
((MyViewHolder) holder).valueView.setText("value: " + valueToDisplay);
}
#Override
public int getItemCount() {
return dataList.size();
}
private class MyViewHolder extends RecyclerView.ViewHolder {
private OnRecyclerItemClickListener onRecyclerItemClickListener;
private TextView position;
private TextView title;
private TextView valueView;
public MyViewHolder(View itemView, OnRecyclerItemClickListener onRecyclerItemClickListener) {
super(itemView);
itemView.setOnClickListener(onRecyclerItemClickListener);
this.onRecyclerItemClickListener = onRecyclerItemClickListener;
this.position = (TextView) itemView.findViewById(R.id.position);
this.title = (TextView) itemView.findViewById(R.id.title);
this.valueView = (TextView) itemView.findViewById(R.id.value_view);
}
}
private class OnRecyclerItemClickListener implements View.OnClickListener {
private int position = -1;
public void updatePosition(int position) {
this.position = position;
}
#Override
public void onClick(View v) {
int oldValue = positionToValueMap.get(position); // get current value
oldValue++; // increment
positionToValueMap.put(position, oldValue); // save current value
notifyItemChanged(position); // update clicked view so that it picks up the new saved value from the positionToValueMap in onBindViewHolder
}
}
}
RecyclerView item layout
<TextView
android:id="#+id/position"
android:layout_width="30dp"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_light"
android:layout_alignParentLeft="true"/>
<TextView
android:id="#+id/title"
android:layout_width="50dp"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_dark"
android:layout_toRightOf="#id/position" />
<TextView
android:id="#+id/value_view"
android:layout_width="match_parent"
android:layout_height="50dp"
android:textColor="#android:color/white"
android:gravity="center"
android:background="#android:color/holo_green_light"
android:layout_toRightOf="#id/title"
android:layout_alignParentRight="true"/>
</RelativeLayout>
And Activity to test it out
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setAdapter(new MyAdapter(getApplicationContext(), getSampleData()));
}
private static List<String> getSampleData() {
List<String> dataList = new ArrayList<>();
dataList.add("zero");
dataList.add("one");
dataList.add("two");
dataList.add("three");
dataList.add("four");
dataList.add("five");
dataList.add("six");
dataList.add("seven");
dataList.add("eight");
dataList.add("nine");
dataList.add("ten");
dataList.add("eleven");
dataList.add("twelve");
dataList.add("thirteen");
dataList.add("fourteen");
dataList.add("fifteen");
dataList.add("sixteen");
dataList.add("seventeen");
dataList.add("eighteen");
dataList.add("nineteen");
dataList.add("twenty");
return dataList;
}
}
activity layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"/>
</RelativeLayout>
I looked up for the possible solutions but I could not figure out how to apply them in my case.
I am using a RecyclerView to display several CardViews inside it. Initially all cards have white background and I want to change the background color when a card is touched. Each CardView displays a name and an id as described in 'MyCards' class :
public class MyCards {
private String sName;
private int sId;
private boolean sPresent;
public String getName() {
return this.sName;
}
public MyCards(String sName, int sId, boolean sPresent) {
this.sName = sName;
this.sId = sId;
this.sPresent = sPresent;
}
public void setName(String t) {
this.sName = t;
}
public int getId() {
return sId;
}
public void setId(int id) {
this.sId = id;
}
public boolean isPresent() {
return sPresent;
}
public void setPresent(boolean present) {
this.sPresent = present;
}
}
I am making an ArrayList of these MyCards object in the 'Roster' class :
public class Roster extends ActionBarActivity{
private static final int READ_REQUEST_CODE = 42;
private static final String TAG = null;
private RecyclerView rObject;
private MyAdapter adapter;
String abc = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.roster_recycle);
rObject = (RecyclerView)findViewById(R.id.recycler_view);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
rObject.setLayoutManager(llm);
MyCards c1 = new MyCards("Abhinav", 123, true);
MyCards c2 = new MyCards("Abhishek", 13, false);
performFileSearch();
c1.setName("Abhinav");
c2.setName("Baba");
List<MyCards> cardList = new ArrayList<MyCards>();
cardList.add(c1);
cardList.add(c2);
adapter = new MyAdapter(Roster.this,cardList);
rObject.setAdapter(adapter);
}
The CardView is defined in the item_layout.xml file :
<android.support.v7.widget.CardView
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
card_view:cardCornerRadius="4dp" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/sName"
android:layout_width="match_parent"
android:layout_height="20dp"
android:gravity="center_vertical"
android:text="contact det"
android:textSize="14dp" />
<TextView
android:id="#+id/sId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/sName"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:text="Name"
android:textSize="10dp" />
<TextView
android:id="#+id/sPresent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/sId"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:text="Present"
android:textSize="10dp" />
</RelativeLayout>
</android.support.v7.widget.CardView>
My question is : If I click on a card displaying data for 'c1' object then how can I identify that it was from 'c1' and not 'c2'. How do I use click handler in such cases where we display multiple cards?
I'm sorry if my question is too basic but I'm really stuck at it.
Thank you so much for your responses, they really helped. Finally I found a video on YouTube which explained the concept in a nice manner. I am posting the link so that others can also benefit if they get stuck. Here is the video -
see this :- https://www.youtube.com/watch?v=zE1E1HOK_E4
Take a look at this answer for using an onItemClickListener with a RecyclerView.
public class MyAdapter extends RecyclerView.Adapter {
Context mContext;
ArrayList<MyCard> mData;
public MyAdapter(Context context , ArrayList<MyCard> data ) {
mContext = context;
mData = data;
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView sName, sId , sPresent;
public ViewHolder(View itemView) {
super(itemView);
sName = (TextView) itemView.findViewById(R.id.sName);
sId = (TextView) itemView.findViewById(R.id.sId);
sPresent = (TextView) itemView.findViewById(R.id.sPresent);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// your logic
}
});
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout , parent , false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public int getItemCount() {
return mData.size();
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final MyCard card = mData.get(position);
holder.sName.setText(card.getName().toString());
holder.sId.setText(card.getId().toString());
holder.sPresent.setText(card.getPresent().toString());
}
}