Is there a way to pin an address to the top of a placeautocomplete search for an android app?
http://jsfiddle.net/v9rt3t2y/
This example is in JS/HTML, but I couldn't find anything for native android studio.
Anyway you can use customized AutoCompleteTextView like in this article. You should add your custom place name in protected void publishResults(CharSequence constraint, FilterResults results) just after filling places list from results.values; from Task<AutocompletePredictionBufferResponse>.
So, for custom place name "-> Custom place <-" with MainActivity.java like:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final String TAG = MainActivity.class.getSimpleName();
private GoogleMap mGoogleMap;
private SupportMapFragment mMapSupportedFragment;
private AutoCompleteTextView mPlaceAutoCompleteTextView;
private PlacesAdapter mPlacesAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlacesAdapter = new PlacesAdapter(this);
mPlaceAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.place_autocomplete);
mPlaceAutoCompleteTextView.setThreshold(1);
mPlaceAutoCompleteTextView.setAdapter(mPlacesAdapter);
mMapSupportedFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map_fragment);
mMapSupportedFragment.getMapAsync(MainActivity.this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
}
class PlacesAdapter extends ArrayAdapter {
Context context;
List<String> placesList = new ArrayList<>();
GeoDataClient geoDataClient;
PlacesAdapter.PlacesAutoCompleteFilter filter = new PlacesAdapter.PlacesAutoCompleteFilter();
public PlacesAdapter(Context context) {
super(context, android.R.layout.simple_dropdown_item_1line,
new ArrayList<Place>());
this.context = context;
geoDataClient = Places.getGeoDataClient(context, null);
}
#Override
public int getCount() {
return placesList.size();
}
#Override
public String getItem(int position) {
return placesList.get(position);
}
#Override
public Filter getFilter() {
return filter;
}
#Override
public View getView(int position, View view, #NonNull ViewGroup parent) {
if (view == null) {
view = LayoutInflater.from(parent.getContext())
.inflate(android.R.layout.simple_dropdown_item_1line,
parent, false);
}
TextView textOne = view.findViewById(android.R.id.text1);
textOne.setText(placesList.get(position));
return view;
}
class PlacesAutoCompleteFilter extends Filter {
private Object lock = new Object();
private Object lockTwo = new Object();
private boolean placeResults = false;
#Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
placeResults = false;
final List<String> predictedPlacesList = new ArrayList<>();
if (prefix == null || prefix.length() == 0) {
synchronized (lock) {
results.values = new ArrayList<Place>();
results.count = 0;
}
} else {
final String searchStrLowerCase = prefix.toString().toLowerCase();
Task<AutocompletePredictionBufferResponse> task
= getAutoCompletePlaces(searchStrLowerCase);
task.addOnCompleteListener(new OnCompleteListener<AutocompletePredictionBufferResponse>() {
#Override
public void onComplete(#NonNull Task<AutocompletePredictionBufferResponse> task) {
if (task.isSuccessful()) {
Log.d(TAG, "Auto complete prediction successful");
AutocompletePredictionBufferResponse predictions = task.getResult();
for (AutocompletePrediction prediction : predictions) {
predictedPlacesList.add((prediction.getFullText(null)).toString());
}
predictions.release();
} else {
Log.d(TAG, "Auto complete prediction unsuccessful");
}
placeResults = true;
synchronized (lockTwo) {
lockTwo.notifyAll();
}
}
});
while (!placeResults) {
synchronized (lockTwo) {
try {
lockTwo.wait();
} catch (InterruptedException e) {
}
}
}
results.values = predictedPlacesList;
results.count = predictedPlacesList.size();
Log.d(TAG, "Autocomplete predictions size after wait" + results.count);
}
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.values != null) {
placesList = (ArrayList<String>) results.values;
} else {
placesList = null;
}
// add your custom place here:
placesList.add(0, "-> Custom place <-");
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
private Task<AutocompletePredictionBufferResponse> getAutoCompletePlaces(String query) {
AutocompleteFilter.Builder filterBuilder = new AutocompleteFilter.Builder();
Task<AutocompletePredictionBufferResponse> results =
geoDataClient.getAutocompletePredictions(query, null,
filterBuilder.build());
return results;
}
}
}
}
and activity_main.xml (NB! according to Usage Limits:
If your app uses the autocomplete service programmatically, your UI
must either display a 'Powered by Google' attribution, or appear
within a Google-branded map.
) like:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="<YOUR_PACKAGE_NAME>.MainActivity">
<fragment class="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/map_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<AutoCompleteTextView android:id="#+id/place_autocomplete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/background_light"
android:layout_margin="16dp"
android:padding="8dp"
android:inputType="text"
android:imeOptions="actionNext"
android:textSize="16sp"
android:hint="Type place name here" />
</RelativeLayout>
when you enter letter "a" to text field you should get something like that:
And don't forget to activate Places SDK on Google Cloud Platform Console.
Related
Hi in the below code Implementaing a search functionality.Gridview is used to display the grid layout .My grid layout is working fine .In that Grid I am searching by name but it is not working .
Example I have three names named as cardiology ,Ent ,Ortho if I am searching or typing ca means giving me exact one cardiology .if I type o means again showing me the cardiology the result should be ortho
can any one help me where I did the mistake
Layout:
<androidx.appcompat.widget.SearchView
android:id="#+id/search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:queryHint="Search By Speciality"
android:iconifiedByDefault="false"
app:searchHintIcon="#drawable/ic_baseline_search_24"
app:searchIcon="#drawable/ic_baseline_search_24"
android:textSize="18sp"
android:inputType="text"
app:closeIcon="#drawable/ic_baseline_close_24"
android:background="#drawable/rectangle_border"
android:textColor="#color/black" />
Fragement.java:
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
Log.d("TAG","new Text ==>"+newText);
speclializationAdapter.getFilter().filter(newText);
return true;
}
});
Adapter:
public class SpeclializationAdapter extends BaseAdapter implements Filterable {
private Context mContext;
private ArrayList<DataList> doctorListModels;
private ArrayList<DataList> completeList;
private SpeclializationAdapter.MyItemClickListener clickListener;
private DoctorAdapter.SelectIemClickListner selectIemClickListner;
public SpeclializationAdapter(Context context, ArrayList<DataList> doctorListModels, MyItemClickListener clickListener){
mContext=context;
this.doctorListModels=doctorListModels;
this.clickListener=clickListener;
this.completeList=doctorListModels;
this.completeList = new ArrayList<DataList>();
this.completeList.addAll(doctorListModels);
}
#Override
public int getCount() {
return doctorListModels.size();
}
#Override
public Object getItem(int position)
{
return position;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView = null;
final ImageView speclialistimage;
final TextView specialization;
final LinearLayout speclist;
if (convertView == null) {
gridView = new View(mContext);
convertView=inflater.inflate(R.layout.speclialist, null);
speclialistimage=convertView.findViewById(R.id.specilistimage);
speclist=convertView.findViewById(R.id.speclist);
specialization=convertView.findViewById(R.id.specialization);
specialization.setText(doctorListModels.get(position).getSpecialization());
// specialization.setText(speclistListFiltered.get(position).getSpecialization());
final String specliality_name=doctorListModels.get(position).getSpecialization();
if(specliality_name.equals("Cardiology")){
speclialistimage.setImageResource(R.drawable.cardiology);
}
if(specliality_name.equals("ENT specialist")){
speclialistimage.setImageResource(R.drawable.neurology);
}
if(specliality_name.equals("Orthopedics")){
speclialistimage.setImageResource(R.drawable.orthopedic);
}
final View finalGridView = gridView;
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
speclialistimage.setBackgroundResource(R.drawable.like_button);
clickListener.myItemClick(position);
}
});
}
return convertView;
}
#Override
public Filter getFilter() {
Filter filter=new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults=new FilterResults();
ArrayList<DataList> searchResult = new ArrayList<DataList>();
if (constraint != null && constraint.length() > 0) {
constraint = constraint.toString().toUpperCase();
for (int i = 0; i < completeList.size(); i++) {
if (completeList.get(i).getSpecialization().toUpperCase().contains(constraint)) {
DataList d = new DataList(completeList.get(i).getSpecialization());
searchResult.add(d);
}
}
} else {
searchResult.addAll(completeList);
}
filterResults.count = searchResult.size();
filterResults.values = searchResult;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults filterResults) {
doctorListModels= (ArrayList<DataList>) filterResults.values;
notifyDataSetChanged();
}
};
return filter;
}
public interface MyItemClickListener{
void myItemClick(int position);
}
}
You have messed up in reference . Right now your both ArrayList i.e specialistListFiltered and doctorListModels pointing to same object . So any modification you make in one of them affects both.
Where as one list shoould contain all items and other one should contain the filtered item and only filtered List will be used with Adapter.
private ArrayList<DataList> doctorListModels;
private ArrayList<DataList> completeList;
public SpeclializationAdapter(Context context, ArrayList<DataList> doctorListModels, MyItemClickListener clickListener){
mContext=context;
this.doctorListModels=doctorListModels;
this.clickListener=clickListener;
this.completeList = new ArrayList<DataList>();
this.completeList.addAll(doctorListModels)
}
As above i have changed the name to completeList just to avoid confusion . Not you will be using complete list during filtering.
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults=new FilterResults();
ArrayList<DataList> searchResult = new ArrayList<DataList>();
if (constraint != null && constraint.length() > 0) {
constraint = constraint.toString().toUpperCase();
for (int i = 0; i < completeList.size(); i++) {
if (completeList.get(i).getSpecialization().toUpperCase().contains(constraint)) {
DataList d = new DataList(completeList.get(i).getSpecialization());
searchResult.add(d);
}
}
} else {
searchResult.addAll(completeList);
}
filterResults.count = searchResult.size();
filterResults.values = searchResult;
return filterResults;
}
PS you should be already using RecyclerView not GridView . ListView and GridView are legacy now .
I am working on an android app where I am going to store school names under one node for e.g. schools. I want to implement Autocomplete functionality for the schoolnames, .i.e when user starts typing school name he/she will see the schoolnames starting/matching the particular condition(top 5 records matching the condition can be shown). Assume that each schoolname is a String.
public class SchoolsAutoCompleteAdapter extends BaseAdapter implements Filterable {
private static final int MAX_RESULTS = 10;
private Context mContext;
FirebaseDatabase database;
DatabaseReference myRef;
private List<School> schools = new ArrayList<School>();
public SchoolsAutoCompleteAdapter(Context mContext) {
this.mContext = mContext;
database=FirebaseDatabase.getInstance();
myRef=database.getReference("mschools");
schools=new ArrayList<>();
}
#Override
public int getCount() {
return schools.size();
}
#Override
public School getItem(int position) {
return schools.get(position);
}
#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.school_autocomplete_list_row, parent, false);
}
((TextView) convertView.findViewById(R.id.autocomplete_email)).setText(getItem(position).getEmail());
((TextView) convertView.findViewById(R.id.autocomplete_name)).setText(getItem(position).getName());
return convertView;
}
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null) {
schools = findSchools(constraint.toString());
// Assign the data to the FilterResults
filterResults.values = schools;
filterResults.count = schools.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}};
return filter;
}
private List<School> findSchools(String studentUsername) {
final List<School> schools=new ArrayList<>();
Query abc= myRef.orderByChild("schoolname").startAt(studentUsername).endAt(studentUsername+"\uf8ff").limitToFirst(5);
abc.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
//schools.add(childDataSnapshot.getValue(School.class));
School s=childDataSnapshot.getValue(School.class);
schools.add(new School(s.getEmail(),s.getName()));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return schools;
}
}
As per the code return schools line is executing before the onDataChange method as firebase executes asynchronously .So it is returning empty record.
Some relational database can be used to implement this functionality, but I don't want to add extra database to implement just this functionality. If I keep breakpoint at return schools; line, I am able to see the result. Can I implement this scenario using Firebase or am I missing something?
I'm new in android programming and I have this snippet from somewhere in the internet and it says "cannot resolve getActivity()" I then tried to use getApplicationContext() but the Autocomplete did not function. What should I do to get it running without problems?
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, DirectionFinderListener {
private GoogleMap mMap;
private Button btnFindPath;
//private EditText etOrigin;
//private EditText etDestination;
private List<Marker> originMarkers = new ArrayList<>();
private List<Marker> destinationMarkers = new ArrayList<>();
private List<Polyline> polylinePaths = new ArrayList<>();
private ProgressDialog progressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
AutoCompleteTextView etOriginView = (AutoCompleteTextView) findViewById(R.id.etOrigin);
etOriginView.setAdapter(new PlacesAutoCompleteAdapter(getActivity(), R.layout.autocomplete_list_item));
etOriginView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Get data associated with the specified position
// in the list (AdapterView)
String description = (String) parent.getItemAtPosition(position);
Toast.makeText(getActivity(), description, Toast.LENGTH_SHORT).show();
}
});
btnFindPath = (Button) findViewById(R.id.btnFindPath);
//etOrigin = (EditText) findViewById(R.id.etOrigin);
//etDestination = (EditText) findViewById(R.id.etDestination);
btnFindPath.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendRequest();
}
});
}
PlacesAutoCompleteAdapter Class
class PlacesAutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
ArrayList<String> resultList;
Context mContext;
int mResource;
PlaceAPI mPlaceAPI = new PlaceAPI();
public PlacesAutoCompleteAdapter(Context context, int resource) {
super(context, resource);
mContext = context;
mResource = resource;
}
#Override
public int getCount() {
// Last item will be the footer
return resultList.size();
}
#Override
public String getItem(int position) {
return resultList.get(position);
}
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null) {
resultList = mPlaceAPI.autocomplete(constraint.toString());
filterResults.values = resultList;
filterResults.count = resultList.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
notifyDataSetChanged();
}
else {
notifyDataSetInvalidated();
}
}
};
return filter;
}
}
Any help is appreciated, thanks in advance!
My Google Places API Web Service tells me that I have 100% errors, so does it mean that something is wrong with my Adapter?
Try MapsActivity.this insted of getActivity()
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?
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;
}
So,i am trying to make a searchview on my actionBar so when i type,autocompltes or shows the Json listview in a list format in that searchview ,and so that i can click on those i just searched. But i find it hard to implement.Everything else is working fine.I can display the list of json parsed elemnts and geet serializable content.Now i just need the searchbar to function
Here is my java class for the ListAdapter and JSON parsing.
public class Collegelist extends ActionBarActivity {
HTTPConnection http;
List<Colleges> college = new ArrayList<Colleges>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.college_list);
http = new HTTPConnection(getApplicationContext());
if (http.isNetworkConnection()) {
//String data = http.HTTPGetData("http://localhost/minorproject/show.php");
//Toast.makeText(getApplicationContext(),data ,Toast.LENGTH_LONG).show();
task.execute();
}
else {
Toast.makeText(getApplicationContext(), "check your connection",
Toast.LENGTH_LONG).show();
}
}
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String data = http.HTTPGetData("http://my-ip-address/minorproject/show.php");
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
populateList(result);
displayList();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
};
protected void populateList(String result) {
try {
//Toast.makeText(getApplicationContext(),result,Toast.LENGTH_LONG).show();
JSONObject jobj = new JSONObject(result);
String res = jobj.getString("success");
if (!res.equals("true")) {
Toast.makeText(getApplicationContext(), "JSON Error",
Toast.LENGTH_LONG).show();
return;
}
else
{
JSONArray data = jobj.getJSONArray("msg");
// Toast.makeText(getApplicationContext(),"successss",Toast.LENGTH_SHORT).show();
for (int i = 0; i < data.length(); i++) {
JSONObject col = data.getJSONObject(i);
Colleges cg = new Colleges(col.getString("cname"),
col.getString("caddress"),
col.getString("ccontact_a"),
col.getString("ccontact_b"),
col.getString("cwebsites"));
college.add(cg);
}
}
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
}
protected void displayList() {
ArrayAdapter<Colleges> adapter = new ArrayAdapter<Colleges>(this, R.layout.list_item,college){
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = getLayoutInflater().inflate(R.layout.list_item,null);
//set values
Colleges c = college.get(position);
((TextView)view.findViewById(R.id.name)).setText(c.getName());
/*((TextView)view.findViewById(R.id.address)).setText(c.getAddress());*/
return view;
}
};
final ListView collegelistnew = (ListView) findViewById(R.id.listView);
collegelistnew.setAdapter(adapter);
collegelistnew.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
/*Toast.makeText(
getApplicationContext(),
"You clicked position" + position + "with item name"
+ college.get(position).getName(),
Toast.LENGTH_LONG).show();*/
Intent newIntent =new Intent(getApplicationContext(),CollegeDetails.class);
newIntent.putExtra("college", college.get(position));
startActivity(newIntent);
}
});
}
and my getter and setter class
public class Colleges implements Serializable{
String cname,caddress,ccontact,cwebsites,ccontactb;
public Colleges( String cname, String cwebsites,String caddress, String ccontact, String ccontactb) {
this.cname = cname;
this.caddress = caddress;
this.ccontact = ccontact;
this.ccontact = ccontactb;
this.cwebsites = cwebsites;
}
public String getName() {
return cname;
}
public void setName(String cname) {
this.cname = cname;
}
public String getAddress() {
return caddress;
}
public void setAddress(String caddress) {
this.caddress = caddress;
}
public String getContact() {
return ccontact;
}
public void setContact(String ccontact) {
this.ccontact = ccontact;
}
public String getContactb() {
return ccontactb;
}
public void setContactb(String ccontactb) {
this.ccontactb = ccontactb;
}
public String getWebsites(){
return cwebsites;
}
public void setWebsites(String cwebsites){
this.cwebsites = cwebsites;
}
Here is menu_main xml file
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="#+id/action_settings" android:title="#string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
<item android:id="#+id/action_search"
android:icon="#drawable/search"
android:title="#string/search_title"
app:showAsAction="always|collapseActionView"
android:actionViewClass="android.widget.SearchView"
app:actionViewClass="android.support.v7.widget.SearchView"/>
Assuming that your list is ready and adapter is also ready to be shown.
From SearchView what you can get is the current text that the user has typed or typing. What you have to do now is pass this text into a method that would create new filtered list.
On onCreateOptionsMenu
SearchManager searchManager = (SearchManager) SearchActivity.this.getSystemService(Context.SEARCH_SERVICE);
SearchView searchView;
if (searchItem != null) {
searchView = (SearchView) searchItem.getActionView();
if (searchView != null) {
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
setSearchAdapter(s);
return false;
}
#Override
public boolean onQueryTextChange(String s) {
setSearchAdapter(s);
return false;
}
});
}
}
You will do your listing tasks in method setSearchAdapter(s), on the basis of the String 's' you will have to recreate a list on every text change that will be populated using the adapter.
This is how your method should look like
private void setSearchAdapter(String s) {
// filter list codes
// ....
searchAdapter =new SearchAdapter(SearchActivity.this,
filteredList);
listView.setAdapter(searchAdapter);
}
There are many ways to create a filtered list.
If you want to save your data in database then you can create Virtual Table and query for search as follows
Cursor cursor = myDataProvider.query(VirtualTable.CONTENT_URI, null, VirtualTable.NAME + " MATCH ? ", new String[]{s + "*"}, null, null);
Note: For simplicity, you can use raw Match query.
Then populate it using suitable adapter class.
We can use Filter class for asynchronous filter as follows:
private class MyFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
for (int i = 0; i < collegeList.size(); i++) {
String name = collegeList.get(i);
if (name.toUpperCase().startsWith(constraint.toString().toUpperCase())) {
nFilteredList.add(name);
}
}
results.values = nFilteredList;
results.count = nFilteredList.size();
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredList = (ArrayList<String>) results.values;
}
}
You need to call searchAdapter.getFilter().filter(s); on text change and override getFilter() method in your adapter.
I hope this solves your query.