A dialog that allows the user to select multiple entries.
/**
* Copyright (C) 2010 Christian Meyer
* This file is part of Drupal Editor.
*
* Drupal Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Drupal Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Drupal Editor. If not, see <http://www.gnu.org/licenses/>.
*/
//package ch.dissem.android.utils;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
/**
* {@link BaseAdapter}-Implementation for the {@link MultiChoice} Dialog.
*
* @author christian
* @param <T>
* Type this Adapter contains. Should have some useful toString()
* implementation.
*/
class MultiChoiceListAdapter<T> extends BaseAdapter {
private Context ctx;
private Collection<T> options;
private Collection<T> selection;
private List<T> filteredOptions;
public MultiChoiceListAdapter(Context context, Collection<T> options,
Collection<T> selection) {
this.ctx = context;
this.options = options;
this.selection = selection;
this.filteredOptions = new ArrayList<T>(options.size());
setFilter(null);
}
@Override
public int getCount() {
return filteredOptions.size();
}
@Override
public T getItem(int position) {
return filteredOptions.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ChoiceView view;
T item = getItem(position);
boolean selected = selection.contains(item);
if (convertView == null) {
view = new ChoiceView(ctx, item, selected);
} else {
view = (ChoiceView) convertView;
view.setItem(item, selected);
}
return view;
}
public void setFilter(String filter) {
if (filter != null)
filter = filter.toLowerCase();
filteredOptions.clear();
for (T item : selection)
filteredOptions.add(item);
for (T item : options)
if (!selection.contains(item)
&& (filter == null || item.toString().toLowerCase()
.contains(filter)))
filteredOptions.add(item);
}
public class ChoiceView extends CheckBox implements OnCheckedChangeListener {
private T object;
public ChoiceView(Context context, T object, Boolean selected) {
super(context);
this.object = object;
setOnCheckedChangeListener(this);
setItem(object, selected);
}
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (selection != null) {
if (isChecked && !selection.contains(object))
selection.add(object);
else if (!isChecked)
selection.remove(object);
}
notifyDataSetChanged();
}
public void setItem(T object, Boolean selected) {
this.object = object;
setChecked(selected);
setText(object.toString());
}
}
}
/**
* A dialog that allows the user to select multiple entries.
*
* @author christian
* @param <T>
* Type for this dialog. Should have some useful toString()
* implementation.
*/
class MultiChoice<T> extends Dialog {
private ListView listView;
private Map<T, Boolean> optionsWithSelection;
private Collection<T> options;
private Collection<T> selection;
public MultiChoice(Context context, Collection<T> options,
Collection<T> selection) {
super(context);
this.options = options;
this.selection = selection;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context ctx = getContext();
LinearLayout layout = new LinearLayout(ctx);
layout.setOrientation(LinearLayout.VERTICAL);
listView = new ListView(ctx);
final MultiChoiceListAdapter<T> adapter;
adapter = new MultiChoiceListAdapter<T>(ctx, options, selection);
listView.setAdapter(adapter);
if (options.size() > 10) {
EditText search = new EditText(ctx);
search.setInputType(InputType.TYPE_TEXT_VARIATION_FILTER);
search.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
adapter.setFilter(s.toString());
adapter.notifyDataSetChanged();
}
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
layout.addView(search);
}
layout.addView(listView);
setContentView(layout);
}
public Map<T, Boolean> getOptionsMap() {
return optionsWithSelection;
}
public Set<T> getSelection() {
Set<T> result = new LinkedHashSet<T>();
for (Entry<T, Boolean> e : optionsWithSelection.entrySet())
if (Boolean.TRUE.equals(e.getValue()))
result.add(e.getKey());
return result;
}
}
Related examples in the same category