Save selected items in RecyclerView when closing app or switching fragments - java

I have a Recycler View in my fragment that opens activities when an item is clicked and highlights the item when it is long clicked. However, when I switch fragments or close my app and reopen it, I want the previously selected items to stay selected. I imagine this is done with Shared Preferences, but how are the selected items saved and then filled again?
Here is my custom Adapter. The TextViews are selected in onBindViewHolder :
public class ExampleAdapter extends RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder> {
private ArrayList<Workout> mExampleList;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public static class ExampleViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView1,mTextView2,mTextView3,mTextView4;
CardView mCardView;
public ExampleViewHolder(View itemView, final OnItemClickListener listener)
{
super(itemView);
mTextView1 = itemView.findViewById(R.id.listTextView1);
mTextView2 = itemView.findViewById(R.id.listTextView2);
mTextView3 = itemView.findViewById(R.id.listTextView3);
mTextView4 = itemView.findViewById(R.id.listTextView4);
mCardView = itemView.findViewById(R.id.cardView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(position);
}
}
}
});
}
}
public ExampleAdapter(ArrayList<Workout> exampleList) {
mExampleList = exampleList;
}
#NonNull
#Override
public ExampleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_view_item,parent,false);
ExampleViewHolder evh = new ExampleViewHolder(v, mListener);
return evh;
}
#Override
public void onBindViewHolder(#NonNull final ExampleViewHolder holder, final int position) {
Workout workout = mExampleList.get(position);
holder.mTextView1.setText(workout.getText1());
holder.mTextView2.setText(workout.getText2());
holder.mTextView3.setText(workout.getText3());
holder.mTextView4.setText(workout.getText4());
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
if(holder.mTextView1.isSelected()) {
holder.mTextView1.setSelected(false);
holder.mTextView2.setSelected(false);
holder.mTextView3.setSelected(false);
holder.mTextView4.setSelected(false);
} else {
holder.mTextView1.setSelected(true);
holder.mTextView2.setSelected(true);
holder.mTextView3.setSelected(true);
holder.mTextView4.setSelected(true);
}
return true;
}
});
}
#Override
public int getItemCount() {
return mExampleList.size();
}
}
This is my fragment:
public class HomeFragment extends Fragment implements View.OnClickListener{
private RecyclerView mRecyclerView;
private ExampleAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
ArrayList<Workout> exampleList;
MainActivity mainActivity;
DataModel dataModel = new DataModel();
View rootView;
private TextView[] textViews;
private CardView[] cardViews;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_home,container,false);
mainActivity = (MainActivity) getActivity();
mainActivity.setToolbarName("Workouts");
textViews = new TextView[16];
cardViews = new CardView[3];
for(int i=0; i<textViews.length; i++) {
{
String buttonID = "textView" + (i+1);
int resID = getResources().getIdentifier(buttonID, "id", getActivity().getPackageName());
textViews[i] = ((TextView) rootView.findViewById(resID));
}
}
updateWeekText();
textViews[2].setText(roundDecimals(mainActivity.getBenchMax()));
textViews[4].setText(roundDecimals(mainActivity.getSquatMax()));
textViews[6].setText(roundDecimals(mainActivity.getDeadliftMax()));
textViews[8].setText(roundDecimals(mainActivity.getPressMax()));
Button buttonNextWeek = rootView.findViewById(R.id.buttonNextWeek);
buttonNextWeek.setOnClickListener(this);
int week = MainActivity.getWeekNumber();
exampleList = new ArrayList<>();
if(week == 1 || week == 2 || week == 3 || week == 4){
exampleList.add(new Workout("Day 1", "C-S", "C-B", "Rack Pulls"));
exampleList.add(new Workout("Day 2", "2ct Paused Squat", "C-P", "Pendlay Row"));
exampleList.add(new Workout("Day 3", "C-D", "Floor Press", "Leg Press"));
} else {
exampleList.add(new Workout("Day 1", "C-S", "C-B", "2ct Paused Deadlift"));
exampleList.add(new Workout("Day 2", "Pin Squat", "C-P", "Pendlay Row"));
exampleList.add(new Workout("Day 3", "C-D", "2ct Paused Bench", "303 Tempo Squat"));
}
buildRecyclerView();
return rootView;
}
public void buildRecyclerView() {
mRecyclerView = rootView.findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getContext());
mAdapter = new ExampleAdapter(exampleList);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
if (position == 0) {
startActivity(new Intent(getActivity(),ActivityDay1.class));
}
if (position == 1) {
startActivity(new Intent(getActivity(),ActivityDay2.class));
}
}
});
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.buttonNextWeek:
createDialog();
break;
}
}
private void updateWeekText() {
textViews[9].setText("Current week: "+String.valueOf(mainActivity.getWeekNumber()));
}
private void createDialog(){
int nextWeek = mainActivity.getWeekNumber()+1;
AlertDialog.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = new AlertDialog.Builder(getContext(), android.R.style.Theme_Material_Dialog_Alert);
} else {
builder = new AlertDialog.Builder(getContext());
}
builder.setTitle("Start week "+nextWeek+"?")
.setMessage("Are you sure?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mainActivity.setWeekNumber(mainActivity.getWeekNumber()+1);
updateWeekText();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.setIcon(R.drawable.ic_navigate_next_black_24dp)
.show();
}
public String roundDecimals(double a){
NumberFormat nf = new DecimalFormat("##.###");
return nf.format(a);
}
I'll appreciate any help.
Let me know if more code is needed.

