选择 Spinner 时从 TextInputLayout 移除焦点
Remove focus from TextInputLayout when Spinner is selected
我有一个包含两个 TextInputLayouts 和一个 Spinner 的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="test.focustest.MainActivity">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="I don't like"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="My favourite"/>
</android.support.design.widget.TextInputLayout>
<Spinner
android:id="@+id/planets_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"></Spinner>
</LinearLayout>
这里是 activity 的代码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Spinner spinner = (Spinner) findViewById(R.id.planets_spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.planets_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
}
}
当我在两个 TextInputLayouts 之间切换时,焦点按预期工作:
这是它的样子,当第一个 EditText 被 selected:
这就是第二个 EditText selected 时的样子:
然而,当我 select 微调器时,最后一个 selected TextInputLayout 仍然聚焦:
我想在 Spinner 打开时从两个 TextInputLayouts 中移除焦点。有什么想法可以实现吗?
我在这个post的帮助下设法解决了这个问题:Link to post
我添加了一个自定义微调器,它会在微调器打开时通知我的 activity 清除焦点。这是代码:
public class CustomSpinner extends AppCompatSpinner {
public interface OnSpinnerEventsListener {
void onSpinnerOpened(AppCompatSpinner spinner);
void onSpinnerClosed(AppCompatSpinner spinner);
}
public CustomSpinner(Context context) {
super(context);
}
public CustomSpinner(Context context, int mode) {
super(context, mode);
}
public CustomSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode) {
super(context, attrs, defStyleAttr, mode);
}
public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode, Resources.Theme popupTheme) {
super(context, attrs, defStyleAttr, mode, popupTheme);
}
private OnSpinnerEventsListener mListener;
private boolean mOpenInitiated = false;
// implement the Spinner constructors that you need
@Override
public boolean performClick() {
// register that the Spinner was opened so we have a status
// indicator for when the container holding this Spinner may lose focus
mOpenInitiated = true;
if (mListener != null) {
mListener.onSpinnerOpened(this);
}
return super.performClick();
}
public void setSpinnerEventsListener(
OnSpinnerEventsListener onSpinnerEventsListener) {
mListener = onSpinnerEventsListener;
}
public void performClosedEvent() {
mOpenInitiated = false;
if (mListener != null) {
mListener.onSpinnerClosed(this);
}
}
public boolean hasBeenOpened() {
return mOpenInitiated;
}
public void onWindowFocusChanged (boolean hasFocus) {
if (hasBeenOpened() && hasFocus) {
performClosedEvent();
}
}
}
然后activity实现这个接口:
public class MainActivity extends AppCompatActivity implements CustomSpinner.OnSpinnerEventsListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final CustomSpinner spinner = (CustomSpinner) findViewById(R.id.planets_spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.planets_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
findViewById(R.id.root).clearFocus();
spinner.setSpinnerEventsListener(this);
}
@Override
public void onSpinnerOpened(AppCompatSpinner spinner) {
View view = this.getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
findViewById(R.id.root).clearFocus();
}
@Override
public void onSpinnerClosed(AppCompatSpinner spinner) {
}
}
我还为根LinearLayout添加了一个id:root。这样我就可以清除焦点了。
我有一个包含两个 TextInputLayouts 和一个 Spinner 的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="test.focustest.MainActivity">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="I don't like"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="My favourite"/>
</android.support.design.widget.TextInputLayout>
<Spinner
android:id="@+id/planets_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"></Spinner>
</LinearLayout>
这里是 activity 的代码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Spinner spinner = (Spinner) findViewById(R.id.planets_spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.planets_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
}
}
当我在两个 TextInputLayouts 之间切换时,焦点按预期工作: 这是它的样子,当第一个 EditText 被 selected:
这就是第二个 EditText selected 时的样子:
然而,当我 select 微调器时,最后一个 selected TextInputLayout 仍然聚焦:
我想在 Spinner 打开时从两个 TextInputLayouts 中移除焦点。有什么想法可以实现吗?
我在这个post的帮助下设法解决了这个问题:Link to post
我添加了一个自定义微调器,它会在微调器打开时通知我的 activity 清除焦点。这是代码:
public class CustomSpinner extends AppCompatSpinner {
public interface OnSpinnerEventsListener {
void onSpinnerOpened(AppCompatSpinner spinner);
void onSpinnerClosed(AppCompatSpinner spinner);
}
public CustomSpinner(Context context) {
super(context);
}
public CustomSpinner(Context context, int mode) {
super(context, mode);
}
public CustomSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode) {
super(context, attrs, defStyleAttr, mode);
}
public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr, int mode, Resources.Theme popupTheme) {
super(context, attrs, defStyleAttr, mode, popupTheme);
}
private OnSpinnerEventsListener mListener;
private boolean mOpenInitiated = false;
// implement the Spinner constructors that you need
@Override
public boolean performClick() {
// register that the Spinner was opened so we have a status
// indicator for when the container holding this Spinner may lose focus
mOpenInitiated = true;
if (mListener != null) {
mListener.onSpinnerOpened(this);
}
return super.performClick();
}
public void setSpinnerEventsListener(
OnSpinnerEventsListener onSpinnerEventsListener) {
mListener = onSpinnerEventsListener;
}
public void performClosedEvent() {
mOpenInitiated = false;
if (mListener != null) {
mListener.onSpinnerClosed(this);
}
}
public boolean hasBeenOpened() {
return mOpenInitiated;
}
public void onWindowFocusChanged (boolean hasFocus) {
if (hasBeenOpened() && hasFocus) {
performClosedEvent();
}
}
}
然后activity实现这个接口:
public class MainActivity extends AppCompatActivity implements CustomSpinner.OnSpinnerEventsListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final CustomSpinner spinner = (CustomSpinner) findViewById(R.id.planets_spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.planets_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
findViewById(R.id.root).clearFocus();
spinner.setSpinnerEventsListener(this);
}
@Override
public void onSpinnerOpened(AppCompatSpinner spinner) {
View view = this.getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
findViewById(R.id.root).clearFocus();
}
@Override
public void onSpinnerClosed(AppCompatSpinner spinner) {
}
}
我还为根LinearLayout添加了一个id:root。这样我就可以清除焦点了。