RecyclerView does not display items - android

I am using RecyclerView in Android with a model class that has title and details. Nothing is showing. Even after log inside Adapter nothing is shown in Android Monitor.
MainActivity.class
public ArrayList<Menu> menu_list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu);
initUi();
}
public void initUi(){
RecyclerView menu_recycler = (RecyclerView) findViewById(R.id.main_menu_recycler_view);
//set the layout manager
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation( linearLayoutManager.VERTICAL );
menu_recycler.setLayoutManager( linearLayoutManager );
//set adapter
MainMenuAdapter mainMenuAdapter = new MainMenuAdapter( getMenulist() );
menu_recycler.setAdapter( mainMenuAdapter );
}
public ArrayList<Menu> getMenulist() {
menu_list = new ArrayList<Menu>();
menu_list.add( new Menu("About Us", " Learn more about our values, mission and vision ") );
menu_list.add( new Menu("Services ", " In implementing its mandate, the Agency will provide the following to its external and internal customers:\n"));
menu_list.add( new Menu("Stakeholders", " Who are the key players, Find out more") );
menu_list.add( new Menu("Learn about Counterfeits", "Gain more insight on counterfeit products"));
return menu_list;
}
and here is my adapter
public class MainMenuAdapter extends RecyclerView.Adapter<MainMenuAdapter.MyViewHolder> {
public List<Menu> list_of_menus;
public MainMenuAdapter( List<Menu> list_of_menus){
this.list_of_menus = list_of_menus;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.row,parent, false);
return new MyViewHolder(v);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Menu menu = list_of_menus.get(position);
Log.e("MENU IN ADAPTER TITLE", menu.title);
holder.title_text.setText( menu.title );
holder.details_text.setText( menu.details );
}
#Override
public int getItemCount() {
return 0;
}
/*
View Holder class
* */
public class MyViewHolder extends RecyclerView.ViewHolder{
public TextView title_text, details_text;
public MyViewHolder(View itemView) {
super(itemView);
title_text = (TextView) itemView.findViewById(R.id.menu_title);
details_text = (TextView) itemView.findViewById(R.id.menu_details);
}
}
}
And the Model Class
public class Menu {
public String title, details;
public Menu(String title, String details){
this.details = details;
this.title = title;
}
}
And the layout file main_activity
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.maos.aca.MainMenuActivity">
<android.support.v7.widget.RecyclerView
android:layout_width="334dp"
android:layout_height="453dp" app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp" android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent" android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent" android:id="#+id/main_menu_recycler_view"
android:scrollbars="vertical"/>
</android.support.constraint.ConstraintLayout>
And finally the row
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/menu_title"
android:textStyle="bold"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:id="#+id/menu_details"/>
</LinearLayout>
I know this question has been asked before, but none of the answers helped me out.I'll appreciate any lead.

You need to change the getItemCount() method to this:
#Override
public int getItemCount() {
return list_of_menus.size();
}
The RecyclerView will not display any elements if you are reporting that its size is zero.

Change this:
#Override
public int getItemCount() {
return 0;
}
To this:
#Override
public int getItemCount() {
return list_of_menus.size();
}

Related

recyclerview data changed on scrolling (Not Duplicate) and dynamic textview got doubled on scrolling

