How to implement TextWatcher for SearchDialog - android

I need to update my ListView according to the userinput in SearchDialog. For this I need to set a TextWatcher for SearchDialog. How to do this?

you can do it as below:
yourEditText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// process new items for list view
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// push new items into adapter and call notifyDataSetChanged() on it
}
});

Here is what I did actually a few months ago to achieve the same thing that you need. I had to sort my list view depending on user input while I was populating the list view from sqlite database with sqlite statements. Not sure if it's the best way,but in my situation it works perfectly.
So on my EditText field I add this (which name is searchBar) :
searchString = "";
searchBar.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
// this is where actually I was changing the sqlite statement which sort my list view
names.clear();
categories.clear();
paths.clear();
count.clear();
cardId.clear();
myCardID.clear();
searchString = s.toString();
Log.e("","searchString : "+searchString);
sqlQuery = getSqlStatement(sort, collId, ascDesc,searchString);
Log.e(""," sqlquery : "+sqlQuery);
sqlQuery = getSqlStatement(sort, collId, ascDesc, searchString);
Cursor cursor = userDbHelper.executeSQLQuery(sqlQuery);
if (cursor.getCount() == 0) {
noCards.setVisibility(View.VISIBLE);
} else if (cursor.getCount() > 0) {
noCards.setVisibility(View.GONE);
for (cursor.move(0); cursor.moveToNext(); cursor.isAfterLast()) {
objectId = Integer.parseInt(cursor.getString(cursor.getColumnIndex("objectId")));
cardId.add(objectId);
title = cursor.getString(cursor.getColumnIndex("title"));
catTitle = cursor.getString(cursor.getColumnIndex("catTitle"));
if(extra!=0 && sort!=3){
tags.setText(catTitle);
}
int repeats = Integer.parseInt(cursor.getString(cursor.getColumnIndex("repeatsCount")));
count.add(repeats);
String cardsm = "SELECT objectId FROM cardmedias " +
"WHERE cardId="+
objectId +
" AND mediaType=" +
5012;
Cursor cardsM = userDbHelper.executeSQLQuery(cardsm);
if (cardsM.getCount() == 0) {
String defCard = "SELECT objectId FROM collectionmedias " +
"WHERE collectionId="+
collId +
" AND mediaType=" +
3003;
Cursor getDefCard = userDbHelper.executeSQLQuery(defCard);
getDefCard.moveToFirst();
objectID = Integer.parseInt(getDefCard.getString(getDefCard
.getColumnIndex("objectId")));
String filename = "mediacollection-"+objectID;
if(storageID==1){
path = RPCCommunicator.getImagePathFromInternalStorage(servername, userId, filename, getApplicationContext());
} else if(storageID==2){
path = RPCCommunicator.getImagePathFromExternalStorage(servername, userId, filename);
}
hm.put(objectID, path);
path = hm.get(objectID);
paths.add(path);
names.add(title);
categories.add(catTitle);
} else if (cardsM.getCount() > 0) {
for (cardsM.move(0); cardsM.moveToNext(); cardsM.isAfterLast()) {
objectID = Integer.parseInt(cardsM.getString(cardsM
.getColumnIndex("objectId")));
String filename = "mediacard-"+objectID;
if(storageID==1){
path = RPCCommunicator.getImagePathFromInternalStorage(servername, userId, filename, getApplicationContext());
} else if(storageID==2){
path = RPCCommunicator.getImagePathFromExternalStorage(servername, userId, filename);
}
hm.put(objectID, path);
path = hm.get(objectID);
paths.add(path);
names.add(title);
categories.add(catTitle);
}
}
cardsM.close();
}
}
cursor.close();
// don't forget to add this!!!
adapter.notifyDataSetChanged();
}
});
And in my onCreate() actually I'm doing the same thing as in TextWatcher to sort my list view, so I think you can implement the same logic as I did.
If you have any problems to do that, just paste some of your code so we can help you! : )
Hope this helps!

Related

Filter a contact List through TextWatcher in Android

