Android Realm Database not updating Record - android

I am new to Android Development i am trying to sort item position in Recyclerview i am useing Realm Database and my data-set for Adapter is RealmResults<ShoppingList>
here is my Adapter please take look my moveItemDown and updateItemPosition method i m trying to update item position in updateItemPosition Method but it's not working. i also attached my view below the adapter
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
private RealmResults<ShoppingList> dataList;
private Realm mRealm;
private LayoutInflater mInflater;
public RecyclerAdapter(Context context, RealmResults<ShoppingList> data, Realm reamDatabaseInstence){
this.dataList = data;
this.mInflater = LayoutInflater.from(context);
mRealm = reamDatabaseInstence;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.i("Recycler", "onCreateViewHolder");
View view = mInflater.inflate(R.layout.shopping_list_item, parent,false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
#Override
public int getItemCount() {
return dataList.size();
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Log.i("Recycler", "onBindViewHolder " + position);
ShoppingList currentItem = dataList.get(position);
holder.setData(currentItem, position);
holder.setListener();
}
public void moveItemDown(int position){
if( position == (dataList.size()-1) ) { return; }
int oi = position;
int ni = position+1;
updateItemPosition(oi, ni);
notifyDataSetChanged();
}
public void moveItemUp(int position){
// Need to implement after down sort work
}
private void updateItemPosition(final int pos, final int new_pos){
mRealm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
ShoppingList old_item = realm.where(ShoppingList.class)
.equalTo("position", pos)
.findFirst();
old_item.setPosition(new_pos);
Log.d("UpdateData: ",old_item.getTitle()+" "+old_item.getPosition());
ShoppingList new_item = realm.where(ShoppingList.class)
.equalTo("position", new_pos)
.findFirst();
new_item.setPosition(pos);
Log.d("UpdateData: ",new_item.getTitle()+" "+new_item.getPosition());
}
});
}
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView title;
ImageButton up, down;
ImageView image;
int position;
ShoppingList current;
MyViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.shopping_card_view_title);
image = (ImageView) itemView.findViewById(R.id.shopping_card_view_image);
up = (ImageButton) itemView.findViewById(R.id.shopping_card_view_up_btn);
down = (ImageButton) itemView.findViewById(R.id.shopping_card_view_down_btn);
}
void setData(ShoppingList i, int position) {
title.setText( i.getTitle() );
image.setImageResource(i.getImageId());
this.position = position;
this.current = i;
}
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.shopping_card_view_up_btn:
moveItemUp(position);
break;
case R.id.shopping_card_view_down_btn:
moveItemDown(position);
break;
}
}
void setListener() {
up.setOnClickListener(MyViewHolder.this);
down.setOnClickListener(MyViewHolder.this);
}
}
}

It's late reply by it would help to you and this is the combination of both answer EpicPandaForce give a great example to work with RealmRecyclerViewAdapter and make your Recyclerview automated.
Second Option
this is to use UNIQUE ID FIELD in order to make changes in list item.
Here is the problem happening in you Code
Basically when you get an item by it's position for instance position=1; and you updated to position 2 right? notice now you have two item with same position = 2 and now when you try to get first item with position = 2 Realm return the same item that you updated from position 1 to 2 now what happening here you updated dated position back to position=1;
taman neupane give you good idea but he is not describe much.
Please TRY THIS
private void updateItemPosition(final int pos, final int new_pos){
final String current_item_id = dataList.get(pos).get_id();
final String new_item_id = dataList.get(new_pos).get_id();
mRealm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
// Try to find the result with unique id replace this .equalTo("Your Unique ID Field name", current_item_id)
ShoppingList old_item = realm.where(ShoppingList.class).equalTo("position", pos).findFirst();
old_item.setPosition(new_pos);
// Also here Try to find the result with unique id replace this .equalTo("Your Unique ID Field name", new_item_id)
ShoppingList new_item = realm.where(ShoppingList.class).equalTo("position", new_pos).findFirst();
new_item.setPosition(pos);
//new you can tell you adapter about the changes in dataset.
notifyItemMoved(pos, new_pos);
notifyItemRangeChanged(pos, dataList.getSize());
}
});
}
and then update your both function with that
public void moveItemDown(int position){
if( position == (dataList.size()-1) ) { return; }
int oi = position;
int ni = position+1;
updateItemPosition(oi, ni);
}
public void moveItemUp(int position){
if( position == 0 ) { return; }
int oi = position;
int ni = position-1;
updateItemPosition(ni, oi);
}
And That's it.
If anyone want to modify my explanation i will appreciate because i am not good in english.
Happy Coding.

