spinners and focus
I'm having a problem with spinners in a form activity.
I was expecting a spinner to gain focus when a user "touched" it but this does not seem to happen. A spinner only seems to gain focus if I use my tracker ball (on a Nexus One) to move between the different components.
This is annoying because I'm 开发者_StackOverflow中文版using the android:selectAllOnFocus="true" attribute on the first EditText view in the form. Because the spinners never take focus away from the EditText component its contents are always hi-lighted (which is ugly IMO).
I've tried using
spinner.requestFocus();
but this (seemingly) has no effect.
I've tried requesting focus on the spinner in a AdapterView.OnItemSelectedListener but his just results in
Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@44cb0380
Can anyone explain this odd behaviour and/or possible ways around it.
Many Thanks,
Tim
You have to use setFocusableInTouchMode()
first. Then you run into a different problem: you have to tap the spinner twice to change it (once to set focus, then again to see the list of options). My solution is to create my own Spinner subclass that causes the focus gain from the first tap to simulate the second:
class MySpinnerSubclass extends Spinner {
private final OnFocusChangeListener clickOnFocus = new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
// We don't want focusing the spinner with the d-pad to expand it in
// the future, so remove this listener until the next touch event.
setOnFocusChangeListener(null);
performClick();
}
};
// Add whatever constructor(s) you need. Call
// setFocusableInTouchMode(true) in them.
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
// Only register the listener if the spinner does not already have
// focus, otherwise tapping it would leave the listener attached.
if (!hasFocus()) {
setOnFocusChangeListener(clickOnFocus);
}
} else if (action == MotionEvent.ACTION_CANCEL) {
setOnFocusChangeListener(null);
}
return super.onTouchEvent(event);
}
}
To give proper credit, I got my inspiration from Kaptkaos's answer to this question.
精彩评论