Prevent listView item ImageButton from changing state on scroll. And prevent other ImageButtons from changing...












0















I'm creating a DataSet_Collector kind of app where a user is displayed his conversation threads in ListView. The user selects spam threads. Those Threads will be sent to an excel sheet. Then the rest of the threads(The non spam) are shown and the user selects those threads that he wants to send.
So far I've displayed the threads, stored in LinkedHashMap<String, String>, in ListView using extended SimpleAdapter i.e ThreadsAdapter. The Key of the LinkedHashMap<> is the sender and the Value at that Key is the thread. I have created a layout called listView_layout_item.xml that contains two TextView and an ImageButton. Every item of the ListView is inflated with listView_layout_item.xml in getView() like the following.



ThreadsAdapter.java

public class ThreadsAdapter extends SimpleAdapter {

private Context context;

/**
* Constructor
*
* @param context The context where the View associated with this SimpleAdapter is running
* @param data A List of Maps. Each entry in the List corresponds to one row in the list. The
* Maps contain the data for each row, and should include all the entries specified in
* "from"
* @param resource Resource identifier of a view layout that defines the views for this list
* item. The layout file should include at least those named views defined in "to"
* @param from A list of column names that will be added to the Map associated with each
* item.
* @param to The views that should display column in the "from" parameter. These should all be
* TextViews. The first N views in this list are given the values of the first N columns
*/
ThreadsAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String from, int to) {
super(context, data, resource, from, to);
//This 'data' is an ArrayList() of LinkedHashMap<String, String>
//first String for sender of the thread, second String for the thread
//ListView will list sender as item and thread as subitem in
//every getView() instance
this.context = context;
}


private class ViewHolder{
private ImageButton threadCheck;
private boolean isTChecked;
}

@SuppressLint("InflateParams")
@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
ViewHolder view;
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
if (convertView == null) {
convertView = inflater.inflate(R.layout.listView_layout_item, null);
view = new ViewHolder();
view.threadCheck =(ImageButton) convertView.findViewById(R.id.threadChecker);
view.isTChecked = false; // in the start of the app.
final ViewHolder finalView = view;
view.threadCheck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(finalView.isTChecked)
finalView.threadCheck.setImageResource(R.drawable.circle_unchecked);
else
finalView.threadCheck.setImageResource(R.drawable.circle_checked);
finalView.isTChecked = !finalView.isTChecked;
}
});
convertView.setTag(view);
} else {
view = (ViewHolder) convertView.getTag();
}
super.getView(position, convertView, parent);
return convertView;
}
}


super.getView() is called at the end of getView() because I want to use the Text and Subtext format of SimpleAdapter for ListView.



With the given code



when I click on one ImageButton of a ListView item to change it's state, other ImageButtons of other items in ListView also change their state. Why?! and how do I fix it?



And when I scroll up or down, the state of any ImageButton changes randomly. Why?! and how do I fix it?



I'm new to ListView and ListView adapters. The present answers don't make sense so I posted my own special problem.