To get automatic updates, you should use RealmRecyclerViewAdapter from https://github.com/realm/realm-android-adapters
public class RecyclerAdapter extends RealmRecyclerViewAdapter<ShoppingList, RecyclerAdapter.MyViewHolder> { // <-- !
private Realm mRealm;
private LayoutInflater mInflater;
public RecyclerAdapter(Context context, RealmResults<ShoppingList> data, Realm realm){
super(data, true);
this.mInflater = LayoutInflater.from(context);
mRealm = realm;
}
and replace dataList with getData()

I think your ShoppingList item has unique id for all. Just make id field primary and use realmInsertorUpdate feature . You don't have to check for any thing else. If the id is available it will update the database and if id is not available it will just insert.

Related

Recyclerview single item selection not working correctly

I've implemented a recyclerview with staggered gridLayout containing about 31 items in the arrayList, recyclerview is working correctly, but I faced issue relating to single item selection.
When I select the value till "26" as shown in figure, its working fine
But, when I select the value after "26", the values from top most item are also selected, as shown in this next figure.
I require to only select one item at a time.
I've implemented the following code in my adapter class
public class DialogAdapter extends
RecyclerView.Adapter<DialogAdapter.DialogHolder>
{
// components
public Context context;
public ArrayList<AlertDialogModel> dialogArrayList = new
ArrayList<AlertDialogModel>();
private final ArrayList<Integer> selected = new ArrayList<>();
private int lastCheckedPosition = -1;
public Interface interface;
// parameterized constructor
public DialogAdapter(Context context, ArrayList<AlertDialogModel>
dialogArrayList,Interface interface)
{
this.context = context;
this.dialogArrayList = dialogArrayList;
this.interface = interface;
}
#NonNull
#Override
public DialogHolder onCreateViewHolder(#NonNull ViewGroup parent, int
viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_cardview,parent,false);
DialogHolder dialogHolder = new DialogHolder(view);
return dialogHolder;
}
#Override
public void onBindViewHolder(#NonNull final DialogHolder holder, final int position)
{
final AlertDialogModel alertDialogModel = dialogArrayList.get(position);
holder.textView.setText(alertDialogModel.getDisplayValue());
if(lastCheckedPosition == position)
{
holder.textView.setTextColor(context.getResources().getColor(R.color.white));
holder.textView.setBackground(context.getResources().getDrawable(R.drawable.circular_shape_selection));
}
else
{
}
holder.textView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
lastCheckedPosition = position;
notifyDataSetChanged();
holder.textView.setTextColor(context.getResources().getColor(R.color.white));
holder.textView.setBackground(context.getResources().getDrawable(R.drawable.circular_shape_selection));
interface.getSelectedValue(alertDialogModel.getDisplayValue());
}
});
}
#Override
public int getItemCount()
{
return dialogArrayList.size();
}
public static class DialogHolder extends RecyclerView.ViewHolder
{
public TextView textView;
public DialogHolder(View itemView)
{
super(itemView);
textView = (TextView)itemView.findViewById(R.id.textView);
}
}
}
Can anyone relate my code and identify the issue ?
holder.textView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
lastCheckedPosition = position;
notifyDataSetChanged();
holder.textView.setTextColor(context.getResources().getColor(R.color.white));
holder.textView.setBackground(context.getResources().getDrawable(R.drawable.circular_shape_selection));
interface.getSelectedValue(alertDialogModel.getDisplayValue());
//below line is important to remove previous selected position from the variable
lastCheckedPosition = -1;
}
});
you should put the text view to the original state:
if(lastCheckedPosition == position)
{
holder.textView.setTextColor(context.getResources().getColor(R.color.white));
holder.textView.setBackground(context.getResources().getDrawable(R.drawable.circular_shape_selection));
}
else
{
holder.textView.setTextColor(context.getResources().getColor(R.color.transparent));
holder.textView.setBackground(null));
}

Recyclerview pass the data to next item upon deletion of one item

