programing

Android Spinner : 아이템 회피초기화 중에 선택한 호출

css3 2023. 9. 27. 18:07

Android Spinner : 아이템 회피초기화 중에 선택한 호출

.Spinner그리고.TextViewTextView()의 Spinner) 텍스트 보기의 스피너 드롭다운 목록에서 선택한 항목을 표시합니다.했습니다.onCreate하면 method때합니다에 이 표시됩니다.TextView(드롭다운 목록에서 항목을 선택하기 전에).

드롭다운 목록에서 항목을 선택한 후에만 텍스트 보기에 값을 표시하고 싶습니다.이거 어떻게 해요?

여기 내 코드가 있습니다.

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;

public class GPACal01Activity extends Activity implements OnItemSelectedListener {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Spinner spinner = (Spinner) findViewById(R.id.noOfSubjects);

        // Create an ArrayAdapter using the string array and a default spinner layout
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,R.array.noofsubjects_array, android.R.layout.simple_spinner_item);
        // Specify the layout to use when the list of choices appears
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        // Apply the adapter to the spinner
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(this);
    }

    public void onItemSelected(AdapterView<?> parent, View arg1, int pos,long id) {
        TextView textView = (TextView) findViewById(R.id.textView1);
        String str = (String) parent.getItemAtPosition(pos);
        textView.setText(str);
    }

    public void onNothingSelected(AdapterView<?> arg0) {
        // TODO Auto-generated method stub

    }
}
spinner.setOnItemSelectedListener(this); // Will call onItemSelected() Listener.

그래서 처음에는 정수 값으로 이 문제를 처리합니다.

:eint check = 0;

public void onItemSelected(AdapterView<?> parent, View arg1, int pos,long id) {
   if(++check > 1) {
      TextView textView = (TextView) findViewById(R.id.textView1);
      String str = (String) parent.getItemAtPosition(pos);
      textView.setText(str);
   }
}

부울 값을 사용할 수도 있고 현재 위치와 이전 위치를 확인할 수도 있습니다.여기를 보시오

설정하기 에 이 선만 놓으면 됩니다.OnItemSelectedListener

spinner.setSelection(0,false)

은 이기 가 있습니다.setSelection(int, boolean)setSelectionInt()리스너가 추가되면 이미 항목이 선택되도록 내부적으로 설정됩니다.

하세요 하세요.setSelection(int)효과가 없을 거예요, 왜냐면 그게 전화거든요.setNextSelectedPositionInt()

API 레벨 3부터 부울이 있는 Activity의 User Interaction()에서 사용자가 장치와 상호 작용하는지 여부를 확인할 수 있습니다.

http://developer.android.com/reference/android/app/Activity.html#onUserInteraction()

@Override
public void onUserInteraction() {
     super.onUserInteraction();
     userIsInteracting = true;
}

액티비티의 필드로서 다음을 수행합니다.

 private boolean userIsInteracting;

마지막으로, 스피너:

      mSpinnerView.setOnItemSelectedListener(new OnItemSelectedListener() {

           @Override
           public void onItemSelected(AdapterView<?> arg0, View view, int position, long arg3) {
                spinnerAdapter.setmPreviousSelectedIndex(position);
                if (userIsInteracting) {
                     updateGUI();
                }
           }

           @Override
           public void onNothingSelected(AdapterView<?> arg0) {

           }
      });

활동을 수행할 때 부울이 false로 재설정됩니다.매력적으로 작용합니다.

이거 나한테 통했어요.

스피너의 안드로이드 초기화가 문제가 되는 경우가 종종 있는데, 이 패턴에 의해 위의 문제가 해결되었습니다.

Spinner.setAdapter();
Spinner.setSelected(false);  // must
Spinner.setSelection(0,true);  //must
Spinner.setonItemSelectedListener(this);

설정 어댑터는 첫 번째 부분과 onItem이어야 합니다.스피너를 초기화할 때 SelectedListener(이)가 마지막에 표시됩니다.스피너 초기화 중에 내 OnItemSelected()의 위 패턴에 의해 호출되지 않습니다.