share|improve this question





























    0















    I'm creating a DataSet_Collector kind of app where a user is displayed his conversation threads in ListView. The user selects spam threads. Those Threads will be sent to an excel sheet. Then the rest of the threads(The non spam) are shown and the user selects those threads that he wants to send.
    So far I've displayed the threads, stored in LinkedHashMap<String, String>, in ListView using extended SimpleAdapter i.e ThreadsAdapter. The Key of the LinkedHashMap<> is the sender and the Value at that Key is the thread. I have created a layout called listView_layout_item.xml that contains two TextView and an ImageButton. Every item of the ListView is inflated with listView_layout_item.xml in getView() like the following.



    ThreadsAdapter.java

    public class ThreadsAdapter extends SimpleAdapter {

    private Context context;

    /**
    * Constructor
    *
    * @param context The context where the View associated with this SimpleAdapter is running
    * @param data A List of Maps. Each entry in the List corresponds to one row in the list. The
    * Maps contain the data for each row, and should include all the entries specified in
    * "from"
    * @param resource Resource identifier of a view layout that defines the views for this list
    * item. The layout file should include at least those named views defined in "to"
    * @param from A list of column names that will be added to the Map associated with each
    * item.
    * @param to The views that should display column in the "from" parameter. These should all be
    * TextViews. The first N views in this list are given the values of the first N columns
    */
    ThreadsAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String from, int to) {
    super(context, data, resource, from, to);
    //This 'data' is an ArrayList() of LinkedHashMap<String, String>
    //first String for sender of the thread, second String for the thread
    //ListView will list sender as item and thread as subitem in
    //every getView() instance
    this.context = context;
    }


    private class ViewHolder{
    private ImageButton threadCheck;
    private boolean isTChecked;
    }

    @SuppressLint("InflateParams")
    @Override
    public View getView(final int position, View convertView,
    ViewGroup parent) {
    ViewHolder view;
    LayoutInflater inflater = ((Activity) context).getLayoutInflater();
    if (convertView == null) {
    convertView = inflater.inflate(R.layout.listView_layout_item, null);
    view = new ViewHolder();
    view.threadCheck =(ImageButton) convertView.findViewById(R.id.threadChecker);
    view.isTChecked = false; // in the start of the app.
    final ViewHolder finalView = view;
    view.threadCheck.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    if(finalView.isTChecked)
    finalView.threadCheck.setImageResource(R.drawable.circle_unchecked);
    else
    finalView.threadCheck.setImageResource(R.drawable.circle_checked);
    finalView.isTChecked = !finalView.isTChecked;
    }
    });
    convertView.setTag(view);
    } else {
    view = (ViewHolder) convertView.getTag();
    }
    super.getView(position, convertView, parent);
    return convertView;
    }
    }


    super.getView() is called at the end of getView() because I want to use the Text and Subtext format of SimpleAdapter for ListView.



    With the given code



    when I click on one ImageButton of a ListView item to change it's state, other ImageButtons of other items in ListView also change their state. Why?! and how do I fix it?



    And when I scroll up or down, the state of any ImageButton changes randomly. Why?! and how do I fix it?



    I'm new to ListView and ListView adapters. The present answers don't make sense so I posted my own special problem.










    share|improve this question



























      0












      0








      0








      I'm creating a DataSet_Collector kind of app where a user is displayed his conversation threads in ListView. The user selects spam threads. Those Threads will be sent to an excel sheet. Then the rest of the threads(The non spam) are shown and the user selects those threads that he wants to send.
      So far I've displayed the threads, stored in LinkedHashMap<String, String>, in ListView using extended SimpleAdapter i.e ThreadsAdapter. The Key of the LinkedHashMap<> is the sender and the Value at that Key is the thread. I have created a layout called listView_layout_item.xml that contains two TextView and an ImageButton. Every item of the ListView is inflated with listView_layout_item.xml in getView() like the following.



      ThreadsAdapter.java

      public class ThreadsAdapter extends SimpleAdapter {

      private Context context;

      /**
      * Constructor
      *
      * @param context The context where the View associated with this SimpleAdapter is running
      * @param data A List of Maps. Each entry in the List corresponds to one row in the list. The
      * Maps contain the data for each row, and should include all the entries specified in
      * "from"
      * @param resource Resource identifier of a view layout that defines the views for this list
      * item. The layout file should include at least those named views defined in "to"
      * @param from A list of column names that will be added to the Map associated with each
      * item.
      * @param to The views that should display column in the "from" parameter. These should all be
      * TextViews. The first N views in this list are given the values of the first N columns
      */
      ThreadsAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String from, int to) {
      super(context, data, resource, from, to);
      //This 'data' is an ArrayList() of LinkedHashMap<String, String>
      //first String for sender of the thread, second String for the thread
      //ListView will list sender as item and thread as subitem in
      //every getView() instance
      this.context = context;
      }


      private class ViewHolder{
      private ImageButton threadCheck;
      private boolean isTChecked;
      }

      @SuppressLint("InflateParams")
      @Override
      public View getView(final int position, View convertView,
      ViewGroup parent) {
      ViewHolder view;
      LayoutInflater inflater = ((Activity) context).getLayoutInflater();
      if (convertView == null) {
      convertView = inflater.inflate(R.layout.listView_layout_item, null);
      view = new ViewHolder();
      view.threadCheck =(ImageButton) convertView.findViewById(R.id.threadChecker);
      view.isTChecked = false; // in the start of the app.
      final ViewHolder finalView = view;
      view.threadCheck.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
      if(finalView.isTChecked)
      finalView.threadCheck.setImageResource(R.drawable.circle_unchecked);
      else
      finalView.threadCheck.setImageResource(R.drawable.circle_checked);
      finalView.isTChecked = !finalView.isTChecked;
      }
      });
      convertView.setTag(view);
      } else {
      view = (ViewHolder) convertView.getTag();
      }
      super.getView(position, convertView, parent);
      return convertView;
      }
      }


      super.getView() is called at the end of getView() because I want to use the Text and Subtext format of SimpleAdapter for ListView.



      With the given code



      when I click on one ImageButton of a ListView item to change it's state, other ImageButtons of other items in ListView also change their state. Why?! and how do I fix it?



      And when I scroll up or down, the state of any ImageButton changes randomly. Why?! and how do I fix it?



      I'm new to ListView and ListView adapters. The present answers don't make sense so I posted my own special problem.










      share|improve this question
















      I'm creating a DataSet_Collector kind of app where a user is displayed his conversation threads in ListView. The user selects spam threads. Those Threads will be sent to an excel sheet. Then the rest of the threads(The non spam) are shown and the user selects those threads that he wants to send.
      So far I've displayed the threads, stored in LinkedHashMap<String, String>, in ListView using extended SimpleAdapter i.e ThreadsAdapter. The Key of the LinkedHashMap<> is the sender and the Value at that Key is the thread. I have created a layout called listView_layout_item.xml that contains two TextView and an ImageButton. Every item of the ListView is inflated with listView_layout_item.xml in getView() like the following.



      ThreadsAdapter.java

      public class ThreadsAdapter extends SimpleAdapter {

      private Context context;

      /**
      * Constructor
      *
      * @param context The context where the View associated with this SimpleAdapter is running
      * @param data A List of Maps. Each entry in the List corresponds to one row in the list. The
      * Maps contain the data for each row, and should include all the entries specified in
      * "from"
      * @param resource Resource identifier of a view layout that defines the views for this list
      * item. The layout file should include at least those named views defined in "to"
      * @param from A list of column names that will be added to the Map associated with each
      * item.
      * @param to The views that should display column in the "from" parameter. These should all be
      * TextViews. The first N views in this list are given the values of the first N columns
      */
      ThreadsAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String from, int to) {
      super(context, data, resource, from, to);
      //This 'data' is an ArrayList() of LinkedHashMap<String, String>
      //first String for sender of the thread, second String for the thread
      //ListView will list sender as item and thread as subitem in
      //every getView() instance
      this.context = context;
      }


      private class ViewHolder{
      private ImageButton threadCheck;
      private boolean isTChecked;
      }

      @SuppressLint("InflateParams")
      @Override
      public View getView(final int position, View convertView,
      ViewGroup parent) {
      ViewHolder view;
      LayoutInflater inflater = ((Activity) context).getLayoutInflater();
      if (convertView == null) {
      convertView = inflater.inflate(R.layout.listView_layout_item, null);
      view = new ViewHolder();
      view.threadCheck =(ImageButton) convertView.findViewById(R.id.threadChecker);
      view.isTChecked = false; // in the start of the app.
      final ViewHolder finalView = view;
      view.threadCheck.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
      if(finalView.isTChecked)
      finalView.threadCheck.setImageResource(R.drawable.circle_unchecked);
      else
      finalView.threadCheck.setImageResource(R.drawable.circle_checked);
      finalView.isTChecked = !finalView.isTChecked;
      }
      });
      convertView.setTag(view);
      } else {
      view = (ViewHolder) convertView.getTag();
      }
      super.getView(position, convertView, parent);
      return convertView;
      }
      }


      super.getView() is called at the end of getView() because I want to use the Text and Subtext format of SimpleAdapter for ListView.



      With the given code



      when I click on one ImageButton of a ListView item to change it's state, other ImageButtons of other items in ListView also change their state. Why?! and how do I fix it?



      And when I scroll up or down, the state of any ImageButton changes randomly. Why?! and how do I fix it?



      I'm new to ListView and ListView adapters. The present answers don't make sense so I posted my own special problem.







      android listview






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 24 '18 at 10:27









      Nisse Engström

      4,14892134




      4,14892134










      asked Nov 24 '18 at 9:11









      AhmadAhmad

      117




      117
























          1 Answer
          1






          active

          oldest

          votes


















          0














          In ListViews, rows (ViewHolders in your case) are recycled, reused, which means that you see stuff going up and down, but it's the same set of rows over and over again.



          Keeping that in mind, it is not correct to store any state in the rows because when stuff gets reused, they will use state they previously had, which on first glance appears random.



          What you should do is store the isTChecked state in your data. To that end, I would advise you to switch the LinkedHashMap to a ArrayList and use simple Java objects. You could have a class like this:



          public class ConversationThread {
          public String sender;
          public String thread;
          public Boolean isChecked = false; /* Initially false, to match your scenario. */
          }


          Your adapter's getView override would become something like this:



          public View getView(final int position, View convertView, ViewGroup parent) {
          /* 'getItem' would bring you the data for the provided position, once you
          * switch from a LinkedHashMap to an ArrayList. */
          final ConversationThread conversationThread = getItem(position);

          ViewHolder view;

          if (convertView == null) {
          /* Here, the row is created for the first time, hence why you inflate
          * the XML layout. */
          LayoutInflater inflater = ((Activity) context).getLayoutInflater();
          convertView = inflater.inflate(R.layout.listView_layout_item, null);

          view = new ViewHolder();
          view.threadCheck = (ImageButton) convertView.findViewById(R.id.threadChecker);

          /* You save the ViewHolder as the View's tag, to be able to reuse it. */
          convertView.setTag(view);
          } else {
          /* Here, the row exists, so you fetch the ViewHolder to actually reuse it. */
          view = (ViewHolder) convertView.getTag();
          }

          /* Once you have your ViewHolder, old or new, you can then update it.
          * That means updating the image and using a new click listener as well. */
          if (conversationThread.isChecked)
          view.threadCheck.setImageResource(R.drawable.circle_checked);
          else
          view.threadCheck.setImageResource(R.drawable.circle_unchecked);

          view.threadCheck.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v /* This is the actual view clicked (view.threadCheck) */) {
          /* On click, toggle the flag and then update the View. */
          conversationThread.isChecked = !conversationThread.isChecked;

          if (conversationThread.isChecked)
          v.setImageResource(R.drawable.circle_checked);
          else
          v.setImageResource(R.drawable.circle_unchecked);
          }
          });

          /* If you also need to call super, you can do so. */
          super.getView(position, convertView, parent);

          return convertView;
          }


          This is in no way optimal, I just tried to make things clear with moving as little code around as possible.






          share|improve this answer


























          • Thanks, bro. you saved my day. The problem wasn't big, I was thinking small. So I used, like you told, an inner class conversationThread and extended BaseAdapter. How easy was that.

            – Ahmad
            Nov 24 '18 at 13:32











          • @Ahmad please mark as correct answer if it helped :)

            – iFanie
            Nov 25 '18 at 14:59











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53456737%2fprevent-listview-item-imagebutton-from-changing-state-on-scroll-and-prevent-oth%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          In ListViews, rows (ViewHolders in your case) are recycled, reused, which means that you see stuff going up and down, but it's the same set of rows over and over again.



          Keeping that in mind, it is not correct to store any state in the rows because when stuff gets reused, they will use state they previously had, which on first glance appears random.



          What you should do is store the isTChecked state in your data. To that end, I would advise you to switch the LinkedHashMap to a ArrayList and use simple Java objects. You could have a class like this:



          public class ConversationThread {
          public String sender;
          public String thread;
          public Boolean isChecked = false; /* Initially false, to match your scenario. */
          }


          Your adapter's getView override would become something like this:



          public View getView(final int position, View convertView, ViewGroup parent) {
          /* 'getItem' would bring you the data for the provided position, once you
          * switch from a LinkedHashMap to an ArrayList. */
          final ConversationThread conversationThread = getItem(position);

          ViewHolder view;

          if (convertView == null) {
          /* Here, the row is created for the first time, hence why you inflate
          * the XML layout. */
          LayoutInflater inflater = ((Activity) context).getLayoutInflater();
          convertView = inflater.inflate(R.layout.listView_layout_item, null);

          view = new ViewHolder();
          view.threadCheck = (ImageButton) convertView.findViewById(R.id.threadChecker);

          /* You save the ViewHolder as the View's tag, to be able to reuse it. */
          convertView.setTag(view);
          } else {
          /* Here, the row exists, so you fetch the ViewHolder to actually reuse it. */
          view = (ViewHolder) convertView.getTag();
          }

          /* Once you have your ViewHolder, old or new, you can then update it.
          * That means updating the image and using a new click listener as well. */
          if (conversationThread.isChecked)
          view.threadCheck.setImageResource(R.drawable.circle_checked);
          else
          view.threadCheck.setImageResource(R.drawable.circle_unchecked);

          view.threadCheck.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v /* This is the actual view clicked (view.threadCheck) */) {
          /* On click, toggle the flag and then update the View. */
          conversationThread.isChecked = !conversationThread.isChecked;

          if (conversationThread.isChecked)
          v.setImageResource(R.drawable.circle_checked);
          else
          v.setImageResource(R.drawable.circle_unchecked);
          }
          });

          /* If you also need to call super, you can do so. */
          super.getView(position, convertView, parent);

          return convertView;
          }


          This is in no way optimal, I just tried to make things clear with moving as little code around as possible.






          share|improve this answer


























          • Thanks, bro. you saved my day. The problem wasn't big, I was thinking small. So I used, like you told, an inner class conversationThread and extended BaseAdapter. How easy was that.

            – Ahmad
            Nov 24 '18 at 13:32











          • @Ahmad please mark as correct answer if it helped :)

            – iFanie
            Nov 25 '18 at 14:59
















          0














          In ListViews, rows (ViewHolders in your case) are recycled, reused, which means that you see stuff going up and down, but it's the same set of rows over and over again.



          Keeping that in mind, it is not correct to store any state in the rows because when stuff gets reused, they will use state they previously had, which on first glance appears random.



          What you should do is store the isTChecked state in your data. To that end, I would advise you to switch the LinkedHashMap to a ArrayList and use simple Java objects. You could have a class like this:



          public class ConversationThread {
          public String sender;
          public String thread;
          public Boolean isChecked = false; /* Initially false, to match your scenario. */
          }


          Your adapter's getView override would become something like this:



          public View getView(final int position, View convertView, ViewGroup parent) {
          /* 'getItem' would bring you the data for the provided position, once you
          * switch from a LinkedHashMap to an ArrayList. */
          final ConversationThread conversationThread = getItem(position);

          ViewHolder view;

          if (convertView == null) {
          /* Here, the row is created for the first time, hence why you inflate
          * the XML layout. */
          LayoutInflater inflater = ((Activity) context).getLayoutInflater();
          convertView = inflater.inflate(R.layout.listView_layout_item, null);

          view = new ViewHolder();
          view.threadCheck = (ImageButton) convertView.findViewById(R.id.threadChecker);

          /* You save the ViewHolder as the View's tag, to be able to reuse it. */
          convertView.setTag(view);
          } else {
          /* Here, the row exists, so you fetch the ViewHolder to actually reuse it. */
          view = (ViewHolder) convertView.getTag();
          }

          /* Once you have your ViewHolder, old or new, you can then update it.
          * That means updating the image and using a new click listener as well. */
          if (conversationThread.isChecked)
          view.threadCheck.setImageResource(R.drawable.circle_checked);
          else
          view.threadCheck.setImageResource(R.drawable.circle_unchecked);

          view.threadCheck.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v /* This is the actual view clicked (view.threadCheck) */) {
          /* On click, toggle the flag and then update the View. */
          conversationThread.isChecked = !conversationThread.isChecked;

          if (conversationThread.isChecked)
          v.setImageResource(R.drawable.circle_checked);
          else
          v.setImageResource(R.drawable.circle_unchecked);
          }
          });

          /* If you also need to call super, you can do so. */
          super.getView(position, convertView, parent);

          return convertView;
          }


          This is in no way optimal, I just tried to make things clear with moving as little code around as possible.






          share|improve this answer


























          • Thanks, bro. you saved my day. The problem wasn't big, I was thinking small. So I used, like you told, an inner class conversationThread and extended BaseAdapter. How easy was that.

            – Ahmad
            Nov 24 '18 at 13:32











          • @Ahmad please mark as correct answer if it helped :)

            – iFanie
            Nov 25 '18 at 14:59














          0












          0








          0







          In ListViews, rows (ViewHolders in your case) are recycled, reused, which means that you see stuff going up and down, but it's the same set of rows over and over again.



          Keeping that in mind, it is not correct to store any state in the rows because when stuff gets reused, they will use state they previously had, which on first glance appears random.



          What you should do is store the isTChecked state in your data. To that end, I would advise you to switch the LinkedHashMap to a ArrayList and use simple Java objects. You could have a class like this:



          public class ConversationThread {
          public String sender;
          public String thread;
          public Boolean isChecked = false; /* Initially false, to match your scenario. */
          }


          Your adapter's getView override would become something like this:



          public View getView(final int position, View convertView, ViewGroup parent) {
          /* 'getItem' would bring you the data for the provided position, once you
          * switch from a LinkedHashMap to an ArrayList. */
          final ConversationThread conversationThread = getItem(position);

          ViewHolder view;

          if (convertView == null) {
          /* Here, the row is created for the first time, hence why you inflate
          * the XML layout. */
          LayoutInflater inflater = ((Activity) context).getLayoutInflater();
          convertView = inflater.inflate(R.layout.listView_layout_item, null);

          view = new ViewHolder();
          view.threadCheck = (ImageButton) convertView.findViewById(R.id.threadChecker);

          /* You save the ViewHolder as the View's tag, to be able to reuse it. */
          convertView.setTag(view);
          } else {
          /* Here, the row exists, so you fetch the ViewHolder to actually reuse it. */
          view = (ViewHolder) convertView.getTag();
          }

          /* Once you have your ViewHolder, old or new, you can then update it.
          * That means updating the image and using a new click listener as well. */
          if (conversationThread.isChecked)
          view.threadCheck.setImageResource(R.drawable.circle_checked);
          else
          view.threadCheck.setImageResource(R.drawable.circle_unchecked);

          view.threadCheck.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v /* This is the actual view clicked (view.threadCheck) */) {
          /* On click, toggle the flag and then update the View. */
          conversationThread.isChecked = !conversationThread.isChecked;

          if (conversationThread.isChecked)
          v.setImageResource(R.drawable.circle_checked);
          else
          v.setImageResource(R.drawable.circle_unchecked);
          }
          });

          /* If you also need to call super, you can do so. */
          super.getView(position, convertView, parent);

          return convertView;
          }


          This is in no way optimal, I just tried to make things clear with moving as little code around as possible.






          share|improve this answer















          In ListViews, rows (ViewHolders in your case) are recycled, reused, which means that you see stuff going up and down, but it's the same set of rows over and over again.



          Keeping that in mind, it is not correct to store any state in the rows because when stuff gets reused, they will use state they previously had, which on first glance appears random.



          What you should do is store the isTChecked state in your data. To that end, I would advise you to switch the LinkedHashMap to a ArrayList and use simple Java objects. You could have a class like this:



          public class ConversationThread {
          public String sender;
          public String thread;
          public Boolean isChecked = false; /* Initially false, to match your scenario. */
          }


          Your adapter's getView override would become something like this:



          public View getView(final int position, View convertView, ViewGroup parent) {
          /* 'getItem' would bring you the data for the provided position, once you
          * switch from a LinkedHashMap to an ArrayList. */
          final ConversationThread conversationThread = getItem(position);

          ViewHolder view;

          if (convertView == null) {
          /* Here, the row is created for the first time, hence why you inflate
          * the XML layout. */
          LayoutInflater inflater = ((Activity) context).getLayoutInflater();
          convertView = inflater.inflate(R.layout.listView_layout_item, null);

          view = new ViewHolder();
          view.threadCheck = (ImageButton) convertView.findViewById(R.id.threadChecker);

          /* You save the ViewHolder as the View's tag, to be able to reuse it. */
          convertView.setTag(view);
          } else {
          /* Here, the row exists, so you fetch the ViewHolder to actually reuse it. */
          view = (ViewHolder) convertView.getTag();
          }

          /* Once you have your ViewHolder, old or new, you can then update it.
          * That means updating the image and using a new click listener as well. */
          if (conversationThread.isChecked)
          view.threadCheck.setImageResource(R.drawable.circle_checked);
          else
          view.threadCheck.setImageResource(R.drawable.circle_unchecked);

          view.threadCheck.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v /* This is the actual view clicked (view.threadCheck) */) {
          /* On click, toggle the flag and then update the View. */
          conversationThread.isChecked = !conversationThread.isChecked;

          if (conversationThread.isChecked)
          v.setImageResource(R.drawable.circle_checked);
          else
          v.setImageResource(R.drawable.circle_unchecked);
          }
          });

          /* If you also need to call super, you can do so. */
          super.getView(position, convertView, parent);

          return convertView;
          }


          This is in no way optimal, I just tried to make things clear with moving as little code around as possible.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 24 '18 at 10:32

























          answered Nov 24 '18 at 10:27









          iFanieiFanie

          1718




          1718













          • Thanks, bro. you saved my day. The problem wasn't big, I was thinking small. So I used, like you told, an inner class conversationThread and extended BaseAdapter. How easy was that.

            – Ahmad
            Nov 24 '18 at 13:32











          • @Ahmad please mark as correct answer if it helped :)

            – iFanie
            Nov 25 '18 at 14:59



















          • Thanks, bro. you saved my day. The problem wasn't big, I was thinking small. So I used, like you told, an inner class conversationThread and extended BaseAdapter. How easy was that.

            – Ahmad
            Nov 24 '18 at 13:32











          • @Ahmad please mark as correct answer if it helped :)

            – iFanie
            Nov 25 '18 at 14:59

















          Thanks, bro. you saved my day. The problem wasn't big, I was thinking small. So I used, like you told, an inner class conversationThread and extended BaseAdapter. How easy was that.

          – Ahmad
          Nov 24 '18 at 13:32





          Thanks, bro. you saved my day. The problem wasn't big, I was thinking small. So I used, like you told, an inner class conversationThread and extended BaseAdapter. How easy was that.

          – Ahmad
          Nov 24 '18 at 13:32













          @Ahmad please mark as correct answer if it helped :)

          – iFanie
          Nov 25 '18 at 14:59





          @Ahmad please mark as correct answer if it helped :)

          – iFanie
          Nov 25 '18 at 14:59




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53456737%2fprevent-listview-item-imagebutton-from-changing-state-on-scroll-and-prevent-oth%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Costa Masnaga

          Fotorealismo

          Sidney Franklin