The title seems confusing because I cannot explain this properly using text.
I'll try my best to explain my problem.
Currently I have items in my recyclerview :
Each item contains a delete button that will remove the item in the recyclerview.
Lets assume that I have 5 items in the list:
what I want to attain is when the user deletes
Item 2
the information/data from item 3 will be transferred to Item 2,
the data from item 4 will be transferred to item 3 and
the data from item 5 will be transferred to item 4
and lastly the item 5 will be deleted.
I currently have no code for this but I'm trying my best to construct it.
Here is my adapter code, it might help:
public class CreditCard_PostPayAdapter extends RecyclerView.Adapter<CreditCard_PostPayAdapter.MyViewHolder> {
private static String TAGedittext = "";
//private final AccountHistoryTransactionActivity homeActivity;
private Context mContext;
private ArrayList<Integer> mHeaderText;
CreditCard_PostPayAdapter adapter;
public CreditCard_PostPayAdapter(Context mContext, ArrayList<Integer> mHeaderTextList ) {
this.mContext = mContext;
this.mHeaderText = mHeaderTextList;
}
#Override
public CreditCard_PostPayAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.creditcard_postpay_item, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final CreditCard_PostPayAdapter.MyViewHolder holder, int position) {
final int pos = position + 1;
final int mPosition = position;
if (mHeaderText.size() == 1) {
holder.mDeleteButton.setVisibility(View.GONE);
} else {
holder.mDeleteButton.setVisibility(View.VISIBLE); }
holder.mDeleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mHeaderText.remove(mPosition);
ArrayList<Integer> temp = new ArrayList<Integer>();
for (int i = 0 ; mHeaderText.size() - 1 >= i ; i++) {
temp.add(i);
Log.d("Counter++",""+i);
}
holder.mMerchantName.setText("");
holder.mTransactionAmountEditText.setText("");
holder.mTransactionDateEditText.setText("");
holder.mPostingDateEditText.setText("");
mHeaderText.clear();
mHeaderText.addAll(temp);
notifyDataSetChanged();
}
});
}
#Override
public int getItemCount() {
return mHeaderText.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView mHeaderTitle
public ImageView mArrowHeader;
public ImageButton mDeleteButton;
public TextInputEditText mTransactionDateEditText,
mPostingDateEditText,
mTransactionAmountEditText;
public MyViewHolder(View view) {
super(view);
this.mHeaderTitle = (TextView) view.findViewById(R.id.header_title);
this.mDeleteButton = view.findViewById(R.id.mDeleteButton);
this.mMerchantName = view.findViewById(R.id.mMerchantNameTextView);
this.mTransactionDateEditText = view.findViewById(R.id.Transaction_date);
this.mPostingDateEditText = view.findViewById(R.id.posting_date);
this.mTransactionAmountEditText = view.findViewById(R.id.Transaction_amount);
}
}
}
My current delete button function is to:
Delete the item(n) and recount all of the remaining item.
Replace your onBindViewHolder method and try,
#Override
public void onBindViewHolder(final CreditCard_PostPayAdapter.MyViewHolder holder, int position) {
holder.mDeleteButton.setTag(position);
holder.mDeleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int clickedPos = (int) view.getTag();
mHeaderText.remove(clickedPos);
notifyItemRemoved(position);
}
});
}
If you want to delete the 2nd element. delete the element and remaining will be taken care by recyclerAdapter to remove the row and align the data.
inside your onClickListener, remove the data from ArrayList and the call notifyItemRemoved()
write your onClick inside ViewHolder class
onClick(View view){
mHeaderText.remove(getAdapterPosition());
notifyItemRemoved(getAdapterPosition());
}
i hope this will help you..
you an delete the item in list and refresh your adapter by just doing this in your onClick:
holder.mDeleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mHeaderText.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mHeaderText.size());
}
});

How to update recycleview single item while realm database update?