하하... 같은 질문이 있습니다.initViews()에서는 이렇게 합니다.순서가 관건이고 듣는 사람이 마지막입니다.행운을 빕니다.

spinner.setAdapter(adapter);
spinner.setSelection(position);
spinner.setOnItemSelectedListener(listener);

초기화 중에 spinner.setOnItemSelectedListener()를 호출하지 않으려면 다음과 같이 하십시오.

spinner.setSelection(Adapter.NO_SELECTION, true); //Add this line before setting listener
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {

    }
});

내 솔루션:

protected boolean inhibit_spinner = true;


@Override
        public void onItemSelected(AdapterView<?> arg0, View arg1,
                int pos, long arg3) {

            if (inhibit_spinner) {
                inhibit_spinner = false;
            }else {

            if (getDataTask != null) getDataTask.cancel(true);
            updateData();
            }

        }

다음과 같은 방법으로 작업을 수행할 수 있습니다.

AdapterView.OnItemSelectedListener listener = new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
            //set the text of TextView
        }

        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {

        }
    });

yourSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
            yourSpinner.setOnItemSelectedListener(listener);
        }

        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {

        }
    });

처음에 리스너를 생성하고 변수 콜백에 연결합니다. 그런 다음 익명으로 두 번째 리스너를 생성하고 처음에 호출되면 리스너가 변경됩니다 =]

onTouch 방식에서 하고 onTouch 를 true 로에서 으로 할 수 .onItemSelected()선택 변경이 처리된 후에.사용자 상호 작용 플래그는 스피너 전용으로 처리되며, 원하는 동작에 영향을 미칠 수 있는 활동의 다른 뷰에 대해서는 처리되지 않기 때문에 이 솔루션을 선호합니다.

코드명:

스피너에 대한 리스너 만들기:

public class SpinnerInteractionListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener {

    boolean userSelect = false;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        userSelect = true;
        return false;
    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
        if (userSelect) { 
            userSelect = false;
            // Your selection handling code here
        }
    }

}

둘 다 합니다.OnItemSelectedListener그리고 또OnTouchListener:

SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);

부울 필드를 만듭니다.

private boolean inispinner;

활동 생성에 대한 내부

    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if (!inispinner) {
                inispinner = true;
                return;
            }
            //do your work here
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });

여러 스피너를 지원하는 이와 유사한 간단한 솔루션은 onItem의 첫 번째 실행 시 AdapterView를 Activities 슈퍼클래스의 컬렉션에 넣는 것입니다.Selected(...) 그런 다음 AdapterView를 실행하기 전에 컬렉션에 있는지 확인합니다.이를 통해 슈퍼클래스에서 한 세트의 메소드를 사용할 수 있으며 여러 AdapterView 및 여러 스피너를 지원합니다.

슈퍼클래스...

private Collection<AdapterView> AdapterViewCollection = new ArrayList<AdapterView>();

   protected boolean firstTimeThrough(AdapterView parent) {
    boolean firstTimeThrough = ! AdapterViewCollection.contains(parent);
    if (firstTimeThrough) {
       AdapterViewCollection.add(parent);
     }
    return firstTimeThrough;
   }

하위 클래스...

public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
      if (! firstTimeThrough(parent)) {
        String value = safeString(parent.getItemAtPosition(pos).toString());
        String extraMessage = EXTRA_MESSAGE;
        Intent sharedPreferencesDisplayIntent = new         Intent(SharedPreferencesSelectionActivity.this,SharedPreferencesDisplayActivity.class);
    sharedPreferencesDisplayIntent.putExtra(extraMessage,value);
    startActivity(sharedPreferencesDisplayIntent);
  }
  // don't execute the above code if its the first time through
  // do to onItemSelected being called during view initialization.

}

이거 먹어봐요.

spinner.postDelayed(new Runnable() {
        @Override
        public void run() {
            addListeners();
        }
    }, 1000);.o

코드

