ListView does not update until keyboard is hidden
Asked Answered
J

3

11

I have a DialogFragment and in it's layout I have a EditText and a ListView. The Listview basically shows the list of contacts (Initially this list has 0 items). When the edittext's value is updated I populate the list with contacts that have the text typed in the EditText.

On the EditText I have used a addTextChangedListener to update the list with desired contacts as the user types in a name or email address of the contact.

The weird problem I am facing is that the list (or maybe the layout) gets updated only when I press the back button to hide the keyboard after typing. As long as the soft keyboard is showing the the list does not get updated (Except for the very first time when items are added to the empty list).

Following is some of the code for better understanding.

CustomDialogFragment.java

(in onCreateView):

    // Set list adapter for contacts list
    contactsList = (ListView) shareView.findViewById(R.id.contactList);
    emailContactAdapter = new EmailContactAdapter(getActivity(), emailContacts, shareFragment);
    contactsList.setAdapter(emailContactAdapter);

    // Implement Phone-book contact share
    sendToInput = (EditText) shareView.findViewById(R.id.contact_name);
    sendToInput.addTextChangedListener(onContactNameSearch);

in onContactNameSearch (TextWatcher):

public TextWatcher onContactNameSearch = new TextWatcher() {

    private generics commonMethods = new generics();

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        emailContacts.clear();
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {
        Log.d("DEBUG::REACH", "After Text Changed called");
        String textValue = s.toString();

        // Show or hide the share apps list based on user input
        // and whether or not the list is already showing or not
        if (textValue.equals("")) {
            Log.d("DEBUG::REACH", "TEXT value is empty");
            showAppList();
            emailContacts.clear();
        } else {

            Log.d("DEBUG::REACH", "TEXT has value");

            // Hide app list if visible
            if (isAppListShowing()) hideAppList();

            // Get the email contacts list based on the user query
            emailContacts.addAll(commonMethods.getEmailContacts(appContext, textValue));
        }

        adapter.notifyDataSetChanged();
    }

My assumption is that the list adapter's list is correctly updated but due to some reason the layout does not reflect the new changes until the soft keyboard is hidden.

Questions:

  • Has anyone faced a similar issue before (Could not find any resources while googling :/) ?
  • Why does this happen ?
  • Is there anything related to this in the official docs ?
  • What's the best way to resolve this ?

PS: The code in the afterTextChanged method was previously in the onTextChanged method and I was facing the same issue.

UPDATE (Added screenshots for better understanding)

  1. The following is when the dialog fragment is shown and no text has been typed in the edittext. This is when the dialog fragment is shown

  2. Now when I type in "A" and the list populates. enter image description here

  3. I add another few letters but the list does not update. I added letters "mit" so now the query becomes "Amit" but no change in the list. enter image description here

  4. Now when I press the hardware back button on the device to hide the keyboard. The keyboard is hidden and the list is updated. enter image description here

(Please do not mind the overlapping contact names and emails, still have to fix the layout :P)

UPDATE2 (Adding EmailContactAdapter code)

Following is the EmailContactAdapter class

public class EmailContactAdapter extends BaseAdapter {

private Activity activity;
private ArrayList<EmailContact> contacts;
private ProductShareFragment fragment;
private LayoutInflater inflater;

/**
 * Constructor
 */
public EmailContactAdapter(Activity activity, ArrayList<EmailContact> contacts, ProductShareFragment fragment) {
    this.activity = activity;
    this.contacts = contacts;
    this.fragment = fragment;
}

@Override
public int getCount() {
    return contacts.size();
}

@Override
public Object getItem(int position) {
    return contacts.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (inflater == null) {
        inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    if (convertView == null) {
        convertView = inflater.inflate(R.layout.email_contact_list_row, null);
    }

    EmailContact contact = contacts.get(position);
    ImageView contactImage = (ImageView) convertView.findViewById(R.id.email_contact_image);
    TextView contactName = (TextView) convertView.findViewById(R.id.email_contact_name);
    TextView contactEmail = (TextView) convertView.findViewById(R.id.email_contact_email);

    // contactImage.setImageBitmap(contact.getImage());
    contactName.setText(contact.getName());
    contactEmail.setText(contact.getEmail());

    return convertView;
}
}
Jape answered 13/5, 2015 at 14:6 Comment(4)
Show your EmailContactAdapter class.Termless
@Termless Hey, I have updated the question to contain the screenshots and the EmailContactAdapter class' code. Thanks.Jape
Have you try getListView().invalidateViews(); like this ?#23185431Abscess
did you ever figure out a solution?Stung
T
0

You are trying to change visible list with changing emailContacts, but adapter still contains old list data.

Solution: after each new text in EditText create new adapter (is a VERY bad way), or create method in EmailContactAdapter to replace items - in your case contacts field.

Termless answered 13/5, 2015 at 14:29 Comment(6)
The adapter class extends the BaseAdapter so if I make any changes to the list that the adapter was initialized with adapter should Ideally handle those changes. Even if it's the case then why would the list update when keyboard is hidden ?Jape
Hide/show keyboard calls changing configuration of the device, so Activity creates from beginning and calls your code of creating adapter.Termless
Shouldn't calling adapter.notifyDataSetChanged(); take care of this ?Jape
Because as far as I remember if I do not call adapter.notifyDataSetChanged(); I got an exception telling me that the list has been changed but the adapter was not notified.Jape
You don't understand - contacts field of your adapter doesn't changing, so notifyDataSetChanged() doesn't make a sence. After changing text you should call some setItems method of your adapter (inside it call notifyDataSetChanged()).Termless
Sorry, I still do not understand if this is the case, Why would it work the first time when the list is empty as even the first time I am making changes to the same list. :/Jape
T
0

In the below code, you are populating the list with the result of commonMethods.getEmailContacts

// Get the email contacts list based on the user query
emailContacts.addAll(commonMethods.getEmailContacts(appContext, textValue));

Surely you first need to do emailContacts.Clear() otherwise the list is not going to change?

Triton answered 13/5, 2015 at 14:53 Comment(2)
Check the beforeTextChanged method, I call emailContacts.clear(); there as it is called before the afterTextChanged.Jape
Also, Initially I was calling emailContacts.clear(); just before adding the new list item to emailContacts but was still facing the same issue.Jape
S
0

Try delete all emailContacts.clear();. Then add emailContacts.clear(); just before emailContacts.addAll(commonMethods.getEmailContacts(appContext, textValue));. You are appending your list for every letter your typed.

Southerly answered 14/5, 2015 at 6:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.