package net.mvla.mvhs.widget;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.ResultReceiver;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.RelativeLayout;
import android.widget.TextView;
import net.mvla.mvhs.R;
import java.lang.reflect.Method;
/**
* SearchView - based on SearchView in appcompat-v7 library's action bar widget
*/
public class SearchView extends RelativeLayout {
static final Reflector HIDDEN_METHOD_INVOKER = new Reflector();
/*
* SearchView can be set expanded before the IME is ready to be shown during
* initial UI setup. The show operation is asynchronous to account for this.
*/
private Runnable mShowImeRunnable = new Runnable() {
public void run() {
InputMethodManager imm = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
HIDDEN_METHOD_INVOKER.showSoftInputUnchecked(imm, SearchView.this, 0);
}
}
};
private DrawerArrowView mDrawerArrowView;
private SearchboxEditText mSearchboxEditText;
private SearchViewCallback mSearchViewCallback;
public SearchView(Context context) {
this(context, null);
}
public SearchView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SearchView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.searchview, this, true);
mSearchboxEditText = (SearchboxEditText) findViewById(R.id.searchbox_edittext);
mSearchboxEditText.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) {
if (mSearchViewCallback != null) {
mSearchViewCallback.onQueryTextChange(s.toString());
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
mSearchboxEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
clearFocus();
}
return false;
}
});
mSearchboxEditText.setCallback(new SearchboxEditText.Callback() {
@Override
public boolean onKeyBackPreIme(KeyEvent event) {
// special case for the back key, we do not even try to send it
// to the drop down list but instead, consume it immediately
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
KeyEvent.DispatcherState state = getKeyDispatcherState();
if (state != null) {
state.startTracking(event, this);
}
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
KeyEvent.DispatcherState state = getKeyDispatcherState();
if (state != null) {
state.handleUpEvent(event);
}
if (event.isTracking() && !event.isCanceled()) {
clearFocus();
return true;
}
}
return false;
}
});
mDrawerArrowView = (DrawerArrowView) findViewById(R.id.searchbox_menu_button);
mDrawerArrowView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mSearchViewCallback != null) {
mSearchViewCallback.onDrawerIconClicked();
}
}
});
setBackgroundResource(R.drawable.searchbox_bg);
setFocusableInTouchMode(true);
mSearchboxEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (mSearchViewCallback != null) {
mSearchViewCallback.onFocusChange(hasFocus);
}
setImeVisibility(hasFocus);
}
});
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasure = MeasureSpec.makeMeasureSpec(getResources().getDimensionPixelSize(R.dimen.searchbox_height), MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasure);
}
@Override
public void clearFocus() {
setImeVisibility(false);
super.clearFocus();
mSearchboxEditText.clearFocus();
}
public void setDrawerIconVisibility(boolean show, boolean animate) {
float editTextTarget = show ? 0f : getResources().getDimensionPixelSize(R.dimen.searchbox_no_menu_offset);
if (animate) {
ObjectAnimator animator = new ObjectAnimator();
animator.setTarget(mSearchboxEditText);
animator.setProperty(TRANSLATION_X);
animator.setFloatValues(editTextTarget);
animator.setDuration(250);
animator.setInterpolator(new FastOutSlowInInterpolator());
animator.start();
ObjectAnimator animator2 = new ObjectAnimator();
animator2.setTarget(mDrawerArrowView);
animator2.setDuration(150);
if (show) animator2.setStartDelay(100);
animator2.setProperty(SCALE_X);
animator2.setFloatValues(show ? 1f : 0f);
animator2.setInterpolator(new FastOutSlowInInterpolator());
animator2.start();
ObjectAnimator animator3 = new ObjectAnimator();
animator3.setTarget(mDrawerArrowView);
animator3.setDuration(150);
if (show) animator3.setStartDelay(100);
animator3.setProperty(SCALE_Y);
animator3.setFloatValues(show ? 1f : 0f);
animator3.setInterpolator(new FastOutSlowInInterpolator());
animator3.start();
} else {
mSearchboxEditText.setTranslationX(editTextTarget);
mDrawerArrowView.setScaleX(show ? 1f : 0f);
mDrawerArrowView.setScaleY(show ? 1f : 0f);
}
}
public void setCallback(SearchViewCallback listener) {
mSearchViewCallback = listener;
}
public void focus() {
mSearchboxEditText.requestFocus();
}
private void setImeVisibility(final boolean visible) {
if (visible) {
post(mShowImeRunnable);
} else {
removeCallbacks(mShowImeRunnable);
InputMethodManager imm = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
}
}
public void clearText() {
mSearchboxEditText.setText("");
}
public void setDrawerIconState(boolean burger, boolean animate) {
mDrawerArrowView.setState(burger, animate);
}
public interface SearchViewCallback {
// boolean onQueryTextSubmit(String query);
void onQueryTextChange(String newText);
void onFocusChange(boolean focused);
void onDrawerIconClicked();
}
private static class Reflector {
private Method showSoftInputUnchecked;
Reflector() {
try {
showSoftInputUnchecked = InputMethodManager.class.getMethod(
"showSoftInputUnchecked", int.class, ResultReceiver.class);
showSoftInputUnchecked.setAccessible(true);
} catch (NoSuchMethodException e) {
// Ah well.
}
}
void showSoftInputUnchecked(InputMethodManager imm, View view, int flags) {
if (showSoftInputUnchecked != null) {
try {
showSoftInputUnchecked.invoke(imm, flags, null);
return;
} catch (Exception ignored) {
}
}
// Hidden method failed, call public version instead
imm.showSoftInput(view, flags);
}
}
}