Android Spinner :当所选项目保持不变时不调用 onItemSelected
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10854329/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spinner : onItemSelected not called when selected item remains the same
提问by elgui
I have a OnItemSelectedListener
for my Spinner
, but it is not called when the selected item is the same as the previous one. Apparently the OnClickListener
is not an option for a Spinner
.
I need to catch everytime a user click on an item. Any idea?
我有一个OnItemSelectedListener
for my Spinner
,但是当所选项目与前一个项目相同时不会调用它。显然OnClickListener
不是Spinner
. 每次用户点击一个项目时,我都需要捕捉。任何的想法?
Maybe the fact that this Spinner
is inside the ActionBar
disturbs normal behavior?
也许这Spinner
是内部ActionBar
干扰正常行为的事实?
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.tracklist_menu, menu);
Spinner spinner = (Spinner) menu.findItem(R.id.option_ordering_spinner)
.getActionView();
spinner.setAdapter(mSpinnerAdapter);
spinner.setSelection(PrefsHelper.getOrderingSpinnerPos(prefs));
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
String str = "selected";
System.out.println(str);
if (optionMenuInitialized) {
switch (position) {
case 0:
// rdm
getActivity()
.sendBroadcast(
new Intent(
MyIntentAction.DO_RESHUFFLE_PLAYLIST));
smp.setCurrentTracklistCursorPos(-1);
trackAdapter.notifyDataSetChanged();
break;
case 1:
// artist
getActivity()
.sendBroadcast(
new Intent(
MyIntentAction.DO_ORDER_PLAYLIST_BY_ARTIST));
smp.setCurrentTracklistCursorPos(-1);
trackAdapter.notifyDataSetChanged();
break;
case 2:
// folder
getActivity()
.sendBroadcast(
new Intent(
MyIntentAction.DO_ORDER_PLAYLIST_BY_FOLDER));
smp.setCurrentTracklistCursorPos(-1);
trackAdapter.notifyDataSetChanged();
break;
}
PrefsHelper.setOrderingSpinnerPos(prefEditor, position);
prefEditor.commit();
}
optionMenuInitialized = true;
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
回答by elgui
Ok, I finally found a solution, by creating my own class extending Spinner :
好的,我终于找到了一个解决方案,通过创建我自己的扩展 Spinner 的类:
public class MySpinner extends Spinner {
OnItemSelectedListener listener;
public MySpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setSelection(int position) {
super.setSelection(position);
if (listener != null)
listener.onItemSelected(null, null, position, 0);
}
public void setOnItemSelectedEvenIfUnchangedListener(
OnItemSelectedListener listener) {
this.listener = listener;
}
}
回答by Eric Leong Zhia Choong
I found out this work instead of the one provided
我发现了这项工作而不是提供的工作
/** Spinner extension that calls onItemSelected even when the selection is the same as its previous value */
public class NDSpinner extends Spinner {
public NDSpinner(Context context)
{ super(context); }
public NDSpinner(Context context, AttributeSet attrs)
{ super(context, attrs); }
public NDSpinner(Context context, AttributeSet attrs, int defStyle)
{ super(context, attrs, defStyle); }
@Override public void
setSelection(int position, boolean animate)
{
boolean sameSelected = position == getSelectedItemPosition();
super.setSelection(position, animate);
if (sameSelected) {
// Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
}
}
@Override public void
setSelection(int position)
{
boolean sameSelected = position == getSelectedItemPosition();
super.setSelection(position);
if (sameSelected) {
// Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
}
}
}
回答by Alecs
Here a little better implementation:
这里有一个更好的实现:
public class SpinnerPlus extends Spinner {
AdapterView.OnItemSelectedListener listener;
public SpinnerPlus(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setSelection(int position) {
super.setSelection(position);
if (listener != null)
listener.onItemSelected(this, getSelectedView(), position, 0);
}
public void setOnItemSelectedEvenIfUnchangedListener(
AdapterView.OnItemSelectedListener listener) {
this.listener = listener;
}
}
回答by Ramiro G.M.
To make your spinner change despite the value of the last index selected just use a:
尽管选择了最后一个索引的值,但要使您的微调器更改,只需使用:
spinner.setSelection(0);
before your other selection is called
在调用您的其他选择之前
spinner.setSelection(number);
this way, the spinner will trigger two times the OnItemSelectedevent. Just make sure the second time it does whatever you need.
这样,微调器将触发两次OnItemSelected事件。只要确保第二次它做你需要的任何事情。
回答by soshial
Rewrote the common solution but with:
重写了通用解决方案,但使用:
- androidx in mind
- extended from
AppCompatSpinner
- use built-in
OnItemSelectedListener
listener instead of creating own one - added initial listener call hack
- androidx 记住了
- 延伸自
AppCompatSpinner
- 使用内置
OnItemSelectedListener
监听器而不是创建自己的监听器 - 添加了初始侦听器调用 hack
Here:
这里:
import android.content.Context;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatSpinner;
public class FixedSpinner extends AppCompatSpinner {
// add other constructors that you need
public FixedSpinner(Context context, int mode) {
super(context, mode);
}
private void processSelection(int position) {
boolean sameSelected = position == getSelectedItemPosition();
final OnItemSelectedListener listener = getOnItemSelectedListener();
if (sameSelected && listener != null) {
// Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
listener.onItemSelected(this, getSelectedView(), position, getSelectedItemId());
}
}
@Override
public void setSelection(int position) {
processSelection(position);
super.setSelection(position);
}
@Override
public void setSelection(int position, boolean animate) {
processSelection(position);
super.setSelection(position, animate);
}
@Override
public void setOnItemSelectedListener(@Nullable OnItemSelectedListener listener) {
// This hack fixes bug, when immediately after initialization, listener is called
// To make this fix work, first add data, only then set listener
// Having done this, you may refresh adapter data as many times as you want
setSelection(0, false);
super.setOnItemSelectedListener(listener);
}
}
回答by Martin Edlman
If it's still actual, correct call of the callback should be
如果它仍然是实际的,则回调的正确调用应该是
@Override
public void setSelection(int position) {
super.setSelection(position);
if(listener != null)
listener.onItemSelected(this, getChildAt(position), position, 0);
}
Martin
马丁
回答by Nishant Shah
Simplest solution :
最简单的解决方案:
spinner.performItemClick(view,position,id)
spinner.performItemClick(view,position,id)
回答by Marek Kondracki
I had same problem, I solved it by setting onItemSelectedListener every time adapter changes items.
我遇到了同样的问题,我通过在每次适配器更改项目时设置 onItemSelectedListener 来解决它。
回答by Abhishek Vishwakarma
i found a simple solution
我找到了一个简单的解决方案
just call setAdapter again in place of notifyDataSetChanged for the second spinner
只需再次调用 setAdapter 代替第二个微调器的 notifyDataSetChanged