I am trying to implement a search of a ListView I create through SimpleCursorAdapter. I have tried various ways and below is what I have so far and it is not working. I want to be able to type in the EditText and my list adjust to the search. Any help would be greatly appreciated and below is my code:
private FoodDatabase foodDB;
private CalendarDBAdapter calendarDB;
private ListView fruitsListVIew;
private String datePassed;
private View dialogView;
private EditText search;
private SimpleCursorAdapter myCursorAdapter;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.fruits);
fruitsListVIew = (ListView)this.findViewById(R.id.fruitsListView);
search = (EditText)this.findViewById(R.id.search_box);
datePassed = GlobalVars.getDate();
openDB();
populateLV();
search.addTextChangedListener(new TextWatcher()
{
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
myCursorAdapter.getFilter().filter(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}
#Override
public void afterTextChanged(Editable s)
{
}
});
}
private void populateLV()
{
String fruitID = "10";
final Cursor c = foodDB.getFoodByGroup(fruitID);
//allow activity to close cursor
startManagingCursor(c);
//Mapping from cursor to view fields
String[] fieldNames = new String[] {FoodDatabase.FOOD_ITEM_NAME, FoodDatabase.CALORIES, FoodDatabase.FAT,
FoodDatabase.MEASURE, FoodDatabase.TYPE_OF_MEASRE};
int[] viewIds = new int[] {R.id.foodNameTxt, R.id.calorieDB, R.id.fatDB, R.id.servingDB, R.id.measureTxt};
//create adapter to map columns to view exercise UI
myCursorAdapter = new SimpleCursorAdapter(this, R.layout.foods_data_layout, c, fieldNames, viewIds);
//Set the adapter for the list view
fruitsListVIew.setAdapter(myCursorAdapter);
fruitsListVIew.setTextFilterEnabled(true);
fruitsListVIew.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
{
qtyDialog(v);
}
});
}
I am able to input text but nothing happens.
Cheers
Try this
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
myCursorAdapter.getFilter().filter(s.toString());
myCursorAdapter.notifyDataSetChanged();
}
It appears to me that you need a FilterQueryProvider :)
myCursorAdapter.setFilterQueryProvider(new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
String partialValue = constraint.toString();
return itemData.getAllSuggestedValues(partialValue);
}
});
Check this - Using an EditText to filter a SimpleCursorAdapter-backed ListView
Related
Good Day everyone!
I am new to android programming, struggling on how to attach _id of database to the listview adapter. Its almost consume as whole trying to figure out on how to do it.
Here's the code for list:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(R.anim.fadein, R.anim.fadeout);
setContentView(R.layout.activity_dictionarylist);
filterText = (EditText)findViewById(R.id.txtsearch);
ListView itemList = (ListView)findViewById(R.id.listView);
DBHelper dbHelper = new DBHelper(Dictionarylist.this);
String[] terms = dbHelper.dictionaryWords();
listAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, android.R.id.text1,terms);
itemList.setAdapter(listAdapter);
itemList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getApplicationContext(), "Position " + position, Toast.LENGTH_LONG).show();
Intent intent = new Intent(Dictionarylist.this, DictionaryActvity.class);
intent.putExtra("DICTIONARY_ID", position);
startActivity(intent);
}
});
filterText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Dictionarylist.this.listAdapter.getFilter().filter(s);
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
Here's the code for Database Helper:
public class DBHelper extends DBCon {
public DBHelper(Context context){
super(context);
}
public String[] dictionaryWords(){
String query = "Select * from main_dictionary";
Cursor cursor = this.getdbconnection().rawQuery(query, null);
ArrayList<String> wordterms = new ArrayList<String>();
if(cursor.moveToFirst()){
do{
String word = cursor.getString(cursor.getColumnIndexOrThrow("main_word"));
wordterms.add(word);
}
while (cursor.moveToNext());
}
cursor.close();
String[] dictionaryWords = new String[wordterms.size()];
dictionaryWords = wordterms.toArray(dictionaryWords);
return dictionaryWords;
}
public Quizzer getQuizById(int quizId){
Quizzer quizzer = null;
String query = "select * from main_dictionary where _id =" + quizId;
Cursor cursor = this.getdbconnection().rawQuery(query, null);
if(cursor.moveToFirst()){
do{
String word = cursor.getString(cursor.getColumnIndexOrThrow("main_word"));
String tagdef = cursor.getString(cursor.getColumnIndexOrThrow("tag_definition"));
String engdef = cursor.getString(cursor.getColumnIndexOrThrow("eng_defintion"));
String sample = cursor.getString(cursor.getColumnIndexOrThrow("example"));
quizzer = new Quizzer(word, tagdef, engdef, sample);
}
while(cursor.moveToNext());
}
cursor.close();
return quizzer;
}
I would appreciate any help.
AFAIK inside RecyclerView's onBindViewHolder(ViewHolder holder, int position), you may want to attach holder.setTag(model.getId) instead of holder.setTag(position) that we do. Take an OnClickListener outside by holder.setOnClickListener(exampleListener) and get that tag inside View.OnclickListener by using int positionId = (int) holder.getTag(). This way you may utilize RecyclerView too.
I'm having trouble with quite a simple layout in Android. Basically, I have a spinner that contains several items from a sqlite database. I also have some EditText fields that receive and display the information from the selected item. What I to do now is to implement a button that allows the user to add a new entry and change its data - all in the same view (the EditText fields are already programmated to do that). Here's my code (what I tried to do is to update the database with default data from the new item and redraw the class, but I can't get to set the spinner to the new position). Do you guys have any idea on how I can do that?
public class Activity_MaterialTab extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_materialtab);
//Opens database
final SQLiteDatabase Estrutura = openOrCreateDatabase("Estutura.db", Context.MODE_PRIVATE, null);
final Cursor cursor = Estrutura.rawQuery("SELECT * FROM MATERIAIS ORDER BY [_id] ASC", null);
final Spinner spnMaterial = (Spinner) findViewById(R.id.mat_spn_material);
final EditText dVol = (EditText) findViewById(R.id.mat_frm_densidade);
final EditText modE = (EditText) findViewById(R.id.mat_frm_elasticidade);
final EditText nome = (EditText) findViewById(R.id.mat_frm_nome);
final ImageButton addMaterial = (ImageButton) findViewById(R.id.mat_btm_add);
final ImageButton excMaterial = (ImageButton) findViewById(R.id.mat_btm_exc);
final Bundle sis = savedInstanceState;
//Spinner
String from[] = {"_id","nome","modE","dVol"};
int to[] = {R.id.txvid,R.id.txvnome,R.id.txvmodE,R.id.txvdVol};
SimpleCursorAdapter ad = new SimpleCursorAdapter(getBaseContext(), R.layout.sp_material, cursor, from, to, 0);
spnMaterial.setAdapter(ad);
try {
spnMaterial.setSelection(sis.getInt("pos"));
} catch (Exception e) {}
//Updates Edittext fields
modE.setText(String.valueOf(cursor.getDouble(2)));
dVol.setText(String.valueOf(cursor.getDouble(3)));
spnMaterial.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view,int position, long id) {
Cursor cursor2 = Estrutura.rawQuery("SELECT * FROM MATERIAIS ORDER BY [_id] ASC", null);
cursor2.moveToPosition(cursor.getPosition());
nome.setText(String.valueOf(cursor2.getDouble(1)));
modE.setText(String.valueOf(cursor2.getDouble(2)));
dVol.setText(String.valueOf(cursor2.getDouble(3)));
cursor.moveToPosition(position);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
modE.addTextChangedListener(new TextWatcher()
{
#Override
public void beforeTextChanged(CharSequence s, int start, int count,int after) {}
#Override
public void onTextChanged(CharSequence s, int start, int before,int count) {}
#Override
public void afterTextChanged(Editable s) {
if (modE.length() != 0) {
String sql = "UPDATE MATERIAIS SET modE="+modE.getText().toString()+" WHERE [_id]="+String.valueOf(cursor.getInt(0));
Estrutura.execSQL(sql);
}
}
});
dVol.addTextChangedListener(new TextWatcher()
{
#Override
public void beforeTextChanged(CharSequence s, int start, int count,int after) {}
#Override
public void onTextChanged(CharSequence s, int start, int before,int count) {}
#Override
public void afterTextChanged(Editable s) {
if (dVol.length() != 0) {
String sql = "UPDATE MATERIAIS SET dVol="+dVol.getText().toString()+" WHERE [_id]="+String.valueOf(cursor.getInt(0));
Estrutura.execSQL(sql);
}
}
});
addMaterial.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v) {
String sql = "INSERT INTO MATERIAIS(nome,modE,dVol) VALUES('Nome',0,0)";
Estrutura.execSQL(sql);
sis.putInt("pos", cursor.getPosition());
onCreate(sis);
spnMaterial.setSelection(3);
}
});
}
}
So, right now, I have the a EditText that filters the data in the ListView as the text is changed. But, I want to change it so that it only filters when the enter key is pressed. I can't seem to figure it out.
It's pulling the data from a database.
public class SearchActivity extends NavDrawerActivity {
private DBHandler dbHelper;
private SimpleCursorAdapter dataAdapter;
private EditText myFilter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main_activity3);
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.activity_frame);
// inflate the custom activity layout
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View activityView = layoutInflater.inflate(R.layout.activity_main_activity3, null, false);
// add the custom layout of this activity to frame layout.
frameLayout.addView(activityView);
dbHelper = new DBHandler(this);
dbHelper.open();
//Clean all data
dbHelper.deleteAllRecipes();
//Add some data
dbHelper.insertSomeRecipes();
//Generate ListView from SQLite Database
displayListView();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
private void displayListView() {
final Cursor cursor = dbHelper.fetchAllRecipes();
// The desired columns to be bound
String[] columns = new String[]{
//DBHandler.COLUMN_CODE,
DBHandler.COLUMN_NAME,
DBHandler.COLUMN_TYPE,
DBHandler.COLUMN_INGRED
};
// the XML defined views which the data will be bound to
int[] to = new int[]{
//R.id.code,
R.id.name,
R.id.type,
R.id.ingredient,
};
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
dataAdapter = new SimpleCursorAdapter(
this, R.layout.recipeinfo,
cursor,
columns,
to,
0);
ListView listView = (ListView) findViewById(R.id.listView1);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
//Cursor cursor = (Cursor) listView.getItemAtPosition(position);
Intent n = new Intent(getApplicationContext(), RecipeActivity.class);
n.putExtra("position", position);
startActivity(n);
}
});
final EditText myFilter = (EditText) findViewById(R.id.myFilter);
myFilter.addTextChangedListener(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) {
dataAdapter.getFilter().filter(s.toString());
}
});
dataAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return dbHelper.fetchRecipesByName(constraint.toString());
}
});
}
}
Instead of this:
final EditText myFilter = (EditText) findViewById(R.id.myFilter);
myFilter.addTextChangedListener(new TextWatcher() {
...
public void onTextChanged(CharSequence s, int start,int before, int count) {
dataAdapter.getFilter().filter(s.toString());
}
});
Try below:
final EditText myFilter = (EditText) findViewById(R.id.myFilter);
myFilter.setImeActionLabel("Filter",1);
myFilter.setPrivateImeOptions("actionUnspecified");
myFilter.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
if (id == 1 || id == EditorInfo.IME_NULL) {
dataAdapter.getFilter().filter(textView.getText().toString());
return true;
}
return false;
}
});
Rather than rely on IME options, why not just add a "Done" button and take the value of your EditText when pressed? You can still use the TextWatcher to make sure the input is valid and no invalid chars are entered.
Set to your edit text android:imeOptions="actionSearch" in xml.
myFilter.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
dataAdapter.getFilter().filter(v.getText.toString());
}
return false;
}
});
no need to create extra filter class . you just keep string from TextWatcher then check that string with your list view data using contain method
searchforcategory.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
getAllCetegory(charSequence.toString());
}
#Override
public void afterTextChanged(Editable editable) {
}
});
now just check that string with your data
for(int i=0;i<response.body().getDataList().size();i++){
if(response.body().getDataList().get(i).getName().contains(checkString)){
productDataLists.add(response.body().getDataList().get(i));
}
}
I want to search for a product name in listView, but nothing displays inside the list after I key in some text inside search text field. I'm not using ArrayAdapter, but I'm using the ResourceCursorAdapter.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
helper = new ComicsData(this);
helper.open();
listSearch=(EditText)findViewById(R.id.inputSearch);
listSearch.addTextChangedListener(filterTextWatcher);
model = helper.getAllProduct(list);
startManagingCursor(model);
adapter=new ShoppingListAdapter(this, model);
listView.setAdapter(adapter);
}
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) {
//String search=listSearch.getText().toString();
//int textLength=search.length();
adapter.getFilter().filter(s);
}
};
ShoppingListAdapter
class ShoppingListAdapter extends ResourceCursorAdapter {
private final String CN = null;
public ShoppingListAdapter(Context context, Cursor c) {
super(context, R.layout.productrow, c);
// TODO Auto-generated constructor stub
}
#Override
public void bindView(View row, Context context, Cursor c) {
// TODO Auto-generated method stub
listName = (TextView) row.findViewById(R.id.produtName);
listName.setText(helper.getProductName(c));
Anybody know my mistake ?
After changing text in listSearch get items according to search text helper.getProducts(searchText); and call adapter.notifyDataSetChanged()
You need provide your adapter with an instance of FilterQueryProvider. This provider takes your filter query and returns cursor with all found items.
I am trying to provide a searchable listview. Each listitem has a name & address text box but I only want to filter on the name. My current code does nothing, i.e no filtering occurs at all. Is there a way of setting the column to filter by?
//class variables
private SimpleCursorAdapter mAdapter;
private EditText filterText = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.add_customer_listview);
//listViewCustomers = (ListView) findViewById(R.id.list);
buildingListViewAdaptor();
setListAdapter(mAdapter);
// set up the filter
filterText = (EditText) findViewById(R.id.search_box);
filterText.addTextChangedListener(filterTextWatcher);
}
private TextWatcher filterTextWatcher = new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
mAdapter.getFilter().filter(s);
Log.d(GlobalTools.ErrorCodes.INFO, "Searchtext=" + s.toString());
}
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
};
private void buildingListViewAdaptor(){
//1. Get the data
CustomerLocationDataHandler clDataHandler = new CustomerLocationDataHandler(getContentResolver());
Cursor cursor = clDataHandler.allCustomerLocations();
clDataHandler=null;
//2. Build the adaptor
mAdapter = new SimpleCursorAdapter(this,
R.layout.list_item_custom_font, // was list_item_custom_font
cursor,
new String[]{MyobiliseData.Columns_CustomerLocations.CUSTOMER_NAME,MyobiliseData.Columns_CustomerLocations.CITY},
new int[] {R.id.text1,R.id.text2}
);
}
check out this post: ListView, SimpleCursorAdapter, an an EditText filter -- why won't it do anything?
I have added in a similar method and it is now working.
To achieve this I needed to re-query the database each time the user typed in the search box. I have included the working code here:
public class AddCustomerActivity extends ListActivity{
//constants
public static final String B4ME = "B4ME"; //Used when passing a boolean to this activity
// dialog constants
private static final int DIALOG_CHECKINSERT = 0;
//class variables
private SimpleCursorAdapter mAdapter;
private EditText filterText = null;
private boolean mInsertB4; //if false ->means insert after
private Long mRunDetailID;
private Long mCustomerLocationId;
private int mSelectedItemPosition;
private long mSelectedItemId;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.add_customer_listview);
readVariablesPassedToThis();
//listViewCustomers = (ListView) findViewById(R.id.list);
buildingListViewAdaptor();
setListAdapter(mAdapter);
// set up the filter
filterText = (EditText) findViewById(R.id.search_box);
filterText.addTextChangedListener(filterTextWatcher);
mAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return filterRefresh(constraint);
}
});
}
private TextWatcher filterTextWatcher = new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
mAdapter.getFilter().filter(s);
}
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
};
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
mSelectedItemPosition = position;
mSelectedItemId = id;
Log.d(GlobalTools.ErrorCodes.INFO, "Selected ItemPosition=" + mSelectedItemPosition + " and itemid ="+mSelectedItemId);
showDialog(DIALOG_CHECKINSERT);
}
private void buildingListViewAdaptor(){
//2. Build the adaptor
mAdapter = new SimpleCursorAdapter(this,
R.layout.list_item_custom_font, // was list_item_custom_font
filterRefresh(null),
new String[]{MyobiliseData.Columns_CustomerLocations.CUSTOMER_NAME,MyobiliseData.Columns_CustomerLocations.CITY},
new int[] {R.id.text1,R.id.text2}
);
}
private Cursor filterRefresh(CharSequence constraint){
//1. Get the data
CustomerLocationDataHandler clDataHandler = new CustomerLocationDataHandler(getContentResolver());
Cursor cursor = clDataHandler.customerLocationsFilteredOn(constraint);
clDataHandler=null;
return cursor;
}