1

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.

Rui Campião
  • 306
  • 1
  • 3
  • 10
  • perhaps you should create an activity itself which will be a dialog activity... check this link for more references:- http://stackoverflow.com/questions/1979369/android-activity-as-a-dialog – Atish Agrawal Feb 04 '14 at 17:47
  • Thank you for your opinion, but I really want to use a dialog and not an Activity, altough it seems to be harder... – Rui Campião Feb 06 '14 at 17:32

2 Answers2

2

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.

Rui Campião
  • 306
  • 1
  • 3
  • 10
1

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.

dominicoder
  • 9,338
  • 1
  • 26
  • 32