I'm showing contacts in a ListView and trying to filter the same list using an EditText. But when I type something, filtering is not happening, though the typed text is coming in Logcat.
Here is my onCreate:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_invite);
EditText filterText = findViewById(R.id.search_box);
filterText.addTextChangedListener(filterTextWatcher);
// The contacts from the contacts content provider is stored in this cursor
mMatrixCursor = new MatrixCursor(new String[]{"_id", "name", "details"});
// Adapter to set data in the listview
mAdapter = new SimpleCursorAdapter(getBaseContext(),
R.layout.contact_layout, null, new String[]{"name", "details"}, new int[]{R.id.tv_name, R.id.tv_details}, 0);
// Getting reference to listview
ListView lstContacts = findViewById(R.id.lst_contacts);
// Setting the adapter to listview
lstContacts.setAdapter(mAdapter);
// Creating an AsyncTask object to retrieve and load listview with contacts
ListViewContactsLoader listViewContactsLoader = new ListViewContactsLoader();
// Starting the AsyncTask process to retrieve and load listview with contacts
listViewContactsLoader.execute();
}
This is my TextWatcher:
private TextWatcher filterTextWatcher = new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
Log.d(TAG, "onTextChanged: " + s);
mAdapter.getFilter().filter(s.toString());
}
};
What am I doing wrong here? Can someone help?
EDIT: Adding my ListViewContactsLoader.
private class ListViewContactsLoader extends AsyncTask<Void, Void, Cursor> {
#Override
protected Cursor doInBackground(Void... params) {
Uri contactsUri = ContactsContract.Contacts.CONTENT_URI;
// Querying the table ContactsContract.Contacts to retrieve all the contacts
Cursor contactsCursor = getContentResolver().query(contactsUri,
null, null, null,
ContactsContract.Contacts.DISPLAY_NAME + " ASC ");
if (contactsCursor.moveToFirst()) {
do {
long contactId = contactsCursor.getLong(contactsCursor
.getColumnIndex("_ID"));
Uri dataUri = ContactsContract.Data.CONTENT_URI;
// Querying the table ContactsContract.Data to retrieve individual items like
// home phone, mobile phone etc corresponding to each contact
Cursor dataCursor = getContentResolver().query(dataUri,
null,
ContactsContract.Data.CONTACT_ID + "=" + contactId,
null, null);
String displayName = "";
String mobilePhone = "";
if (dataCursor.moveToFirst()) {
// Getting Display Name
displayName = dataCursor
.getString(dataCursor
.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
do {
// Getting Phone numbers
if (dataCursor
.getString(
dataCursor
.getColumnIndex("mimetype"))
.equals(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) {
switch (dataCursor.getInt(dataCursor
.getColumnIndex("data2"))) {
case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE:
mobilePhone = dataCursor
.getString(dataCursor
.getColumnIndex("data1"));
break;
}
}
} while (dataCursor.moveToNext());
String details = "";
// Concatenating various information to single string
if (mobilePhone != null && !mobilePhone.equals(""))
details = mobilePhone + "\n";
// Adding id, display name, path to photo and other details to cursor
mMatrixCursor.addRow(new Object[]{
Long.toString(contactId), displayName, details});
}
} while (contactsCursor.moveToNext());
}
return mMatrixCursor;
}
#Override
protected void onPostExecute(Cursor result) {
// Setting the cursor containing contacts to listview
mAdapter.swapCursor(result);
Log.d(TAG, "onPostExecute: " + result);
}
}
You need to reset the ListViewadapter also after adding the text in EditText.
searchEditText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
System.out.println("Text [" + s + "] - Start [" + start + "] - Before [" + before + "] - Count [" + count + "]");
if (count < before) {
listAdapter.resetData(); // MARK: Resetting adapter here
}
listAdapter.getFilter().filter(s);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
Note: resetData() is custom method in which you have to replace the List data with new List Data that appears after applying the Filter. Then finally notify the Adapter.

Android : TextView not show in TextWatcher listener

I want to show text in text view if condition is satisfied with equal method in Text-watcher.I have a string variable used in a method, and I would like to compare the EditText value to that variable and text view is update and if not then display the string with wrong code.But ui is not updated in TextWatcher.
Here is my code
private final TextWatcher vesselWatcher = new TextWatcher()
{
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
Log.e("beforeTextChanged ", " here !!! ");
}
public void onTextChanged(CharSequence s, int start, int before, int count)
{
}
public void afterTextChanged(Editable s)
{
if (s.length() == 0)
{
txtVesselName.setVisibility(View.GONE);
Log.e("afterTextChanged View ", " is gone !!!");
btnPost.setClickable(false);
btnPost.setEnabled(false);
Log.e("afterTextChanged ", " btnPost.setEnabled(false); !!!");
}
else
{
if(notations.contains(etxtVesselCode.getText().toString().trim()))
{
Log.e("AAA strNotations ", " Match !!! = " + etxtVesselCode.getText().toString().trim());
String notations = etxtVesselCode.getText().toString().trim();
SQLiteDatabase db = dbhelper.getWritableDatabase();
Cursor cursor = db.rawQuery("select * from VesselList where Notation " + "= ? ", new String[]{notations});
if (cursor.moveToFirst())
{
do
{
strVesselsTypeName = cursor.getString(cursor.getColumnIndex("VesselsTypeName"));
Log.e("strVesselsTypeName ", "= " + strVesselsTypeName );
SharedPreferences sp;
sp = getApplicationContext().getSharedPreferences(MyPREFERENCES, 0);
SharedPreferences.Editor e = sp.edit();
e.putString("xyz", etxtVesselCode.getText().toString().trim());
e.commit();
Log.e("Match","!!!!");
txtVesselName.setText(strVesselsTypeName);
btnPost.setClickable(true);
btnPost.setEnabled(true);
Log.e("afterTextChanged ", " btnPost.setEnabled(true); !!!");
} while (cursor.moveToNext());
} db.close();
}
else
{
Log.e("Not "," Match !!");
txtVesselName.setText("Wrong Code !!");
btnPost.setClickable(false);
btnPost.setEnabled(false);
}
}
}
};
Make txtVesselName TextView VISIBLE again after calling txtVesselName.txtVesselName when if condition is true:
txtVesselName. setVisibility(View.VISIBLE);

Android: How to Extract the data in 1 row with 2 columns

Here are my codes for my Search Activity
search.addTextChangedListener(new TextWatcher()
{
public void afterTextChanged(Editable s)
{
// Abstract Method of TextWatcher Interface.
}
public void beforeTextChanged(CharSequence s,
int start, int count, int after)
{
// Abstract Method of TextWatcher Interface.
}
public void onTextChanged(CharSequence s,
int start, int before, int count)
{
textlength = search.getText().length();
array_sort.clear();
for (int i = 0; i < listview_array.length; i++)
{
if (textlength <= listview_array[i].length())
{
if(search.getText().toString().equalsIgnoreCase(
(String)
listview_array[i].subSequence(0,
textlength)))
{
array_sort.add(listview_array[i]);
}
}}
listContent1.setAdapter(new ArrayAdapter<String>
(Search_Food.this,
android.R.layout.simple_list_item_1, array_sort));
}
});
my onclicklistener code
AlertDialog.Builder adb = new AlertDialog.Builder(
Search_Food.this);
adb.setTitle("Food Item");
adb.setMessage("Selected Food is = "
+ listContent1.getItemAtPosition(position));
adb.setPositiveButton("Ok", null);
adb.show();
my Dbadapter
public LinkedList<String> search(String string) {
// TODO Auto-generated method stub
LinkedList<String> results = new LinkedList<String>();
Cursor cursor = null;
String search = string;
try{
cursor = this.sqLiteDatabase.query(true, MYDATABASE_TABLE , new String[] { KEY_ID , KEY_FOODNAME , KEY_CALORIES }, KEY_FOODNAME + " = ?" + "COLLATE NOCASE",
new String[] { search }, null, null, null, null);
if(cursor!=null && cursor.getCount()>0 && cursor.moveToFirst()){
int foodName = cursor.getColumnIndex(KEY_FOODNAME );
int keyColories = cursor.getColumnIndex(KEY_CALORIES );
// boolean moveToNext = cursor.moveToNext();
//do{
results.add(
new String(
cursor.getString(foodName) + " " +
cursor.getString(keyColories)
)
);
//}while(moveToNext);
}
}catch(Exception e){
Log.e(APP_NAME, "An error occurred while searching for "+search+": "+e.toString(), e);
}finally{
if(cursor!=null && !cursor.isClosed()){
cursor.close();
}
}
return results;
}
now when i click a data on my searched listview, i want to extract the getitemposition into 2 and thats my columns. the food name and the calories. how can i separate the 2 values.
answers please. help. thank you

Android SimpleCursorAdapter getView how to put previous value back

I have a simple ListActivity that uses the SimpleCursorAdapter. I allow users to change one of the values using an EditText. I perform simple validation to make sure that the number entered is less than 100. If the user entered value fails validation, I want to put the old value back.
I've tried a few different ways. My current approach is to requery it out of the database, but this isn't working. I'm always getting the value associated with the last entry in the ListActivity, regardless of which one was actually changed. I noticed in LogCat that onTextChanged and afterTextChanged are firing multiple times for each row in the ListActivity and not just the one that changed.
Here's the code:
public class MySimpleCursorAdapter extends SimpleCursorAdapter {
Context lcontext;
boolean changed;
String lastval;
private PortfolioData pfdata;
public MySimpleCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
lcontext = context;
}
#Override
public View getView(final int pos, View v, ViewGroup parent) {
v = super.getView(pos, v, parent);
final EditText et = (EditText) v.findViewById(R.id.classpercentage);
final TextView tv = (TextView) v.findViewById(R.id._id);
et.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
Log.d("TEST", "In afterTextChanged s=" + s.toString() + " "
+ tv.getText() + " POS = " + Integer.toString(pos));
lastval = tv.getText().toString();
if (changed == true) {
String enteredValue = s.toString();
if (checkNullValues(enteredValue)) {
if (Float.parseFloat(enteredValue.trim()) > 100.0f) {
AlertDialog.Builder builder = new AlertDialog.Builder(
lcontext);
builder.setMessage("Percentage Value should be Less than 100");
builder.setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
public void onClick(
DialogInterface arg0, int arg1) {
String sql = "select c.percentage as PERCENTAGE " +
"from asset_classes c WHERE c._id = " + lastval + ";";
pfdata = new PortfolioData(lcontext);
SQLiteDatabase db = pfdata.getReadableDatabase();
Cursor cursor = db.rawQuery(sql, null);
if (cursor != null)
{
cursor.moveToFirst();
et.setText(cursor.getString(0));
}
cursor.close();
pfdata.close();
}
});
// End of the Alert
if (changed == true)
{
builder.show();
}
}
}
changed = false;
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// Log.d("TEST", "In beforeTextChanged start=" +
// Integer.toString(start) +" count="+ Integer.toString(count) +
// " after=" + Integer.toString(after) + " s=" + s + " " + tv);
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
Log.d("TEST", "In onTextChanged start=" +
Integer.toString(start) + " count=" + Integer.toString(count)
+ " before=" + Integer.toString(before) + " s=" + s + " " +
tv);
changed = true;
}
});
return v;
}
}
I would really appreciate a fresh perspective on this. As always, thanks in advance.
Try to use an onFocusChangeListener. When it gets focus, save the current text into field of the class.
Something like:
String oldText - Would be your old text field.
Then you do:
et.setOnFocusChangeListener(new OnFocusChangeListener()) {
#Override
public void onFocusChange(View whatever, boolean hasFocus) {
if (hasFocus) {
//code
} else {
//code or maybe empty
}
}
}
Then if the number is > 100 you just get the oldText value and put in the EditText.
I think you're not aware of recycling in ListView. Having 1000 rows in Cursor there is only 10-20 (depends on screen size) row views created.
Don't store data in view!
At beggining I recommend you to read http://commonsware.com/Android/excerpt.pdf