You need to fix some errors in Adapter implementation first.
Add isCompleted boolean field into your Workout class. With current adapter implementation your "selected" state is going to get messed up merely by scrolling the recyclerView, since your don't store the value, only change ViewHolder state.
Move body of your LongLickListener into new method of ViewHolder:
void setSelected(boolean selected){
mTextView1.setSelected(selected);
mTextView2.setSelected(selected);
mTextView3.setSelected(selected);
mTextView4.setSelected(selected);
}
Now you can change your LongClickListener into:
#Override
public boolean onLongClick(View view) {
workout.isCompleted = !workout.isCompleted;
holder.setSelected(workout.isCompleted);
return true;
}
This way state of workout completion is actually stored in your data list. To ensure view state is correct, add this line to your onBindViewHolder:
holder.setSelected(workout.isCompleted);
Otherwise ViewHolder that was previously bound to "completed" workout would incorrectly display when showing "not completed" one.
As for storing the selected items - this is a bit tricky since it's mostly a persistence/database design issue.
Are your Workout items just a definition of a workout?
are they recurring?
can user add/remove workout definitions?
is there a history for completed workouts? Or it's reset daily?
You need to at least define some stable ID for each workout to properly persist them, then I suggest looking into database implementation with raw SQLite, Room or Realm.

Related

How to highlight a selected RecyclerView item and use its values in Activity

I have a list of words with translations in RecyclerView. I want the selected word to be highlighted, but at the same time I could use these values in Activity. I can highlight selected values or use the values of a selected item, but the combination of the both fails.
Please, maybe You see where I am wrong and can help solve my problem.
p.s. Please don’t judge me for the not enough clean code and my English, I’m learning. :)
MyListActivity.java
public class MyListActivity extends AppCompatActivity {
public ArrayList<MyWord> myWordList = new ArrayList<>();
SelectData sd = new SelectData();
int wordId;
String word;
String translation;
public RecyclerView mRecycleView;
public MyAdapter mAdapter;
public RecyclerView.LayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_list);
sd.selectMyWords(myWordList);
buildRecycleView();
Button btnInsert = findViewById(R.id.mywords_button_insert);
Button btnEdit = findViewById(R.id.mywords_button_edit);
Button btnDelete = findViewById(R.id.mywords_button_delete);
Button btnMain = findViewById(R.id.mywords_button_backttomain);
mAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
// **This is my selected item values**
wordId = myWordList.get(position).getWordId();
word = myWordList.get(position).getWord();
translation = myWordList.get(position).getTranslation();
Toast.makeText(MyListActivity.this, "Selected -> " + word, Toast.LENGTH_SHORT).show();
}
});
btnEdit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!(word == null)) {
Intent intentInsert = new Intent(MyListActivity.this, InsertActivity.class);
intentInsert.putExtra("W", word);
intentInsert.putExtra("TR", translation);
intentInsert.putExtra("ACTION", "ED");
startActivity(intentInsert);
} else {
Toast.makeText(MyListActivity.this, "Select word", Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
public void buildRecycleView(){
mRecycleView = findViewById(R.id.mywords_RecycleView);
mRecycleView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mAdapter = new MyAdapter(myWordList);
mRecycleView.setLayoutManager(mLayoutManager);
mRecycleView.setAdapter(mAdapter);
if (myWordList.isEmpty()){
Toast.makeText(this, "word list is empty", Toast.LENGTH_SHORT).show();
}
}
}
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private ArrayList<MyWord> mMyWordList;
private OnItemClickListener mListener;
public interface OnItemClickListener{
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener){
mListener = listener;
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView mTextViewEN;
public TextView mTextViewLT;
public ImageView imageViewLearned;
public MyViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
mTextViewEN = itemView.findViewById(R.id.myList_textView_word);
mTextViewLT = itemView.findViewById(R.id.myList_textView_translation);
imageViewLearned = itemView.findViewById(R.id.iV_learned);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION){
listener.onItemClick(position);
}
}
}
});
}
}
public MyAdapter(ArrayList<MyWord> myWordList){
mMyWordList = myWordList;
}
int selectedItem = -1;
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_list_view_layout, parent, false);
MyViewHolder mvh = new MyViewHolder(v, mListener);
return mvh;
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, final int position) {
MyWord currentMyWord = mMyWordList.get(position);
holder.mTextViewEN.setText(currentMyWord.getWord());
holder.mTextViewLT.setText(currentMyWord.getTranslation());
// TODO - START (select item highlight) - if I activate highlighting, the assignment of values no longer works in MyListActivity.
/* holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectedItem = position;
notifyDataSetChanged();
}
});
if (selectedItem == position) {
holder.itemView.setBackgroundColor(Color.parseColor("#C0C0C0"));
} else {
holder.itemView.setBackgroundColor(Color.parseColor("#F8F8F8"));
} */
//TODO -END
}
#Override
public int getItemCount() {
return mMyWordList.size();
}
}
Looks like your commented code would overwrite your click listener with one that only hightlights. Try combining them:
public MyViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
mTextViewEN = itemView.findViewById(R.id.myList_textView_word);
mTextViewLT = itemView.findViewById(R.id.myList_textView_translation);
imageViewLearned = itemView.findViewById(R.id.iV_learned);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION){
selectedItem = position;
notifyDataSetChanged();
listener.onItemClick(position);
}
}
}
});
}

