简体   繁体   中英

AutoCompleteTextView does not display any dropdown

I am working on a requirement where an Auto Complete text view is used to fetch matching Localities . The user has to enter a few characters, and a list of Localities matching these characters is returned from the server. The Autocomplete Text View then should display this list as a dropdown(or popup). For some reason, even though I am receiving valid Localities from server, the autocomplete dropdown does not come up. Here is my code.

Locality (Model)

public class Locality {
    private int Id;
    private String name;
    private boolean selected;

    //Getters and Setters
}

DonorSearchFragment.xml (layout file containing AutoCompleteTextView)

<AutoCompleteTextView
    android:id="@+id/actLocality"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

LocalityListAdapter View (locality_row.xml)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    <TextView
        android:id="@+id/txvLocalityName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

</LinearLayout>

LocalityListAdapter.java

public class LocalityListAdapter  extends ArrayAdapter<Locality> {

    List<Locality> localities;
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //The Current View
        View view = convertView;
        if (view == null) {
            LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.locality_row, null);
        }
        Locality currentLocality = localities.get(position);
        if (currentLocality != null) {
            TextView txvLocalityName = (TextView) view.findViewById(R.id.txvLocalityName);
            txvLocalityName.setText(currentLocality.getName());
        }
        return view;
    }
}

DonorSearchFragment.java (Fragment showing the AutoCompleteTextView)

public class DonorSearchFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        searchFragmentView = inflater.inflate(R.layout.fragment_donor_search, container, false);

        //Locality AutoComplete
        localityList = new ArrayList<Locality>();
        AutoCompleteTextView actLocality = (AutoCompleteTextView) searchFragmentView.findViewById(R.id.actLocality);
        localityListAdapter = new LocalityListAdapter(this.getActivity(), R.layout.locality_row, localityList);
        actLocality.setAdapter(localityListAdapter);

        actLocality.addTextChangedListener(new TextWatcher() {
        ...
            @Override
            public void afterTextChanged(Editable editable) {
                new LocalitySearchTask().execute();
            }
        });


    private class LocalitySearchTask extends AsyncTask<Void, Void, List<Locality>> {
        ...
        protected List<Locality> doInBackground(Void... voids) {
            List<Locality> localities = null;

            //Call WebService and populate localities

            return localities;
        }

        @Override
        protected void onPostExecute(List<Locality> localities) { 

            //Refresh List backing the Adapter
            //I see valid localities here, but somehow they are not shown by AutoComplete

            localityListAdapter.clear();
            for(Locality locality : localities){
                localityList.add(locality);
            }
            localityListAdapter.notifyDataSetChanged();
        }

    }
}

In onPostExecute() I checked that I am receiving valid Localities List and then pushing them in the LocalityList backing the adapter, but these Localities are not shown by the dropdown. In fact there is no dropdown displayed. Any reasons what could be wrong or missing ?

I feel there is a better way to handle this scenario which obviates the use of AsyncTask . Instead a Filter can be used, which provides performFiltering() callback that actually runs in a worker thread. Here the matching data can be decided / prepared (like by a server call or similar). When the results are prepared the publishResults callback which runs on UI thread, can be used to modifiy the list backing the Custom Adapter. I am just beginning to understand the Android Adapters so I may be incorrect here though. Here is the code that I am using

public class LocalityListAdapter  extends ArrayAdapter<Locality> {

    List<Locality> localities;
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        if (view == null) {
            LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.locality_row, null);
        }
        Locality currentLocality = localities.get(position);
        if (currentLocality != null) {
            TextView txvLocalityName = (TextView) view.findViewById(R.id.txvLocalityName);
            txvLocalityName.setText(currentLocality.getName());
        }
        return view;
    }

    @Override
    public Filter getFilter() {
        return localityFilter;
    }

    Filter localityFilter = new Filter() {
        @Override
        public CharSequence convertResultToString(Object resultValue) {
            Locality locality = (Locality) resultValue;
            return locality.getName();
        }

        protected FilterResults performFiltering(CharSequence constraint) {
            List<Locality> localityList = new ArrayList<Locality>();
            ...Get Data from Server 
            //Return FilterResults created from response
            FilterResults filterResults = new FilterResults();
            filterResults.values = localityList;
            filterResults.count = localityList.size();
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
            localities.clear();
            List<Locality> filteredList = (List<Locality>) filterResults.values;
            for(Locality locality : filteredList) {
                localities.add(locality);
            }
            notifyDataSetChanged();
        }
    }
}            

DonorSearchFragment.java (From MainActivity)

public class DonorSearchFragment extends Fragment {
    ...
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        searchFragmentView = inflater.inflate(R.layout.fragment_donor_search, container, false);

        //Locality AutoComplete
        localityList = new ArrayList<Locality>();
        actLocality = (AutoCompleteTextView) searchFragmentView.findViewById(R.id.actLocality);
        localityListAdapter = new LocalityListAdapter(this.getActivity(), R.layout.locality_row, localityList);
        actLocality.setAdapter(localityListAdapter);
        ...
        return searchFragmentView;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM