How can I send text value from ViewHolder to ItemTouchHelper class? - java

I've been learning Java and Android Development for about a month. Maybe, I don't know some features... But I can't find any advise for a week.
I need to send value from one of my fields in ViewHolder (created by onBindViewHolder) to overrided method onChildDraw (in class, that extends ItemTouchHelper). But I can't understand, how can I do this.
I want to call new activity after swipe action and send value of field "name" to that activity. Can I do this with Intent? Or maybe have other way?
Creating ViewHolder (public class ModelsDataAdapter extends RecyclerView.Adapter):
#Override
public void onBindViewHolder(ModelsViewHolder holder, int position) {
ModelsData model = models.get(position);
holder.name.setText(model.getName()); // <-- I NEED THIS VALUE
holder.tags.setText(model.getTags());
holder.keywords.setText(model.getKeywords());
holder.cost.setText(model.getCost().toString());
//-- some code --//
}
My onChildDraw (public class SwipeControl extends ItemTouchHelper.Callback):
#Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
//-- some code --//
int x = 0;
if (dX < -200){ //
viewHolder.itemView.findViewById(R.id.card_foreground).setTranslationX(dX / 3);
} else if (dX > 200){
viewHolder.itemView.findViewById(R.id.card_foreground).setTranslationX(dX / 3);
openStatCard();
} else if (dX == 0){
checkActivity = false;
}
}
Opening new activity (inside SwipeControl.class):
private void openStatCard(){
if (!checkActivity) {
checkActivity = true;
Intent intent = new Intent(context, StatCards.class);
intent.putExtra("choosingModel", model); // <-- PUT "name" IN "model"
context.startActivity(intent);
}
}

Inside onChildDraw method use viewHolder.getAdapterPositon() method to get the position. And when you need the value just use that position to find Name from the models list
EDIT
Inside onChildDraw get the TextView using viewHolder.itemView.findViewById(R.id.name); and then use getText() method to get the Name.

Related

How to change background colour to specific viewholder items in a RecycleView?