public class MyAdapterMarket extends RecyclerView.Adapter<MyAdapterMarket.MyViewHolder> {
Context c;
ArrayList<MarketObject> marketObject;
public RecyclerView recyclerView;
public MyAdapterMarket(MarketActivity.MyFragment c, ArrayList<MarketObject> marketObject) {
this.marketObject = marketObject;
}
// I AM ABLE TO GET UPDATED OBJECT HERE BUT HOW CAN I UPDATE IN RECYCLEVIEW AT PARTICULAR POSITION. // marketObject.getLast() gives updated value in Realm Database
public static void updateEmployeeListItems(MarketObject marketObject) {
Log.e("UPDATED OBJECT FROM REALM DATABASE",""+marketObject.getLast());
}
#Override
public MyAdapterMarket.MyViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.calender_market_list, parent, false);
return new MyAdapterMarket.MyViewHolder(v);
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView market_title, country_name, market_last, market_time, market_dailyPercentageChange, market_dailyChange;
public LinearLayout actual, previous, constant;
public MyViewHolder(View itemView) {
super(itemView);
c = itemView.getContext();
recyclerView = (RecyclerView) itemView.findViewById(R.id.calendar_fragment_recycleview);
market_title = (TextView) itemView.findViewById(R.id.market_title);
country_name = (TextView) itemView.findViewById(R.id.country_name);
market_last = (TextView) itemView.findViewById(R.id.market_last);
market_time = (TextView) itemView.findViewById(R.id.market_time);
market_dailyPercentageChange = (TextView) itemView.findViewById(R.id.market_dailyPercentageChange);
market_dailyChange = (TextView) itemView.findViewById(R.id.market_dailyChange);
}
}
#Override
public void onBindViewHolder(MyAdapterMarket.MyViewHolder holder, final int position) {
final MarketObject market = marketObject.get(position);
holder.market_title.setText(market.getName());
holder.country_name.setText(capitalize(market.getCountry()));
holder.market_last.setText(market.getLast());
holder.market_time.setText(market.getTime());
holder.market_dailyPercentageChange.setText(market.getDailypercentualchange());
holder.market_dailyChange.setText(market.getDailychange());
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Log.v("RECYCLEVIEW POSITION", "Element " + getAdapterPosition() + " clicked.");
AutoUpdate(position, "0.007");
Context context = v.getContext();
Intent intent = new Intent(context, MarketDetail.class);
intent.putExtra( "NAME" , market.getName());
//context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return marketObject.size();
}
}
Give code is my Adapter code, Now I am getting live data of market which update perfectly in Realm Database with MarketObject. I want to reflect that data in Recycleview also with animation so a user can see this market Rate is updated. How does it possible. While updating this value in Realm Database I am passing Object in this function "updateEmployeeListItems()". Now I am not able to update in RecycleView at a particular position.
In the following Image when I get updates from server I am updating data in Realm Database and as I explain in "updateEmployeeListItems()" I am getting updated object from, Now I want to update this object data in RecycleView
Okay so if you want to leverage Realm's fine-grained notifications, then you should be using RealmRecyclerViewAdapter, and on top of that
public class MyAdapterMarket extends RealmRecyclerViewAdapter<MarketObject, MyAdapterMarket.MyViewHolder> {
public MyAdapterMarket(OrderedRealmCollection<MarketObject> results {
super(results, true, false); // passing `false` to handle `change` manually
}
#Override
public MyAdapterMarket.MyViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
return new MyAdapterMarket.MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.calender_market_list, parent, false));
}
public class MyViewHolder extends RecyclerView.ViewHolder {
Context c;
RecyclerView recyclerView;
TextView market_title, country_name, market_last, market_time, market_dailyPercentageChange, market_dailyChange;
LinearLayout actual, previous, constant;
public MyViewHolder(View itemView) {
super(itemView);
c = itemView.getContext();
recyclerView = (RecyclerView) itemView.findViewById(R.id.calendar_fragment_recycleview);
market_title = (TextView) itemView.findViewById(R.id.market_title);
country_name = (TextView) itemView.findViewById(R.id.country_name);
market_last = (TextView) itemView.findViewById(R.id.market_last);
market_time = (TextView) itemView.findViewById(R.id.market_time);
market_dailyPercentageChange = (TextView) itemView.findViewById(R.id.market_dailyPercentageChange);
market_dailyChange = (TextView) itemView.findViewById(R.id.market_dailyChange);
}
RealmObjectChangeListener realmChangeListener = new RealmObjectChangeListener<MarketObject>() {
#Override
public void onChange(MarketObject market, ObjectChangeSet changeSet) {
if(changeSet.isDeleted()) return;
if(changeSet.isFieldChanged("name")) {
market_title.setText(market.getName());
}
if(changeSet.isFieldChanged("country")) {
country_name.setText(capitalize(market.getCountry()));
}
if(changeSet.isFieldChanged("last")) {
market_last.setText(market.getLast());
}
if(changeSet.isFieldChanged("time")) {
market_time.setText(market.getTime());
}
if(changeSet.isFieldChanged("dailypercentualchange")) {
market_dailyPercentageChange.setText(market.getDailypercentualchange());
}
if(changeSet.isFieldChanged("dailychange")) {
market_dailyChange.setText(market.getDailychange());
}
}
}
MarketObject market;
public void bind(MarketObject market) {
if(this.market != null && this.market.isValid()) {
this.market.removeAllChangeListeners();
}
this.market = market;
market.addChangeListener(realmChangeListener);
market_title.setText(market.getName());
country_name.setText(capitalize(market.getCountry()));
market_last.setText(market.getLast());
market_time.setText(market.getTime());
market_dailyPercentageChange.setText(market.getDailypercentualchange());
market_dailyChange.setText(market.getDailychange());
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Log.v("RECYCLEVIEW POSITION", "Element " + getAdapterPosition() + " clicked.");
AutoUpdate(position, "0.007");
Context context = v.getContext();
Intent intent = new Intent(context, MarketDetail.class);
intent.putExtra( "NAME" , market.getName());
//context.startActivity(intent);
}
});
}
}
#Override
public void onBindViewHolder(MyAdapterMarket.MyViewHolder holder, final int position) {
final MarketObject market = marketObject.get(position);
holder.bind(market);
}
}
If you're only updating one item, you can update your backing list with the new item (i.e. replacing it at old item's index), then tell the RecyclerView adapter about the change by calling recyclerView.getAdapter().notifyItemChanged(POSITION), where POSITION is the integer index of your updated item in the list/array.
If you get an entire new list of items, you can use the DiffUtil to find the diff between the old list of backing items and the updated list of backing items, then dispatch those changes to the RecyclerView adatper:
That being said, user #Saran Sankaran's suggestion of using RealmRecyclerViewAdapter is probably what you're looking for. If you use that, you don't need to do any of the notifyItemChanged logic yourself.