Android set new Cursor to a listView

I have a little issue with settings a new Adapter to a listView when user enter letters in EditText. So the thing which I'm doing is, when my Activity starts for the first time, I'm populating the listView from Database with Cursor and Custom Adapter. When user enter some text in EditText I'm creating new sql statement and getting the data with new Cursor. After that I'm creating new Custom Adapter and trying to set it to my list view.
The problem is that when I start typing in edit text I can saw in Logs from LogCat that the sql statement is the right one, and cursor size, but my ListView isn't populated with the new data. It's staying the same. Here is how I'm doing it :
This is how I'm populating the listView for first time :
cursor = userDbHelper.executeSQLQuery(sqlQuery);
if (cursor.getCount() == 0) {
noCards.setVisibility(View.VISIBLE);
noCards.setText(getString(R.string.no_cards));
} else if (cursor.getCount() > 0) {
noCards.setVisibility(View.GONE);
for (cursor.move(0); cursor.moveToNext(); cursor.isAfterLast()) {
objectId = Integer.parseInt(cursor.getString(cursor.getColumnIndex("objectId")));
cardId.add(objectId);
title = cursor.getString(cursor.getColumnIndex("title"));
catTitle = cursor.getString(cursor.getColumnIndex("catTitle"));
int repeats = Integer.parseInt(cursor.getString(cursor.getColumnIndex("repeatsCount")));
count.add(repeats);
if(extra != 0){
String cardsm = "SELECT objectId FROM cardmedias "
+ "WHERE cardId="
+ objectId
+ " AND mediaType="
+ 5012;
Cursor cardsM = userDbHelper.executeSQLQuery(cardsm);
if (cardsM.getCount() == 0) {
} else if (cardsM.getCount() > 0) {
for (cardsM.move(0); cardsM.moveToNext(); cardsM.isAfterLast()) {
objectID = Integer.parseInt(cardsM.getString(cardsM.getColumnIndex("objectId")));
String filename = "mediacard-"+objectID;
if(storageID==1){
path = RPCCommunicator.getImagePathFromInternalStorage(servername, userId, filename, this);
} else if(storageID==2){
path = RPCCommunicator.getImagePathFromExternalStorage(servername, userId, filename);
}
hm.put(objectID, path);
path = hm.get(objectID);
Log.i("","path : "+path);
paths.add(path);
names.add(title);
categories.add(catTitle);
}
}
} else if (extra==0){
names.add(title);
categories.add(catTitle);
}
}
}
cursor.close();
adapter = new LazyAdapter(this, paths, names, categories, count);
listView.setAdapter(adapter);
and this is how I'm creating the new Cursor and adapter with TextWatcher :
searchString = "";
sqlQuery = getSqlQuery(sort, collId, ascDesc,searchString);
searchBar.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
check = 1;
listView.setAdapter(null);
searchString = s.toString();
Log.e("","searchString : "+searchString);
sqlQuery = getSqlQuery(sort, collId, ascDesc,searchString);
Log.e(""," sqlquery : "+sqlQuery);
Cursor cursor = userDbHelper.executeSQLQuery(sqlQuery);
Log.e("","cursor count : "+cursor.getCount());
if (cursor.getCount() == 0) {
noCards.setVisibility(View.VISIBLE);
noCards.setText(getString(R.string.no_cards));
} else if (cursor.getCount() > 0) {
noCards.setVisibility(View.GONE);
for (cursor.move(0); cursor.moveToNext(); cursor.isAfterLast()) {
objectId = Integer.parseInt(cursor.getString(cursor.getColumnIndex("objectId")));
cardId.add(objectId);
title = cursor.getString(cursor.getColumnIndex("title"));
catTitle = cursor.getString(cursor.getColumnIndex("catTitle"));
int repeats = Integer.parseInt(cursor.getString(cursor.getColumnIndex("repeatsCount")));
count.add(repeats);
if(extra != 0){
String cardsm = "SELECT objectId FROM cardmedias "
+ "WHERE cardId="
+ objectId
+ " AND mediaType="
+ 5012;
Cursor cardsM = userDbHelper.executeSQLQuery(cardsm);
if (cardsM.getCount() == 0) {
} else if (cardsM.getCount() > 0) {
for (cardsM.move(0); cardsM.moveToNext(); cardsM.isAfterLast()) {
objectID = Integer.parseInt(cardsM.getString(cardsM.getColumnIndex("objectId")));
String filename = "mediacard-"+objectID;
if(storageID==1){
path = RPCCommunicator.getImagePathFromInternalStorage(servername, userId, filename, OwnedStampii.this);
} else if(storageID==2){
path = RPCCommunicator.getImagePathFromExternalStorage(servername, userId, filename);
}
hm.put(objectID, path);
path = hm.get(objectID);
Log.i("","path : "+path);
paths.add(path);
names.add(title);
categories.add(catTitle);
}
}
} else if (extra==0){
names.add(title);
categories.add(catTitle);
}
}
}
cursor.close();
LazyAdapter adapter = new LazyAdapter(OwnedStampii.this, paths, names, categories, count);
listView.setAdapter(adapter);
}
});
So any ideas how can I refresh my list View with the new adapter. I've already tried with adapter.notifySetDataChanged(); and it's not working.
Thanks in advance!
clear your data sources in this case it is paths, names, categories, count.
Load new results into data sources of list(paths, names, categories, count), and don's set list adapter to null, and call notifyDataSetChanged.
I fix that, in my afterTextChanged() I'm just clearing the arraylists using for storing the data and putting the new data on them.

Categories

Resources