How to Dynamically Add Suggestions to Autocompletetextview With Preserving Character Status

How to dynamically add suggestions to autocompletetextview with preserving character status along with images

ok try this:

    LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);

AutoCompleteTextView actv = new AutoCompleteTextView(this);
actv.setThreshold(1);
String[] from = {"name"};
int[] to = {android.R.id.text1};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_dropdown_item_1line, null, from, to) {

// required for Spanned data
@Override
public void bindView(View view, Context context, Cursor cursor) {
MyCursor c = (MyCursor) cursor;
TextView tv = (TextView) view;
tv.setText(c.getSpanned());
}

// required for Spanned data
@Override
public CharSequence convertToString(Cursor cursor) {
MyCursor c = (MyCursor) cursor;
return c.getSpanned();
}
};
FilterQueryProvider provider = new FilterQueryProvider() {
@Override
public Cursor runQuery(CharSequence constraint) {
if (constraint == null) {
return null;
}
MyCursor c = new MyCursor();
// fake web service responses
List<String> names = callFakeWebService(constraint);
int i = 0;
for (String name: names) {
SpannableStringBuilder ssb = new SpannableStringBuilder(name);
int start = name.indexOf(" ");
ForegroundColorSpan what = new ForegroundColorSpan(0xffff0000);
ssb.setSpan(what, start + 1, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
c.newRow().add(i++).add(name);
c.addSpanned(ssb);
}
return c;
}

// fake web service request
private List<String> callFakeWebService(CharSequence constraint) {
Log.d(TAG, "callFakeWebService for: " + constraint);
String[] namesArr = {
"Mark Smith",
"Monica Thompson",
"John White",
"Jane Brown"
};
String stringConstraint = constraint.toString().toLowerCase();
List<String> names = new ArrayList<String>();
for (int i = 0; i < namesArr.length; i++) {
String name = namesArr[i];
if (name.toLowerCase().startsWith(stringConstraint)) {
names.add(name);
}
}
return names;
}
};
adapter.setFilterQueryProvider(provider);
actv.setAdapter(adapter);
ll.addView(actv);
TextView tv = new TextView(this);
tv.setTextSize(32);
tv.setTextColor(0xffff0000);
tv.setText("type one of:\n mark,\n monica,\n john\n jane");
ll.addView(tv);
setContentView(ll);

where custom Cursor could look like this (it is minimalistic version supporting only one Spanned in a row):

static class MyCursor extends MatrixCursor {
private static final String[] NAMES = {BaseColumns._ID, "name"};
private ArrayList<Spanned> mSpannedList;

public MyCursor() {
super(NAMES);
mSpannedList = new ArrayList<Spanned>();
}

public void addSpanned(Spanned s) {
mSpannedList.add(s);
}

public Spanned getSpanned() {
return mSpannedList.get(mPos);
}
}

EDIT with no Spanned text:

    AutoCompleteTextView actv = new AutoCompleteTextView(this);
actv.setThreshold(1);
final String[] from = {BaseColumns._ID, "name", "artist", "title"};
int[] to = {R.id.list_image, R.id.textView1, R.id.textView2, R.id.textView3};
final SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.list_row, null, from, to);
adapter.setStringConversionColumn(1);
ViewBinder viewBinder = new ViewBinder() {
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (columnIndex == 0) {
ImageView iv = (ImageView) view;
Bitmap bitmap = cursor.getExtras().getParcelable("image");
if (bitmap != null) {
iv.setImageBitmap(bitmap);
}
return true;
}
return false;
}
};
adapter.setViewBinder(viewBinder);
FilterQueryProvider provider = new FilterQueryProvider() {
ExecutorService mPool = Executors.newCachedThreadPool();
Uri URI = Uri.parse("adapter://autocomplete");

public Cursor runQuery(CharSequence constraint) {
if (constraint == null) {
return null;
}
try {
return callWebService(constraint, from);
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}

// here you make the web request
private Cursor callWebService(CharSequence constraint, String[] columnNames) throws JSONException {
Log.d("TAG", "callWebService for: " + constraint);
MatrixCursor cursor = new MyMatrixCursor(columnNames);

// TODO do real network request
// call web service here and keep the result in "jsonStr"
String jsonStr = "{\"ResultArray\":[{\"data\":{ \"sno\":\"sno1\", \"date\":\"2011-08-21 14:27:09\", \"user\":\"1\", \"link\":\"http://scm-l3.technorati.com/11/11/17/56749/google-docs-revision.jpg?t=20111117074048\", \"name\":\"Aa\" }},{\"data\":{ \"sno\":\"sno2\", \"date\":\"2011-08-21 14:28:09\", \"user\":\"2\", \"link\":\"http://kcclaveria.com/wp-content/uploads/2013/02/google-panda-penguin.jpg\", \"name\":\"Bb\" }}]}";

JSONObject json = new JSONObject(jsonStr);
JSONArray resultArray = json.getJSONArray("ResultArray");

int length = resultArray.length();
for (int i = 0; i < length; i++) {
JSONObject data = resultArray.getJSONObject(i).getJSONObject("data");

cursor.newRow().add(i)
.add(data.getString("name"))
.add(data.getString("user"))
.add(data.getString("sno"));

String link = data.getString("link");
// get cached Bundle based on "link" (use HashMap<String, Bundle>)
// or if new link initiate async request for getting the bitmap

// TODO implement HashMap caching

// new async request
Bundle extras = new Bundle();
try {
mPool.submit(new ImageRequest(link, extras));
} catch (MalformedURLException e) {
e.printStackTrace();
}
cursor.respond(extras);
}
cursor.setNotificationUri(getContentResolver(), URI);
return cursor;
}

class ImageRequest implements Runnable {
private URL mUrl;
private Bundle mExtra;

public ImageRequest(String link, Bundle extra) throws MalformedURLException {
mUrl = new URL(link);
mExtra = extra;
}

@Override
public void run() {
// TODO do real network request
// simulate network delay
Log.d(TAG, "getting " + mUrl);
try {
Thread.sleep(2000 + (long) (4000 * Math.random()));
} catch (InterruptedException e) {
e.printStackTrace();
}
Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
mExtra.putParcelable("image", b);
getContentResolver().notifyChange(URI, null);
Log.d(TAG, "run got a bitmap " + b.getWidth() + "x" + b.getHeight());
}
}
};
adapter.setFilterQueryProvider(provider);
actv.setAdapter(adapter);

LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
setContentView(actv, params);

and the custom MatrixCursor:

class MyMatrixCursor extends MatrixCursor {
List<Bundle> mBundles = new ArrayList<Bundle>();

public MyMatrixCursor(String[] columnNames) {
super(columnNames);
}

@Override
public Bundle respond(Bundle extras) {
mBundles.add(extras);
return extras;
}

@Override
public Bundle getExtras() {
return mBundles.get(mPos);
}
}

Dynamically updating an AutoCompleteTextView adapter

This is how I update my AutoCompleteTextView:

String[] data = terms.toArray(new String[terms.size()]);  // terms is a List<String>
ArrayAdapter<?> adapter = new ArrayAdapter<Object>(activity, android.R.layout.simple_dropdown_item_1line, data);
keywordField.setAdapter(adapter); // keywordField is a AutoCompleteTextView
if(terms.size() < 40) keywordField.setThreshold(1);
else keywordField.setThreshold(2);

Now of course, this is static and doesn't deal with an over-the-air suggestions but, I can also suggest you to notify adapter for the changes after you assign it to the AutoCompleteTextView:

adapter.notifyDataSetChanged();   

Hope this helps.

-serkan

Android - AutoCompleteTextView wildcard suggestion

Okay here's how I made it work. Major props to pskink for the lead.
It's very similar to the code I have above, with some changes to make the runQuery method work.

The same logic/thought pattern is used, only that I changed the runQuery method. Read the comments for a walkthrough.

//create ACTV Here
AutoCompleteTextView search = (AutoCompleteTextView) findViewById(R.id.actvCatalogueSearch);
search.setThreshold(1);

//I don't know what these are for, honestly.
String[] from = { "name" };
int[] to = { android.R.id.text1 };

//create a simple cursorAdapter
SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_dropdown_item_1line, null, from, to, 0);