spinner.setOnTouchListener(new View.OnTouchListener() { 
@Override public boolean onTouch(View view, MotionEvent motionEvent) { isSpinnerTouch=true; return false; }});

holder.spinner_from.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int slot_position, long l) {
                if(isSpinnerTouch)
                {
                    Log.d("spinner_from", "spinner_from");
                    spinnerItemClickListener.onSpinnerItemClickListener(position, slot_position, AppConstant.FROM_SLOT_ONCLICK_CODE);
                }
                else {

                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });

효과가 있었습니다.

    spinner.setSelection(0, false);
    new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                spinner.setOnItemSelectedListener(listener);
            }, 500);

setOn으로 달성할 수 있습니다.먼저 Listener를 누른 다음 OnItemSelectedListener를 onTouch에 설정합니다.

@Override
public boolean onTouch(final View view, final MotionEvent event) {
 view.setOnItemSelectedListener(this)
 return false;
}

Abhi의 대답에 근거하여 나는 이 단순한 청취자를 만들었습니다.

class SpinnerListener constructor(private val onItemSelected: (position: Int) -> Unit) : AdapterView.OnItemSelectedListener {

    private var selectionCount = 0

    override fun onNothingSelected(parent: AdapterView<*>?) {
        //no op
    }

    override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
        if (selectionCount++ > 1) {
           onItemSelected(position)
        }
    }
}

사용자 정의를 생성할 수 있습니다.OnItemSelectedListener이것처럼.제가 찍었습니다.val check=0그리고 안에onItemSelected()은 카운트가 했습니까 0요?0이면 초기화 중에 호출됩니다.그러니 그냥 무시하세요.

라고 onUserItemSelected()는 이 은라고 부르겠습니다.check > 0이 가 있습니다 저는 이 방법이 아주 좋습니다.

abstract class MySpinnerItemSelectionListener : AdapterView.OnItemSelectedListener {

abstract fun onUserItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long)
private var check = 0
override fun onItemSelected(
    parent: AdapterView<*>?,
    view: View,
    position: Int,
    id: Long
) {
    if (++check > 1) {
        onUserItemSelected(parent, view, position, id)
    }
}

override fun onNothingSelected(parent: AdapterView<*>?) {}

}

그런 다음 청취자를 이렇게 설정할 수 있습니다.

mySpinner.onItemSelectedListener =  object : MySpinnerItemSelectionListener() {
        override fun onUserItemSelected(
            parent: AdapterView<*>?,
            view: View?,
            position: Int,
            id: Long
        ) {
            //your user selection spinner code goes here
        }

    }

저도 같은 문제를 겪었고, 이것이 저에게 효과가 있습니다.

저는 스피너 2개를 보유하고 있으며 초기 및 다른 컨트롤과의 상호 작용 중 또는 서버에서 데이터를 가져온 후 업데이트합니다.

템플릿은 다음과 같습니다.

public class MyClass extends <Activity/Fragment/Whatever> implements Spinner.OnItemSelectedListener {

    private void removeSpinnersListeners() {
        spn1.setOnItemSelectedListener(null);
        spn2.setOnItemSelectedListener(null);
    }

    private void setSpinnersListeners() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                spn1.setOnItemSelectedListener(MyClass.this);
                spn2.setOnItemSelectedListener(MyClass.this);
            }
        }, 1);
    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        // Your code here
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {

    }
}

클래스를 시작할 때 리스너를 직접 설정하는 대신 setSpinnersListeners()를 사용합니다.

Runnable은 스피너가 아이템에 발화하는 것을 방지합니다.값을 설정한 직후에 선택합니다.

서버 호출 등 후 스피너를 업데이트해야 하는 경우 업데이트 줄 바로 앞에 removeSpinnersListeners()를 사용하고 업데이트 줄 바로 뒤에 SpinnersListeners()를 설정합니다.이렇게 하면 항목에서 방지됩니다.업데이트 후 발사에서 선택합니다.

저는 Abhi의 솔루션이 Api 레벨 27까지 잘 작동합니다.

