Skip to content

Instantly share code, notes, and snippets.

@esabook
Last active January 19, 2020 09:09
Show Gist options
  • Save esabook/9490928cbeeb5ecb94848b4e7b09de04 to your computer and use it in GitHub Desktop.
Save esabook/9490928cbeeb5ecb94848b4e7b09de04 to your computer and use it in GitHub Desktop.
expand autocomplete pupup dialog to separated popup dialog
package ***;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StyleRes;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.SearchView;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import java.security.InvalidParameterException;
import java.util.concurrent.atomic.AtomicReference;
/**
* {@link SearchablePopupDialog} is separate dialog window for showing selectable list and {@link SearchView}.
* use {@see registerFromView} to auto calling this dialog when view touched {@see onTouch}
*
* example usage:
*
* <pre><code>
* new SearchablePopupDialog(getContext)
* .registerFromView(mAutoCompleteTextView, mStringAdapter);
*
* ...
*
* new SearchablePopupDialog(getContext)
* * .registerFromView(mSpinner, mSpinnerStringAdapter);
* </code></pre>
*/
public class SearchablePopupDialog extends Dialog
implements View.OnTouchListener,
View.OnFocusChangeListener,
SearchView.OnQueryTextListener,
AdapterView.OnItemClickListener, DialogInterface.OnShowListener {
private final static @StyleRes
int mTheme = R.style.AppTheme_PopupAlertDialog;
private final AtomicReference<EditText> mAttachedView = new AtomicReference<>();
private final AtomicReference<ArrayAdapter<String>> mAdapter = new AtomicReference<>();
private SearchView search;
private ListView listView;
private SwipeRefreshLayout refreshLayout;
public SearchablePopupDialog(View v) {
this(v.getContext());
}
public SearchablePopupDialog(@NonNull Context context) {
this(context, mTheme);
}
public SearchablePopupDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
init();
}
protected SearchablePopupDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
init();
}
/**
* define default configuration for layout, behavior
*/
void init() {
if (mAdapter.get() == null)
mAdapter.set(new ArrayAdapter<String>(getContext(), android.R.layout.simple_dropdown_item_1line));
setContentView(R.layout.dialog_dropdown);
search = findViewById(R.id.search);
listView = findViewById(R.id.list_item);
refreshLayout = findViewById(R.id.swipe_refresh);
refreshLayout.setEnabled(false);
setCancelable(true);
setCanceledOnTouchOutside(true);
setOnShowListener(this);
}
@Override
public void setOnShowListener(@Nullable OnShowListener listener) {
super.setOnShowListener(listener);
}
/**
* Open {@link SearchablePopupDialog} with {@link View}
*
* @param v
* @param adapter
*/
public void registerFromView(View v, ArrayAdapter<String> adapter) {
if (v instanceof EditText) {
v.setOnTouchListener(this);
mAttachedView.set((EditText) v);
mAdapter.set(adapter);
} else {
throw new InvalidParameterException("View is not instance of EditText");
}
}
/**
* Open {@link SearchablePopupDialog} with {@link Spinner}
*
* @param spinner
* @param adapter
*/
public void registerFromView(final Spinner spinner, final ArrayAdapter<String> adapter) {
spinner.setOnTouchListener(this);
mAdapter.set(adapter);
EditText editText = new EditText(spinner.getContext());
mAttachedView.set(editText);
editText.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) {
spinner.setSelection(adapter.getPosition(s.toString()));
}
});
try {
editText.setText(spinner.getSelectedItem().toString());
} catch (Exception ignore) {
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (!isShowing())
show();
return true;
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus)
show();
}
@Override
public boolean onQueryTextSubmit(String s) {
mAdapter.get().getFilter().filter(s);
return false;
}
@Override
public boolean onQueryTextChange(String s) {
mAdapter.get().getFilter().filter(s);
return false;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mAttachedView.get().setText(mAdapter.get().getItem(position));
dismiss();
}
/**
* reassign view configuration when dialog in showing
*
* @param dialog
*/
@Override
public void onShow(DialogInterface dialog) {
listView.setAdapter(mAdapter.get());
mAdapter.get().notifyDataSetChanged();
listView.setOnItemClickListener(this);
search.setOnQueryTextListener(this);
search.setQuery(mAttachedView.get().getText(), true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment