package oak.demo.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Created by ericrichardson on 10/13/14.
*/
public class DefaultPromptSpinner extends Spinner {
public DefaultPromptSpinner(Context context) {
super(context);
}
public DefaultPromptSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DefaultPromptSpinner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setAdapter(SpinnerAdapter orig) {
final SpinnerAdapter adapter = newProxy(orig);
super.setAdapter(adapter);
try {
final Method m = AdapterView.class.getDeclaredMethod(
"setNextSelectedPositionInt", int.class);
m.setAccessible(true);
m.invoke(this, -1);
final Method n = AdapterView.class.getDeclaredMethod(
"setSelectedPositionInt", int.class);
n.setAccessible(true);
n.invoke(this, -1);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected SpinnerAdapter newProxy(SpinnerAdapter obj) {
return (SpinnerAdapter) java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
new Class[]{SpinnerAdapter.class},
new SpinnerAdapterProxy(obj));
}
/**
* Intercepts getView() to display the prompt if position < 0
*/
protected class SpinnerAdapterProxy implements InvocationHandler {
protected SpinnerAdapter obj;
protected Method getView;
protected SpinnerAdapterProxy(SpinnerAdapter obj) {
this.obj = obj;
try {
this.getView = SpinnerAdapter.class.getMethod(
"getView", int.class, View.class, ViewGroup.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
try {
return m.equals(getView) &&
(Integer) (args[0]) < 0 ?
getView((Integer) args[0], (View) args[1], (ViewGroup) args[2]) :
m.invoke(obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected View getView(int position, View convertView, ViewGroup parent)
throws IllegalAccessException {
if (position < 0) {
final TextView v =
(TextView) ((LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE)).inflate(
android.R.layout.simple_spinner_item, parent, false);
v.setText(getPrompt());
return v;
}
return obj.getView(position, convertView, parent);
}
}
}