How To Refresh Item Positions In Recylcerview for filtering?

I want to filter recyclerView items, my code is working well in terms of displaying filtered items but when I am clicking on those items it's clicking on previous items though those items are not visible. I thought the problem is on item clickListener implementation but I have tried two recylcerview onitemClickListener implementation but both of them aren't working.
Can You Please Help? Thanks In Advance.
Here is the filter code in Recyclerview Adapter.
public void updateList(List<ProductInfo> list){
mProductList = list;
notifyDataSetChanged();
}
Here is the Clicklistener on Recyclerview in Activity.
mProductAdapter = new AdapterTest(mProductInfos, new AdapterTest.ClickListener(){
#Override
public void onPositionClicked(View v, int position) {
ProductInfo productInfo = mProductInfos.get(position);
Intent intent = new Intent(VegetableActivity.this, DescriptionActvity.class);
intent.putExtra(MainActivity.EXTRA_OBJECT, productInfo);
startActivity(intent);
}
#Override
public void onLongClicked(View v, int position) {
}
});
And This is the Adapter Class.
public class AdapterTest extends RecyclerView.Adapter<AdapterTest.MyviewHolder> {
private List<ProductInfo> mProductList;
private ClickListener listener;
public class MyviewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener{
private TextView mProductName, mProductPrice, mProductRating;
private ImageView mProductImage;
private WeakReference<ClickListener> listenerRef;
public MyviewHolder(View itemView, ClickListener listener) {
super(itemView);
listenerRef = new WeakReference<>(listener);
mProductName = itemView.findViewById(R.id.product_name);
mProductPrice = itemView.findViewById(R.id.product_price);
//mProductRating = itemView.findViewById(R.id.product_rating);
mProductImage = itemView.findViewById(R.id.product_image);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
// if(view.getId() == decreaseView.getId()){
// Toast.makeText(view.getContext(), "ITEM PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
// }else {
// Toast.makeText(view.getContext(), "ROW PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();
// }
listenerRef.get().onPositionClicked(view, getAdapterPosition());
}
#Override
public boolean onLongClick(View view) {
return false;
}
}
public AdapterTest(List<ProductInfo> productList, ClickListener listener){
mProductList = productList;
this.listener = listener;
}
#Override
public MyviewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.vegetable_layout, parent, false);
return new MyviewHolder(itemView, listener);
}
#Override
public void onBindViewHolder(MyviewHolder holder, int position) {
ProductInfo productInfo = mProductList.get(position);
holder.mProductName.setText(productInfo.getProductName());
holder.mProductPrice.setText(productInfo.getProductPrice());
//holder.mProductRating.setText(productInfo.getProductRating());
Picasso.get()
.load(productInfo.getProductImage())
.into(holder.mProductImage);
}
#Override
public int getItemCount() {
return mProductList.size();
}
public interface ClickListener {
void onPositionClicked(View v, int position);
void onLongClicked(View v, int position);
}
public void updateList(List<ProductInfo> list){
mProductList = list;
notifyDataSetChanged();
}
}
you can move below code segement to onCLick evenet of the recycle item
Intent intent = new Intent(VegetableActivity.this, DescriptionActvity.class);
intent.putExtra(MainActivity.EXTRA_OBJECT, productInfo);
startActivity(intent);
you donot need the onPositionClicked listener for that and you can remove ProductInfo productInfo = mProductInfos.get(position); as well. I have no clear idea about what u doing. but let say u want to nevigate to another page when u click on recycle item. u can add it like below
#Override
public void onBindViewHolder(MyviewHolder holder, int position) {
ProductInfo productInfo = mProductList.get(position);
holder.mProductName.setText(productInfo.getProductName());
holder.mProductPrice.setText(productInfo.getProductPrice());
//holder.mProductRating.setText(productInfo.getProductRating());
Picasso.get()
.load(productInfo.getProductImage())
.into(holder.mProductImage);
//new code - start here
holder.anyuielementInItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
// Do things you want
}
});
//
}