My recyclerview data changed while I scrolling down/up.
when I scroll the layout it appears every time with new values
I've added both methods and as well and false recyclable too. But, didn't work out.
Here's is how my adapter looks like.
public class DetailListAdapter extends RecyclerView.Adapter<DetailListAdapter.ViewHolder> {
Context context;
ArrayList<KcResponse> kcList;
String birthDate; }
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_client_detail, parent, false);
DetailListAdapter.ViewHolder vh = new DetailListAdapter.ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(#NonNull DetailListAdapter.ViewHolder holder, int position) {
holder.setIsRecyclable(false);
holder.periodTv.setText(kcList.get(position).getPeriod());
TextView textView1 = new TextView(context);
textView1.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
for (int i = 0; i < arr.length; i++) {
String line = arr[i];
SpannableString ss = new SpannableString(line);
ss.setSpan(new BulletSpan(bulletGap), 0, line.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append(ss);
//avoid last "\n"
if (i + 1 < arr.length)
ssb.append("\n");
}
textView1.setTextSize(12);
textView1.setTextColor(ContextCompat.getColor(context, R.color.black_text));
textView1.setPadding(15, 0, 0, 0);
textView1.setText(ssb); // bullet text
holder.effectsLl.addView(textView1);
holder.periodTv.setBackgroundColor(Color.parseColor(kcList.get(position).getColor()));}
#Override
public int getItemCount() {
return kcList.size();
}
You do not have more than one type of views in your recylcerview so one thing for sure that you do not need to override getItemViewType(int position).
Also the usage of method getItemId(int position) is incorrect. That method is used to get the stable ID for the item at position.
Add this overriding method to your custom adapter
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
The adapter code you shared is not enough to identify the issue. So I am sharing a very simple recyclerview and its adapter code, just try to use that. I hope it will help you.
Happy coding...
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private DataAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerView);
adapter = new DataAdapter();
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new DividerItemDecoration(this));
}
}
Adapter class code
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
public DataAdapter() {
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View listItem = layoutInflater.inflate(R.layout.adapter_layout, parent, false);
ViewHolder viewHolder = new ViewHolder(listItem);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.textView.setText("TextView1");
holder.textView.setText("TextView2");
}
#Override
public int getItemCount() {
return 20;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView imageView;
public TextView textView;
public ViewHolder(View itemView) {
super(itemView);
this.imageView = itemView.findViewById(R.id.textView1);
this.textView = (TextView) itemView.findViewById(R.id.textView2);
}
}
}
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"
android:background="#f1f1f1"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
adapter_layout.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="wrap_content"
android:padding="4dp"
tools:context=".MainActivity">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView1" />
</androidx.constraintlayout.widget.ConstraintLayout>

Why isn't my DiffUtil with RecyclerView working?

I'm trying to create a simple DiffUtil Adapter to work with a RecyclerView and nothing shows up (I only get a blank activity). Here is the code:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private MyAdapter mAdapter;
private ArrayList<User> myDataset;
private RecyclerView mRecyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new MyAdapter();
myDataset = new ArrayList<User>();
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
myDataset.add(new User("User1"));
myDataset.add(new User("User2"));
myDataset.add(new User("User3"));
mRecyclerView.setAdapter(mAdapter);
mAdapter.updateList(myDataset);
}
}
Here is MyAdapter.java:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private AsyncListDiffer<User> mAsyncListDiffer;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView singleItemTextView;
public View layout;
public ConstraintLayout constraintLayout;
public MyViewHolder(View v) {
super(v);
layout = v;
singleItemTextView = (TextView) v.findViewById(R.id.singleItemTextView);
constraintLayout = (ConstraintLayout) v.findViewById(R.id.constraintLayout);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter() {
DiffUtil.ItemCallback<User> diffUtilCallback = new DiffUtil.ItemCallback<User>() {
#Override
public boolean areItemsTheSame(#NonNull User newUser, #NonNull User oldUser) {
return newUser.getUserId().equals(oldUser.getUserId());
}
#Override
public boolean areContentsTheSame(#NonNull User newUser, #NonNull User oldUser) {
return newUser.equals(oldUser);
}
};
mAsyncListDiffer = new AsyncListDiffer<>(this, diffUtilCallback);
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_text_view, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
User user = mAsyncListDiffer.getCurrentList().get(position);
holder.singleItemTextView.setText(user.getUserId());
}
#Override
public int getItemCount() {
return mAsyncListDiffer.getCurrentList().size();
}
public void updateList(ArrayList<User> newList) {
mAsyncListDiffer.submitList(newList);
}
}
Here is User.java:
public class User {
private String mUserId;
public User(String userId) {
mUserId = userId;
}
public String getUserId() {
return mUserId;
}
}
Here are the XML files:
acivity_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:id="#+id/my_recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="4dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:background="#FFFFFF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
and here is single_text_view.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:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:layout_editor_absoluteY="81dp">
<TextView
android:id="#+id/singleItemTextView"
android:layout_width="78dp"
android:layout_height="78dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
I know that DiffUtil is supposed to compare 2 different lists and here I only set up the initial list, but still, shouldn't it at least display the first list (with 3 users in this case)?
Set LayoutManager with Recyclerview
// add data on list
private ArrayList<User> myDataset=new ArrayList;
myDataset.add(new User("abc"));
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
LayoutManager layoutManager=new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
MyAdapter myAdapter=new MyAdapter();
mAdapter.updateList(myDataset);
mRecyclerView.setAdapter(mAdapter);
Do you check if your getItemCount() method returns more than 0 ?
If it is, you should look at your item view. Try to remove constraints on this view first to see if anything appears on the screen.