android: Sort List after Adding items to the existing list using RecyclerView.Adapter

I have a RecyclerView which shows list of items sorted in descending order that works fine when I initially launch the screen, but when I add some more items to the existing list and setting it to the adapter with notifyDataSetChanged() method the existing list gets sorted in ascending order and the new items get added at the bottom of the view.
below is adapter
public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolder> {
private List<Cinema> lists;
private int savedItems;
public RecycleAdapter(List<Cinema> cinemas, int savedItems) {
this.lists = cinemas;
this.savedItems = savedItems;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView cinemaTitle;
public TextView cinemaDescription;
public TextView cinemaDate;
public LinearLayout newLayout;
public ViewHolder(View view) {
super(view);
cinemaTitle = (TextView) view.findViewById(R.id.cinema_title);
cinemaDescription = (TextView) view.findViewById(R.id.description_text);
cinemaDate = (TextView) view.findViewById(R.id.cinema_date);
newLayout = (LinearLayout) view.findViewById(R.id.new_cinema_layout);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_cinema, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Cinema cinema = cinemas.get(position);
if (cinema.getId() > savedItems) {
holder.newLayout.setVisibility(View.VISIBLE);
} else {
holder.newLayout.setVisibility(View.INVISIBLE);
}
String title = cinema.getMessage().trim();
String description = cinema.getDescription().trim();
String date = cinema.getPublishedDate().trim();
holder.cinemaTitle.setText(title);
holder.cinemaDescription.setText(description);
holder.cinemaDate.setText(date);
}
public void setCineams(List<Cinema> cinemas) {
this.cinemas = cinemas;
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return cinemas.size();
}
}
and the method which updates the list from Fragment is given below:
#Override
public void onCinemaUpdated() {
cinemas = firebaseHelper.getAllCinemas();
//Method which sorts the lists in descending order after adding new items into it
sortCinemas();
if (recycleAdapterAdapter != null) {
recycleAdapterAdapter.setCineams(cinemas);
}
}
I am not sure why am I getting this behaviour. Can anyone clarify on this?
Change your constructor and setCinemas method code to : Let me know if it helps..
public RecycleAdapter(List<Cinema> cinemas, int savedItems) {
this.lists = cinemas;
this.savedItems = savedItems;
}
public void setCineams(List<Cinema> cinemas) {
this.lists = cinemas;
notifyDataSetChanged();
}

How to implement RecycerView With Items having Radio buttons with single choice mode

I need to show a recyclerview with single choice item. but Recyclerview doesn't have the choice mode.
Does any one know how to resolve this?
Thanks in advance.
Store the states of the checked items in a SparseBooleanArray with the position as key.As you change the state of the button,update it's status in the booleanArray and call notifyItemChanged(position).And in BindviewHolder(ViewHolder viewholder,int position) method load the state from booleanArray like viewholder.radioButton.setChecked(boolean.get(position)).Have a look at this for basic idea
You could use something like this, it stores position for selected item, you could add a bit more code to store the item itself if your adapter reorders itself
public class SingleChoiceAdapter extends RecyclerView.Adapter<SingleChoiceAdapter.ItemViewHolder> {
private static final int NO_POSITION = -1;
private static final String SELECTED_ITEM_POSITION = "SELECTED_ITEM_POSITION";
private final LayoutInflater inflater;
private final List<Item> items;
private int selectedItemPosition = NO_POSITION;
public SingleChoiceAdapter(Context context, Bundle savedInstanceState) {
inflater = LayoutInflater.from(context);
items = new ArrayList<>();
if (savedInstanceState != null) {
selectedItemPosition = savedInstanceState.getInt(SELECTED_ITEM_POSITION, NO_POSITION);
}
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = inflater.inflate(R.layout.item, parent, false);
return new ItemViewHolder(view);
}
#Override
public void onBindViewHolder(final ItemViewHolder holder, int position) {
final Item item = items.get(position);
holder.textView.setText(item.name);
holder.textView.setBackgroundColor(position == selectedItemPosition
? Color.LTGRAY
: Color.TRANSPARENT);
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updateSelectedItem(holder.getAdapterPosition());
}
});
}
#Override
public int getItemCount() {
return items.size();
}
public void setItems(List<Item> items) {
this.items.clear();
this.items.addAll(items);
notifyDataSetChanged();
}
public Item getSelectedItem() {
if (selectedItemPosition == NO_POSITION) {
return null;
}
return items.get(selectedItemPosition);
}
public void onSaveInstanceState(Bundle outState) {
outState.putInt(SELECTED_ITEM_POSITION, selectedItemPosition);
}
private void updateSelectedItem(int newSelectedItemPosition) {
if (selectedItemPosition != NO_POSITION) {
notifyItemChanged(selectedItemPosition);
}
selectedItemPosition = newSelectedItemPosition;
notifyItemChanged(newSelectedItemPosition);
}
public static class ItemViewHolder extends RecyclerView.ViewHolder {
public final TextView textView;
public ItemViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.text_view);
}
}
}
Displaying already checks-
You can maintain a boolean array of size of your list. On bind view handle the boolean(true/ false) logic, like setting check true/false of a radio button.
Handling new clicks-
Then on the onclick of the radio button, set the value of every array element to false and setting the current array position to true after that. Now call notifyDatatSetChanged().
You can even do it with just one single integer variable instead of maintaining an array which is costly in devices like android where space is a constraint.
So, just maintain a single integer variable, lets say int selectedPosition=-1 initially.
In onBind check if the position==selectedPosition, if true check the button else uncheck.
Whenever user checks/unchecks the button, just update the selectedPosition
Something like this,
if(selectedPosition==position)
selectedPosition=-1
else{
selectedPosition=position
notifyItemChanged(selectedPosition);
}
notifyItemChanged(position);
Please set the id for the position in onBindViewHolder then you can process action in this method too. Update data set and call notifyDataSetChanged
Here is my example code
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
ItemObject itemObject = mDataset.get(position);
((ViewHolder)holder).mTextView.setText(itemObject.getTitle());
Button mButton = ((ViewHolder) holder).mButton;
mButton.setSelected(itemObject.isSelected());
if(itemObject.isSelected()){
((ViewHolder)holder).mTextView.setText("OK");
}
mButton.setTag(position);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updateDatset((Integer) v.getTag());
}
});
}
In the updateDataset method, I update information of this dataset and call notifyDataSetChanged()
Good luck

Categories

Resources