Item removed from ArrayList, but notifyDataSetChanged() only deletes the bottom item

I have a recycler view, with an ArrayList from custom objects.
Each row has a delete button, when clicked the item is deleted from the recyclerview.
Now the delete button works, and deletes the correct item from the arraylist, however when the items are displayed again in the list, only the bottom item is deleted, and the item which was really deleted from the list stays there.
Its really weird, and I cannot figure out why?
I manage the deleted item from the activity, here is the code of the activity:
public class ManageExerciseActivity extends AppCompatActivity {
private static final String TAG = "999.OffLimitsActivity";
private RecyclerView exerciseRecyclerView;
private ExerciseManageAdapter exerciseAdapter;
public ArrayList<Exercise> exerciseList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_exercise);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(ManageExerciseActivity.this, AddExerciseActivity.class);
startActivity(intent);
}
});
fab.setImageBitmap(textAsBitmap("ADD", 40, Color.WHITE));
exerciseList = new ArrayList<>();
getSupportActionBar().setTitle("Manage my exercises");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
exerciseRecyclerView = (RecyclerView) findViewById(R.id.exercise_manage_recycler_view);
exerciseAdapter = new ExerciseManageAdapter(exerciseList);
exerciseAdapter.setOnItemClickListener(new ExerciseManageAdapter.ClickListener() {
#Override
public void onItemClick(final int position, final View v) {
Log.d(TAG, "onItemClick pos = " + position);
// custom dialog
AlertDialog.Builder builder = new AlertDialog.Builder(ManageExerciseActivity.this);
builder.setMessage("Do you wish to delete this exercise?")
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String itemRemoved = exerciseList.get(position).getNameOfExercise();
exerciseList.remove(position);
exerciseAdapter.notifyDataSetChanged();
Snackbar.make(v, itemRemoved + " deleted", Snackbar.LENGTH_LONG)
.setAction("Undo", null).show();
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Create the AlertDialog object and return it
builder.create();
builder.show();
}
});
exerciseRecyclerView.setAdapter(exerciseAdapter);
exerciseRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
and here is the adapter:
public class ExerciseManageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static ClickListener clickListener;
public ImageView exerciseItemIcon;
public TextView exerciseNameTextView;
public TextView exerciseDurationTextView;
public TextView exerciseTimesRemainingTextView;
public ImageView deleteImageView;
ArrayList<Exercise> exerciseArrayList = new ArrayList<>();
public ExerciseManageAdapter(ArrayList<Exercise> exerciseArrayList) {
this.exerciseArrayList = exerciseArrayList;
}
public interface ClickListener {
void onItemClick(int position, View v);
}
class ExerciseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public ExerciseViewHolder(View view) {
super(view);
// view.setOnClickListener(this);
exerciseNameTextView = (TextView)view.findViewById(R.id.exercise_manage_name_textView);
exerciseDurationTextView = (TextView)view.findViewById(R.id.exercise_manage_duration_textview);
exerciseTimesRemainingTextView = (TextView)view.findViewById(R.id.exercise_manage_times_remaining);
exerciseItemIcon = (ImageView)view.findViewById(R.id.exercise_manage_item_icon);
deleteImageView = (ImageView)view.findViewById(R.id.delete_exercise_button);
deleteImageView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
clickListener.onItemClick(getAdapterPosition(), v);
}
}
public void setOnItemClickListener(ClickListener clickListener) {
ExerciseManageAdapter.clickListener = clickListener;
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getItemCount() {
return exerciseArrayList.size();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.exercise_manage_item_row, parent, false);
return new ExerciseViewHolder(itemView);
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
ExerciseViewHolder exerciseViewHolder = (ExerciseViewHolder) holder;
exerciseNameTextView.setText(exerciseArrayList.get(position).getNameOfExercise());
exerciseDurationTextView.setText(exerciseArrayList.get(position).getDurationOfExercise());
exerciseTimesRemainingTextView.setText(exerciseArrayList.get(position).getTimesPerWeek() + " times a week");
exerciseItemIcon.setImageResource(exerciseArrayList.get(position).getExerciseIcon());
}
}
Thanks
try this.!
notifyItemRemoved(position);
notifyItemRangeChanged(position, mData.size());

