Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/197.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 微调器:当选定项保持不变时,未调用onItemSelected_Android_Spinner_Listener_Android Actionbar_Actionbarsherlock - Fatal编程技术网

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) {
                
            }
        });