//again, I don't know what this is for
cursorAdapter.setStringConversionColumn(1);

//create the filter query provider
FilterQueryProvider provider = new FilterQueryProvider(){
@Override
public Cursor runQuery(CharSequence constraint) {
// TODO Auto-generated method stub
//I need to do this because my list items are in all caps
String constrain = (String) constraint;
constrain = constrain.toUpperCase();

if (constraint == null) {
return null;
}

//I'll be honest again, no clue what these lines do.
String[] columnNames = { Columns._ID, "name" };
MatrixCursor c = new MatrixCursor(columnNames);

try {
//here's what I do, I go though my Array (pdflist)
//when a list item contains the user input, I add that to the Matrix Cursor
//this matrix cursor will be returned and the contents will be displayed
for (int i = 0; i < pdflist.length; i++) {
if(pdflist[i].contains(constrain)){
c.newRow().add(i).add(pdflist[i]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return c;
}
};

//use the filter query provider on the cursor adapter
cursorAdapter.setFilterQueryProvider(provider);

//finally, use the adapter on your ACTV
search.setAdapter(cursorAdapter);

It's a bit of a work but it gets the job done. Honestly, I'm a bit surprised that there's no "straightforward/intuitive" way of doing this. Something to the tune of just enabling/disabling something in your AutoCompleteTextView then it's done.

I guess we'll have to stick with this solution until further notice.

how to show suggestions of autocomplete Text Box contains with??

You need to extend the ArrayAdapter that implements Filterable.
Check this SO question and the answer: Filtering AutoCompleteTextView to show partial match

So your solution would be (the combination of question and answer):

public class CodesArrayAdapter extends ArrayAdapter implements Filterable{

List<String> allCodes;
List<String> originalCodes;
StringFilter filter;

public CodesArrayAdapter(Context context, int resource, List<String> keys) {
super(context, resource, keys);
allCodes=keys;
originalCodes=keys;
}

public int getCount() {
return allCodes.size();
}

public Object getItem(int position) {
return allCodes.get(position);
}

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

private class StringFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {

String filterString = constraint.toString().toLowerCase();
FilterResults results = new FilterResults();
final List<String> list = originalCodes;

int count = list.size();
final ArrayList<String> nlist = new ArrayList<String>(count);
String filterableString ;

for (int i = 0; i < count; i++) {
filterableString = list.get(i);
if (filterableString.toLowerCase().contains(filterString)) {
nlist.add(filterableString);
}
}

results.values = nlist;
results.count = nlist.size();
return results;
}

@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
allCodes = (ArrayList<String>) results.values;
notifyDataSetChanged();
}

}


@Override
public Filter getFilter()
{
return new StringFilter();
}
}

AutoCompleteTextView Text Filtering

So, I fixed the problem myself doing this. So, I use a normal BaseAdapter and extend Filterable So, for those that may need how to use RealmDB with AutoCompleteTextView there you go

 public class LgasAutoCompleteAdapter extends BaseAdapter implements Filterable {

private static final String TAG = "LgasAutoComp";
private Context mContext;
private List<Lga> mResult = new ArrayList<>();
private LayoutInflater inflater;

public LgasAutoCompleteAdapter(Context mContext) {
this.mContext = mContext;
}

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

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

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

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

if (view == null)
view = inflater.inflate(R.layout.item_baker_autocomplete, parent, false);

Lga lga = mResult.get(position);

TextView customerNameLabel = (TextView) view.findViewById(R.id.bakerName);
TextView bakerAddress = (TextView) view.findViewById(R.id.bakerAddress);

if (lga != null) {
if (customerNameLabel != null) {
// Log.i(MY_DEBUG_TAG, "getView Customer Name:"+customer.getName());
customerNameLabel.setText(lga.getName());
bakerAddress.setVisibility(View.GONE);
}
}

return view;
}

@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
return null;
}

@Override
protected void publishResults(CharSequence constraint, FilterResults filterResults) {
if (constraint != null) {
//String query = constraint.toString().toLowerCase();
mResult = filterStates(constraint.toString());
Log.e(TAG, ""+mResult.size());
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
}

@NonNull
private List<Lga> filterStates(String query) {
Realm mRealm = RealmUtils.getRealmInstance(mContext);
return mRealm.where(Lga.class)
.contains("name", query)
.or()
.beginsWith("name", query)
.findAll();
}
}


Related Topics



Leave a reply



Submit