How to add sections for checked and unchecked items in recyclerview?

I have a list of tasks in recyclerview. Each task item has a check box to show if the task is completed or pending.
Now I want to show two sections in my list. One for checked items and another for unchecked items.
I have gone through this library to add the sections.
https://github.com/afollestad/sectioned-recyclerview
But how can I divide the items in list on the basis of they are checked or not?
Also I want to add the task into another section if checked or unchecked , i.e onClick.
If task is unchecked, and if I check it, it should get added to the completed section and vise versa.
I have a recyclerview now with swipe layout. Following is the adapter.
adapetr:
public class IAdapter extends RecyclerSwipeAdapter<IAdapter.ItemViewHolder> , SectionedRecyclerViewAdapter<IAdapter.ItemViewHolder> {
public ArrayList<Task> items;
Context conext;
public int _mId;
List<Task> itemsPendingRemoval = new ArrayList<>();
public IAdapter(Context context, ArrayList<Task> item) {
this.conext=context;
this.items=item;
}
#Override
public int getSectionCount() {
return 2;
}
#Override
public int getItemCount(int section) {
return items.size();
}
public static class ItemViewHolder extends RecyclerView.ViewHolder {
Task task;
CheckBox cb;
SwipeLayout swipeLayout;
TaskTableHelper taskTableHelper;
ItemViewHolder(final View itemView) {
super(itemView);
taskTableHelper= new TaskTableHelper(itemView.getContext());
swipeLayout = (SwipeLayout) itemView.findViewById(R.id.swipe);
cb = (CheckBox) itemView.findViewById(R.id.checkbox);
}
}
#Override
public void onBindViewHolder(final ItemViewHolder itemViewHolder,final int i) {
itemViewHolder.cb.setText(items.get(i).getTitle());
itemViewHolder.task = items.get(i);
int taskId = itemViewHolder.task.getId();
itemViewHolder.task = itemViewHolder.taskTableHelper.getTask(taskId);
int status = itemViewHolder.task.getStatus();
if(status == 0)
{
itemViewHolder.cb.setTextColor(Color.WHITE);
}
else {
itemViewHolder.cb.setChecked(true);
itemViewHolder.cb.setTextColor(Color.parseColor("#B0BEC5"));
}
itemViewHolder.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
itemViewHolder.cb.setTextColor(Color.parseColor("#B0BEC5"));
itemViewHolder.task.setStatus(1);
itemViewHolder.taskTableHelper.updateStatus(itemViewHolder.task);
}
else
{
itemViewHolder.cb.setTextColor(Color.WHITE);
itemViewHolder.task.setStatus(0);
itemViewHolder.taskTableHelper.updateStatus(itemViewHolder.task);
}
}
});
final Task item = items.get(i);
itemViewHolder.swipeLayout.addDrag(SwipeLayout.DragEdge.Right,itemViewHolder.swipeLayout.findViewById(R.id.bottom_wrapper_2));
itemViewHolder.swipeLayout.setShowMode(SwipeLayout.ShowMode.LayDown);
itemViewHolder.swipeLayout.setOnDoubleClickListener(new SwipeLayout.DoubleClickListener() {
#Override
public void onDoubleClick(SwipeLayout layout, boolean surface) {
Toast.makeText(conext, "DoubleClick", Toast.LENGTH_SHORT).show();
}
});
itemViewHolder.swipeLayout.findViewById(R.id.trash2).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mItemManger.removeShownLayouts(itemViewHolder.swipeLayout);
items.remove(i);
notifyItemRemoved(i);
notifyItemRangeChanged(i, items.size());
mItemManger.closeAllItems();
itemViewHolder.taskTableHelper.deleteTask(item);
_mId = item.getAlertId();
cancelNotification();
Toast.makeText(view.getContext(), "Deleted " + itemViewHolder.cb.getText().toString() + "!", Toast.LENGTH_SHORT).show();
}
});
itemViewHolder.swipeLayout.findViewById(R.id.done).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
itemViewHolder.task.setStatus(1);
itemViewHolder.taskTableHelper.updateStatus(itemViewHolder.task);
itemViewHolder.cb.setChecked(true);
Toast.makeText(conext, "Task Completed.", Toast.LENGTH_SHORT).show();
}
});
itemViewHolder.swipeLayout.getSurfaceView().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean mEditMode;
int id = item.getId();
int priority = item.getTaskPriority();
String title = item.getTitle();
String alertDate = item.getAlertDate();
String alertTime = item.getAlertTime();
String dueDate = item.getDueDate();
String dueTime = item.getDueTime();
_mId = item.getAlertId();
int listId = item.getList();
mEditMode = true;
Intent i = new Intent(conext, AddTaskActivity.class);
i.putExtra("taskId", id);
i.putExtra("taskTitle", title);
i.putExtra("taskPriority", priority);
i.putExtra("taskAlertTime", alertTime);
i.putExtra("taskAlertDate", alertDate);
i.putExtra("taskDueDate", dueDate);
i.putExtra("taskDueTime", dueTime);
i.putExtra("taskListId", listId);
i.putExtra("EditMode", mEditMode);
i.putExtra("AlertId",_mId);
conext.startActivity(i);
}
});
mItemManger.bindView(itemViewHolder.itemView, i);
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup,int position) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.card_layout, viewGroup, false);
return new ItemViewHolder(itemView);
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
public void remove(int position) {
Task item = items.get(position);
if (itemsPendingRemoval.contains(item)) {
itemsPendingRemoval.remove(item);
}
if (items.contains(item)) {
items.remove(position);
notifyItemRemoved(position);
}
}
public void cancelNotification()
{
AlarmManager alarmManager = (AlarmManager)conext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(conext, NotificationReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(conext,_mId, intent, 0);
alarmManager.cancel(pendingIntent);
}
#Override
public int getSwipeLayoutResourceId(int position) {
return R.id.swipe;
}
}
Can anyone help please?
Thank you..
You can add "sections" to your recyclerview with the library SectionedRecyclerViewAdapter.
First create a Section class to group your tasks:
class TaskSection extends StatelessSection {
String title;
List<Task> list;
public TaskSection(String title, List<Task> list) {
// call constructor with layout resources for this Section header, footer and items
super(R.layout.section_header, R.layout.section_item);
this.title = title;
this.list = list;
}
#Override
public int getContentItemsTotal() {
return list.size(); // number of items of this section
}
public int addTask(Task task) {
return list.add(task;
}
public int removeTask(Task task) {
return list.remove(task;
}
#Override
public RecyclerView.ViewHolder getItemViewHolder(View view) {
// return a custom instance of ViewHolder for the items of this section
return new MyItemViewHolder(view);
}
#Override
public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
MyItemViewHolder itemHolder = (MyItemViewHolder) holder;
// bind your view here
itemHolder.tvItem.setText(list.get(position).getTitle());
}
#Override
public RecyclerView.ViewHolder getHeaderViewHolder(View view) {
return new SimpleHeaderViewHolder(view);
}
#Override
public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) {
MyHeaderViewHolder headerHolder = (MyHeaderViewHolder) holder;
// bind your header view here
headerHolder.tvItem.setText(title);
}
}
Then you set up the RecyclerView with your Sections:
// Create an instance of SectionedRecyclerViewAdapter
SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter();
// Create your sections with the list of data
TaskSection compSection = new TaskSection("Completed", compList);
TaskSection pendSection = new TaskSection("Pending", pendList);
// Add your Sections to the adapter
sectionAdapter.addSection(compSection);
sectionAdapter.addSection(pendSection);
// Set up your RecyclerView with the SectionedRecyclerViewAdapter
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(sectionAdapter);
Now if you want to send a task from "Pending" section to "Completed":
pendSection.removeTask(task);
compSection.addTask(task);
sectionAdapter.notifyDataSetChanged();
Regarding to the SwipeLayout, don't extend RecyclerSwipeAdapter, extend SectionedRecyclerViewAdapter and implement the SwipeLayout in ItemViewHolder / onBindItemViewHolder as you have done.

