So i'm trying to make a searchable list view using a custom array adapter.
I finally got the search working but the results are not exactly accurate.
Its actually a hit and miss kinda thing e.g Searching for Drupal gets me Google Plus, you knw what I saying?
So here's my adapter
public class CustomListAdapter extends ArrayAdapter<String> implements Filterable {
private final Activity context;
private final String[] web;
private final String[] imageIdUrl;
public CustomListAdapter(Activity context, String[] web, String[] imageId) {
super(context, R.layout.list_single, web);
this.context = context;
this.web = web;
this.imageIdUrl = imageId;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
//find row view
View rowView= inflater.inflate(R.layout.list_single, null, true);
//find text
TextView txtTitle = (TextView) rowView.findViewById(R.id.txt);
//find image
ImageView imageView = (ImageView) rowView.findViewById(R.id.img);
//set text
txtTitle.setText(web[position]);
//set image traditional
//imageView.setImageResource(imageIdUrl[position]);
//set image with picasso
Picasso.with(this.context).load(imageIdUrl[position]).into(imageView);
//return row
return rowView;
}
}
And heres my Main Activity class
public class MainActivity extends ActionBarActivity {
ListView list;
EditText editsearch;
String[] web = {
"Google Plus",
"Twitter",
"Windows",
"Bing",
"Itunes",
"Wordpress",
"Drupal"} ;
String[] imageIdUrl = {
"http://www.h3dwallpapers.com/wp-content/uploads/2015/05/Google_Logo_04.jpg",
"http://www.h3dwallpapers.com/wp-content/uploads/2015/05/Google_Logo_04.jpg" ,
"http://www.h3dwallpapers.com/wp-content/uploads/2015/05/Google_Logo_04.jpg",
"http://www.h3dwallpapers.com/wp-content/uploads/2015/05/Google_Logo_04.jpg",
"http://www.h3dwallpapers.com/wp-content/uploads/2015/05/Google_Logo_04.jpg",
"http://www.h3dwallpapers.com/wp-content/uploads/2015/05/Google_Logo_04.jpg",
"http://www.h3dwallpapers.com/wp-content/uploads/2015/05/Google_Logo_04.jpg"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final CustomListAdapter adapter = new CustomListAdapter(MainActivity.this, web, imageIdUrl);
list=(ListView)findViewById(R.id.list);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this, "You Clicked at " + web[+position], Toast.LENGTH_SHORT).show();
}
});
// Locate the EditText in listview_main.xml
editsearch = (EditText) findViewById(R.id.editText);
editsearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
String text = editsearch.getText().toString().toLowerCase(Locale.getDefault());
adapter.getFilter().filter(text);
}
#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
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
I'll be grately thankful for any help. This is proving to be a major headache
Change the code in onTextChanged() method to afterTextChanged() method as below:
#Override
public void afterTextChanged(Editable s) {
String str=s.toString();
getSearchItems(str);
}
In getSearchItems use the filter properly. I used other way to filter as,
public void getSearchItems(String searchText){
List<Employee> searchList=new ArrayList<Employee>();
List<Employee> employeeList=getEmployeeList();
if(employeeList2!=null){
for(Employee e:employeeList){
if(e.name.toLowerCase().contains(searchText.toLowerCase())){
searchList.add(e);
}
}
}
adapter.refresh(searchList);
}
Then In adapter use another method refresh() as below:
public void refresh(List<Employee> employeeList){
this.employeeList=employeeList;
notifyDataSetChanged();
}
Actually I used Employee class which contains his name and address, and I made search using employee name. So u change the above code which suits your search.
Related
I have an a gridView that has items, each item has a name and quantity. When I click the item in the gridView, I would like to add the item and the quantity to a dynamic list view that is in the same activity. If I click on the item a several times, the items quantity in the dynamic listView should be increased (no duplicate items are allowed.) This is my current gridView, I have removed the code that adds and a previous listView that failed and I am having it just toast for now:
public class GridviewAdapter extends BaseAdapter
{
private ArrayList<String> listItem;
private ArrayList<Integer> listPicture;
private Activity activity;
public GridviewAdapter(Activity activity, ArrayList<String> listItem, ArrayList<Integer> listPicture) {
super();
this.listItem = listItem;
this.listPicture = listPicture;
this.activity = activity;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return listItem.size();
}
#Override
public String getItem(int position) {
// TODO Auto-generated method stub
return listItem.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public static class ViewHolder
{
public ImageView itemPicture;
public TextView itemName;
public TextView itemPrice;
public TextView itemStock;
public TextView itemAvailability;
}
#Override
public View getView(int position, View convertView, ViewGroup
parent) {
// TODO Auto-generated method stub
ViewHolder view;
LayoutInflater inflator = activity.getLayoutInflater();
if(convertView==null)
{
view = new ViewHolder();
convertView = inflator.inflate(R.layout.item_grid_row,
null);
view.itemName = (TextView)
convertView.findViewById(R.id.itemName);
view.itemPrice = (TextView)
convertView.findViewById(R.id.itemPrice);
view.itemStock = (TextView)
convertView.findViewById(R.id.itemStock);
view.itemAvailability = (TextView)
convertView.findViewById(R.id.itemAvailability);
view.itemPicture = (ImageView)
convertView.findViewById(R.id.itemPicture);
convertView.setTag(view);
}
else
{
view = (ViewHolder) convertView.getTag();
}
view.itemName.setText(listItem.get(position));
// view.itemPicture.setImageDrawable(listItem.get(position));
return convertView;
}
}
this is the code for the checkout fragment where the gridView is clicked.
public class CheckoutFragment extends Fragment {
private CheckoutViewModel checkoutViewModel;
private EditText editText1;
private GridviewAdapter mAdapter;
private ArrayList<String> listItem;
private ArrayList<Integer> listPicture;
private GridView gridView;
DBHelper db;
LinearLayout layout_total, layout_grid;
private Button sum;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle
savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_checkout,
container, false);
db = new DBHelper(getActivity());
Display display =
getActivity().getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
editText1 = (EditText)root.findViewById(R.id.editText1);
editText1.setHeight(height/12);
editText1.setShowSoftInputOnFocus(false);
editText1.setFocusable(false);
editText1.setTextColor(Color.parseColor("#FFFFFF"));
editText1.setHintTextColor(Color.parseColor("#FFFFFF"));
editText1.getBackground().setColorFilter(Color.parseColor("#008577"),
PorterDuff.Mode.SRC_ATOP);
editText1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent cart = new Intent(getActivity(),
CartActivity.class);
startActivity(cart);
}
});
prepareList();
// prepared arraylist and passed it to the Adapter class
mAdapter = new GridviewAdapter(getActivity(),db.getAll(),
listPicture);
// Set custom adapter to gridview
gridView = (GridView)root.findViewById(R.id.gridView1);
gridView.setAdapter(mAdapter);
// Implement On Item click listener
gridView.setOnItemClickListener(new
AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int
position,
long arg3) {
//this is where the grid is clicked and items added to dynamic listView
Toast.makeText(getActivity(),
mAdapter.getItem(position), Toast.LENGTH_SHORT).show();
}
});
return root;
}
public void prepareList() {
// listItem = new ArrayList<String>();
db = new DBHelper(getActivity());
List<Item> listItem = new ArrayList<>();
listItem = db.getAllItems(db.ITEMS_TABLE_NAME);
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
}
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch(item.getItemId()) {
case R.id.action_add_customer:
//startActivity(getActivity(),
NewCustomerActivity.class);
Intent newCustomer = new Intent(getActivity(),
NewCustomerActivity.class);
startActivity(newCustomer);
return true;
/* case R.id.action_add_customer:
return true;*/
default:
return super.onOptionsItemSelected(item);
}
}
}
You need to explain the situation a bit better. For now i assume your problem is that the items are duplicating the second list instead of appending the count. For this there is no
one line solution. What you need to do is once an item is selected in the grid, search if it exists in the second list. In that case update the quantity, otherwise add it to the list. Since your second list is based on a Table , you have to execute 2 queries. One to identify if the item already exists (Select Query) and other to change the value (Insert or Update Query). If i misunderstood please correct me so that i can help you better.
Why don't you return the model class in your GridView getItem(..) method instead of 'String' it should work like this
public class GridviewAdapter extends BaseAdapter
{
ArrayList<GridModel> gridItems;
//Constructor
public GridviewAdapter(Activity activity, ArrayList<GridModel> gridItems) {
super();
this.gridItems = gridItems;
this.activity = activity;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return griditems.size();
}
#Override
public GridModel getItem(int position) {
// TODO Auto-generated method stub
return gridItems.get(position);
}
//...add your getView...
}
//GridModel Should be Like So..
class GridModel {
public String itemPicture;
public String itemName;
public String itemPrice;
public String itemStock;
public String itemAvailability;
//or use private variables with getter-setter methods
}
So essentially I have a listview that contains a custom adapter that deals with formatting the listview. The custom view used by the adapter contains a checkbox that I want to be checked with the check locked when the listview item is selected. After much searching and various attempts at accomplishing this I have not been successful. Any ideas as to how to accomplish this would be greatly appreciated.
Here is the code for my main class:
public class AbWorkout extends Activity {
Button back;
ListView workoutExerciseList;
WorkoutTracker tracker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ab_workout);
/**
* The database used to pull all exercises for this workout routine
*/
final DatabaseHandler db = new DatabaseHandler(this);
final SQLiteDatabase database = db.getReadableDatabase();
final Context context = this;
/**
* Get all exercises from Triceps and Chest workout and put in arraylist
*/
workoutExerciseList = (ListView)findViewById(R.id.listView10);
final List<String> arrayWorkoutExercises = new ArrayList<String>();
final ArrayAdapter<String> exListAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_multiple_choice, arrayWorkoutExercises);
workoutExerciseList.setAdapter(exListAdapter);
//Holds all the available exercises
final List<WorkoutTracker> exerciseList = db.getRepetitionWorkoutRoutine(context, database, "Abs");
/**
* Populates the listView with each exercise for this workout routine. This includes the
* each exercise name, the number of repetitions, the weight of the exercise, and any
* comments included.
*/
List<AbWorkout.RepListViewItem> repProgressList = new ArrayList<>();
for(int i = 0; i<exerciseList.size(); i++) {
final int j = i;
repProgressList.add(new AbWorkout.RepListViewItem()
{{
REPETITIONS = exerciseList.get(j).getReps();
WEIGHT = exerciseList.get(j).getWeight();
COMMENT = exerciseList.get(j).getComment();
EXERCISE_NAME = exerciseList.get(j).getExerciseName();
}});
}
final AbViewAdapter adapter = new AbViewAdapter(this, repProgressList);
workoutExerciseList.setAdapter(adapter);
CheckBox checkBox = (CheckBox)findViewById(R.id.CheckBox);
workoutExerciseList.setItemChecked(ListView.CHOICE_MODE_MULTIPLE, true);
/*
Upon selection of an exercise, it is highlighted and its name, date,
and number of reps is stored in repetition progress table
*/
workoutExerciseList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> myAdapter, View myView, int myItemInt, long mylng) {
CheckBox check = (CheckBox) findViewById(R.id.CheckBox);
//check.setChecked(true);
Calendar calendar = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yy");
//Get today's date formatted like this: dd-MM-yy
String exDate = format.format(calendar.getTime());
//When exercise is selected, change the color and make it unselectable.
myAdapter.getChildAt(myItemInt).setBackgroundColor(Color.MAGENTA);
myAdapter.getChildAt(myItemInt).setEnabled(false);
myAdapter.getChildAt(myItemInt).setClickable(false);
myView.setClickable(true);
tracker = exerciseList.get(myItemInt);
db.addNewRepProgress(new WorkoutTracker(tracker.getExerciseName(), tracker.getReps(), tracker.getWeight(), tracker.getComment(), exDate), context, database);
Toast.makeText(context.getApplicationContext(), "Workout Progress was successfully saved.", Toast.LENGTH_LONG).show();
}
});
back = (Button)findViewById(R.id.back);
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_ab_workout, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public class RepListViewItem
{
public int REPETITIONS;
public double WEIGHT;
public String COMMENT;
public String EXERCISE_NAME;
public String DATE;
}
}
And here is the code for my adapter class:
public class AbViewAdapter extends BaseAdapter
{
LayoutInflater inflater;
List<AbWorkout.RepListViewItem> items;
int pos = 0;
public AbViewAdapter(Activity context, List<AbWorkout.RepListViewItem> items) {
super();
this.items = items;
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
AbWorkout.RepListViewItem item = items.get(position);
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.rep_item_row, null);
TextView exerciseName = (TextView)vi.findViewById(R.id.FullProgress);
TextView exerciseReps = (TextView)vi.findViewById(R.id.Time);
TextView exerciseComment = (TextView)vi.findViewById(R.id.Comment);
TextView exerciseWeight = (TextView)vi.findViewById(R.id.Distance);
CheckBox check = (CheckBox)vi.findViewById(R.id.CheckBox);
exerciseName.setText(item.EXERCISE_NAME);
exerciseReps.setText(String.valueOf(item.REPETITIONS));
exerciseComment.setText(item.COMMENT);
exerciseWeight.setText(String.valueOf(item.WEIGHT));
pos = position;
return vi;
}
}
because when you scroll your listview, the item in A will be destroyed. When scroll up, the item in A will be re-created.
So the CheckBox is re-create too, you need to store item when to restore this current state when scroll up. Let see ViewHolder
In your AbViewAdapter.getView(), add an OnClickListener
Then, in the OnClickListener, toggle the checkbox state with:
check.setChecked(!isChecked())
Full answer here: Android listview with check boxes?
Full tutorial here: http://www.mysamplecode.com/2012/07/android-listview-checkbox-example.html
i need help to save the rating of rating bar in my list view for each item.My question is how can i do it because the OnItemClickListener does not work.
this is how my custom array adapter looks like
public class CustomArrayAdapter extends ArrayAdapter<String> {
public ArrayList<String> ratings;
private Activity context;
private int[] imageID;
private String[] stdName;
private double[] GPA;
private String[] course;
private String[] rollNo;
public float cRating;
public CustomArrayAdapter(Activity context, int[] imageID, String[] stdName, double[] GPA, String[] course, String[] rollNo) {
super(context, R.layout.row_design, stdName);
this.context = context;
this.imageID = imageID;
this.stdName = stdName;
this.GPA = GPA;
this.course = course;
this.rollNo = rollNo;
}
static class ViewContainer
{
public ImageView stdImage;
public ImageView possibleImage;
public TextView primaryTV;
public TextView secondryTV;
public RatingBar ratingBar;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewContainer viewContainer;
View rowView = convertView;
if(rowView == null) {
//converting the XML file into view objects
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.row_design, null, true);
viewContainer = new ViewContainer();
//getting the refrence of widgets
viewContainer.stdImage = (ImageView) rowView.findViewById(R.id.student_image);
viewContainer.possibleImage = (ImageView) rowView.findViewById(R.id.possibility_image);
viewContainer.primaryTV = (TextView) rowView.findViewById(R.id.primary_text_view);
viewContainer.secondryTV = (TextView) rowView.findViewById(R.id.secondry_text_view);
viewContainer.ratingBar = (RatingBar) rowView.findViewById(R.id.rating_bar);
rowView.setTag(viewContainer);
} else {
viewContainer = (ViewContainer) rowView.getTag();
viewContainer.ratingBar.setRating(0.0f);
rowView.setBackground(null);
}
viewContainer.ratingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
#Override
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
cRating = rating;
}
});
//setting the possible values to widgets
viewContainer.stdImage.setImageResource(imageID[position]);
viewContainer.primaryTV.setText(stdName[position] + " (GPA:" + GPA[position] + ")");
viewContainer.secondryTV.setText(course[position] + " (RollNo:" + rollNo[position] + ")");
if (GPA[position] < 3.0) {
rowView.setBackgroundResource(android.R.color.holo_red_light);
viewContainer.possibleImage.setImageResource(R.drawable.cross_small);
} else {
viewContainer.possibleImage.setImageResource(R.drawable.tick_small);
}
return rowView;
}
}
and this is my activity where i want to get the rating
public class StudentSelectionActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_student_selection);
//getting the refrence of list view
ListView listView = (ListView) findViewById(R.id.list);
//creating object of Rating activity to access it's public instances
final MainActivity obj = new MainActivity();
//creating custom adapter
final CustomArrayAdapter adapter = new CustomArrayAdapter(this, obj.imageID, obj.stdName, obj.GPA, obj.course, obj.rollNo);
listView.setAdapter(adapter);
//handling events on click listener of list view
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(StudentSelectionActivity.this, "rating = " + adapter.cRating, Toast.LENGTH_SHORT).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_selected_students, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Your setOnItemClickListener did not work for adapter class as you are using another clickable class inside adapter. So one option is to use click listener inside adapter class.
As
rowView.setOnClickListener(new View.onClickListener()
{
//Perform your operation.
});
Create an Entry class. This class holds your attributes, like cRating.
Then extend the CustomArrayAdapter for ArrayAdapter<Entry> instead of ArrayAdapter<String>. Change the constructor to something like this
public CustomArrayAdapter(Context context, int layoutResourceID, List<Entry> listItems) {
super(context, layoutResourceID, listItems);
this.context = context;
this.itemList = listItems;
this.layoutResID = layoutResourceID;
}
In your getView method use
EventDetailEntry item = this.itemList.get(position);
to get the corresponding item. Use this item to set the cRating. Then your onItemClicked method should work as expected. Hope that is clear enough.
I was curious on how to make a listview with a custom adapter searchable. I followed a tutorial and got everything set up, but the app crashes when I try to type anything in the EditText. Now I know why the app crashes, I just don't know how to fix it.
Here is the code to my MainActivity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context ctx = getApplication();
Resources res = ctx.getResources();
String[] options = res.getStringArray(R.array.item_ids);
String[] ids = res.getStringArray(R.array.item_names);
TypedArray icons = res.obtainTypedArray(R.array.item_images);
setListAdapter(new ItemIDAdapter(ctx, R.layout.idslistitem, ids, options, icons));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Get the options menu view from menu.xml in menu folder
getSupportMenuInflater().inflate(R.menu.items_menu, menu);
// Locate the EditText in menu.xml
editsearch = (EditText) menu.findItem(R.id.menu_search).getActionView();
// Capture Text in EditText
editsearch.addTextChangedListener(textWatcher);
// Show the search menu item in menu.xml
MenuItem menuSearch = menu.findItem(R.id.menu_search);
menuSearch.setOnActionExpandListener(new OnActionExpandListener() {
// Menu Action Collapse
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Empty EditText to remove text filtering
editsearch.setText("");
editsearch.clearFocus();
return true;
}
// Menu Action Expand
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
// Focus on EditText
editsearch.requestFocus();
// Force the keyboard to show on EditText focus
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
return true;
}
});
// Show the settings menu item in menu.xml
MenuItem menuSettings = menu.findItem(R.id.home);
// Capture menu item clicks
menuSettings.setOnMenuItemClickListener(new OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
Intent intent2 = new Intent(ItemId.this, Home.class);
startActivity(intent2);
return true;
}
});
return true;
}
// EditText TextWatcher
private TextWatcher textWatcher = new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
String text = editsearch.getText().toString()
.toLowerCase(Locale.getDefault());
adapter.getFilter().filter(text);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
};
And here is the code to my custom listview adapter:
public class ItemIDAdapter extends ArrayAdapter<String> {
public LayoutInflater mInflater;
public String[] mStrings;
public String[] mIds;
public TypedArray mIcons;
public int mViewResourceId;
ArrayAdapter<String> adapter;
public ItemIDAdapter(Context ctx, int viewResourceId,
String[] strings, String[] ids, TypedArray icons) {
super(ctx, viewResourceId, strings);
mInflater = (LayoutInflater)ctx.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mStrings = strings;
mIds = ids;
mIcons = icons;
mViewResourceId = viewResourceId;
}
#Override
public int getCount() {
return mStrings.length;
}
#Override
public String getItem(int position) {
return mStrings[position];
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(mViewResourceId, null);
ImageView iv = (ImageView)convertView.findViewById(R.id.option_icon);
iv.setImageDrawable(mIcons.getDrawable(position));
TextView tv = (TextView)convertView.findViewById(R.id.option_text);
tv.setText(mStrings[position]);
TextView tv1 = (TextView)convertView.findViewById(R.id.itemids);
tv1.setText(mIds[position]);
return convertView;
}
}
The reason the app crashes when I try to search, is because in the TextWatcher, this line: adapter.getFilter().filter(text); adapter is only defined at the top of my main activity, but it isn't used with my listview at ALL. I'm stuck here and really don't know what to replace adapter with, because ItemIDAdapter doesn't work. Thanks for your help!
Replace
setListAdapter(new ItemIDAdapter(ctx, R.layout.idslistitem, ids, options, icons));
with
adapter = new ItemIDAdapter(ctx, R.layout.idslistitem, ids, options, icons)
setListAdapter(adapter );
I have a listview that has a custom adapter, and I was trying to make it searchable using an Action Item. When I click the search icon in the action bar, the edit text comes up, but when I enter text and click "done" on the keyboard, nothing happens.
Here is the main class:
public class ItemId extends SherlockListActivity {
EditText editsearch;
ArrayAdapter<String> adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context ctx = getApplication();
Resources res = ctx.getResources();
String[] options = res.getStringArray(R.array.item_ids);
String[] ids = res.getStringArray(R.array.item_names);
TypedArray icons = res.obtainTypedArray(R.array.item_images);
adapter = new ItemIDAdapter(ctx, R.layout.idslistitem, ids, options, icons);
setListAdapter(adapter );
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Get the options menu view from menu.xml in menu folder
getSupportMenuInflater().inflate(R.menu.items_menu, menu);
// Locate the EditText in menu.xml
editsearch = (EditText) menu.findItem(R.id.menu_search).getActionView();
// Capture Text in EditText
editsearch.addTextChangedListener(textWatcher);
// Show the search menu item in menu.xml
MenuItem menuSearch = menu.findItem(R.id.menu_search);
menuSearch.setOnActionExpandListener(new OnActionExpandListener() {
// Menu Action Collapse
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Empty EditText to remove text filtering
editsearch.setText("");
editsearch.clearFocus();
return true;
}
// Menu Action Expand
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
// Focus on EditText
editsearch.requestFocus();
// Force the keyboard to show on EditText focus
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
return true;
}
});
// Show the settings menu item in menu.xml
MenuItem menuSettings = menu.findItem(R.id.home);
// Capture menu item clicks
menuSettings.setOnMenuItemClickListener(new OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
Intent intent2 = new Intent(ItemId.this, Home.class);
startActivity(intent2);
return true;
}
});
return true;
}
// EditText TextWatcher
private TextWatcher textWatcher = new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
String text = editsearch.getText().toString()
.toLowerCase(Locale.getDefault());
adapter.getFilter().filter(text);
};
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
};
}
And here is the Adapter class:
public class ItemIDAdapter extends ArrayAdapter<String> implements Filterable {
public LayoutInflater mInflater;
public String[] mStrings;
public String[] mIds;
public TypedArray mIcons;
public int mViewResourceId;
public ItemIDAdapter(Context ctx, int viewResourceId,
String[] strings, String[] ids, TypedArray icons) {
super(ctx, viewResourceId, strings);
mInflater = (LayoutInflater)ctx.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mStrings = strings;
mIds = ids;
mIcons = icons;
mViewResourceId = viewResourceId;
}
#Override
public int getCount() {
return mStrings.length;
}
#Override
public String getItem(int position) {
return mStrings[position];
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(mViewResourceId, null);
ImageView iv = (ImageView)convertView.findViewById(R.id.option_icon);
iv.setImageDrawable(mIcons.getDrawable(position));
TextView tv = (TextView)convertView.findViewById(R.id.option_text);
tv.setText(mStrings[position]);
TextView tv1 = (TextView)convertView.findViewById(R.id.itemids);
tv1.setText(mIds[position]);
return convertView;
}
}
If anyone has any idea as to why nothing happens when I search, or knows how to fix it, it'd be greatly appreciated. Thanks!!
You need to implement a custom filter. Have a look at this post here someone else has had a similar problem which he solved: https://stackoverflow.com/a/8258457/2045570
Below is mine code, which is working perfectly:-
public class ExpenditureAdapter extends ArrayAdapter<Expenditure> implements Filterable {
ArrayList<Expenditure> listArray;
ArrayList<Expenditure> filteredlistArray;
private Filter mFilter;
public ExpenditureAdapter(#NonNull Context context, ArrayList<Expenditure> list) {
super(context,0, list);
listArray=list;
filteredlistArray=list;
}
#Override
public int getCount() {
return filteredlistArray.size(); // total number of elements in the list
}
public void add(Expenditure object) {
listArray.add(object);
this.notifyDataSetChanged();
}
public Filter getFilter() {
if (mFilter == null) {
mFilter = new CustomFilter();
}
return mFilter;
}
#Override
public Expenditure getItem(int i) {
return filteredlistArray.get(i); // single item in the list
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
#Override
public long getItemId(int i) {
return i; // index number
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Expenditure expenditure = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.listexpenditure, parent, false);
}
// Lookup view for data population
TextView ExpId = (TextView) convertView.findViewById(R.id.ExpId);
TextView ExDate = (TextView) convertView.findViewById(R.id.ExDate);
TextView ExpAmt = (TextView) convertView.findViewById(R.id.ExpAmt);
TextView ExpDetail = (TextView) convertView.findViewById(R.id.ExpDetail);
// Populate the data into the template view using the data object
ExpId.setText(expenditure.ExpId);
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
String dateTime = dateFormat.format(expenditure.ExpDate);
ExDate.setText(dateTime);
ExpAmt.setText(String.valueOf(expenditure.ExpAmt));
ExpDetail.setText(expenditure.ExpDetail);
return convertView;
}
private class CustomFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if(constraint == null || constraint.length() == 0) {
ArrayList<Expenditure> list = new ArrayList<Expenditure>(listArray);
results.values = list;
results.count = list.size();
} else {
ArrayList<Expenditure> newValues = new ArrayList<Expenditure>();
for(int i = 0; i < listArray.size(); i++) {
Expenditure e_item = listArray.get(i);
if(e_item.ExpDetail.contains(constraint)) {
newValues.add(e_item);
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
filteredlistArray = (ArrayList<Expenditure>) results.values;
notifyDataSetChanged();
}
}
and use it in your code as below:-
private TextWatcher textWatcher = new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
String text = txtSearch.getText().toString()
.toLowerCase(Locale.getDefault());
adapter.getFilter().filter(text);
};
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
};