Android 微调器:当选定项保持不变时,未调用onItemSelected
对于我的Android 微调器:当选定项保持不变时,未调用onItemSelected,android,spinner,listener,android-actionbar,actionbarsherlock,Android,Spinner,Listener,Android Actionbar,Actionbarsherlock,对于我的微调器,我有一个OnItemSelectedListener,但当所选项目与上一个项目相同时,不会调用它。显然,OnClickListener不是微调器的选项。 我需要捕捉用户每次单击某个项目的时间。有什么想法吗 这个微调器位于操作栏内的事实可能会干扰正常行为 @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.tracklist
微调器
,我有一个OnItemSelectedListener
,但当所选项目与上一个项目相同时,不会调用它。显然,OnClickListener
不是微调器的选项。
我需要捕捉用户每次单击某个项目的时间。有什么想法吗
这个微调器
位于操作栏
内的事实可能会干扰正常行为
@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) {
}
});
}
@覆盖
创建选项菜单(菜单菜单,菜单充气机){
充气机。充气(右菜单。轨迹列表菜单,菜单);
微调器微调器=(微调器)菜单.findItem(R.id.option\u ordering\u微调器)
.getActionView();
spinner.setAdapter(mSpinnerAdapter);
spinner.setSelection(PrefsHelper.getOrderingSpinnerPos(prefs));
spinner.setOnItemSelectedListener(新的OnItemSelectedListener(){
@凌驾
已选择公共视图(AdapterView父视图、视图、,
内部位置,长id){
String str=“selected”;
系统输出打印项次(str);
如果(选项菜单已初始化){
开关(位置){
案例0:
//rdm
getActivity()
.发送广播(
新意图(
MyIntentAction.是否重新排列播放列表);
smp.setCurrentTracklistCursorPos(-1);
trackAdapter.notifyDataSetChanged();
打破
案例1:
//艺术家
getActivity()
.发送广播(
新意图(
我的意图。你要订购播放列表吗;
smp.setCurrentTracklistCursorPos(-1);
trackAdapter.notifyDataSetChanged();
打破
案例2:
//文件夹
getActivity()
.发送广播(
新意图(
MyIntentAction.DO_ORDER_PLAYLIST_BY_FOLDER));
smp.setCurrentTracklistCursorPos(-1);
trackAdapter.notifyDataSetChanged();
打破
}
PrefsHelper.setOrderingSpinnerPos(prefEditor,位置);
提交();
}
optionMenuInitialized=true;
}
@凌驾
未选择公共无效(AdapterView父级){
}
});
}
好的,通过创建自己的类扩展微调器,我终于找到了解决方案:
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;
}
}
若它仍然是实际的,那个么正确的回调调用应该是
@Override
public void setSelection(int position) {
super.setSelection(position);
if(listener != null)
listener.onItemSelected(this, getChildAt(position), position, 0);
}
马丁我发现了这件作品而不是提供的那件
/** 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());
}
}
}
最简单的解决方案:
spinner.performItemClick(视图、位置、id)这里有一个更好的实现:
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;
}
}
要使微调器在上一个选定索引的值不变的情况下进行更改,只需使用:
spinner.setSelection(0);
在调用其他选择之前
spinner.setSelection(number);
这样,微调器将触发两次选定事件。只要确保第二次它执行您需要的任何操作。我也遇到了同样的问题,我通过在每次适配器更改项目时设置onItemSelectedListener来解决它。重写了常见的解决方案,但使用了:
心中的安卓
扩展自AppCompatSpinner
使用内置的OnItemSelectedListener
监听器,而不是创建自己的监听器
添加了初始侦听器调用hack
在这里:
我找到了一个简单的解决办法
只需再次调用setAdapter,而不是为第二个微调器调用notifyDataSetChanged-
自定义微调器类-
import android.content.Context;
import android.util.AttributeSet;
import androidx.appcompat.widget.AppCompatSpinner;
public class CSpinner extends AppCompatSpinner {
private int lastPosition = 0;
public CSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setSelection(int position) {
super.setSelection(position);
boolean sameSelected = lastPosition == getSelectedItemPosition();
OnItemSelectedListener onItemSelectedListener = getOnItemSelectedListener();
if (sameSelected && onItemSelectedListener != null) {
onItemSelectedListener.onItemSelected(this, getSelectedView(), position, getSelectedItemId());
}
lastPosition = position;
}
}
设置侦听器-
spn.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.d("onItemSelected", String.valueOf(position));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spn.setOnItemSelectedListener(新的AdapterView.OnItemSelectedListener(){
@凌驾
已选择公共视图(AdapterView父视图、视图视图、整型位置、长id){
Log.d(“onItemSelected”,String.valueOf(position));
}
@凌驾
未选择公共无效(AdapterView父级){
}
});
你读过这篇文章吗是的,但那没有帮助。。。无论如何,我刚刚找到了解决方案,并准备在这里写下=)这不相关,但将微调器可见性设置为VIEW.GONE也会导致此问题。您能否分享一些想法,了解如何实现ActionBar导航列表的相同功能?@benoffi7您的答案在哪里?@dhams抱歉,我的答案出错,我将其删除。@elgui此行侦听器.onItemSelected(null,null,position,0);给我一个NPE,你能告诉我怎样才能让AdapterView&View通过上面这一行吗。ThanksHow我是否在listener.onItemSelected(null,null,position,0)中获取父对象和视图;?这不是正确的回调。首先,您应该使用getItemIdAtPosition(position)
作为最后一个参数,第二个getChildAt(position)
不应该在这种情况下使用Spinner
s使用View
recycling就像ListView
s一样,因此不能使用getChildAt
从适配器中检索位置项。获取正确ID的最后一个参数是正确的。但要获取视图,可以使用getChildAt(),因为我们要么获得正确的视图(如果存在),要么获得空视图(如果不存在)。在大多数情况下,当单击某个项时会调用该代码,因此在微调器中可见,因此getChildAt()返回正确的视图。至少我从未遇到过返回错误视图的情况。不,你不正确。例如,微调器有100个项目,最后一个项目被单击。但只有10个是可见的。在这种情况下,getChildAt()
将始终返回带有99个位置的null,因为它没有100个子视图。您不能依赖于getC
spn.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.d("onItemSelected", String.valueOf(position));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});