Passing RecyclerView CardView Clicked Item Data To Activity

I have a question about passing clicked cardview data to activity, and here the full story :
I have an Activity called "Details", which contains 2 TextViews in it's layout, Title & Description .
I have setup a fragment ( tab_1 ) which contain the recyclerview codes and the the items data, each item of those contain : title & description .
What i want :
When the user click the item, it will open the Details Activity, and change Details layout title, with clicked item title, and the same for description .
I've manged to create the other activity as an example, and made intent to start it, plus adding "addOnTouchlistener" thanks to Stackoverflow, i've found the way to make it .
So, how to make this alive? I've tried many ways of the available answers on Stackoverflow, but all of them not working, or not related to my request .
Here are my files :
itemsdata.java :
public class itemsdata {
int CatPic;
String title;
String Descr;
int Exapnd;
int expand_no;
tab_1.java ( fragment )
public class tab_1 extends Fragment implements SearchView.OnQueryTextListener {
private RecyclerView mRecyclerView;
public RecyclingViewAdapter adapter;
private Activity context;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.tab_1, container, false);
mRecyclerView = (RecyclerView)layout.findViewById(R.id.recycler_view);
mRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener
(getContext(), new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Intent i = new Intent(view.getContext(), DetailsActivity.class);
view.getContext().startActivity(i);
}
}));
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter = new RecyclingViewAdapter(getActivity(),Listed());
mRecyclerView.setAdapter(adapter);
return layout;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
final MenuItem item = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setOnQueryTextListener(this);
}
#Override
public boolean onQueryTextChange(String query) {
final List<itemsdata> filteredModelList = filter(Listed(), query);
adapter.animateTo(filteredModelList);
mRecyclerView.scrollToPosition(0);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
private List<itemsdata> filter(List<itemsdata> models, String query) {
query = query.toLowerCase();
final List<itemsdata> filteredModelList = new ArrayList<>();
for (itemsdata model : models) {
final String text = model.title.toLowerCase();
if (text.contains(query)) {
filteredModelList.add(model);
}
}
return filteredModelList;
}
public List<itemsdata> Listed()
{
//Titles Strings
String sys_title1 = getString(R.string.system_item_title_1);
String sys_title2 = getString(R.string.system_item_title_2);
String sys_title3 = getString(R.string.system_item_title_3);
//Description Strings
String sys_descr1 = getString(R.string.system_item_desc_1);
String sys_descr2 = getString(R.string.system_item_desc_2);
String sys_descr3 = getString(R.string.system_item_desc_3);
//Adding New Cards
List<itemsdata> data = new ArrayList<>();
//Categories Icons New Items ** Make It The Same
int[] icons = {
R.drawable.facebook_icon ,
R.drawable.twitter_icon ,
R.drawable.twitter_icon
};
//Expand Button New Items
int[] expandbutton = {
R.drawable.expanded ,
R.drawable.expanded ,
R.drawable.expanded
};
//UnExpand Button New Items
int[] unexpandbutton = {
R.drawable.ca_expand ,
R.drawable.ca_expand ,
R.drawable.ca_expand
};
//Titles New Items
String[] titles = {
sys_title1 ,
sys_title2 ,
sys_title3
};
//Description New Items
String[] Description = {
sys_descr1 ,
sys_descr2 ,
sys_descr3
};
for(int i = 0;i<titles.length && i < icons.length && i < Description.length && i < unexpandbutton.length && i < expandbutton.length ; i++)
{
itemsdata current = new itemsdata();
current.CatPic = icons[i];
current.title = titles[i];
current.Descr = Description[i];
current.expand_no = unexpandbutton[i];
current.Exapnd = expandbutton[i];
data.add(current);
}
return data;
}
}
Details Activity :
public class DetailsActivity extends AppCompatActivity{
TextView title;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.details);
title = (TextView)findViewById(R.id.details_title);
}
EDIT : I've made it, i have added a button which open the fragment, and passed the data, in the Adapter, but i want it via tab_1.java, not the Adapter, i mean i want to click on the item to open the fragment, not on a button, here a snap from my Adapter code ( i've added it in OnBindViewHolder )
I've setup a OnClick and implemented the Vew.setOnClick ..etc, but when i click the item, nothing happen.
#Override
public void onBindViewHolder(final MyRecycleViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(v.getContext(),DetailsActivity.class);
v.getContext().startActivity(i);
}
});
//Referencing Data
final itemsdata currentobject = mdata.get(position);
//Referencing Items
holder.ProbTitle.setText(currentobject.title);
holder.ProbDescr.setText(currentobject.Descr);
holder.CategoryPic.setImageResource(currentobject.CatPic);
holder.ExpandButton.setImageResource(currentobject.Exapnd);
holder.ExpandNoButton.setImageResource(currentobject.expand_no);
//What Happen When You Click Expand Button .
holder.ExpandButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(v.getContext(), DetailsActivity.class);
i.putExtra("TitleKey",holder.ProbTitle.getText().toString());
v.getContext().startActivity(i);
}
}
);
public static class MyRecycleViewHolder extends RecyclerView.ViewHolder
{
SwipeLayout swipeLayout;
//Defining Items .
TextView ProbTitle;
ImageButton ExpandButton;
TextView ProbDescr;
ImageButton ExpandNoButton;
ImageView CategoryPic;
/*
TextView Card_Star;
TextView Card_UnStar;
*/
TextView Card_Share;
//Referencing Resources
public MyRecycleViewHolder(final View itemView) {
super(itemView);
ProbTitle = (TextView) itemView.findViewById(R.id.prob_title);
CategoryPic = (ImageView) itemView.findViewById(R.id.cat_pic);
ProbDescr = (TextView) itemView.findViewById(R.id.prob_descr);
ExpandButton = (ImageButton) itemView.findViewById(R.id.expand_button);
ExpandNoButton = (ImageButton) itemView.findViewById(R.id.expand_no_button);
/*
Card_Star = (TextView) itemView.findViewById(R.id.card_star);
Card_UnStar = (TextView) itemView.findViewById(R.id.card_unstar);
*/
Card_Share = (TextView) itemView.findViewById(R.id.card_share);
swipeLayout = (SwipeLayout) itemView.findViewById(R.id.swipe);
}
create an Interface inside your adapter containing methods. And while implementing your Adapter, those methods will be implemented in your activity and you can perform whatever action you want.
public class Adapter extends RecyclerView.Adapter<MyRecycleViewHolder> {
public interface Callbacks {
public void onButtonClicked(String titleKey);
}
private Callbacks mCallbacks;
public Adapter() {
}
#Override
public MyRecycleViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_details, null);
return new MyRecycleViewHolder(v);
}
#Override
public void onBindViewHolder(final MyRecycleViewHolder holder, final int i) {
holder.ExpandButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mCallbacks != null) {
mCallbacks.onButtonClicked(holder.ProbTitle.getText().toString());
}
}
});
}
#Override
public int getItemCount() {
return;
}
public void setCallbacks(Callbacks callbacks) {
this.mCallbacks = callbacks;
}
}
you may try do this on your onItemClick()
Intent i = new Intent(view.getContext(), DetailsActivity.class);
i.putExtra("title", yourTitle);
i.putExtra("description", yourDescription);
view.getContext().startActivity(i);
and when oncreate in your DetailActivity,do this
String title = getIntent().getStringExtra("title");
String description = getIntent().getStringExtra("description");
so you can pass title and description to DetailActivity
IMO, you implement setOnClickListener inside Adapter of RecyclerView. You can refer to my following sample code, then apply its logic to your code. Hope it helps!
public class MyRVAdapter extends RecyclerView.Adapter<MyRVAdapter.ViewHolder> {
Context mContext;
List<String> mStringList;
public MyRVAdapter(Context mContext, List<String> mStringList) {
this.mContext = mContext;
this.mStringList = mStringList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview, parent, false);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView textView1 = (TextView) v.findViewById(R.id.textView1);
TextView textView2 = (TextView) v.findViewById(R.id.textView2);
Bundle bundle = new Bundle();
bundle.putString("key1", textView1.getText().toString());
bundle.putString("key2", textView2.getText().toString());
passToAnotherActivity(bundle);
}
});
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// do something...
}
#Override
public int getItemCount() {
if (mStringList != null) {
return mStringList.size();
}
return 0;
}
private void passToAnotherActivity(Bundle bundle) {
if (mContext == null)
return;
if (mContext instanceof MainActivity) {
MainActivity activity = (MainActivity) mContext;
activity.passToAnotherActivity(bundle); // this method must be implemented inside `MainActivity`
}
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public ViewHolder(View itemView) {
super(itemView);
// do something...
}
#Override
public void onClick(View v) {
}
}
}
First of all make your "itemsdata" object to implement Parcelable. You can check it here . In your onItemClick method you pass the object to your Details activity using intent.putExtra("key",listOfDataItems.get(position));
In your DetailsActivity you can get your custom object with getParcelable("key")
All above methods worked, but kinda long, so this one worked for me :
Cardview cardview;
cardView = (CardView)itemView.findViewById(R.id.cv);
cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent (view.getContext(), DetailsActivity.class);
i.putExtra("TitleKey",ProbTitle.getText().toString());
i.putExtra("DescrKey",ProbDescr.getText().toString());
view.getContext().startActivity(i);
}
});
And in Details.java :
TextView title;
TextView Descr;
title = (TextView)findViewById(R.id.details_title);
Descr = (TextView)findViewById(R.id.details_descr);
String titleresult = result.getExtras().getString("TitleKey");
String Descrresult = result.getExtras().getString("DescrKey");
title.setText(titleresult);
Descr.setText(Descrresult);

Categories

Resources