This question already has answers here:
ReyclerView isn't working
(6 answers)
Closed 4 years ago.
I have been making an app that uses a RecyclerView but its not showing any thing..why contents of the recycler view have not been showing up.my codes are bellow
activity_history.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=".HistoryActivity"
android:fitsSystemWindows="true"
android:orientation="vertical"
android:id="#+id/layout">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/historyRecyclerView"
android:scrollbars="vertical">
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.NestedScrollView>
HistoryActivity.java
public class HistoryActivity extends AppCompatActivity {
private RecyclerView mHistoryRecyclerView;
private RecyclerView.Adapter mHistoryAdapter;
private RecyclerView.LayoutManager mHistoryLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
Toast.makeText(this, "dddd", Toast.LENGTH_SHORT).show();
mHistoryRecyclerView = (RecyclerView) findViewById(R.id.historyRecyclerView);
mHistoryRecyclerView.setNestedScrollingEnabled(false);
mHistoryRecyclerView.setHasFixedSize(true);
mHistoryLayoutManager = new LinearLayoutManager(HistoryActivity.this);
mHistoryRecyclerView.setLayoutManager(mHistoryLayoutManager);
mHistoryAdapter = new HistoryAdapter(getDataSetHistory(), HistoryActivity.this);
mHistoryRecyclerView.setAdapter(mHistoryAdapter);
HistoryObject obj=new HistoryObject("12345");
resultsHistory.add(obj);
mHistoryAdapter.notifyDataSetChanged();
}
private ArrayList resultsHistory = new ArrayList<HistoryObject>();
private List<HistoryObject> getDataSetHistory() {
return resultsHistory;
}
}
HistoryAdapter.java
public class HistoryAdapter extends RecyclerView.Adapter<HistoryViewHolders> {
private List<HistoryObject> itemList;
private Context context;
public HistoryAdapter(List<HistoryObject> itemList, Context context) {
this.itemList = itemList;
this.context = context;
Toast.makeText(context,itemList.size()+"" , Toast.LENGTH_SHORT).show();
}
#NonNull
#Override
public HistoryViewHolders onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_history, null, false);
HistoryViewHolders rcv = new HistoryViewHolders(layoutView);
return rcv;
}
#Override
public void onBindViewHolder(#NonNull HistoryViewHolders holder, int position) {
holder.rideId.setText(itemList.get(position).getRideId());
Toast.makeText(context, holder.rideId.getText().toString(), Toast.LENGTH_SHORT).show();
}
#Override
public int getItemCount() {
return 0;
}
}
HistoryObject
package com.example.ikramkhan.insta.historyRecyclerView;
public class HistoryObject {
private String rideId;
public HistoryObject(String rideId) {
this.rideId = rideId;
}
public String getRideId() {
return rideId;
}
public void setRideId(String rideId) {
this.rideId = rideId;
}
}
HistoryViewHolders.java
public class HistoryViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView rideId;
public HistoryViewHolders(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
rideId = (TextView) itemView.findViewById( R.id.rideId);
}
#Override
public void onClick(View v) {
}
}
You're returning zero for the itemCount, therefore your adapter thinks you don't have any items. Try this in your adapter:
#Override
public int getItemCount() {
return itemList.size();
}
Related
I have a fragment that is suppose to display the results of my alert dialog in my RecyclerView. Every time I click the "ADD" in my dialog, it adds duplicated results to my RecyclerView. I've searched and searched but cannot seem to find what I am doing wrong. I've tried adding .clear(); but if I add that, nothing shows up in my RecyclerView at all. I've added in my adapter getItemId and getItemViewType to return position; but the items still get duplicated. I've added adapter.setData(model) followed by adapter.notifyDataSetChange(); and my RecyclerView still shows duplicated items. The app runs so I have no logcat to post. Thank you.
Model
public class SubjectsModel
{
//private long id;
private String mTitle;
private String mTeacher;
public String getmTitle()
{
return mTitle;
}
public void setmTitle(String title)
{
this.mTitle = title;
}
public String getmTeacher()
{
return mTeacher;
}
public void setmTeacher(String teacher)
{
this.mTeacher = teacher;
}
}
Fragment
public class SubjectsFrag extends DialogFragment implements
SubjectsEditor.OnAddSubjectListener
{
private static final String TAG = SubjectsFrag.class.getSimpleName();
#NonNull
Context context;
private EditText titleView, teacherView;
private String sTitle, sTeacher;
public EmptyRecyclerView recyclerView;
public RecyclerView.LayoutManager layoutManager;
public RecyclerSubAdapter recyclerSubAdapter;
public ArrayList<SubjectsModel> subMod = new ArrayList<>();
DbHelper helper;
#BindView(R.id.main_root)
ViewGroup root;
public SubjectsFrag() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_subjects, container, false);
FloatingActionButton fab = view.findViewById(R.id.fab_sub);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showDialog();
}
});
helper = new DbHelper(getActivity());
helper.getSubject();
titleView = view.findViewById(R.id.edit_subject);
teacherView = view.findViewById(R.id.edit_subject_teacher);
View emptyView = view.findViewById(R.id.empty_subject_view);
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerSubAdapter = new RecyclerSubAdapter(getContext(), subMod);
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(recyclerSubAdapter);
return view;
}
#Override
public void OnAddSubjectSubmit(String title, String teacher)
{
SubjectsModel model = new SubjectsModel();
model.setmTitle(title);
model.setmTeacher(teacher);
//subMod.clear();
subMod.add(model);
recyclerSubAdapter.setData(subMod);
recyclerSubAdapter.notifyDataSetChanged();
}
private void showDialog()
{
SubjectsEditor addSubjectDialog = new SubjectsEditor();
addSubjectDialog.setTargetFragment(this, 0);
addSubjectDialog.show(getFragmentManager(), null);
}
}
Adapter
public class RecyclerSubAdapter extends RecyclerView.Adapter<RecyclerSubAdapter.ViewHolder>
{
private static final String TAG = RecyclerSubAdapter.class.getSimpleName();
public List<SubjectsModel> subMod = new ArrayList<>();
private OnItemClicked onClick;
static ClickListener clickListener;
Context context;
DbHelper helper;
public RecyclerSubAdapter(Context context, ArrayList<SubjectsModel> subMod)
{
this.context = context;
this.subMod = subMod;
this.helper = new DbHelper(context);
}
#NonNull
#Override
public RecyclerSubAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.subjects_item_list, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(final RecyclerSubAdapter.ViewHolder holder, final int position)
{
SubjectsModel currentSubject = subMod.get(position);
holder.titleView.setText(currentSubject.getmTitle());
holder.teacher.setText(currentSubject.getmTeacher());
//helper.addClass(subMod.get(position));
}
public class ViewHolder extends RecyclerView.ViewHolder implements
View.OnClickListener
{
TextView titleView;
TextView teacher;
CardView cardView;
public ViewHolder(View itemView)
{
super(itemView);
titleView = itemView.findViewById(R.id.subject_subject);
teacher = itemView.findViewById(R.id.subject_teacher_text);
cardView = itemView.findViewById(R.id.card_view);
}
#Override
public void onClick(View view)
{
if (clickListener != null)
{
}
}
}
#Override
public int getItemCount()
{
if (subMod == null)
{
Log.d(TAG, "sub is null");
}
return subMod.size();
}
#Override
public long getItemId(int position)
{
return position;
}
#Override
public int getItemViewType(int position)
{
return position;
}
public interface OnItemClicked
{
void onItemClick(int position);
}
public void setOnClick(OnItemClicked onClick)
{
this.onClick = onClick;
}
public void setClickListener(ClickListener clicked)
{
RecyclerSubAdapter.clickListener = clicked;
}
public interface ClickListener
{
void itemClicked(SubjectsModel model, int position);
}
public void setData(ArrayList<SubjectsModel> data)
{
this.subMod = data;
//this.subMod.clear();
this.subMod.addAll(data);
notifyDataSetChanged();
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main_root">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.ashleighwilson.schoolscheduler.adapter.EmptyRecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="60dp"/>
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<TextView
android:id="#+id/empty_subject_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone"
android:text="#string/no_subjects"/>
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_sub"
style="#style/FAB" />
</RelativeLayout>
In OnAddSubjectSubmit() you call subMod.add(model);
and then you call recyclerSubAdapter.setData(subMod); which in turn calls this.subMod.addAll(data);.
Check it yourself. I believe it's there where you add the new item twice.
Suggestion: comment out recyclerSubAdapter.setData(subMod); from OnAddSubjectSubmit().
this.subMod = data;
this.subMod.addAll(data);
You initilize subMod by assigning data to it, and later you add data again:
this.subMod.addAll(data);
Here, I have two recyclerview that has parentRecyclerViewAdapter and childRecyclerViewAdapter. Parent adapter has LinearLayoutManager.VERTICAL layout manager whereas Clild adapter has GridLayoutManager(mContext, 2) layout manager with itemDecoration.
When scrolling for the first time the RecyclerView scrolling is laggy and once the data is viewed the scrolling is smooth. Until the app instance is not completely removed the scrolling will be smooth and when the app reinitiate the scrolling is laggy again.
Please help me out to figure out this BUG!!
ParentRecyclerViewAdapter
public class RecyclerViewDataAdapter extends RecyclerView.Adapter<RecyclerViewDataAdapter.ItemRowHolder> {
private ArrayList<SectionDataModel> dataList;
private Context mContext;
private RecyclerListItemClick onListClick;
public RecyclerViewDataAdapter(Context context, ArrayList<SectionDataModel> dataList) {
this.dataList = dataList;
this.mContext = context;
onListClick = (RecyclerListItemClick) context;
}
#Override
public ItemRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
return new ItemRowHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_row_template_section, null));
}
#Override
public void onBindViewHolder(ItemRowHolder itemRowHolder, int i) {
ArrayList<SingleTemplateModel> templateModelArrayList = dataList.get(i).getTemplateModelArrayList();
String sectionName = dataList.get(i).getHeaderTitle();
itemRowHolder.itemTitle.setText(sectionName);
TemplateChooserAdapter itemListDataAdapter = new TemplateChooserAdapter(mContext, templateModelArrayList , dataList.get(i).getHeaderTitle());
itemRowHolder.recycler_view_list.setAdapter(itemListDataAdapter);
}
#Override
public int getItemCount() {
return (null != dataList ? dataList.size() : 0);
}
public class ItemRowHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView itemTitle;
private RecyclerView recycler_view_list;
private ItemRowHolder(View view) {
super(view);
this.itemTitle = view.findViewById(R.id.itemTitle);
this.recycler_view_list = view.findViewById(R.id.recycler_view_list);
this.recycler_view_list.setOnClickListener(this);
this.recycler_view_list.setHasFixedSize(true);
this.recycler_view_list.setLayoutManager(new GridLayoutManager(mContext, 2));
this.recycler_view_list.addItemDecoration(new SpacesItemDecoration(2 , 25 , false));
}
#Override
public void onClick(View v) {
onListClick.onRecyclerItemClicked(dataList.get(getAdapterPosition()).getHeaderTitle());
}
}
}
ChildRecyclerAdapter
public class TemplateChooserAdapter extends RecyclerView.Adapter<TemplateChooserAdapter.ViewHolder> {
private static final String TAG = TemplateChooserAdapter.class.getSimpleName();
private Context context;
private ArrayList<SingleTemplateModel> templateModelArrayList;
private OnTemplatesListClicked onListClick;
public TemplateChooserAdapter(Context context, ArrayList<SingleTemplateModel> templateModelArrayList, String sectionName) {
this.context = context;
this.templateModelArrayList = templateModelArrayList;
onListClick = (OnTemplatesListClicked) context;
AppUtils.showLog(TAG, "CorporateUserAdapter");
}
#Override
public TemplateChooserAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(
LayoutInflater.from(parent.getContext()).inflate(R.layout.single_row_template_chooser, parent, false)
);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.templateView.setImageResource(templateModelArrayList.get(position).getImage());
}
#Override
public int getItemCount() {
return templateModelArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ImageView templateView;
public ViewHolder(View itemView) {
super(itemView);
templateView = itemView.findViewById(R.id.template_view);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
templateModelArrayList.get(getAdapterPosition()).setShowIndicator(true);
onListClick.onTemplateClick(templateModelArrayList.get(getAdapterPosition())); // TODO send model when item clicked
}
}
}
Activity.java
private void recyclerViewJob() {
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
RecyclerViewDataAdapter adapter = new RecyclerViewDataAdapter(this, allSampleData);
recyclerView.setAdapter(adapter);
}
SectionDataModel.java
public class SectionDataModel {
private String headerTitle;
private ArrayList<SingleTemplateModel> templateModelArrayList;
public SectionDataModel() {
}
public SectionDataModel(String headerTitle, ArrayList<SingleTemplateModel> templateModelArrayList) {
this.headerTitle = headerTitle;
this.templateModelArrayList = templateModelArrayList;
}
public String getHeaderTitle() {
return headerTitle;
}
public void setHeaderTitle(String headerTitle) {
this.headerTitle = headerTitle;
}
public ArrayList<SingleTemplateModel> getTemplateModelArrayList() {
return templateModelArrayList;
}
public void setTemplateModelArrayList(ArrayList<SingleTemplateModel> templateModelArrayList) {
this.templateModelArrayList = templateModelArrayList;
}
}
SingleTemplateModel.java
public class SingleTemplateModel {
private String title;
private String skuName;
private int image;
private boolean showIndicator;
public SingleTemplateModel(String title, String skuName, int image, boolean showIndicator) {
this.title = title;
this.skuName = skuName;
this.image = image;
this.showIndicator = showIndicator;
}
public String getSkuName() {
return skuName;
}
public void setSkuName(String skuName) {
this.skuName = skuName;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getImage() {
return image;
}
public void setImage(int image) {
this.image = image;
}
public boolean isShowIndicator() {
return showIndicator;
}
public void setShowIndicator(boolean showIndicator) {
this.showIndicator = showIndicator;
}
}
single_row_template_section.xml
<?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="wrap_content"
android:orientation="vertical"
android:paddingTop="30dp"
android:clickable="true"
android:focusable="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/itemTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:text="Sample title"
android:textColor="#color/white"
android:textSize="20sp"
android:textStyle="bold"
android:paddingLeft="5dp"
android:paddingBottom="10dp"/>
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="horizontal" />
</LinearLayout>
single_row_template_chooser.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="280dp"
card_view:cardElevation="6dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/template_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="#mipmap/model_9" />
</RelativeLayout>
</android.support.v7.widget.CardView>
I think you can try to lazy load your images from resources. There are libraries like Picasso or Glide that will help you with that.
So it may look like this:
Picasso:
import com.squareup.picasso.Picasso;
...
public class TemplateChooserAdapter extends RecyclerView.Adapter<TemplateChooserAdapter.ViewHolder> {
...
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Picasso.with(holder.itemView.getContext()).load(templateModelArrayList.get(position).getImage()).into(holder.templateView);
}
...
}
I tried databinding with RecyclerView, but my main_activity doesn't show the RecyclerView Content for my Objects. I dont know where the point of failure is.
Thanks for any advice.
Here my simple Code
class: User
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class: UserAdapter
public class UserAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Activity host;
private ArrayList<User> items;
public UserAdapter(Activity activity, ArrayList<User> items) {
this.host = activity;
this.items = items;
Log.i("UserAdapterName", items.get(0).getName().toString()); //log shows Gordon
}
#Override
public UserAdapter.ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// inflate layout and retrieve binding
ListItemsBinding binding = DataBindingUtil.inflate(host.getLayoutInflater(),
R.layout.list_items, parent, false);;
return new ItemViewHolder(binding);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
User item = items.get(position);
ItemViewHolder itemViewHolder = (ItemViewHolder)holder;
itemViewHolder.bindItem(item);
}
#Override
public int getItemCount() {
return items.size();
}
static class ItemViewHolder extends RecyclerView.ViewHolder {
ListItemsBinding binding;
ItemViewHolder(ListItemsBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
void bindItem(User item) {
binding.setUser(item);
binding.executePendingBindings();
}
}
}
class: MainActivity
public class MainActivity extends AppCompatActivity {
private ArrayList<User> userList = new ArrayList<User>();
private ActivityMainBinding binding;
private UserAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
fillData();
adapter = new UserAdapter(MainActivity.this,userList);
binding.recycler.setAdapter(adapter);
}
private void fillData() {
userList.add(new User("Gordon", 26));
userList.add(new User("Dick", 34));
userList.add(new User("Ivan",20));
}
}
layout: activity_main
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Activity Text"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
layout: list_items
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="user"
type="de.bp2go.recgo.User" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{user.name}"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/black"
tools:text="Name" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{user.age}"
android:textColor="#android:color/black"
tools:text="Age" />
</LinearLayout>
</layout>
For me it looks like You forgot to set proper LayoutManager for RecyclerView.
Missing line for vertical list:
binding.recycler.setLayoutManager(new LinearLayoutManager(this));
public class MainActivity extends AppCompatActivity {
private ArrayList<User> userList = new ArrayList<User>();
private ActivityMainBinding binding;
private UserAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fillData();
recycler = (RecyclerView) findViewById(R.id.recycler);
LinearLayoutManager manager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
recycler.setLayoutManager(manager);
adapter = new UserAdapter(MainActivity.this,userList);
recycler.setAdapter(adapter);
}
private void fillData() {
userList.add(new User("Gordon", 26));
userList.add(new User("Dick", 34));
userList.add(new User("Ivan",20));
}
}
public class UserAdapter extends RecyclerView.Adapter<ItemViewHolder.ViewHolder> {
private Activity host;
private ArrayList<User> items;
LayoutInflater inflator;
public UserAdapter(Activity activity, ArrayList<User> items) {
this.host = activity;
this.items = items;
Log.i("UserAdapterName", items.get(0).getName().toString()); //log shows Gordon
inflator=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public UserAdapter.ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// inflate layout and retrieve binding
View view =inflator.inflate(R.layout.list_items, parent,false);
return new ItemViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
User item = items.get(position);
ItemViewHolder itemViewHolder = (ItemViewHolder)holder;
itemViewHolder.bindItem(item);
}
#Override
public int getItemCount() {
return items.size();
}
static class ItemViewHolder extends RecyclerView.ViewHolder {
ListItemsBinding binding;
ItemViewHolder(ListItemsBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
void bindItem(User item) {
binding.setUser(item);
binding.executePendingBindings();
}
}
}
I have a recyclerview which populates data from SQL database. Now each row in the recyclerview has a seekbar which when moved displays it's progress in a textview inside the same row. The problem is when I scroll the recyclerview up or down then return back to the first changed row, the seekbar is returned to its default position. How can I make it save the new position ? In normal activities/fragments I use lifecycle methods as "onPause" to save/restore the state. Here we have onAttachedToRecyclerView, I think it should solve my problem but I don't know exactly how.
EDIT : here is a full simple app files which I'm working on to test this problem.
MainActivity.class
public class MainActivity extends AppCompatActivity {
private List<Score> scoreList = new ArrayList<>();
private RecyclerView recyclerView;
private MyAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
mAdapter = new MyAdapter(scoreList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
prepareScoreData();
}
private void prepareScoreData() {
Score score = new Score("title", 5);
scoreList.add(score);
for(int i= 0; i<1000; i++){
score = new Score("title", 5);
scoreList.add(score);
}
mAdapter.notifyDataSetChanged();
}
}
MyAdapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<Score> scoresList;
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView title, scoreView;
SeekBar seekbar;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
scoreView = (TextView) view.findViewById(R.id.score);
seekbar = (SeekBar) view.findViewById(R.id.seekbar);
}
}
public MyAdapter(List<Score> scoresList) {
this.scoresList = scoresList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
final Score score = scoresList.get(position);
holder.title.setText(score.getTitle());
if (!score.getProgressed()) {
holder.seekbar.setProgress(0) ;
} else {
holder.seekbar.setProgress(score.getSeekbarProgress());
}
holder.seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
holder.scoreView.setText(String.valueOf(i));
score.setSeekbarProgress(i);
score.setProgressed(true);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
#Override
public int getItemCount() {
return scoresList.size();
}
}
Score class
public class Score {
private String title;
int seekbarProgress;
boolean progressed;
public Score() {
}
public Score(String title,int seekbarProgress) {
this.title = title;
this.seekbarProgress = seekbarProgress;
}
public void setProgressed(boolean progressed) {
this.progressed = progressed;
}
public void setTitle(String title) {
this.title = title;
}
public void setSeekbarProgress(int seekbarProgress) {
this.seekbarProgress = seekbarProgress;
}
public String getTitle() {
return title;
}
public int getSeekbarProgress() {
return seekbarProgress;
}
public boolean getProgressed() {
return progressed;
}
}
MainActivity_Layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.moaness.tut_recyclerview.MainActivity">
<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
item.xml
<?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"
android:focusable="true"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="60dp"
android:paddingBottom="60dp"
android:layout_marginBottom="10dp"
android:clickable="true"
android:background="#f2f2f2"
android:orientation="vertical">
<TextView
android:id="#+id/title"
android:text="title"
android:textColor="#color/title"
android:textSize="16dp"
android:paddingTop="16dp"
android:textStyle="bold"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/score"
android:text="score"
android:layout_below="#+id/title"
android:textSize="16dp"
android:paddingBottom="16dp"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/score"
android:id="#+id/seekbar"
/>
</RelativeLayout>
If you are using recyclerview you need to maintain states of each row, means if you are checking using a condition(i.e. if) at any stage of recyclerview item(in recyclerview adapter class) then you need to handle else as well. I can send you a code snippet so you can have a good idea for recyclerview adapter.
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ViewHolder> {
List<ViewHolder> holders = new ArrayList<ViewHolder>();
private ArrayList<ContactModel> arrayList = new ArrayList<>();
private Context context;
private LayoutInflater inflater;
public void clearAdapter() {
arrayList.clear();
notifyDataSetChanged();
}
public ContactsAdapter(Context context, ArrayList<ContactModel> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
public void setList(ArrayList<ContactModel> listSearch) {
this.arrayList = listSearch;
notifyItemRangeChanged(0, listSearch.size());
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.custom_row_for_contacts, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
holders.add(viewHolder);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final ContactModel current = this.arrayList.get(position);
holder.txtDriverName.setText(current.getName());
holder.txtDriverPhone.setText(current.getPhone());
if (current.getImgUrl().length() > 0) {
String urlLicenceThumb = UrlEndPoints.parentUrl + current.getImgUrl();
Glide.with(context).load(urlLicenceThumb).error(R.mipmap.ic_launcher).into(holder.imgDriver);
} else {
Glide.with(context).load(R.mipmap.ic_launcher).into(holder.imgDriver);
}
}
public void delete(int position) {
arrayList.remove(position);
notifyItemRemoved(position);
}
#Override
public int getItemCount() {
return (null != arrayList ? arrayList.size() : 0);
}
class ViewHolder extends RecyclerView.ViewHolder {
private TextView txtDriverName, txtDriverPhone;
private CircleImageView imgDriver;
private Button btnInvite;
private CheckBox chkAdd;
public ViewHolder(View itemView) {
super(itemView);
chkAdd = (CheckBox) itemView.findViewById(R.id.chkAdd);
imgDriver = (CircleImageView) itemView.findViewById(R.id.imgDriver);
txtDriverName = (TextView)itemView.findViewById(R.id.txtDriverName);
txtDriverPhone = (TextView) itemView.findViewById(R.id.txtDriverPhone);
btnInvite = (Button) itemView.findViewById(R.id.btnInvite);
}
}
}
i'm searching function that programmatically click method. so i found some method. 'performClick()'
like that :
recyclerView.findViewHolderForAdapterPosition(position).itemView.performClick();
but it dosen't work in my case. I can't find solution. How do i use the performClick in Activity???
my Adapter - ViewHolder:
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView virtNo;
private TextView score01;
private TextView score02;
private TextView score03;
private TextView totalScore;
private LinearLayout linearLayout;
public ViewHolder(View itemView) {
super(itemView);
this.virtNo = (TextView) itemView.findViewById(R.id.tv_virtNo);
this.score01 = (TextView) itemView.findViewById(R.id.tv_score01);
this.score02 = (TextView) itemView.findViewById(R.id.tv_score02);
this.score03 = (TextView) itemView.findViewById(R.id.tv_score03);
this.totalScore = (TextView) itemView.findViewById(R.id.tv_totalScore);
this.linearLayout = (LinearLayout) itemView.findViewById(R.id.ll_item_score);
virtNo.setOnClickListener(this);
score01.setOnClickListener(this);
score02.setOnClickListener(this);
score03.setOnClickListener(this);
score10.setOnClickListener(this);
}
#Override
public void onClick(View v) {
onClickListener.onClick(v, getAdapterPosition(), items.get(getAdapterPosition()));
}
}
public void setOnClickListener(OnClickListener<Score> onClickListener) {
this.onClickListener = onClickListener;
}
public interface OnClickListener<T> {
void onClick(View v, int position, T item);
}
my Adapter - onBindViewHolder
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Score item = items.get(position);
holder.virtNo.setText(item.virtNo);
holder.score01.setText(item.score01);
holder.score02.setText(item.score02);
holder.score03.setText(item.score03);
holder.totalScore.setText(itemSum(item));
}
}
I have tried to keep things easy to understand here, it is a complete example for listening to click event on individual items in RecyclerView, there are other ways to do it as well. This code works, You may modify it as it fits you, in case you have any question write them in comments. code is also available at GitHub
public class RecyclerViewOneActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_view_one);
initializeUI();
}
private void initializeUI() {
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.RecyclerViewOneActivity_RecyclerView);
RecyclerView.LayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
ArrayList<String> strings = new ArrayList<>();
strings.add("first");
strings.add("second");
MyAdapter adapter = new MyAdapter(getApplicationContext(), strings);
recyclerView.setAdapter(adapter);
}
private class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
private ArrayList<String> strings;
private LayoutInflater layoutInflater;
public MyAdapter(Context context, ArrayList<String> strings) {
this.context = context;
this.strings = strings;
layoutInflater = LayoutInflater.from(this.context);
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = layoutInflater.inflate(R.layout.single_item_recycler_view_one, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final String text = this.strings.get(position);
holder.textView.setText("" + text);
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, ""+text, Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return strings.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
private LinearLayout linearLayout;
private TextView textView;
public MyViewHolder(View itemView) {
super(itemView);
linearLayout = (LinearLayout) itemView.findViewById(R.id.single_item_recycler_view_one_linear_layout);
textView = (TextView) itemView.findViewById(R.id.single_item_recycler_view_one_textView);
}
}
}
}
single_item_recycler_view_one.xml
<?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="wrap_content"
android:layout_margin="8dp"
android:id="#+id/single_item_recycler_view_one_linear_layout"
android:orientation="vertical">
<TextView
android:id="#+id/single_item_recycler_view_one_textView"
android:layout_width="match_parent"
android:textColor="#000"
android:layout_height="wrap_content"
android:text="Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>