1

I have manage to create a custom adapter and read data from web API but the suggestions are not displayed in the dropdown. I followed the tutorial at

http://makovkastar.github.io/blog/2014/04/12/android-autocompletetextview-with-suggestions-from-a-web-service/

Here is my custom AutoCompleteTextView

public class AutoCompleteDelay extends AutoCompleteTextView {

    private static final int MESSAGE_TEXT_CHANGED = 100;
    private static final int DEFAULT_AUTOCOMPLETE_DELAY = 750;

    private int mAutoCompleteDelay = DEFAULT_AUTOCOMPLETE_DELAY;
    private ProgressBar mLoadingIndicator;

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            AutoCompleteDelay.super.performFiltering((CharSequence) msg.obj, msg.arg1);
        }
    };

    public AutoCompleteDelay(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setLoadingIndicator(ProgressBar progressBar) {
        mLoadingIndicator = progressBar;
    }

    public void setAutoCompleteDelay(int autoCompleteDelay) {
        mAutoCompleteDelay = autoCompleteDelay;
    }

    @Override
    protected void performFiltering(CharSequence text, int keyCode) {
        if (mLoadingIndicator != null) {
            mLoadingIndicator.setVisibility(View.VISIBLE);
        }
        mHandler.removeMessages(MESSAGE_TEXT_CHANGED);
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_TEXT_CHANGED, text), mAutoCompleteDelay);
    }

    @Override
    public void onFilterComplete(int count) {
        if (mLoadingIndicator != null) {
            mLoadingIndicator.setVisibility(View.GONE);
        }
        super.onFilterComplete(count);
    }
}

This is my custom Adapter

public class SearchAdapter extends BaseAdapter implements Filterable {

    private static final int MAX_RESULTS = 10;
    private Context mContext;
    private List<User> resultList = new ArrayList<User>();

    public SearchAdapter(Context context) {
        mContext = context;
    }

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

    @Override
    public User getItem(int index) {
        return resultList.get(index);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) mContext
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.search_results, parent, false);
        }
        ((TextView) convertView.findViewById(R.id.user_name)).setText(getItem(position).getName());
        ((TextView) convertView.findViewById(R.id.user_phone)).setText(getItem(position).getPhone());
        return convertView;
    }

    @Override
    public Filter getFilter() {
        Filter filter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults filterResults = new FilterResults();
                if (constraint != null) {
                    List<User> users = findUsers(mContext, constraint.toString());

                    // Assign the data to the FilterResults
                    filterResults.values = users;
                    filterResults.count = users.size();
                }
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                if (results != null && results.count > 0) {
                    resultList = (List<User>) results.values;
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }};
        return filter;
    }

    /**
     * Returns a search result for the given book title.
     */
    private List<User> findUsers(Context context, String query) {
        // GoogleBooksProtocol is a wrapper for the Google Books API
        SearchUser request = new SearchUser(context);
        return request.sendRequest(query);
    }

}

This is xml file for Adapter View

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/user_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Name"
        android:textSize="18dp"
        android:textIsSelectable="false"
        android:layout_marginBottom="4dp"
        android:textColor="@color/abc_background_cache_hint_selector_material_dark" />

    <TextView
        android:id="@+id/user_phone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="0000000000"
        android:textSize="16dp"
        android:textIsSelectable="false"
        android:layout_marginBottom="4dp"
        android:textColor="@color/switch_thumb_disabled_material_dark" />

</LinearLayout>

This is the xml file where I am using 'AutoCompleteTextView`

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/error_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="User already exists"
        android:visibility="gone"
        android:textStyle="bold"
        android:textColor="@color/design_textinput_error_color_light"
        android:singleLine="true"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <com.example.krazz.futsaladmin.classes.AutoCompleteDelay
                android:id="@+id/query"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:imeOptions="actionNext"
                android:inputType="textAutoComplete"></com.example.krazz.futsaladmin.classes.AutoCompleteDelay>

        </android.support.design.widget.TextInputLayout>

        <ProgressBar
            android:id="@+id/pb_loading_indicator"
            style="?android:attr/progressBarStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:visibility="gone" />

    </RelativeLayout>

</LinearLayout>