하지만 Api 레벨 28 이상부터 Item 상에서Listener가 설정되어 있을 때 Selected()가 호출되지 않습니다. 이는 항목에 대한 의미입니다.선택한()이(가) 호출되지 않습니다.

따라서 Api 레벨을 확인하기 위해 간단한 if-state를 추가하였습니다.

public void onItemSelected(AdapterView<?> parent, View arg1, int pos,long id) {

            if(Build.VERSION.SDK_INT >= 28){ //onItemSelected() doesn't seem to be called when listener is set on Api 28+
                check = 1;
            }

            if(++check > 1) {
                //Do your action here
            }
        }

저는 그것이 꽤 이상하다고 생각하고 다른 사람들도 이런 문제를 가지고 있는지 확신할 수 없지만, 저의 경우는 잘 작동했습니다.

사용자가 클릭하기 전에 Spinner의 모양을 더 잘 제어할 수 있도록 Spinner의 상단에 텍스트 뷰(TextView)를 배치했습니다.텍스트 뷰를 사용하면 사용자가 상호 작용을 시작할 때 텍스트 뷰를 사용하여 플래그를 지정할 수도 있습니다.

내 코틀린 코드는 다음과 같습니다.

private var mySpinnerHasBeenTapped = false

private fun initializeMySpinner() {

    my_hint_text_view.setOnClickListener {
        mySpinnerHasBeenTapped = true //turn flag to true
        my_spinner.performClick() //call spinner click
    }

    //Basic spinner setup stuff
    val myList = listOf("Leonardo", "Michelangelo", "Rafael", "Donatello")
    val dataAdapter: ArrayAdapter<String> = ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, myList)
    my_spinner.adapter = dataAdapter

    my_spinner.onItemSelectedListener = object : OnItemSelectedListener {

        override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {

            if (mySpinnerHasBeenTapped) { //code below will only run after the user has clicked
                my_hint_text_view.visibility = View.GONE //once an item has been selected, hide the textView
                //Perform action here
            }
        }

        override fun onNothingSelected(parent: AdapterView<*>?) {
            //Do nothing
        }
    }
}

레이아웃 파일은 다음과 같이 보이는데, Spinner와 TextView가 같은 폭, 높이 및 여백을 공유한다는 것이 중요한 부분입니다.

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <Spinner
                android:id="@+id/my_spinner"
                android:layout_width="match_parent"
                android:layout_height="35dp"
                android:layout_marginStart="10dp"
                android:layout_marginEnd="10dp"
                android:background="@drawable/bg_for_spinners"

                android:paddingStart="8dp"
                android:paddingEnd="30dp"
                android:singleLine="true" />

            <TextView
                android:id="@+id/my_hint_text_view"
                android:layout_width="match_parent"
                android:layout_height="35dp"                
                android:layout_marginStart="10dp"
                android:layout_marginEnd="10dp"
                android:background="@drawable/bg_for_spinners"

                android:paddingStart="8dp"
                android:paddingEnd="30dp"
                android:singleLine="true"
                android:gravity="center_vertical"
                android:text="*Select A Turtle"
                android:textColor="@color/green_ooze"
                android:textSize="16sp" />

        </FrameLayout>

다른 해결책들은 당신이 아이템의 첫번째를 무시하는 것에서 작동한다고 확신합니다.선택된 전화입니다만, 항상 전화가 걸려올 거라고 가정하는 생각은 정말 마음에 들지 않습니다.

저는 이 문제를 다음과 같이 해결했습니다.Resume()에 이름이 있는 액티비티 라이프사이클 메소드에서: Spinner.setOnItemSelectedListener(이)를 추가했습니다;

결과적으로 초기화 시 스피너가 클릭 시 호출하는 방법이 작동하지 않습니다.onResume 메서드는 완성된 Android 페이지가 표시되면 작동을 시작합니다.

언급URL : https://stackoverflow.com/questions/13397933/android-spinner-avoid-onitemselected-calls-during-initialization