I am trying to change background color in specific item(s) in a RecycleView.
Because I need to set text too, I have the following code that works fine:
protected void populateViewHolder(RankingViewHolder viewHolder, final Ranking model, int position)
{
final Context mContext = getActivity().getApplicationContext();
viewHolder.txt_name.setText(model.getUserName());
viewHolder.txt_score.setText(String.valueOf(model.getScore()));
viewHolder.txt_class.setText(model.getUser_class());
Picasso.with(mContext).load(model.getAvatarUrl()).error(R.drawable.ic_people_black_24dp).into(viewHolder.personPhoto);
int totalRanking = adapter.getItemCount();
int realRank = totalRanking - viewHolder.getAdapterPosition();
viewHolder.ranknumber.setText("# "+String.valueOf(realRank));
}
This works as I want and realRanktakes the correct values, and the viewHolder.ranknumber.setText("# "+String.valueOf(realRank));
Sets the right text with no problem.
Now I am trying (as I got a number/text result correct, to make an if statement like this:
if(adapter.getItemCount() -viewHolder.getAdapterPosition() == 0)
{
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
if(adapter.getItemCount() -viewHolder.getAdapterPosition() == 1)
{
viewHolder.itemView.setBackgroundColor(Color.YELLOW);
}
if(adapter.getItemCount() -viewHolder.getAdapterPosition() == 2)
{
viewHolder.itemView.setBackgroundColor(Color.BLUE);
}
(I tried with String.valueOf(realRank)equality, with realRankequality too)
In all cases I have the same result. The color changes as its should at positions 1,2,3 BUT it changes at positions 7,8,9 and 14,15,16 and 21,22,23 etc.
What am I missing here?
public class RankingViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
private ItemClickListener itemClickListener;
public TextView txt_name, txt_score, txt_class, ranknumber;
public ImageView personPhoto;
public RankingViewHolder(View itemView)
{
super(itemView);
txt_name = itemView.findViewById(R.id.txt_name);
txt_score = itemView.findViewById(R.id.txt_score);
personPhoto = itemView.findViewById(R.id.person_photo);
txt_class = itemView.findViewById(R.id.txt_class);
ranknumber = itemView.findViewById(R.id.ranknumber);
itemView.setOnClickListener(this);
}
public void setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
#Override
public void onClick(View view) {
itemClickListener.onClick(view , getAdapterPosition(),false);
}
}
The adapter:
adapter = new FirebaseRecyclerAdapter<Ranking, RankingViewHolder>(
Ranking.class,
R.layout.layout_ranking,
RankingViewHolder.class,
rankingTbl.orderByChild("score").limitToFirst(100)
)
This line of code int realRank = totalRanking - viewHolder.getAdapterPosition();gives a number (1,2,3,4,5,6 etc.) Why i cannot use this number to check equality?
Notice
Keeping this code for NOT working solution, just for future reference:
if(position == 0){
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
else if(position == 1){
viewHolder.itemView.setBackgroundColor(Color.YELLOW);
}
else if(position == 2){
viewHolder.itemView.setBackgroundColor(Color.BLUE);
}
else{
viewHolder.itemView.setBackgroundColor(Color.WHITE);
}
This changes the color BUT not for only 3 first items. As you scroll down, changes the color for every 3 first viewable items like before, meaning 1,2,3, 7,8,9, etc.
Update:
I dont use a custom adapter, i use FirebaseRecyclerAdapter.
Thanks to #Muhammad Haroon comment i checked that has getItemViewType. So now i m trying with it like
position =adapter.getItemViewType( 0);
if(position == 0){
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
Not working for now, but i think its the correct direction...
Update 2
With position its not possible as RecycleView recycles the views so i have the same result. The working code is
if (linearLayoutManager.findFirstVisibleItemPosition() > 0) {
viewHolder.itemView.setBackgroundResource(R.drawable.blackframe);
}
else{
viewHolder.itemView.setBackgroundResource(R.drawable.goldframe);
}
Works fine except that after scrolling loosing the change of background.
So as we want and need the perfection, any idea for keeping even after scroll?
hi try add this in your Adapater it may solve your problem.
#Override
public int getItemViewType(int position) {
return position;
}
Please give this a try
override in your custom adapter
#Override
public long getItemId(int position) {
return position;
}
and in in your adapter object:
myAdapter.setHasStableIds(true);
In populateViewHolder add these line of code
if(position == 0){
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
else if(position == 1){
viewHolder.itemView.setBackgroundColor(Color.YELLOW);
}
else if(position == 2){
viewHolder.itemView.setBackgroundColor(Color.BLUE);
}
else{
viewHolder.itemView.setBackgroundColor(Color.WHITE);
}
position is a parameter in populateViewHolder.

Movement animation with RealmRecyclerViewAdapter with Drag&Drop

I have a RealmRecyclerViewAdapter that listens to a query in realm, and I've Implemented a drag and drop functionality on it using the ItemTouchHelper.
private final ItemTouchHelper.Callback _ithCallback = new ItemTouchHelper.Callback() {
private int fromPosition;
private int toPosition;
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
if (viewHolder.getItemViewType() != target.getItemViewType()) {
return false;
}
toPosition = target.getAdapterPosition();
adapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
}
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (viewHolder.getItemViewType() == TaskListRecyclerViewAdapter.FOOTER) {
return 0;
} else {
return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0);
}
}
#Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
fromPosition = viewHolder.getAdapterPosition();
toPosition = viewHolder.getAdapterPosition();
} else if (actionState == ItemTouchHelper.ACTION_STATE_IDLE
&& fromPosition != toPosition) {
// adapter.onDetachedFromRecyclerView(mRecyclerView);
dragAndDropManager.executeDragAndDrop(liveRealm, store.getStoreUid(), fromPosition, toPosition);
...
...
// adapter.onAttachedToRecyclerView(mRecyclerView);
}
}
};
To indicate the movement, whenever I drag an item over another Item, I call the adapter's notifyItemMoved method:
adapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
and whenever the user releases the item he dragged, I commit the changes to the realm DB:
dragAndDropManager.executeDragAndDrop(liveRealm, store.getStoreUid(), fromPosition, toPosition);
the problem is - whenever I release the item I've dragged, the animation appears to be working as if I haven't dropped the item in its location, but as if the item starts moving from its original location to the location in which I've dropped it.
I understand that this happens because I've committed the changes to Realm and as such the change is notified in the adapter, but the animation looks buggy.
I've tried calling
adapter.onDetachedFromRecyclerView(mRecyclerView);
and
adapter.onAttachedToRecyclerView(mRecyclerView);
to remove and add the listener to the adapter but it seems to be unreliable.
Is there a better solution for this issue?
Michael - did you ever get this working to your satisfaction?
I just ran across your post, having the same issue. I'm using the local Java DB version of Realm and after reviewing several examples that show similar techniques for implementing drag and drop with the stock recyclerView (generally they are all using an array of strings as the data model, NOT something like a live DB such as Realm) here is my experience - what I saw as issues with the "standard" techniques and how I resolved them:
Issues To Resolve
Issue 1: Custom Callback class forwards large numbers of onMove events
The various examples I found (like this one here) always utilize a
custom class that extends ItemTouchHelper.Callback. This classes typically defines
an interface that is in turn implemented by the adapter. Then this class overrides
onMove()/onSwiped from the Callback to call the onViewMoved()/onViewSwiped() method of the interface implemented by the adapter:
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
contract.onViewMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
In the onViewMoved() implementation that is in the adapter, the examples typically update the data source, then call notifyItemMoved():
public void onViewMoved(int oldPosition, int newPosition) {
User targetUser = usersList.get(oldPosition);
User user = new User(targetUser);
usersList.remove(oldPosition);
usersList.add(newPosition, user);
notifyItemMoved(oldPosition, newPosition);
}
In the example above, the data model is a simple ArrayList of "User" objects.
The problem I found with this when using Realm is that in the Callback onMove() gets called a lot as the user drags, which
given what is happening in the standard interface implementation would cause a huge amount of DB
writes.
Issue 2: The drag animation stops as soon as a single row change is detected
I noticed that as I was dragging the top row of the recyclerview down, as soon as it reached the very next row the animation stopped. Why? It is because as you found out the base class RealmRecyclerViewAdapter automatically updates itself when it gets notifications that the data model has changed, and this update apparently triggers the ItemTouchHelper to stop the animation.
To solve these two issues, I did the following:
Like the examples I found, I extended ItemTouchHelper.Callback into my own class. I utilize some variables to keep track of whether I have dragged over a new target or not:
public class RecyclerViewSwipeAndDragHelper extends ItemTouchHelper.Callback {
private SwipeAndDraggable implementor;
private static final int POSITION_UNKNOWN = -1;
private int oldPosition = POSITION_UNKNOWN;
private int newPosition = POSITION_UNKNOWN;
And similar to the example, in this class I define the interface that will be used by my adapter:
public interface SwipeAndDraggable {
void onViewMoved(int oldPosition, int newPosition);
void onViewSwiped(int position);
void onClearView(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder);
}
I added the onClearView() method in this interface to what is typically shown in the examples, more on how that is used in a moment.
To solve the first issue, I needed to consolidate all the onMove() callbacks into only a single call into my adapter. Fortunately, ItemTouchHelper already does a lot of this work for us. A return value of TRUE from onMove() will trigger a follow-up call to onMoved(). Returning FALSE does not. So, in my Callback implementation when I override onMove(), I don't call the implementer of the interface. Instead, I only keep track of whether or not I've dragged over the same target position, so that it only returns TRUE the first time I hit a new target (and I also noticed through testing the sometimes I would get an initial -1 value for viewHolder.getAdapterPosition(), so I test for that as well):
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
oldPosition = viewHolder.getAdapterPosition();
if ( oldPosition > POSITION_UNKNOWN) {
if ( newPosition != target.getAdapterPosition() ) {
newPosition = target.getAdapterPosition();
return true;
}
}
return false;
}
Only when onMove() returns TRUE is onMoved() in the Callback subsequently called. It is in that method that I call my implementation of onViewMoved():
#Override
public void onMoved(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, int fromPos, #NonNull RecyclerView.ViewHolder target, int toPos, int x, int y) {
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y);
implementor.onViewMoved(fromPos, toPos);
}
That is how I solved the first issue of needing to consolidate all the onMove() callbacks into a single update. I only get a call a single time now as the user drags over individual viewholders.
As to the second issue - like you I have disabled the data listening in the RealmRecyclerView. I used the technique in the article to utilize an image in my viewholder to instigate the drag (in my case, it is a thumbnail image representing the individual entry in the recyclerview). This is done as the last step in the onBindViewHolder() method:
holder.getMediaImageView().setOnTouchListener((View view, MotionEvent motionEvent) -> {
if (motionEvent.getAction()== MotionEvent.ACTION_DOWN) {
// Turn off the data change listener within the RealmRecyclerViewAdapter superclass, so that
// when we make changes via the drag it doesn't automatically update - we will handle that manually
onDetachedFromRecyclerView(mMediaRecyclerView);
mItemTouchHelper.startDrag(holder);
}
return false;
});
Now when my onViewMoved() method is called, I can adjust the data model manually and notify the adapter:
public void onViewMoved(int oldPosition, int newPosition) {
Timber.d("Recognized a movement to a new position: old position, new position is: %d, %d", oldPosition, newPosition);
MediaDataMgr.get().moveMediaInPlaylist(oldPosition, newPosition, mPlaylist.getId());
// RealmRecyclerViewAdapter is no longer automatically notified when underlying data changes, so need to make notify()* calls here
notifyItemMoved(oldPosition, newPosition);
}
MediaDataManager is a class I wrote that consolidates all my Realm access. Here is that method as an example of how I do this (as well as the technique of insuring I'm calling Realm from the same thread I am currently on):
public void moveMediaInPlaylist(int from, int to, String playlistId) {
boolean success = false;
boolean mainThread = Thread.currentThread().equals(Looper.getMainLooper().getThread());
Realm realm = null;
if (mainThread) {
realm = mUIThreadRealm;
} else {
realm = Realm.getDefaultInstance();
}
try {
Playlist p = getPlaylist(playlistId);
if ( p== null) {
throw new Exception("Error retrieving playlist with ID: "+ playlistId );
}
realm.beginTransaction();
p.getMediaList().move(from, to);
success = true;
} catch (Exception e) {
Timber.d( "Exception deleting a Media in Playlist: %s", e.getMessage());
success = false;
} finally {
if ( success ) {
realm.commitTransaction();
} else {
realm.cancelTransaction();
}
if (!mainThread) {
realm.close();
}
}
}
Then when clearView() is called in the Callback, I forward this to the adapter via the interface definition. In Callback:
public void clearView(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
oldPosition = POSITION_UNKNOWN;
newPosition = POSITION_UNKNOWN;
implementor.onClearView(recyclerView, viewHolder);
}
And in adapter implementation of the interface I use this to re-attach the data listener:
public void onClearView(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder) {
// reset RealmRecyclerViewAdapter data listener
onAttachedToRecyclerView(mMediaRecyclerView);
}
Now I am able to get a smooth looking animation, updating the DB in real time only once as items are dragged down the recyclerview using Realm:

Click listener inside OnBindViewHolder

I have the following code for the recyclerview adapter for an android app that I'm working on right now:
#Override
public void onBindViewHolder(final FeedViewHolder contactViewHolder, final int i) {
final FeedInfo ci = feedInfoList.get(i);
//Set the text of the feed with your data
contactViewHolder.feedText.setText(ci.getFeed());
contactViewHolder.surNameText.setText(ci.getSurName());
contactViewHolder.nameText.setText(ci.getFirstName());
contactViewHolder.feedDate.setText(ci.getDate());
contactViewHolder.numberOfGoingText.setText(ci.getNumber_of_going());
contactViewHolder.numberOfInterestedText.setText(ci.getNumber_of_interested());
//seteaza fotografia de profil in postare
new ProfilePictureDownloadImage(contactViewHolder.profilePicture).execute(ci.getProfileImageURL());
ImageButton interestedButton = contactViewHolder.interestedButton;
interestedButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = i;
FeedInfo fi = feedInfoList.get(position);
int displayedNumberOfInterested = Integer.parseInt(ci.getNumber_of_interested()) + 1;
contactViewHolder.numberOfInterestedText.setText(Integer.toString(displayedNumberOfInterested));
System.out.println("emilutzy interested from within" + fi.getPostID());
contactViewHolder.surNameText.setText("kk");
}
});
}
The problem is the click listener. In theory the button I press should increment the number right next to it. However, since I have to declare onBindViewHolder's arguments as final, only the first click works, the rest of the clicks do not change the value of the number. I am new to Android, so could you please help me find a better solution?
There's a nice method called getAdapterPosition() that you can use in your RecyclerView's ViewHolder.
Instead of setting the click listener in onBindViewHolder, set it in the constructor of your ViewHolder like so:
public class FeedViewHolder extends RecyclerView.ViewHolder {
private TextView feedText;
private TextView surNameText;
private Button interestedButton;
// ... the rest of your viewholder elements
public FeedViewHolder(View itemView) {
super(itemView);
feedtext = itemView.findViewById(R.id.feedtext);
// ... find your other views
interestedButton.setOnClickListener(new View.OnClickListener() {
final FeedInfo fi = feedInfoList.get(getAdapterPosition());
int numInterested = Integer.parseInt(ci.getNumber_of_interested()) + 1;
// setting the views here might work,
// but you will find that they reset themselves
// after you scroll up and down (views get recycled).
// find a way to update feedInfoList,
// I like to use EventBus to send an event to the
// host activity/fragment like so:
EventBus.getDefault().post(
new UpdateFeedInfoListEvent(getAdapterPosition(), numInterested));
// in your host activity/fragment,
// update the list and call
// notifyDatasetChanged/notifyDataUpdated()
//on this RecyclerView adapter accordingly
});
}
}
Don't set your position in onBindViewHolder to final (Android Studio will warn you why).
I'm not sure how the object FeedInfo looks like but you could also at a method called for example increaseNumberOfInterested() which would increase the value of Number_of_interested by one and would persist in the object when the recyclerview recycle the cell. it would like kind of like below
#Override
public void onBindViewHolder(final FeedViewHolder contactViewHolder, final int i) {
final FeedInfo ci = feedInfoList.get(i);
//Set the text of the feed with your data
contactViewHolder.numberOfInterestedText.setText(ci.getNumber_of_interested());
contactViewHolder.interestedButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Increase the number of interested in the object, so it can be persisted when cell is reclycled
ci.setNumberOfInterested(ci.getNumber_of_interested()) + 1);
//Get new value and display
contactViewHolder.numberOfInterestedText.setText(Integer.toString(ci.getNumber_of_interested()));
}

