Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.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 微调器:如何知道项目选择是以编程方式更改的,还是通过用户界面的用户操作更改的_Android - Fatal编程技术网

Android 微调器:如何知道项目选择是以编程方式更改的,还是通过用户界面的用户操作更改的

Android 微调器:如何知道项目选择是以编程方式更改的,还是通过用户界面的用户操作更改的,android,Android,我有运行微调器事件的代码。因此,当我采用这种方法时: public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) { // I want to do something here if it's a user who changed the the selected item } 已选择公共视图(AdapterView父视图、View

我有运行微调器事件的代码。因此,当我采用这种方法时:

public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
    // I want to do something here if it's a user who changed the the selected item
}
已选择公共视图(AdapterView父视图、View selectedItemView、int位置、长id){ //如果是用户更改了所选项目的名称,我想在此执行一些操作 }
…我如何知道项目选择是通过编程方式还是通过用户界面的用户操作完成的?

我不知道这与方法中的操作有什么区别。事实上,这是很多人都面临的一个问题,当旋转器启动时,
onItemSelected
被触发。目前,唯一的解决办法似乎是为此使用外部变量

private Boolean isUserAction = false;

...

public void onItemSelected( ... ) {

    if( isUserAction ) {
       // code for user initiated selection
    } else {
       // code for programmatic selection
       // also triggers on init (hence the default false)
    }

    // reset variable, so that it will always be true unless tampered with
    isUserAction = true;
}

public void myButtonClick( ... ) {
    isUserAction = false;
    mySpinner.setSelectedItem ( ... );
}

我知道这已经晚了,但我刚刚开始使用android,面对这个问题,我找到了一个合适的解决办法

我使用了一种基于可聚焦触摸模式场景的解决方案

  • 将微调器视图设置为可在触摸模式下聚焦

  • 设置微调器的聚焦更改侦听器,以便在聚焦时调用spinner.performClick()

  • 在微调器的onItemSelected侦听器中,将焦点返回到布局的父视图(或您认为合适的视图)

  • 可以通过检查微调器是否具有焦点来识别用户输入,因为编程更改不会请求焦点


  • PS:在onCreate中为微调器设置focusableintouchmode时,请确保立即将焦点返回到父视图,以防缺少任何其他可聚焦视图。

    我想出了一个简单通用的解决方法。请参阅此问题的公认答案:


    因此,如果
    position
    不等于
    spin.getTag(R.id.pos)
    ,则您知道回调是由于用户进行了更改,因为每当您自己进行更改时,您都将标记设置为
    spin.setTag(R.id.pos,pos)
    ,其中pos是您设置的值。如果使用这种方法,请确保在完成工作后在
    onItemSelected
    中设置标记

    SeekBar
    a
    Spinner
    不同,a
    Spinner没有检测更改是编程的还是由用户进行的内置支持,因此我建议不要将Spinner用于任何类型的递归编程任务。当我尝试使用到
    SeekBar
    Spinner
    的递归连接实现
    MediaPlayer
    时,我的体验非常糟糕。结果令人失望。所以,只有当你喜欢不快乐和失望时,你才能尝试

    注: 我通过在微调器选择中添加应用
    按钮
    解决了问题。
    不要把我们的时间浪费在解决不必要的事情上。我的意思是做变通并不是一个好的实践,而是重新实现
    微调器来拥有我们自己的预期行为


    如果上述陈述是错误的,我真的很抱歉。我之所以分享这个,是因为我喜欢编码器和编码。

    我创建了一个新的Spinner类,封装了上述原则。但即使这样,您也必须确保调用正确的方法,而不是
    setSelection

    同样的事情

    导入android.content.Context;
    导入android.util.AttributeSet;
    导入android.view.view;
    导入android.widget.AdapterView;
    /**
    *用于区分用户选择和程序选择
    *调用{@link Spinner#programmaticallySetPosition}以使用此功能。
    *由vedant于2015年6月1日创建。
    */
    公共类微调器扩展了android.widget.Spinner,实现了AdapterView.OnItemSelectedListener{
    OnItemSelectedListenerMListener;
    /**
    *用于确定用户是否在微调器上选择了项目(而不是以编程方式)
    */
    私有布尔值museRactionOnInspinner=true;
    @凌驾
    已选择公共视图(AdapterView父视图、视图视图、整型位置、长id){
    if(mListener!=null){
    mListener.onItemSelected(父对象、视图、位置、id、MuseRactionOnInspect);
    }
    //重置变量,使其始终为真,除非被篡改
    museActionnspinner=true;
    }
    @凌驾
    未选择公共无效(AdapterView父级){
    if(mListener!=null)
    无选择的mListener.onNothingSelected(母公司);
    }
    公共接口OnItemSelectedListener{
    /**
    *当此视图中的项已被删除时调用的回调方法
    *已选择。仅当新选择的
    *位置与先前选择的位置不同,或者
    *没有选定的项目

    * *如果需要访问,推动器可以调用getItemAtPosition(position) *与所选项目关联的数据。 * *@param parent发生选择的AdapterView *@param view单击的AdapterView中的视图 *@param position视图在适配器中的位置 *@param id所选项目的行id */ void onItemSelected(AdapterView父对象、视图、int位置、长id、布尔用户选择); /** *当选择从此列表中消失时要调用的回调方法 *视图。例如,当触摸被激活时,选择可能会消失 *或者当适配器变空时。 * *@param parent当前不包含选定项的AdapterView。 */ 无选择无效(AdapterView父项); } public void programmaticallySetPosition(int-pos,布尔动画){ museActionnspinner=false; 设置选择(位置、动画); } public void setOnItemSelectedListener(OnItemSelectedListener侦听器){ mListener=监听器; } 公共微调器(上下文){ 啜饮
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.View;
    import android.widget.AdapterView;
    
    /**
     * Used this to differentiate between user selected and prorammatically selected
     * Call {@link Spinner#programmaticallySetPosition} to use this feature.
     * Created by vedant on 6/1/15.
     */
    public class Spinner extends android.widget.Spinner implements AdapterView.OnItemSelectedListener {
    
        OnItemSelectedListener mListener;
    
        /**
         * used to ascertain whether the user selected an item on spinner (and not programmatically)
         */
        private boolean mUserActionOnSpinner = true;
    
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    
            if (mListener != null) {
    
                mListener.onItemSelected(parent, view, position, id, mUserActionOnSpinner);
            }
            // reset variable, so that it will always be true unless tampered with
            mUserActionOnSpinner = true;
        }
    
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            if (mListener != null)
                mListener.onNothingSelected(parent);
        }
    
        public interface OnItemSelectedListener {
            /**
             * <p>Callback method to be invoked when an item in this view has been
             * selected. This callback is invoked only when the newly selected
             * position is different from the previously selected position or if
             * there was no selected item.</p>
             *
             * Impelmenters can call getItemAtPosition(position) if they need to access the
             * data associated with the selected item.
             *
             * @param parent The AdapterView where the selection happened
             * @param view The view within the AdapterView that was clicked
             * @param position The position of the view in the adapter
             * @param id The row id of the item that is selected
             */
            void onItemSelected(AdapterView<?> parent, View view, int position, long id, boolean userSelected);
    
            /**
             * Callback method to be invoked when the selection disappears from this
             * view. The selection can disappear for instance when touch is activated
             * or when the adapter becomes empty.
             *
             * @param parent The AdapterView that now contains no selected item.
             */
            void onNothingSelected(AdapterView<?> parent);
        }
    
        public void programmaticallySetPosition(int pos, boolean animate) {
            mUserActionOnSpinner = false;
            setSelection(pos, animate);
        }
    
        public void setOnItemSelectedListener (OnItemSelectedListener listener) {
            mListener = listener;
        }
    
        public Spinner(Context context) {
            super(context);
            super.setOnItemSelectedListener(this);
        }
    
        public Spinner(Context context, int mode) {
            super(context, mode);
            super.setOnItemSelectedListener(this);
        }
    
        public Spinner(Context context, AttributeSet attrs) {
            super(context, attrs);
            super.setOnItemSelectedListener(this);
        }
    
        public Spinner(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            super.setOnItemSelectedListener(this);
        }
    
        public Spinner(Context context, AttributeSet attrs, int defStyle, int mode) {
            super(context, attrs, defStyle, mode);
            super.setOnItemSelectedListener(this);
        }
    }
    
    // Instance variables
    boolean spinnerTouched = false;
    Spinner spinner;
    
    // onCreate() / onCreateView() / etc. method..
    spinner = ...;
    spinner.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
    
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                spinnerTouched = true; // User DID touched the spinner!
            }
    
            return false;
        }
    });
    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
    
            if (spinnerTouched) {
                // Do something
            }
            else {
                // Do something else
            }
    
        }
    
        @Override
        public void onNothingSelected(AdapterView<?> parentView) {
        }
    });
    
    // Your method that you use the change the spinner selection programmatically...
    private void changeSpinnerSelectionProgrammatically(int pos) {
        stateSpinnerTouched = false; // User DIDN'T touch the spinner
        boolean useAnimation = false;
        spinner.setSelection(pos, useAnimation); // Calls onItemSelected()
    }