Data from JSON does not appear on the RecyclerView layout

I have created RecyclerView and showing data from JSON.
Issue I'm facing is, while Toast data is showing correctly, but in RecyclerView same data is not appear.
Here is code:
public class MainActivity extends AppCompatActivity {
private static final int NUM_LIST_ITEMS = 100;
private static final String TOKEN =
"71cf2d3dec294394e267fbb0bf28916f4198f8d6";
private CuloAdapter culoAdapter;
List<Hotel> lh = new ArrayList<>();
RecyclerView recyclerView;
#Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.rv_tiketapi);
LinearLayoutManager layout = new LinearLayoutManager(this);
layout.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layout);
CuloAdapter ar = new CuloAdapter(lh);
recyclerView.setAdapter(ar);
loadHotelLocation();
}
private void loadHotelLocation() {
final search apiService = ApiService.getService(search.class);
retrofit2.Call<SingleResult<Hotel>> call = apiService.findHotel(TOKEN,
"json");
call.enqueue(new Callback<SingleResult<Hotel>>() {
#Override
public void onResponse(retrofit2.Call<SingleResult<Hotel>> call,
Response<SingleResult<Hotel>> response) {
if (response.body().getDiagnostic().isSuccess()) {
//SingleResult.ResultList list =
response.body().getResults();
List<Hotel> mHotels = (List<Hotel>)
response.body().getResults().getResult();
lh.addAll(mHotels);
Toast.makeText(getApplicationContext(), "OK" +lh,
Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(retrofit2.Call<SingleResult<Hotel>> call,
Throwable t) {
}
});
}
RecyclerView Adapter :
public class CuloAdapter extends
RecyclerView.Adapter<CuloAdapter.ViewHolder> {
public CuloAdapter(List<Hotel> lh) {
this.items = lh;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView txtTitle;
public TextView txtSubTitle;
public ImageView imgIcon;
public ViewHolder(final View container) {
super(container);
txtTitle = (TextView) container.findViewById(R.id.airportName);
txtSubTitle = (TextView) container.findViewById(R.id.airportCode);
}
}
private List<Hotel> items;
public CuloAdapter(final Activity activity, List<Hotel> items) {
this.items = items;
}
#Override
public int getItemCount() {
return items.size();
}
#Override
public void onBindViewHolder(CuloAdapter.ViewHolder holder, int position) {
Hotel item = items.get(position);
holder.txtTitle.setText(item.getLabel());
holder.txtSubTitle.setText(item.getId());
}
#Override
public CuloAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int
viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_flight, parent, false);
return new ViewHolder(v);
}
}
MainActivity XML :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.admin.exampletiketapi.MainActivity">
<EditText
android:id="#+id/et_find"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_tiketapi"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
Item List XML :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/airportsLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp">
<TextView
android:id="#+id/airportName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:text="Soekarno Hatta" />
<TextView
android:id="#+id/airportCode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:text="20" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="5dp"
android:background="#DDD"
android:visibility="visible" />
</LinearLayout>
In your code you are trying to set adapter before loading data.
CuloAdapter ar = new CuloAdapter(lh);
recyclerView.setAdapter(ar);
loadHotelLocation();
What i found is You are getting data in loadHotelLocation(), but trying to set adpter before that,
Call notifyDatasetChanged after lh.addAll(mHotels). And check for null's else you are heading for crash in case search results are zero/null

ReclyclerView and CardView, onclick method perform the action on several CardViews at same time

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>

unable to understand onClick event for multiple CardViews inside RecycleView

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());
}
}

Categories

Resources