trying to pass an int variable from Activity to Adapter

I'm trying to pass the int pub_or_priv from my Activity1 to Myadapter.
I've looked at posts here and I think I've followed them correctly but it's still not working. The value in my adapter is always 0 whereas it should be 0,1 or 2, as is the case with the value in my Activity1.
Here's what I've done.
In my Activity1 I get "publicorprivate" from my server and convert it to an int with:
//convert public_or_private to an integer
pub_or_priv = Integer.parseInt(obj.getString("publicorprivate"));
For different cells in my recyclerView it will be 0,1 or 2.
Now I want to pass this to my adapter so in my adapter contructor I have:
public MyAdapter(List<Review> reviewUsers, Activity activity, int pub_or_priv) {
this.activity = activity;
the_reviews = reviewUsers;
this.mPub_or_priv = pub_or_priv;
}
And in my Activity1:
pAdapter = new MyAdapter(reviewList, this, pub_or_priv);
Then in MyAdapter:
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
Review r = the_reviews.get(position);
//shared_status will be Just U, Private or Public
String shared_status ="";
if(mPub_or_priv==0){
//change colour depending on value
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#DA850B"));
shared_status = "Just U";
}
if(mPub_or_priv==1){
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#0A7FDA"));
shared_status = "Private";
}
if(mPub_or_priv==2){
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#2AB40E"));
shared_status = "Public";
}
((ReviewHolder) viewHolder).phone_user_name.setText(shared_status);
etc..etc..
However in the recyclerView in all cells the phone_user_name textbox is always "Just U", in the #DA850B colour, whereas in fact it is supposed to be Private and Public in some cells, as per the pub_or_priv value in Activity1.
How can I get pub_or_priv correctly into my adapter?, thanks.
It looks like you're using one value in the activity/adapter, so of course all rows show the same value.
In the adapter, use the value in the Review instance that corresponds to the current cell:
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
Review review = the_reviews.get(position);
int pubOrPriv = review.getPublicOrPrivate();
//shared_status will be Just U, Private or Public
String shared_status = "";
if (pubOrPriv == 0) {
//change colour depending on value
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#DA850B"));
shared_status = "Just U";
}
if (pubOrPriv == 1) {
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#0A7FDA"));
shared_status = "Private";
}
if (pubOrPriv == 2) {
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#2AB40E"));
shared_status = "Public";
}
//.............
}

