I'm trying to create an alert dialog where the user can select multiple options from a pre-defined list, but if the option(s) they want to select aren't there, they can add them (via an edittext and "add" button).
So far, I've added the edittext and button to the top of the dialog using setCustomTitle, and I'm able to add the item to my source data list, but I can't figure out how to reapply this to the list in the dialog.
(Filter model just has a string and a boolean to determine whether it's selected, so if the user reopens the dialog I can set the selected items)
Here's my code so far...
private void selectSomething() {
AlertDialog.Builder selectSomethingBuilder = new AlertDialog.Builder(mContext);
View header = getLayoutInflater().inflate(R.layout.common_multichoice_dialog_header, null);
Button addButton = header.findViewById(R.id.btAdd);
EditText et = header.findViewById(R.id.textView2);
selectSomethingBuilder.setCustomTitle(header);
addButton.setOnClickListener(v -> {
cuisineList.add(new filterModel(et.getText().toString(), true));
boolean[] selectedItems2 = new boolean[cuisineList.size()];
for (int i = 0; i < cuisineList.size(); i++) {
selectedItems2[i] = cuisineList.get(i).isSelected();
}
String[] updatedList = cuisineList.stream().map(filterModel::toString).toArray(String[]::new);
//What to do here? How do I update the list of items with the newly added item
et.setText("");
});
boolean[] selectedItems = new boolean[cuisineList.size()];
for (int i = 0; i < cuisineList.size(); i++) {
selectedItems[i] = cuisineList.get(i).isSelected();
}
selectSomethingBuilder.setMultiChoiceItems(cuisineList.stream().map(filterModel::toString).toArray(String[]::new), selectedItems,
(dialog, which, isChecked) -> cuisineList.get(which).setSelected(isChecked));
selectSomethingBuilder.setPositiveButton(R.string.ok, (dialog, id1) -> {
setCuisineChips();
});
AlertDialog selectItems = selectSomethingBuilder.create();
selectItems.show();
}
Ok, so I got there by extending AlertDialog.Builder - for anyone who comes across this, here's the class I'm using:
public class multichoiceUserAddableDialog extends AlertDialog.Builder {
private final Context context;
private final MultiAdapter adapter;
public multichoiceUserAddableDialog(Context context, List<filterModel> selectList) {
super(context);
this.context = context;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View header = inflater.inflate(R.layout.common_multichoice_dialog_header, null);
Button addButton = header.findViewById(R.id.btAdd);
EditText et = header.findViewById(R.id.textView2);
this.setCustomTitle(header);
adapter = new MultiAdapter(context, android.R.layout.simple_list_item_multiple_choice, selectList);
addButton.setOnClickListener(v -> {
selectList.add(new filterModel(et.getText().toString(), et.getText().toString(), true));
et.setText("");
adapter.notifyDataSetChanged();
});
setAdapter(adapter, (dialogInterface, i) -> {
});
}
#Override
public AlertDialog create() {
AlertDialog x = super.create();
x.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
((filterModel) adapterView.getItemAtPosition(i)).setSelected(!((filterModel) adapterView.getItemAtPosition(i)).isSelected());
adapter.notifyDataSetChanged();
}
});
return x;
}
private class MultiAdapter extends ArrayAdapter<filterModel> {
private List<filterModel> selectList;
ViewHolder holder;
public MultiAdapter(#NonNull Context context, int resource, #NonNull List<filterModel> selectList) {
super(context, resource, selectList);
this.selectList = selectList;
}
class ViewHolder {
CheckedTextView itemTV;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(
android.R.layout.simple_list_item_multiple_choice, null);
holder = new ViewHolder();
holder.itemTV = convertView.findViewById(android.R.id.text1);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.itemTV.setText(selectList.get(position).getText());
holder.itemTV.setChecked(selectList.get(position).isSelected());
return convertView;
}
}
}
This is then used like this:
multichoiceUserAddableDialog selectSomethingBuilder = new multichoiceUserAddableDialog(mContext, activityList);
selectSomethingBuilder.setPositiveButton(R.string.ok, (dialog, id1) -> {
setActivityChips();
});
AlertDialog selectItems = selectSomethingBuilder.create();
selectItems.show();
filterModel has a text field and a boolean (and any other fields you want), and the header layout has an editText and a button (plus a textview with some static text).
Related
In my activity I am displaying a list of data, each row has an edit and delete button. The listeners for these buttons are defined inside the listviews adapter.
I have implemented a custom array adapter:
public class SalesArrayAdapter extends ArrayAdapter<SaleModel> {
private Context context;
private int altColour;
private SaleModel sale;
private int position;
private ArrayList<SaleModel> sales;
private static class ViewHolder{
RelativeLayout container;
TextView tvId;
TextView tvDate;
TextView tvBusNo;
TextView tvDriver;
TextView tvNoOfTrips;
TextView tvTotalExpenditure;
TextView tvTotal;
TextView tvAmountReceived;
TextView tvStatus;
TextView tvReceiptCode;
ImageButton btnEdit;
ImageButton btnRemove;
}
public SalesArrayAdapter(#NonNull Context context, #NonNull ArrayList<SaleModel> sales) {
super(context, R.layout.row_sales, sales);
//this.getContext() = getContext();
//this.sales = sales;
}
#NonNull
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public View getView(final int position, View convertView, #NonNull ViewGroup parent) {
// Get the data item for this position
sale = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
// If there's no view to re-use, inflate a brand new view for row
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.row_sales, parent, false);
viewHolder.container = (RelativeLayout) convertView.findViewById(R.id.row_sales_ll_container);
viewHolder.tvId = (TextView) convertView.findViewById(R.id.row_sales_tv_id);
viewHolder.tvDate = (TextView) convertView.findViewById(R.id.row_sales_tv_date);
viewHolder.tvDriver = (TextView) convertView.findViewById(R.id.row_sales_tv_driver);
viewHolder.tvNoOfTrips = (TextView) convertView.findViewById(R.id.row_sales_tv_total_no_of_trips);
viewHolder.tvTotalExpenditure = (TextView) convertView.findViewById(R.id.row_sales_tv_total_expenditure);
viewHolder.tvTotal = (TextView) convertView.findViewById(R.id.row_sales_tv_total);
viewHolder.tvAmountReceived = (TextView) convertView.findViewById(R.id.row_sales_tv_amount_received);
viewHolder.tvStatus = (TextView) convertView.findViewById(R.id.row_sales_tv_status);
viewHolder.tvReceiptCode = (TextView) convertView.findViewById(R.id.row_sales_tv_receipt_code);
viewHolder.btnEdit = (ImageButton) convertView.findViewById(R.id.row_sales_btn_edit);
viewHolder.btnRemove = (ImageButton) convertView.findViewById(R.id.row_sales_btn_trash);
// Cache the viewHolder object inside the fresh view
convertView.setTag(viewHolder);
} else {
// View is being recycled, retrieve the viewHolder object from tag
viewHolder = (ViewHolder) convertView.getTag();
}
// Populate the data from the data object via the viewHolder object
// into the template view.
if (altColour == 0) {
viewHolder.container.setBackgroundColor(Color.parseColor("#FFFFFF"));
altColour = 1;
} else {
viewHolder.container.setBackgroundColor(Color.parseColor("#EFEFEF"));
altColour = 0;
}
viewHolder.tvId.setText(String.valueOf(sale.getId()));
viewHolder.tvDate.setText(sale.getDate());
viewHolder.tvDriver.setText(sale.getDriver());
double totalTripsAmount = 0;
for(int c = 0; c < sale.getTrips().length(); c++) {
try {
totalTripsAmount += sale.getTrips().getJSONObject(c).getDouble("trip_amount");
} catch (JSONException e) {
e.printStackTrace();
}
}
viewHolder.tvNoOfTrips.setText("GHS "+totalTripsAmount);
double totalExpenditureAmount = 0;
for(int c = 0; c < sale.getExpenditure().length(); c++) {
try {
totalExpenditureAmount += sale.getExpenditure().getJSONObject(c).getDouble("amount");
} catch (JSONException e) {
e.printStackTrace();
}
}
viewHolder.tvTotalExpenditure.setText("GHS "+totalExpenditureAmount);
viewHolder.tvTotal.setText("GHS "+sale.getTotal());
viewHolder.tvAmountReceived.setText("GHS "+sale.getAmountReceived());
viewHolder.tvStatus.setText(sale.getIsPending() == 1 ? "Pending" : "Complete");
viewHolder.tvReceiptCode.setText(sale.getReceiptCode());
viewHolder.btnEdit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent editSaleIntent = new Intent(getContext(), EditSaleActivity.class);
editSaleIntent.putExtra("sale", sale.toJson().toString());
((Activity) getContext()).startActivityForResult(editSaleIntent, 800);
}
});
viewHolder.btnRemove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = new Integer(getPosition(sale));
removeSale(pos);
}
});
// Return the completed view to render on screen
return convertView;
}
private void removeSale(final int position) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Confirm");
builder.setMessage("Are you sure you want to delete?");
builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//Log.i("btnYes", "works");
SalesRequest salesRequest = new SalesRequest(getContext());
remove(getItem(position));
notifyDataSetChanged();
salesRequest.remove(getItem(position).getId(), mTrashOnSuccessListener, mTrashOnErrorListener);
}
});
builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// Do nothing
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
private Response.Listener<JSONObject> mTrashOnSuccessListener = new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//
}
};
Response.ErrorListener mTrashOnErrorListener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Utils.showNetworkResponse(getContext(), error);
}
};
}
Now my issue is when I click the delete or edit button for any item being displayed it always picks the position or id of the last item being display in the listview.
For example if I wanted to delete the second item in the listview with a position of 1 it would pick the last item being displayed with a position of 10.
I've tried soo many things and made soo many changes but nothing has worked so far, this is my final code.
You can add a tag in a button. Tag the current position to the button when getView method is called every time. When the button is clicked get the tage of the button and it will return the updated value/position of the button. And do what you want to do with that current position in call back of that button click. Hope that helps
Adding more information
you have this line of code
viewHolder.btnEdit
this is the edit button . Now you should add a tag to this button using below code. You need to use below code after else clause of Viewholder object initialization.
viewHolder.btnEdit.setTag(position);
And in call back of onclick use below code
button.getTag()
Set the position of each ViewHolder object as a tag to the buttons and retrieve it using getTag() when they are clicked.
Something like this needs to be done:
viewHolder.btnEdit.setTag(position)
And inside onClick(), retrieve the position as viewHolder.btnEdit.getTag()
For using the viewHolder object inside onClick(), it must be declared final so you can copy the object as final ViewHolder finalHolder = viewHolder and do the above with finalHolder object
Try to set the tag for the buttons at each position in the following way, so that when ever a button is clicked you can get back the position using the tag.
#NonNull
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public View getView(final int position, View convertView, #NonNull ViewGroup parent) {
// Get the data item for this position
sale = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
// If there's no view to re-use, inflate a brand new view for row
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.row_sales, parent, false);
//Fetch other views here .....
viewHolder.btnEdit = (ImageButton) convertView.findViewById(R.id.row_sales_btn_edit);
viewHolder.btnRemove = (ImageButton) convertView.findViewById(R.id.row_sales_btn_trash);
// Cache the viewHolder object inside the fresh view
convertView.setTag(viewHolder);
} else {
// View is being recycled, retrieve the viewHolder object from tag
viewHolder = (ViewHolder) convertView.getTag();
}
//Setting the position as the tag for both buttons
viewHolder.btnRemove.setTag(position);
viewHolder.btnEdit.setTag(position);
Now in click listener..
viewHolder.btnRemove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Remove the below line
int pos = new Integer(getPosition(sale));
//Use this
int pos = (int)v.getTag();
removeSale(pos);
}
});
Hope, am helpful.
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (fileDataVo.isPdf()) {
Intent intent = new Intent(context, PdfActivity.class);
intent.putExtra("position", position);
context.startActivity(intent);
} else if (fileDataVo.isExcel()) {
Intent intent = new Intent(context, ExcelFileActivity.class);
intent.putExtra("position", position);
context.startActivity(intent);
}
else if (fileDataVo.isPpt()) {
Intent intent = new Intent(context, PptActivity.class);
intent.putExtra("position", position);
context.startActivity(intent);
}
}
I was wondering if somebody could further explain how to implement a delete button inside a listview that is populated from an SQLite database. I've read the responses to the following question that is essentially what I'm asking as well, but I don't understand it:
How can I implement a delete button in a ListView and delete from database?
In my custom row .xml file, I included a delete button that implements the method delete() onClick. It also includes an alert dialog, by the way. Here's the code that I have so far for my delete() method; whenever I try to use it, it never gets the right activtiy entry.
public void delete(View view){
final int position = listview.getPositionForView((View) view.getParent());
String id = cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_ID));
AlertDialog.Builder myDialog = new AlertDialog.Builder(MainActivity.this);
myDialog.setTitle("Delete activity entry \"" + id + "\"?");
myDialog.setPositiveButton("DELETE", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
mySQLiteAdapter.delete(position);
cursor.requery();
}
});
myDialog.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
}
});
myDialog.show();
}
A solution is to implement a custom ArrayAdapter.
public class MyArrayAdapter extends ArrayAdapter<YourObject>
{
private ArrayList<YourObject> items;
public LiftArrayAdapter(Context context, int textViewResourceId, ArrayList<YourObject> items)
{
super(context, textViewResourceId, items);
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
if (v == null)
{
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.your_view_xml, null);
}
final YourObject obj = items.get(position);
TextView lblLift = (TextView) v.findViewById(R.id.lbl_lift);
ImageButton btnDelete = (ImageButton) v.findViewById(R.id.btn_delete);
btnDelete .setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//TODO delete 'obj' from database
}
});
return v;
}
}
Then, to bind a list of objects to your listview:
List<YourObject> list = ...
MyArrayAdapter myArrayAdapter = new MyArrayAdapter (.., .. , list);
listView.setAdapter(myArrayAdapter);
I have another blocker as I study Android Development.
This time my problem is when I wanted to "selectively" highlight a row in a ListView populated by data from an adapter.
This ListView is actually within a dialog, and purpose is to show a list of friends, where user can multi-select and highlight it as he selects.
The selected values by the way, is stored in an ArrayList "arr_FriendsShare" so that the next time he opens the listview, rows will be highlighted (via onScrollListener) for those previously selected.
What is currently happening, only the "recently" or "last" clicked row/item is highlighted; and seems to be clearing all the previously highlighted rows.
I cannot understand why it is behaving that way, as row's value is successfully stored to/removed from arr_FriendsShare ArrayList, as I click on it.
Below is my listener codes, and thanks in advance for the usual help:
//Item click listener for Select Friends ListView
listview_SelectFriends.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> adapter, View v, int position,
long arg3)
{
String friends_ListItemSelected = (String)adapter.getItemAtPosition(position);
if(!arr_FriendsShare.contains(friends_ListItemSelected)){
arr_FriendsShare.add(friends_ListItemSelected);
}
else{
removeItemFromArrayListString(Main.this, arr_FriendsShare, friends_ListItemSelected);
}
}
});
listview_SelectFriends.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
for (int i = firstVisibleItem; i < (visibleItemCount + firstVisibleItem); i++) {
String listViewItemText = view.getItemAtPosition(i).toString();
if(arr_FriendsShare.contains(listViewItemText)){
ColorDrawable cd = new ColorDrawable(getResources().getColor(R.color.red_light));
view.setSelector(cd);
}
else if(arr_FriendsShare.contains(listViewItemText)){
ColorDrawable cd = new ColorDrawable(Color.TRANSPARENT);
view.setSelector(cd);
}
}
}
});
Additional Code Block:
ArrayList<String> stringArray = new ArrayList<String>();
String jsonURL = <SOME URL HERE>;
stringArray = Global.getStringArrayFromJSON(Main.this, jsonURL, "friends", "FriendUsername");
LayoutInflater inflater = getLayoutInflater();
View convertView = (View) inflater.inflate(R.layout.friends_list_layout, null);
ListView listview_SelectFriends = (ListView) convertView.findViewById(R.id.layout_Friends);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, stringArray);
listview_SelectFriends.setAdapter(adapter);
Change
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, stringArray);
to
// Define this at class level as --> private FriendsAdapter adapter = null;
adapter = new FriendsAdapter(Main.this, stringArray);
add this method in your activity
private void setResetSelection(int index, boolean setSelection){
View v = listview_SelectFriends.getChildAt(index);
if(v != null){
TextView name = (TextView) v.findViewById(R.id.name);
if(setSelection)
name.setBackgroundResource(R.color.red);
else
name.setBackgroundResource(R.color.transparent);
}
}
and create a new class as
public class FriendsAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList<String> mFriends;
private ArrayList<String> mSelectedFriends = new ArrayList<String>();
public GoodPeopleAdapter(Context context, ArrayList<String> friends) {
mInflater = LayoutInflater.from(context);
mFriends= friends;
}
public void setSelectedFriends(ArrayList<String> selectedFriends){
mSelectedFriends = selectedFriends;
}
#Override
public int getCount() {
return mFriends.size();
}
#Override
public Object getItem(int position) {
return mFriends.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
ViewHolder holder;
if(convertView == null) {
view = mInflater.inflate(R.layout.row_layout, parent, false);
holder = new ViewHolder();
holder.name = (TextView)view.findViewById(R.id.name);
view.setTag(holder);
} else {
view = convertView;
holder = (ViewHolder)view.getTag();
}
String name = mFriends.get(position);
holder.name.setText(name);
if(mSelectedFriends.contains(name))
holder.name.setBackgroundResource(R.color.red) // red is in color xml by default, change according to your choice
return view;
}
private class ViewHolder {
public TextView name;
}
}
Add following line at the end of method onItemClick
adapter.setSelectedFriends(arr_FriendsShare);
Add this in the if part of onItemClick
setResetSelection(position, true);
and this in else part
setResetSelection(position, false);
Also create a new xml layout with name row_layout with a textview with id name.
In my android application, I have a list in fragment using an adapter which extends ArrayAdapter. Whenever you hold a row item for long you can delete that row by clicking Yes on an alert-dialogue. But when you click Yes, last row seems to be deleted. When you close that fragment and come back on it then the view is fine with proper row deleted. After debugging for so many days I am unable to fix this.Can anyone please figure out whats wrong ?
Thanks in advance.
AdapterClass
public class DuasListAdapter extends ArrayAdapter<String> {
// class variables
private final Context context;// to save context
private final List<String> duas;// to save list of stores
LayoutInflater inflater;// so save layout inflater for the view
public DuasListAdapter(Context ctx, List<String> duasList) {
super(ctx, R.layout.adapter_list_duas, duasList);
context = ctx;// save context
duas = duasList;// save list of stores
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);// save inflater layout
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
// if view is not loaded
if (!(convertView instanceof View)) {
convertView = inflater.inflate(R.layout.adapter_list_duas, parent, false);
// load the view from holder class
holder = new ViewHolder(convertView);
// set the tag for future use
convertView.setTag(holder);
}
// if view is loaded
else
// get view from tag
holder = (ViewHolder) convertView.getTag();
holder.duaIndex = position;
convertView.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
final View view = v;
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
ViewHolder holder = (ViewHolder) view.getTag();
int index = holder.duaIndex;
((MainActivity) context).removeItemFromList(index);
Toast.makeText(view.getContext(), "Deleted", Toast.LENGTH_LONG).show();
break;
case DialogInterface.BUTTON_NEGATIVE:
// No button clicked
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("Delete Dua from Favorites?").setPositiveButton("Yes", dialogClickListener).setNegativeButton("No", dialogClickListener).show();
return false;
}
});
return convertView;
}
ListFragment
public void removeItemFromList(int index) {
String verses = new SharedPreferencesSupplication().read(SingletonClass.keyListOfVerses, "a1");
String[] versesList = verses.split(",");
String identifier = versesList[index];
new FavoriteDuas().removeDua(identifier);
updatedData();
}
#Override
public void onResume() {
lvDuaas.setAdapter(duasAdapter);
updatedData();
super.onResume();
}
#Override
public void onPause() {
// TODO Auto-generated method stub
lvDuaas.setAdapter(duasAdapter);
updatedData();
super.onPause();
}
public void updatedData() {
boolean keyIsFavSel = new SharedPreferencesSupplication().read(SingletonClass.keyIsFavSelected, false);
if (keyIsFavSel)
new SharedPreferencesSupplication().save(SingletonClass.keyListOfVerses, new SharedPreferencesSupplication().read(SingletonClass.keyFavVerses, "a1"));
String verses = new SharedPreferencesSupplication().read(SingletonClass.keyListOfVerses, "a1");
String[] versesList = verses.split(",");
ArrayList<String> duas = new ArrayList<String>();
for (int i = 0; i < versesList.length; i++) {
if (versesList[i].length() > 0)
duas.add(versesList[i]);
}
duasAdapter.clear();
if (duas.size() > 0) {
for (String object : duas) {
duasAdapter.insert(object, duasAdapter.getCount());
}
}
duasAdapter.notifyDataSetChanged();
}
Delete-Method
public void removeDua(String duaIdentifier) {
String verses = new SharedPreferencesSupplication().read(SingletonClass.keyFavVerses, "");
String[] versesList = verses.split(",");
int indexFound = -1;
for (int i = 0; i < versesList.length; i++) {
if (versesList[i].equals(duaIdentifier)) {
indexFound = i;
break;
}
}
if (indexFound >= 0) {
verses = "";
for (int i = 0; i < versesList.length; i++) {
if (indexFound != i) {
if (verses.isEmpty())
verses = versesList[i];
else
verses = verses + "," + versesList[i];
}
}
new SharedPreferencesSupplication().save(SingletonClass.keyFavVerses, verses);
}
}
You can try to re-instantiate the duasAdapter
duasAdapter = new DuasListAdapter(your_context_here, duas);
instead of
duasAdapter.clear();
if (duas.size() > 0) {
for (String object : duas) {
duasAdapter.insert(object, duasAdapter.getCount());
}
}
duasAdapter.notifyDataSetChanged();
You are using setOnLongClickListener() on your view, use setOnItemLongClickListener() instead.
I'm in an Android project.
I want to show a AlertDialog on which the user can pick one item (about 100 items, it's dynamic). I want to add the possibility of searching also.
My real problem is that it seems I can't change the items once the Dialog is created.
The creation code:
// The List with the beaches with radio buttons, single choice!
public void showBeachesDialog(final Activity context, boolean isFromZonas)
{
AlertDialog.Builder builder = new AlertDialog.Builder(context);
searchAdapter = new SearchDialogAdapater(orderedBeaches, orderedBeachesIds, context);
builder.setSingleChoiceItems(searchAdapter, -1, new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
index = which;
if (!((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE).isEnabled())
((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
}
});
DialogOkOnClickListener listener = new DialogOkOnClickListener(context, isFromZonas);
builder.setPositiveButton(R.string.searchOK, listener);
builder.setNegativeButton(R.string.cancelar, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
// User cancelled the dialog: nothing happens
}
});
builder.setIcon(context.getResources().getDrawable(R.drawable.icon_beach));
builder.setTitle(StaticUtils.DIALOG_TITLE);
View dialogView = context.getLayoutInflater().inflate(R.layout.dialog_beaches, null);
SearchView searchView = (SearchView)dialogView.findViewById(R.id.search_beach);
searchView.setOnQueryTextListener(new SearchQueryListener(searchAdapter));
builder.setView(dialogView);
AlertDialog dialog = builder.create();
dialog.show();
dialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
}
So, now I have the dialog with all the elements I want (the SearchDialogAdapater is fine).
The DialogOnClickListener is also working.
The search view is appearing on the dialog, and my SearchQueryListener is working perfectly, so I won't post here the code, but in Debug I can see that if I type "d" the elements without the "d" are filtered out.
Now I would like to not throw away all the code and find a way to change the items of the dialog without showing a new one...
Sorry for long question and if there is a obvious way I am missing...
Thank you all.
I solved this using a class that implements 4 interfaces so it can handles everything that I want.
The code is now like this, hope it's useful to someone who want to make its own Dialog with personalized search.
public void showBeachesDialog(final Activity context, boolean isFromZonas)
{
AlertDialog.Builder builder = new AlertDialog.Builder(context);
searchAdapter = new SearchDialogAdapater
(orderedBeaches, orderedBeachesIds, context, isFromZonas);
builder.setSingleChoiceItems(searchAdapter, -1, null);
builder.setPositiveButton(R.string.searchOK, searchAdapter);
builder.setNegativeButton(R.string.cancelar, null);
builder.setIcon(context.getResources().getDrawable(R.drawable.icon_beach));
builder.setTitle(StaticUtils.DIALOG_TITLE);
View dialogView = context.getLayoutInflater().inflate
(R.layout.dialog_beaches, null);
SearchView searchView = SearchView)dialogView.findViewById
(R.id.search_beach);
searchView.setOnQueryTextListener(searchAdapter);
builder.setView(dialogView);
AlertDialog dialog = builder.create();
dialog.show();
dialog.getListView().setOnItemClickListener(searchAdapter);
searchAdapter.setDialog(dialog);
dialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
}
The orderedBeaches and orderedBeachesIds are String[] and int[], my data to display.
Below is my adapter which uses a stack to handle the items available at any moment of the searching:
public class SearchDialogAdapater implements ListAdapter, OnQueryTextListener,
OnItemClickListener, OnClickListener {
protected Stack<String[]> stackBeaches;
protected Stack<int[]> stackBeachesIds;
protected Activity context;
protected TreeMap<String, Integer> orderedBeaches;
protected ListView listView;
protected String lastFilter = "";
public SearchDialogAdapater(String[] bs, int[] bIds, Activity cont) {
this.stackBeaches = new Stack<String[]>();
this.stackBeachesIds = new Stack<int[]>();
this.stackBeaches.push(bs);
this.stackBeachesIds.push(bIds);
this.context = cont;
}
#Override
public boolean onQueryTextChange(String newText) {
filter(newText);
this.listView.setAdapter(this);
return true;
}
public void filter(String search) {
// no longer valid the previous selected, must clean selections
selectedPosition = -1;
lastView = null;
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
// hitted "backspace"
if (search.length() < lastFilter.length()) {
if (stackBeaches.size() > 1) {
stackBeaches.pop();
stackBeachesIds.pop();
}
lastFilter = search;
return;
}
// filter
ArrayList<String> filtBs = new ArrayList<String>();
ArrayList<Integer> filtBsIds = new ArrayList<Integer>();
for (int i = 0; i < stackBeaches.peek().length; i++) {
String beach = new String(stackBeaches.peek()[i]);
if (Pattern
.compile(Pattern.quote(search), Pattern.CASE_INSENSITIVE)
.matcher(beach).find()) {
filtBs.add(beach);
filtBsIds.add(stackBeachesIds.peek()[i]);
}
}
String[] beaches = new String[filtBs.size()];
int[] ids = new int[filtBsIds.size()];
int size = filtBs.size();
for (int i = 0; i < size; i++) {
ids[i] = filtBsIds.remove(0);// head
beaches[i] = filtBs.remove(0);
}
stackBeachesIds.push(ids);
stackBeaches.push(beaches);
lastFilter = search;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
String beach = stackBeaches.peek()[position];
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.dialog_item, null);
TextView txtBeach = (TextView) convertView
.findViewById(R.id.dialBeach);
txtBeach.setText(beach);
}
if (position == selectedPosition)// the same color below
convertView.setBackgroundColor(Color.argb(128, 0, 64, 192));
return convertView;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return stackBeachesIds.peek()[position];
}
#Override
public int getCount() {
return stackBeaches.peek().length;
}
#Override
public boolean isEmpty() {
return stackBeaches.peek().length == 0;
}
private View lastView;
private int selectedPosition = -1;
#Override
public void onItemClick(AdapterView<?> adapterView, View view,
int position, long arg3) {
// some color...
view.setBackgroundColor(Color.argb(128, 133, 181, 255));
selectedPosition = position;
if (lastView != null)
lastView.setBackground(null);
lastView = view;
((SurfApplication) context.getApplication()).setBeachId(stackBeachesIds
.peek()[position]);
if (!dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled())
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
}
protected AlertDialog dialog;
public void setDialog(AlertDialog dial) {
this.dialog = dial;
this.listView = dialog.getListView();
}
#Override
public void onClick(DialogInterface dialog, int which) {
((ProgressBar) context.findViewById(R.id.pBar))
.setVisibility(ProgressBar.VISIBLE);
int beachId = stackBeachesIds.peek()[selectedPosition];
String beach = stackBeaches.peek()[selectedPosition];
// do something... Here I am creating a new Intent and starting
// the new activity within my context
}
}
Same methods are not here because they return null or do nothing at all.
Sorry for long post, but I need to answer this properly.
Thank you all and I hope someone find this useful.
Your adapter needs to implement Filterable or extend from an adapter class that does. Adapters that already implement this interface, like ArrayAdapter, should do the filtering automatically for you.
Just call Adapter.getFilter().filter(...); with the value from the search view.