This is the method that returns ArrayList<User>

public ArrayList<User> sendRequest(final String query) {

        RequestQueue requestQueue = VolleySingleton.getsInstance().getmRequestQueue();

        //mErrorText.setVisibility(View.GONE);

        String url = String.format(AppConfig.URL_SEARCH_USERS, query, AppConfig.APP_KEY, 4);
        debug.L(url);

        StringRequest strReq = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {

                try {
                    debug.L(response.toString());
                    JSONObject jObj = new JSONObject(response);
                    JSONArray jsonArray = jObj.getJSONArray("results");

                    if(jsonArray != null){
                        for(int i=0; i<jsonArray.length(); i++){
                            JSONObject currentUser = jsonArray.getJSONObject(i);

                            int id = currentUser.getInt("id");
                            String name = currentUser.getString("name");
                            String phone = currentUser.getString("phone");
                            User users = new User(id, name, phone);
                            searchArrayList.add(users);
                        }
                    }
                    else{
                        /*mErrorText.setText("Users not found.");
                        mErrorText.setVisibility(View.VISIBLE);*/
                        debug.L("users not found");
                    }
                } catch (JSONException e) {
                    /*mErrorText.setText(e.getMessage());
                    mErrorText.setVisibility(View.VISIBLE);*/
                    debug.L(e.toString());
                }

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                /*mErrorText.setText(R.string.error_try_again);
                mErrorText.setVisibility(View.VISIBLE);*/
                debug.L(error.toString());
            }
        });

        requestQueue.add(strReq);
        return searchArrayList;
    }

And finally here is where I am using my AutoCompleteTextView

mQueryInputView = (AutoCompleteDelay) view.findViewById(R.id.query);
        mErrorText = (TextView) view.findViewById(R.id.error_text);

        mQueryInputView.setThreshold(THRESHOLD);
        mQueryInputView.setAdapter(new SearchAdapter(mContext));
        mQueryInputView.setLoadingIndicator((ProgressBar) view.findViewById(R.id.pb_loading_indicator));
        mQueryInputView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                User book = (User) adapterView.getItemAtPosition(position);
                mQueryInputView.setText(book.getPhone());
            }
        });

There is no error or anything but my dropdown suggestion list is not showing even though API returns the values. What am I doing wrong?

Lalit Thapa
  • 311
  • 5
  • 20

1 Answers1

0

The problem is that you are returning an empty ArrayList !!!

When you add a request to the Volley Que, it wall fulfill your request in another thread and return you the data whenever the server respond. so it would take time. But you return the array list exactly after adding the request to the Que

 requestQueue.add(strReq);
 return searchArrayList;

What you should do is:

  if(jsonArray != null){
       for(int i=0; i<jsonArray.length(); i++){
            ...
            searchArrayList.add(users);
       }
   // RENEW YOUR ADAPTER HERE OR ASSIGN IT AGAIN TO THE EDITTEXT
    mAdapter.notifydataSetChanged();
   }

Also try changing the constructor of your SearchAdapter. Once i had a similar problem with a fragment adapter:

private List<User> resultList = new ArrayList<User>();

public SearchAdapter(Context context,List<User> data) {
    mContext = context;
    resultList = data;
}
Omid Heshmatinia
  • 5,089
  • 2
  • 35
  • 50
  • okay I added `searchAdapter.updateAdapter(searchArrayList);` after the response is received from the server. and on `updateAdapter()` I have `searchArrayList = arraylist; this.notifyDataSetChanged();`. But still the dropdown list is not showing up. Please help me with this. – Lalit Thapa May 16 '16 at 04:49
  • try searchAdapter.updateAdapter(searchArrayList); in runOnUiThread. maybe that solve the problem. Also in your updateAdapter function, you should have this 'resultList = searchArrayList' ! @LalitThapa – Omid Heshmatinia May 16 '16 at 05:08
  • I did what you told @Smartiz but still not getting the dropdown list. – Lalit Thapa May 16 '16 at 05:34
  • Thanks @Smartiz for your time but I made it working by simply using the `ArrayAdapter` and I didn't use my custom adapter at all. – Lalit Thapa May 16 '16 at 06:50