Setting image resourse by obtaining tag position for an imageview android

I am making use of recycler view. I have a layout that is highlighted in light red,this layout is included for each item in the recycler view. The light red layout is placed over the background image. I am using setTag method to identify the clicks of the buttons in red layout. That is working properly when i click i get the position. The problem is i want to change the image at specific position.
For example : Consider the heart button. I have set a tag on it like this.
heartButton = findViewById(id);
heartButton.setTag(position);
now i get the position by using the getTag method. But now i want to change the image of the heartButton at the a specific position. Is there something like
heartButton.getTag(position).setImageResouce(drawable);
If not how do i do this then.
use setBackgroundResource(R.drawable.XXX)
http://developer.android.com/reference/android/view/View.html#setBackgroundResource(int)
Proper way to do this is,
You have to keep the state of the heart button stored in the model(POJO) which is passed to custom adapter.
e.g.
class ModelListItem{
public static final int HEART=1,BROKEN_HEART=2;
int heartButtonState;
}
Now in onClick() of heart button, get that object from adapter using position,cosidering you have already figured it out on how to preserve position from heart button
ModelListItem item = (ModelListItem)adapter.getItem(position)
Change the state of heart button;
item.setHeartButtonState(ModelListItem.BROKEN_HEART);
adapter.notifyDatasetChanged();
You already know below explaination but just in case
To work this properly,in your getView methode of adapter you need to put the check on heartButtonState(); and use appropriate image resource.
getView(BOILERPLATE){
BOILERPLATE
switch(item.getheartButtonState()){
case ModelItemList.HEART:
heartbutton.setImageResource(heart_image);
break;
case ModelItemList.BROKEN_HEART:
heartbutton.setImageResource(broken_heart_image);
break;
}
I made a custom click listener and updated the like in the setter getter.But this works only when the view has been moved out of the view (i think it is the scrapeview)
The Setter Getter Class
public class DemoData {
int background;
boolean liked;
public DemoData(int background) {
this.background = background;
}
public int getBackground() {
return background;
}
// public void setBackground(int background) {
// this.background = background;
// }
public boolean isLiked() {
return liked;
}
public void setLiked(boolean liked) {
this.liked = liked;
}
}
The onBindViewHolder function of the recycler view
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
background = (ImageView) holder.view.findViewById(R.id.image);
layout = (LinearLayout) holder.view.findViewById(R.id.layout);
delete = (ImageView) layout.findViewById(R.id.delete);
lock = (ImageView) layout.findViewById(R.id.lock);
delete.setTag("delete_"+position);
lock.setTag("lock_"+position);
if(Constants.demoDatas.get(position).isLiked()){
delete.setImageResource(R.drawable.ic_launcher);
}
else{
delete.setImageResource(android.R.drawable.ic_delete);
}
delete.setOnClickListener(new CustomClickListener(position));
lock.setOnClickListener(new CustomClickListener(position));
}
The custom click listener is as below
public class CustomClickListener implements View.OnClickListener {
int position;
public CustomClickListener(int position) {
this.position = position;
}
#Override
public void onClick(View v) {
String tag = (String) v.getTag();
String identifier[] = tag.split("_");
// this line saves my state in the Setter Getter Class
Constants.demoDatas.get(position).setLiked(true);
}
}

Categories