초기 텍스트“Select One”으로 Android Spinner를 만드는 방법은 무엇입니까?


569

처음에 (사용자가 아직 선택하지 않은 경우) 텍스트 "Select One"을 표시하는 Spinner를 사용하고 싶습니다. 사용자가 스피너를 클릭하면 항목 목록이 표시되고 옵션 중 하나를 선택합니다. 사용자가 선택하면 선택한 항목이 "하나 선택"대신 스피너에 표시됩니다.

Spinner를 만드는 다음 코드가 있습니다.

String[] items = new String[] {"One", "Two", "Three"};
Spinner spinner = (Spinner) findViewById(R.id.mySpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

이 코드를 사용하면 처음에 "One"항목이 표시됩니다. 새 항목 "Select One"을 항목에 추가 할 수 있지만 드롭 다운 목록에 "Select One"도 첫 번째 항목으로 표시됩니다.

이 문제를 어떻게 해결할 수 있습니까?


6
완벽한 해결책은이 질문에 있습니다 : stackoverflow.com/questions/9863378/… getDropDownView () 메소드를 재정의하십시오.
— Sourab Sharma 2016

어댑터의 첫 번째 요소를 "하나 선택"으로 설정해 보셨습니까?
— IgorGanapolsky

[여기 다른 훌륭한 해결책이 있습니다!] [1] [1] : stackoverflow.com/questions/9863378/…
— AirtonCarneiro

재사용 가능한 스피너 : github.com/henrychuangtw/ReuseSpinner
— HenryChuang

답변:


255

다음은 Spinner뷰 를 재정의하는 일반적인 솔루션입니다 . setAdapter()초기 위치를 -1로 설정하도록 대체 하고 제공된 프록시 SpinnerAdapter가 0보다 작은 위치에 대한 프롬프트 문자열을 표시하도록 프록시합니다 .

이것은 안드로이드 1.5에서 4.2까지 테스트되었지만 구매자는 조심하십시오! 이 솔루션은 반사에 의존하기 때문에 개인을 호출 AdapterView.setNextSelectedPositionInt()하고 AdapterView.setSelectedPositionInt()그것은 미래의 OS 업데이트에서 작동하지 않을 수 있어요. 그럴 것 같지만 결코 보장되지는 않습니다.

일반적으로 나는 이와 같은 것을 용납하지 않을 것이지만,이 질문은 충분한 시간을 요구 받았으며 솔루션을 게시 할 것이라고 생각한 합리적인 요청처럼 보입니다.

/**
 * A modified Spinner that doesn't automatically select the first entry in the list.
 *
 * Shows the prompt if nothing is selected.
 *
 * Limitations: does not display prompt if the entry list is empty.
 */
public class NoDefaultSpinner extends Spinner {

    public NoDefaultSpinner(Context context) {
        super(context);
    }

    public NoDefaultSpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public NoDefaultSpinner(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setAdapter(SpinnerAdapter orig ) {
        final SpinnerAdapter adapter = newProxy(orig);

        super.setAdapter(adapter);

        try {
            final Method m = AdapterView.class.getDeclaredMethod(
                               "setNextSelectedPositionInt",int.class);
            m.setAccessible(true);
            m.invoke(this,-1);

            final Method n = AdapterView.class.getDeclaredMethod(
                               "setSelectedPositionInt",int.class);
            n.setAccessible(true);
            n.invoke(this,-1);
        } 
        catch( Exception e ) {
            throw new RuntimeException(e);
        }
    }

    protected SpinnerAdapter newProxy(SpinnerAdapter obj) {
        return (SpinnerAdapter) java.lang.reflect.Proxy.newProxyInstance(
                obj.getClass().getClassLoader(),
                new Class[]{SpinnerAdapter.class},
                new SpinnerAdapterProxy(obj));
    }



    /**
     * Intercepts getView() to display the prompt if position < 0
     */
    protected class SpinnerAdapterProxy implements InvocationHandler {

        protected SpinnerAdapter obj;
        protected Method getView;


        protected SpinnerAdapterProxy(SpinnerAdapter obj) {
            this.obj = obj;
            try {
                this.getView = SpinnerAdapter.class.getMethod(
                                 "getView",int.class,View.class,ViewGroup.class);
            } 
            catch( Exception e ) {
                throw new RuntimeException(e);
            }
        }

        public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
            try {
                return m.equals(getView) && 
                       (Integer)(args[0])<0 ? 
                         getView((Integer)args[0],(View)args[1],(ViewGroup)args[2]) : 
                         m.invoke(obj, args);
            } 
            catch (InvocationTargetException e) {
                throw e.getTargetException();
            } 
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        protected View getView(int position, View convertView, ViewGroup parent) 
          throws IllegalAccessException {

            if( position<0 ) {
                final TextView v = 
                  (TextView) ((LayoutInflater)getContext().getSystemService(
                    Context.LAYOUT_INFLATER_SERVICE)).inflate(
                      android.R.layout.simple_spinner_item,parent,false);
                v.setText(getPrompt());
                return v;
            }
            return obj.getView(position,convertView,parent);
        }
    }
}

7
@emmby 사용자가 설정 한 후 선택을 지우는 방법에 대해 알고 있습니까? 두 개의 invoke () 호출을 clearSelection () 메서드로 리팩토링하려고 시도했지만 실제로 작동하지 않습니다. 팝업 목록에는 이전에 선택한 항목이 선택되지 않은 것으로 표시되지만 스피너 위젯은 여전히 ​​선택된 항목을 표시하며 사용자가 동일한 항목을 다시 선택하면 onItemSelected ()가 호출되지 않습니다.
— Qwertie

3
위의 클래스를 사용하는 방법을 설명 할 수 있습니까?
— Bishan

4
이 솔루션은 android : entries를 사용하는 Android 4.2 (Cyanogenmod 10.1)에서는 100 % 완벽하지 않습니다. 팽창 된 TextView의 높이는 기본 어댑터가 팽창 한 자원의 높이보다 작습니다. 따라서 실제로 옵션을 선택하면 Galaxy S에서 높이가 ~ 10px 증가하여 허용되지 않습니다. 나는 여러 가지 (중력, 패딩, 여백 등)를 시도했지만 어떤 장치에서도 안정적으로 작동하지 않았으므로 다른 솔루션을 선택하려고합니다.
— Maragues

3
@DavidDoria 레이아웃 파일에서 NoDefaultSpinner 클래스를 사용해야합니다. 위에서 소스를 프로젝트 (예 : 패키지 com.example.customviews)로 복사하십시오. 이제 레이아웃 XML에서 <Spinner ...> 대신 <com.example.customviews.NoDefaultSpinner ...>를 사용하십시오. 나머지 코드는 동일하게 유지 될 수 있습니다. 레이아웃의 <com.example.customviews.NoDefaultSpinner>보기에 android : prompt 속성을 추가해야합니다.
— Ridcully

2
@emmby spinnerBrand.setSelection (-1); 작동하지 않습니다
— Sachin C

291

당신이 할 수있는 것은 SpinnerAdapterSpinner가 아무것도 선택하지 않고 표시 할 수 있는 '옵션 선택 ...'보기를 나타내는 것으로 장식하는 것 입니다.

다음은 Android 2.3 및 4.0에서 테스트 된 작동 예제입니다 (호환성 라이브러리에서는 아무것도 사용하지 않으므로 잠시 괜찮습니다). 데코레이터이기 때문에 기존 코드를 쉽게 수정할 수 있으며 CursorLoaders에서도 잘 작동합니다 . ( cursorAdapter물론 랩핑 된 커서를 바꾸십시오 ...)

뷰를 재사용하기가 조금 더 어려워지는 Android 버그가 있습니다. (따라서 정확한지 setTag확인하기 위해 또는 다른 것을 사용해야합니다 convertView.) Spinner는 다중보기 유형을 지원하지 않습니다

코드 노트 : 2 개의 생성자

이를 통해 표준 프롬프트를 사용하거나 자신이 선택한 '아무것도 없음'을 첫 번째 행으로 또는 둘 다로 정의하거나 모두 정의 할 수 없습니다. (참고 : 일부 테마는 대화 상자 대신 스피너의 드롭 다운을 표시합니다. 드롭 다운에는 일반적으로 프롬프트가 표시되지 않습니다)

프롬프트처럼 보이도록 레이아웃을 정의합니다 (예 : 회색으로 표시).

초기에 아무것도 선택하지 않았습니다

표준 프롬프트 사용 (아무 것도 선택되지 않음) :

표준 프롬프트

또는 프롬프트와 동적으로 (프롬프트가 없었을 수도 있음)

프롬프트 및 선택된 행 없음

위의 예에서 사용법

Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.planets_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setPrompt("Select your favorite Planet!");

spinner.setAdapter(
      new NothingSelectedSpinnerAdapter(
            adapter,
            R.layout.contact_spinner_row_nothing_selected,
            // R.layout.contact_spinner_nothing_selected_dropdown, // Optional
            this));

contact_spinner_row_nothing_selected.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    style="?android:attr/spinnerItemStyle"
    android:singleLine="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:textSize="18sp"
    android:textColor="#808080"
    android:text="[Select a Planet...]" />

NothingSelectedSpinnerAdapter.java

import android.content.Context;
import android.database.DataSetObserver;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.SpinnerAdapter;

/**
 * Decorator Adapter to allow a Spinner to show a 'Nothing Selected...' initially
 * displayed instead of the first choice in the Adapter.
 */
public class NothingSelectedSpinnerAdapter implements SpinnerAdapter, ListAdapter {

    protected static final int EXTRA = 1;
    protected SpinnerAdapter adapter;
    protected Context context;
    protected int nothingSelectedLayout;
    protected int nothingSelectedDropdownLayout;
    protected LayoutInflater layoutInflater;

    /**
     * Use this constructor to have NO 'Select One...' item, instead use
     * the standard prompt or nothing at all.
     * @param spinnerAdapter wrapped Adapter.
     * @param nothingSelectedLayout layout for nothing selected, perhaps
     * you want text grayed out like a prompt...
     * @param context
     */
    public NothingSelectedSpinnerAdapter(
      SpinnerAdapter spinnerAdapter,
      int nothingSelectedLayout, Context context) {

        this(spinnerAdapter, nothingSelectedLayout, -1, context);
    }

    /**
     * Use this constructor to Define your 'Select One...' layout as the first
     * row in the returned choices.
     * If you do this, you probably don't want a prompt on your spinner or it'll
     * have two 'Select' rows.
     * @param spinnerAdapter wrapped Adapter. Should probably return false for isEnabled(0)
     * @param nothingSelectedLayout layout for nothing selected, perhaps you want
     * text grayed out like a prompt...
     * @param nothingSelectedDropdownLayout layout for your 'Select an Item...' in
     * the dropdown.
     * @param context
     */
    public NothingSelectedSpinnerAdapter(SpinnerAdapter spinnerAdapter,
            int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context) {
        this.adapter = spinnerAdapter;
        this.context = context;
        this.nothingSelectedLayout = nothingSelectedLayout;
        this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout;
        layoutInflater = LayoutInflater.from(context);
    }

    @Override
    public final View getView(int position, View convertView, ViewGroup parent) {
        // This provides the View for the Selected Item in the Spinner, not
        // the dropdown (unless dropdownView is not set).
        if (position == 0) {
            return getNothingSelectedView(parent);
        }
        return adapter.getView(position - EXTRA, null, parent); // Could re-use
                                                 // the convertView if possible.
    }

    /**
     * View to show in Spinner with Nothing Selected
     * Override this to do something dynamic... e.g. "37 Options Found"
     * @param parent
     * @return
     */
    protected View getNothingSelectedView(ViewGroup parent) {
        return layoutInflater.inflate(nothingSelectedLayout, parent, false);
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        // Android BUG! http://code.google.com/p/android/issues/detail?id=17128 -
        // Spinner does not support multiple view types
        if (position == 0) {
            return nothingSelectedDropdownLayout == -1 ?
              new View(context) :
              getNothingSelectedDropdownView(parent);
        }

        // Could re-use the convertView if possible, use setTag...
        return adapter.getDropDownView(position - EXTRA, null, parent);
    }

    /**
     * Override this to do something dynamic... For example, "Pick your favorite
     * of these 37".
     * @param parent
     * @return
     */
    protected View getNothingSelectedDropdownView(ViewGroup parent) {
        return layoutInflater.inflate(nothingSelectedDropdownLayout, parent, false);
    }

    @Override
    public int getCount() {
        int count = adapter.getCount();
        return count == 0 ? 0 : count + EXTRA;
    }

    @Override
    public Object getItem(int position) {
        return position == 0 ? null : adapter.getItem(position - EXTRA);
    }

    @Override
    public int getItemViewType(int position) {
        return 0;
    }

    @Override
    public int getViewTypeCount() {
        return 1;
    }

    @Override
    public long getItemId(int position) {
        return position >= EXTRA ? adapter.getItemId(position - EXTRA) : position - EXTRA;
    }

    @Override
    public boolean hasStableIds() {
        return adapter.hasStableIds();
    }

    @Override
    public boolean isEmpty() {
        return adapter.isEmpty();
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        adapter.registerDataSetObserver(observer);
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        adapter.unregisterDataSetObserver(observer);
    }

    @Override
    public boolean areAllItemsEnabled() {
        return false;
    }

    @Override
    public boolean isEnabled(int position) {
        return position != 0; // Don't allow the 'nothing selected'
                                             // item to be picked.
    }

}

52
이것은 문제에 대한 우아한 해결책입니다. 코드는 내 프로젝트에 복사하여 붙여 넣은 그대로 작동합니다. 반사가 필요하지 않은 경우 +1
— Richard Le Mesurier 5

2
이것은 훌륭한 솔루션입니다. 항목을 선택하기 직전이 아니라 getView () 호출에서 항상 제목을 재정의하는 방법을 알고 싶은 경우 항상 getNothingSelectedView (또는 다른 사용자 정의보기)를 반환하십시오. 드롭 다운 목록은 여전히 ​​어댑터의 항목으로 채워지지만, 무언가를 선택한 후에도 제목을 제어 할 수 있습니다.
— OldSchool4664

6
이것은 존재해서는 안되는 문제에 대한 정말 우아한 해결책입니다 (iphone 개발 시도). 위대하고 감사합니다! 누군가 패턴 등을 기억하게 된 것을 기쁘게 생각합니다.
— user1700737

3
@ prashantwosti, Lollipop과 작동하도록 코드가 업데이트되었습니다. 특히 getItemViewType () 및 getViewTypeCount ()입니다.
— aaronvargas

3
@aaronvargas가 스피너에서 항목을 선택하면 실행 취소하고 "[행성 선택]"을 선택할 수 있습니까?
— modabeckham

130

나는 Button대신에 사용했다 . a Button가 아닌 동안 Spinner동작을 쉽게 사용자 지정할 수 있습니다.

먼저 평소와 같이 어댑터를 작성하십시오.

String[] items = new String[] {"One", "Two", "Three"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
        android.R.layout.simple_spinner_dropdown_item, items);

simple_spinner_dropdown_item레이아웃 ID로를 사용하고 있습니다. 이렇게하면 경고 대화 상자를 만들 때 더 잘 보일 수 있습니다.

내 버튼의 onClick 핸들러에는 다음이 있습니다.

public void onClick(View w) {
  new AlertDialog.Builder(this)
  .setTitle("the prompt")
  .setAdapter(adapter, new DialogInterface.OnClickListener() {

    @Override
    public void onClick(DialogInterface dialog, int which) {

      // TODO: user specific action

      dialog.dismiss();
    }
  }).create().show();
}

그리고 그게 다야!


10
나는 그 대답에 동의합니다. 게다가, 스피너보다 훨씬 스타일이 쉬운 버튼.
— Romain Piel

@ HRJ 나는 제안한 방식을 구현했지만 이전에 선택된 항목이 강조 표시되지 않습니다 (무선 버튼은 가운데에 회색 점으로 강조 표시되어야 함을 의미합니다) .... OnClick () 메소드에서 어떻게 이것을 달성 할 수 있습니까? 단추. HRJ 도와주세요 .....
— Avadhani Y

2
이 레이아웃이있는 버튼은 완벽한 <Button android : id = "@ + id / city"android : layout_width = "match_parent"android : layout_height = "wrap_content"android : layout_margin = "5dp"android : gravity = "left"android : background = "@ android : drawable / btn_dropdown"android : text = "@ string / city_prompt"/>
— kml_ckr

그런 다음 스피너에서와 같이 선택 사항을 반영하도록 버튼의 텍스트를 어떻게 업데이트합니까?
— shim

3
문제 해결책 : SetAdapter 대신 SetSingleChoiceItems
— Grzegorz Dev

67

먼저, 클래스 의 prompt속성에 관심이있을 수 있습니다 Spinner. 아래 그림을 참조하십시오. "행성을 선택하십시오"는 XML에서로 설정할 수있는 프롬프트입니다 android:prompt="".

여기에 이미지 설명을 입력하십시오

Spinner내부적으로 두 개의 어댑터를 유지 관리 할 수있는 서브 클래 싱을 제안하려고했습니다 . "하나 선택"옵션이있는 하나의 어댑터와 다른 실제 어댑터 (실제 옵션 포함)를 사용한 다음 OnClickListener선택 대화 상자가 표시되기 전에 를 사용 하여 어댑터를 전환하십시오. 그러나 그 아이디어를 구현하려고 시도한 후에 OnClick는 위젯 자체에 대한 이벤트를 수신 할 수 없다는 결론에 도달 했습니다.

스피너를 다른보기로 감싸고보기를 클릭 한 다음 가로 채서 CustomSpinner어댑터를 전환하도록 지시 할 수는 있지만 끔찍한 해킹처럼 보입니다.

"하나만 선택"을 표시해야합니까?


36
"하나만 선택"을 표시 할 필요가있을뿐만 아니라 스피너 값을 선택적으로 비워 둘 수도 있습니다.
— greg7gkb

5
또한이 옵션을 사용하면 아무것도 선택하기 전에 지구가 스피너의 선택 항목으로 표시됩니다. 내 응용 프로그램의 경우 사용자가 아직 아무것도 선택하지 않았다고 말할 수 있습니다.
— dylan murphy

2
이것은 실제로 질문에 대답하지 않습니다. 사람들은 스피너 자체가 기본적으로 행성 목록의 첫 번째 항목이 아닌 "하나 선택"을 표시하는 방법을 찾고 있습니다.이 예에서
— JMRboosties

58

이 코드는 테스트되었으며 Android 4.4에서 작동합니다

여기에 이미지 설명을 입력하십시오

Spinner spinner = (Spinner) activity.findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, android.R.layout.simple_spinner_dropdown_item) {

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {

                View v = super.getView(position, convertView, parent);
                if (position == getCount()) {
                    ((TextView)v.findViewById(android.R.id.text1)).setText("");
                    ((TextView)v.findViewById(android.R.id.text1)).setHint(getItem(getCount())); //"Hint to be displayed"
                }

                return v;
            }       

            @Override
            public int getCount() {
                return super.getCount()-1; // you dont display last item. It is used as hint.
            }

        };

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        adapter.add("Daily");
        adapter.add("Two Days");
        adapter.add("Weekly");
        adapter.add("Monthly");
        adapter.add("Three Months");
        adapter.add("HINT_TEXT_HERE"); //This is the text that will be displayed as hint.


        spinner.setAdapter(adapter);
        spinner.setSelection(adapter.getCount()); //set the hint the default selection so it appears on launch.
        spinner.setOnItemSelectedListener(this);

getItem(getCount())밑줄이 빨간색입니까? setHint
— Zapnologica

나는이 스레드에서 많은 솔루션을 보았습니다. 그러나 왜 모두가 마지막에 힌트를 추가하고 있습니까? 첫 번째 행에 힌트를 추가하는 것이 잘못 되었습니까?
— akashPatra

'setOnItemSelectedListener (this);'를 설정할 수 없습니다. 'implement NavigationView.OnNavigationItemSelectedListener'를 사용하고 있으므로 'setOnItemSelectedListener (this);'를 제거 할 수 있습니까? 문제없이?
— CGR

@akashpatra 마지막 힌트를 추가하는 이유는 Spinner 용 ArrayAdapter가 런타임에 다른 소스에서 값을 가져올 수 있기 때문입니다.
— VinKrish

이 날 정말 도움이
— 선일

31

이 솔루션을 찾았습니다.

String[] items = new String[] {"Select One", "Two", "Three"};
Spinner spinner = (Spinner) findViewById(R.id.mySpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {
        items[0] = "One";
        selectedItem = items[position];
    }

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

"Select One"으로 배열 [0]을 변경 한 다음 onItemSelected에서 "One"으로 이름을 바꿉니다.

고급 솔루션은 아니지만 작동합니다. : D


5
이것은 나를 위해 작동하지 않았습니다. "One"항목을 선택한 후에도 여전히 "One Select"라고 표시됩니다.
— Leo Landau

이것은 onItemSelected 인터페이스가 항상 처음으로 호출되는 원인이되지 않습니다.
— Vaibhav Kadam

20

Spinner에 힌트를 설정하는 기본 API가 없습니다. 추가하려면 안전 반영 구현이 아닌 작은 해결 방법이 필요합니다.

List<Object> objects = new ArrayList<Object>();
objects.add(firstItem);
objects.add(secondItem);
// add hint as last item
objects.add(hint);

HintAdapter adapter = new HintAdapter(context, objects, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

Spinner spinnerFilmType = (Spinner) findViewById(R.id.spinner);
spinner.setAdapter(adapter);

// show hint
spinner.setSelection(adapter.getCount());

어댑터 소스 :

public class HintAdapter
        extends ArrayAdapter<Objects> {

    public HintAdapter(Context theContext, List<Object> objects) {
        super(theContext, android.R.id.text1, android.R.id.text1, objects);
    }

    public HintAdapter(Context theContext, List<Object> objects, int theLayoutResId) {
        super(theContext, theLayoutResId, android.R.id.text1, objects);
    }

    @Override
    public int getCount() {
        // don't display last item. It is used as hint.
        int count = super.getCount();
        return count > 0 ? count - 1 : count;
    }
}

원본 출처


R.id.text1은 무엇입니까? 레이아웃이나 뷰입니까? 답변을 정교하게 작성하십시오
— Anand Savjani

그것은해야한다android.R.id.text1
— Yakiv Mospan

나는이 스레드에서 많은 솔루션을 보았습니다. 그러나 왜 모두가 마지막에 힌트를 추가하고 있습니까? 첫 번째 행에 힌트를 추가하는 것이 잘못 되었습니까?
— akashPatra

@akashpatra 정확히 기억하지 못하지만 첫 번째 항목 목록으로 만들려고 할 때 약간의 문제가있는 것 같습니다. 어쨌든 당신은 항상 그것을 시도 할 수 있고 여기에 언급, 여기에 모든 마법 주위 getCount방법
— Yakiv Mospan

@YakivMospan 나는 이것을 사용할 때 NPE를 얻습니다. 아마도 ProGuard를 사용할 때 Reflection 때문입니다. 이 문제를 해결하는 방법을 알고 있습니까?
— Alan

17

여기에 많은 답변이 있지만 아무도 간단한 해결책을 제안하지 않은 것에 놀랐습니다. Spinner 위에 TextView를 배치하십시오. TextView에 Spinner를 표시하고 spinner.performClick ()을 호출하는 클릭 리스너를 TextView에 설정하십시오.


9

빈 선택으로 스피너와 동일한 문제가 발생하여 더 나은 솔루션을 찾았습니다. 이 간단한 코드를 살펴보십시오.

Spinner lCreditOrDebit = (Spinner)lCardPayView.findViewById(R.id.CARD_TYPE);
spinneradapter lAdapter = 
  new spinneradapter(
    BillPayScreen.this, 
    ndroid.R.layout.simple_spinner_item,getResources().getStringArray(R.array.creditordebit));
lAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
lCreditOrDebit.setAdapter(lAdapter);

여기서 spinneradapter는 arrayadapter를위한 작은 사용자 정의입니다. 다음과 같이 보입니다 :

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;

public class spinneradapter extends ArrayAdapter<String>{
    private Context m_cContext;
    public spinneradapter(Context context,int textViewResourceId, String[] objects) {
        super(context, textViewResourceId, objects);
        this.m_cContext = context;
    }

    boolean firsttime = true;
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(firsttime){
            firsttime = false;
            //Just return some empty view
            return new ImageView(m_cContext);
        }
        //Let the array adapter take care of it this time.
        return super.getView(position, convertView, parent);
    }
}

6
이 방법의 문제점은 목록이 팝업 될 때 여전히 목록의 첫 번째 항목을 선택한다는 것입니다. 이미 선택되었으므로 터치하여 선택할 수 없습니다. 선택한 항목이없는 것처럼 작동합니다.
— jwadsack

7

텍스트보기로 변경하고 이것을 사용할 수 있습니다 :

android:style="@android:style/Widget.DeviceDefault.Light.Spinner"

그런 다음 android:text속성 을 정의하십시오 .


API 14 이상에서만 작동합니다.
— Giulio Piancastelli

6

XML 파일 :

<Spinner android:id="@+id/locationSpinner"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:prompt="@string/select_location" />

활동:

private Spinner featuresSelection;
private ArrayAdapter<CharSequence> featuresAdapter;
private List<CharSequence> featuresList;

onCreate :

featuresList = new ArrayList<CharSequence>();
featuresAdapter = new ArrayAdapter<CharSequence>(this,
  android.R.layout.simple_spinner_item, featuresList);
featuresAdapter.setDropDownViewResource(
  android.R.layout.simple_spinner_dropdown_item);
featuresSelection = ((Spinner) yourActivity.this
  .findViewById(R.id.locationSpinner));
featuresSelection.setAdapter(featuresAdapter);
featuresSelection.setOnItemSelectedListener(
  new MyOnItemSelectedListener());

일부 기능 (프로그래밍 방식으로 어댑터에 항목 추가)>

featuresAdapter.add("some string");

이제 빈 스피너가 있으며 비어있는 경우 대화 상자를 열지 않는 코드를 작성할 수 있습니다. 또는 그들은 다시 누를 수 있습니다. 그러나 런타임 중에 함수 또는 다른 목록으로 채 웁니다.


또한 기본적으로 true로 설정되어야하므로 notifyDataSetChanged ()를 지정할 필요가 없습니다.
— trgraglia

4

나는 다음과 같이 시도했다. 버튼을 클릭하여 클릭 이벤트를 제공하십시오. 버튼 배경을 변경하면 스피너처럼 보입니다.

전역 변수 alertdialog 및 기본값으로 선언하십시오.

AlertDialog d;
static int default_value = 0;
final Button btn = (Button) findViewById(R.id.button1);
btn .setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v)
{
    //c.show();
    final CharSequence str[] = {"Android","Black Berry","Iphone"};
        AlertDialog.Builder builder =
          new AlertDialog.Builder(TestGalleryActivity.this).setSingleChoiceItems(
            str, default_value,new  DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int position)
            {
                Toast.makeText(TestGalleryActivity.this,
                               "" + position,
                               Toast.LENGTH_SHORT).show();
                default_value = position;
                btn.setText(str[position]);
                if(d.isShowing())
                    d.dismiss();
            }
        }).setTitle("Select Any");
        d = builder.create();
        d.show();
    }
});

4

이게 내 방법이야:

List<String> list = new ArrayList<String>();
list.add("string1");
list.add("string2");
list.add("string3");
list.add("[Select one]");
final int listsize = list.size() - 1;
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, list) {
 @Override
public int getCount() {
    return(listsize); // Truncate the list
}
};
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mySpinner.setAdapter(dataAdapter);

mySpinner.setSelection(listsize); // Hidden item to appear in the spinner

이것은 하단 위치에서 스피너를 엽니 다
— SpyZip

3

목록 상단에 요소를 추가하는 일반적인 솔루션은 iosched 앱을 살펴보십시오. 특히, 당신은에서 CursorAdapter, 모양 사용하는 경우 TracksAdapter.java 상단에 별도의 항목을 처리 할 수있는 목록 수를 관리 할 수있는 "setHasAllItem"방법과 관련된 코드를 제공하기 위해 그 정의를 확장합니다.

사용자 정의 어댑터를 사용하여 텍스트를 "하나 선택"으로 설정하거나 최상위 항목에 대해 말할 수있는 모든 것을 설정할 수 있습니다.


3

내 main.xml에 스피너가 있고 그 ID는 @+id/spinner1

이것은 내 OnCreate 함수에서 쓰는 것입니다.

spinner1 = (Spinner)this.findViewById(R.id.spinner1);
final String[] groupes = new String[] {"A", "B", "C", "D", "E", "F", "G", "H"};
ArrayAdapter<CharSequence> featuresAdapter = new ArrayAdapter<CharSequence>(this, android.R.layout.simple_spinner_item, new ArrayList<CharSequence>());
featuresAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner1.setAdapter(featuresAdapter);
for (String s : groupes) featuresAdapter.add(s);

spinner1.setOnItemSelectedListener(new OnItemSelectedListener() {
     public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {
         // Here go your instructions when the user chose something
         Toast.makeText(getBaseContext(), groupes[position], 0).show();
     }
     public void onNothingSelected(AdapterView<?> arg0) { }
});

클래스에서 구현할 필요는 없습니다.


3

나는 이것에 대한 많은 좋은 해결책을 찾았습니다. 대부분은 어댑터 끝에 항목을 추가하여 작동하며 드롭 다운 목록에 마지막 항목을 표시하지 않습니다. 나에게 가장 큰 문제는 스피너 드롭 다운 목록이 목록 맨 아래에서 시작된다는 것입니다. 따라서 사용자는 처음 스피너를 터치 한 후 첫 번째 항목 (표시 할 항목이 많은 경우) 대신 마지막 항목을 볼 수 있습니다.

그래서 힌트 항목을 목록의 시작 부분에 넣었습니다. 드롭 다운 목록에서 첫 번째 항목을 숨 깁니다.

private void loadSpinner(){

    HintArrayAdapter hintAdapter = new HintArrayAdapter<String>(context, 0);

    hintAdapter.add("Hint to be displayed");
    hintAdapter.add("Item 1");
    hintAdapter.add("Item 2");
            .
            .
    hintAdapter.add("Item 30");

    spinner1.setAdapter(hintAdapter);

    //spinner1.setSelection(0); //display hint. Actually you can ignore it, because the default is already 0
    //spinner1.setSelection(0, false); //use this if don't want to onItemClick called for the hint

    spinner1.setOnItemSelectedListener(yourListener);
}

private class HintArrayAdapter<T> extends ArrayAdapter<T> {

    Context mContext;

    public HintArrayAdapter(Context context, int resource) {
        super(context, resource);
        this.mContext = context
    }

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(android.R.layout.simple_spinner_item, parent, false);
        TextView texview = (TextView) view.findViewById(android.R.id.text1);

        if(position == 0) {
            texview.setText("");
            texview.setHint(getItem(position).toString()); //"Hint to be displayed"
        } else {
            texview.setText(getItem(position).toString());
        }

        return view;
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        View view;

        if(position == 0){
            view = inflater.inflate(R.layout.spinner_hint_list_item_layout, parent, false); // Hide first row
        } else {
            view = inflater.inflate(android.R.layout.simple_spinner_dropdown_item, parent, false);
            TextView texview = (TextView) view.findViewById(android.R.id.text1);
            texview.setText(getItem(position).toString());
        } 

        return view;
    }
}

첫 번째 힌트 행을 숨기려면 위치가 0 일 때 @Override getDropDownView ()에서 아래 레이아웃을 설정하십시오.

R.layout.spinner_hint_list_item_layout :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

</LinearLayout>

3

또한 기본값을 표시하는 간단한 트릭이 있습니다.

목록에 기본값을 추가 한 다음 다음을 사용하여 모든 컬렉션을 추가 할 수 있습니다 list.addAll(yourCollection);

실행 가능한 샘플 코드는 다음과 같습니다.

List<FuelName> fuelList = new ArrayList<FuelName>();
                    fuelList.add(new FuelName(0,"Select One"));
                    fuelList.addAll(response.body());
                    ArrayAdapter adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item, fuelList);
                    //fuelName.setPrompt("Select Fuel");
                    fuelName.setAdapter(adapter);

그것이 당신의 복잡성을 회복하기를 바랍니다. 행복한 코딩!


2

가장 쉬운 방법은 인덱스 0에 "select one"이라는 더미 항목을 만든 다음 저장하면 선택 항목이 0이 아닌지 확인하는 것입니다.


4
항목 목록을 보는 것은 어떻습니까? 상단에 "하나 선택"위치를보고 싶으십니까? 저축의 문제 만이 아닙니다.
— Krzysztof Wolny

@KrzysztofWolny 스피너는 기본 디스플레이로 위치 0의 항목은
— RDS

2

이것이 버튼 스피너에 대한 나의 마지막 예제 "올인"입니다

에서 activity_my_form.xml

    <Button
        android:id="@+id/btnSpinnerPlanets"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="left|center_vertical"
        android:singleLine="true"
        android:text="@string/selectAPlanet"
        android:textSize="10sp"
        android:background="@android:drawable/btn_dropdown">
    </Button>

에서 strings.xml의

<string name="selectAPlanet">Select planet&#8230;</string>

<string-array name="planets__entries">
    <item>The Sun with a name very long so long long long long longThe Sun with a name very long so long long long long longThe Sun with a name very long so long long long long long</item>
    <item>Mercury</item>
    <item>Venus</item>
    <item>Earth</item>
    <item>Mars</item>
    <item>Jupiter</item>
    <item>Saturn</item>
    <item>Uranus</item>
    <item>Neptune</item>
</string-array>

에서 MyFormActivity.java

public class MyFormActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ((Button) findViewById(R.id.btnSpinnerPlanets)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final String[] items = view.getResources().getStringArray(R.array.planets__entries);
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(MyFormActivity.this, android.R.layout.simple_spinner_dropdown_item, items);
                new AlertDialog.Builder(MyFormActivity.this).setTitle("the prompt").setAdapter(adapter, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ((Button) findViewById(R.id.btnSpinnerPlanets)).setText(items[which]);
                        dialog.dismiss();
                    }
                }).create().show();
            }
        });     

    }

}   

마지막으로 글꼴 크기를 구성하여 첫 번째 항목을 선택할 수있는 버튼 스피너를 얻지 못했습니다 !!! HRJ 덕분에


1

확장 할 때 SpinnerAdapter, 당신은이 무시 View-producing 방법을, getView(int, View, ViewGroup)하고 getDropDownView(int, View, ViewGroup). 첫 번째는 View삽입물을 Spinner자체에 공급합니다 . 두 번째 View는 이름에서 알 수 있듯이 드롭 다운 목록에를 제공합니다. getView(...)항목을 선택할 때까지 TextView프롬프트 가 포함 된 메시지를 표시하도록 무시할 수 있습니다 . 그런 다음, 항목이 선택되었음을 감지하면 해당 항목을 표시하도록 변경합니다 TextView.

public class PromptingAdapter extends SpinnerAdapter {

    //... various code ...

    private boolean selectionmade = false;

    //call this method from the OnItemSelectedListener for your Spinner
    public setSelectionState(boolean b) {
        selectionmade = b;
    }

    @Override
    public View getView(int position, View recycle, ViewGroup container) {
        if(selectionmade) {
            //your existing code to supply a View for the Spinner
            //you could even put "return getDropDownView(position, recycle, container);"
        }
        else {
            View output;
            if(recycle instanceof TextView) {
                 output = recycle;
            }
            else {
                 output = new TextView();
                 //and layout stuff
            }
            output.setText(R.string.please_select_one);
            //put a string "please_select_one" in res/values/strings.xml
            return output;
        }
    }

//...
}

1
이 방법에서 결함을 발견했습니다. 스피너가 항목을 즉시 자동으로 선택합니다. 나는 이것의 짧은 길을 찾을 것이다.
— 앤드류 Wyld

너무 빨리 말 했어요 그러나 나는 포기하지 않았다. Spinner튜토리얼 에 따르면 ( Toast이후 항목을 선택했을 것으로 추정 됨 )이 OUGHT가 작동 할 것입니다 : developer.android.com/resources/tutorials/views/…
— Andrew Wyld

1

Xamarin을 사용하는 사람들에게는 위의 aaronvargas의 답변과 동등한 C #이 있습니다.

using Android.Content;
using Android.Database;
using Android.Views;
using Android.Widget;
using Java.Lang;

namespace MyNamespace.Droid
{ 
  public class NothingSelectedSpinnerAdapter : BaseAdapter, ISpinnerAdapter, IListAdapter
  {
    protected static readonly int EXTRA = 1;
    protected ISpinnerAdapter adapter;
    protected Context context;
    protected int nothingSelectedLayout;
    protected int nothingSelectedDropdownLayout;
    protected LayoutInflater layoutInflater;

    public NothingSelectedSpinnerAdapter(ISpinnerAdapter spinnerAdapter, int nothingSelectedLayout, Context context) : this(spinnerAdapter, nothingSelectedLayout, -1, context)
    {
    }

    public NothingSelectedSpinnerAdapter(ISpinnerAdapter spinnerAdapter, int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context)
    {
      this.adapter = spinnerAdapter;
      this.context = context;
      this.nothingSelectedLayout = nothingSelectedLayout;
      this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout;
      layoutInflater = LayoutInflater.From(context);
    }

    protected View GetNothingSelectedView(ViewGroup parent)
    {
      return layoutInflater.Inflate(nothingSelectedLayout, parent, false);
    }

    protected View GetNothingSelectedDropdownView(ViewGroup parent)
    {
      return layoutInflater.Inflate(nothingSelectedDropdownLayout, parent, false);
    }

    public override Object GetItem(int position)
    {
      return position == 0 ? null : adapter.GetItem(position - EXTRA);
    }

    public override long GetItemId(int position)
    {
      return position >= EXTRA ? adapter.GetItemId(position - EXTRA) : position - EXTRA;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
      // This provides the View for the Selected Item in the Spinner, not
      // the dropdown (unless dropdownView is not set).
      if (position == 0)
      {
        return GetNothingSelectedView(parent);
      }

      // Could re-use the convertView if possible.
      return this.adapter.GetView(position - EXTRA, null, parent);
    }

    public override int Count
    {
      get
      {
        int count = this.adapter.Count;
        return count == 0 ? 0 : count + EXTRA;
      }
    }

    public override View GetDropDownView(int position, View convertView, ViewGroup parent)
    {
      // Android BUG! http://code.google.com/p/android/issues/detail?id=17128 -
      // Spinner does not support multiple view types
      if (position == 0)
      {
        return nothingSelectedDropdownLayout == -1 ?
          new View(context) :
          GetNothingSelectedDropdownView(parent);
      }

      // Could re-use the convertView if possible, use setTag...
      return adapter.GetDropDownView(position - EXTRA, null, parent);
    }

    public override int GetItemViewType(int position)
    {
      return 0;
    }

    public override int ViewTypeCount => 1;

    public override bool HasStableIds => this.adapter.HasStableIds;

    public override bool IsEmpty => this.adapter.IsEmpty;

    public override void RegisterDataSetObserver(DataSetObserver observer)
    {
      adapter.RegisterDataSetObserver(observer);
    }

    public override void UnregisterDataSetObserver(DataSetObserver observer)
    {
      adapter.UnregisterDataSetObserver(observer);
    }

    public override bool AreAllItemsEnabled()
    {
      return false;
    }

    public override bool IsEnabled(int position)
    {
      return position > 0;
    }
  }
}

1

또한 다음 코드를 사용하여이 문제를 해결했습니다. 예를 들어 품목 목록이 있다고 가정하십시오.

ArrayList<Item> itemsArrayList = new ArrayList<Item>();
Item item1 = new Item();
item1.setId(1);
item1.setData("First Element");
Item item2 = new Item();
item2.setId(2);
Item2.setData("Second Element");
itemsArrayList.add(item1);
itemsArrayList.add(item2);

이제 스피너가 객체를 이해할 수 없기 때문에 스피너에 문자열을 제공해야합니다. 그래서 우리는 다음과 같은 문자열 항목으로 새로운 배열 목록을 만들 것입니다->

ArrayList<String> itemStringArrayList = new ArrayList<String>();
for(Item item : itemsArrayList) {
    itemStringArrayList.add(item.getData());
}

이제 itemStringArrayList두 개의 문자열 항목 이있는 배열 목록이 있습니다. 그리고 "항목 선택"텍스트를 첫 번째 항목으로 표시해야합니다. 따라서에 새 문자열을 삽입해야합니다 itemStringArrayList.

itemStringArrayList.add("Select Item");

이제 배열 목록이 itemsArrayList있고 드롭 다운에 두 개의 요소를 표시하려고합니다. 그러나 여기서 조건은 ... 우리가 아무것도 선택하지 않으면 Select Item사용할 수없는 첫 번째 요소로 표시되어야합니다.

따라서이 기능을 이와 같이 구현할 수 있습니다. 배열 목록 항목을 Android 스피너에로드해야하는 경우 따라서 일부 어댑터를 사용해야합니다. 여기에을 사용하겠습니다 ArrayAdapter. 사용자 정의 어댑터도 사용할 수 있습니다.

ArrayAdapter<String> itemsArrayAdapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.spinner_item, itemsArrayList){
        @Override
        public boolean isEnabled(int position) {
            if(position == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        @Override
        public View getDropDownView(int position, View convertView,
                                    ViewGroup parent) {
            View view = super.getDropDownView(position, convertView, parent);
            TextView tv = (TextView) view;
            if(position == 0){
                // Set the hint text color gray
                tv.setTextColor(Color.GRAY);
            }
            else {
                tv.setTextColor(Color.BLACK);
            }
            return view;
        }
    };

itemsArrayAdapter.setDropDownViewResource(R.layout.spinner_item);
your_spinner_name.setAdapter(itemsArrayAdapter);

여기이 코드가 있습니다. 우리는 맞춤형 스피너 레이아웃을 사용하고 있습니다 R.layout.spinner_item. 간단한 텍스트보기입니다

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:textStyle="italic"
    android:fontFamily="sans-serif-medium"
    />

스피너의 첫 번째 텍스트를 비활성화해야합니다. 따라서 위치 0의 경우 텍스트를 비활성화합니다. 그리고 색상은 getDropDownView 메서드를 재정 의하여 설정할 수도 있습니다. 이런 식으로 우리는 예상 스피너를 얻을 것입니다.


0

세 가지 중에서 선택해야하는 경우 RadioButtons와 함께 RadioGroup을 사용하면 처음에 모두 선택 해제 할 수 있습니다.


0

이전에 제출 한 답변 중 어느 것도 실제로이 문제를 해결하려는 방식으로 작동하지 않았습니다. 나에게 이상적인 해결책은 스피너가 처음 표시 될 때“하나 선택”(또는 초기 텍스트)을 제공하는 것입니다. 사용자가 스피너를 누를 때 초기 텍스트는 표시되는 드롭 다운의 일부가되어서는 안됩니다.

내 특정 상황을 더 복잡하게하기 위해 내 Spinner 데이터가 LoaderManager 콜백을 통해로드되는 커서에서오고 있습니다.

상당한 실험 끝에 다음 해결책을 찾았습니다.

public class MyFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor>{

private static final String SPINNER_INIT_VALUE = "Select A Widget";
private Spinner mSpinner;
private int mSpinnerPosition;
private boolean mSpinnerDropDownShowing = false;
private View mSpinnerDropDown;

private MyCursorAdapter mCursorAdapter;

...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
...

mCursorAdapter = new MyCursorAdapter(getActivity());

mSpinner = (Spinner) rootView.findViewById(R.id.theSpinner);
mSpinner.setOnTouchListener(mSpinnerTouchListener);
mSpinner.setAdapter(mCursorAdapter);

...
}

//Capture the touch events to toggle the spinner's dropdown visibility
private OnTouchListener mSpinnerTouchListener = new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if(mSpinnerDropDown != null && mSpinnerDropDownShowing == false){
            mSpinnerDropDownShowing = true;
            mSpinnerDropDown.setVisibility(View.VISIBLE);
        }
        return false;
    }
};

//Capture the click event on the spinner drop down items
protected OnClickListener spinnerItemClick = new OnClickListener(){

    @Override
    public void onClick(View view) {
        String widget = ((TextView) view.findViewById(android.R.id.text1)).getText().toString();

        if(!widget.equals(SPINNER_INIT_VALUE)){
            if(mCursorAdapter != null){
                Cursor cursor = mCursorAdapter.getCursor();
                if(cursor.moveToFirst()){
                    while(!cursor.isAfterLast()){
                        if(widget.equals(cursor.getString(WidgetQuery.WIDGET_NAME))){

                            ...

                            //Set the spinner to the correct item
                            mSpinnerPosition = cursor.getPosition() + 1;
                            mSpinner.setSelection(mSpinnerPosition);
                            break;
                        }
                        cursor.moveToNext();
                    }
                }
            }
        }

        //Hide the drop down. Not the most elegent solution but it is the only way I could hide/dismiss the drop down
        mSpinnerDropDown = view.getRootView();
        mSpinnerDropDownShowing = false;
        mSpinnerDropDown.setVisibility(View.GONE);
    }
};

private class MyCursorAdapter extends CursorAdapter {

    private final int DISPLACEMENT = 1;
    private final int DEFAULT_ITEM_ID = Integer.MAX_VALUE;

    private Activity mActivity;

    public MyCursorAdapter(Activity activity) {
            super(activity, null, false);
            mActivity = activity;
    }

    //When loading the regular views, inject the defualt item
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(position == 0){
            if(convertView == null){
                convertView = mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false);
            }
            return getDefaultItem(convertView);
        }
        return super.getView(position - DISPLACEMENT, convertView, parent);
    }

    //When loading the drop down views, set the onClickListener for each view
    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent){
        View view = super.getDropDownView(position, convertView, parent);
        view.setOnClickListener(spinnerItemClick);
        return view;
    }

    //The special default item that is being injected
    private View getDefaultItem(View convertView){
        TextView text = (TextView) convertView.findViewById(android.R.id.text1);
        text.setText(SPINNER_INIT_VALUE);
        return convertView;
    }

    @Override
    public long getItemId(int position) {
        if (position == 0) {
            return DEFAULT_ITEM_ID;
        }
        return super.getItemId(position - DISPLACEMENT);
    }

    @Override
    public boolean isEnabled(int position) {
        return position == 0 ? true : super.isEnabled(position - DISPLACEMENT);
    }

    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount() + DISPLACEMENT;
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0) {
            return super.getViewTypeCount();
        }

        return super.getItemViewType(position - DISPLACEMENT);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor){

        if(cursor.isAfterLast()){
            return;
        }

        TextView text = (TextView) view.findViewById(android.R.id.text1);
        String WidgetName = cursor.getString(WidgetQuery.WIDGET_NAME);
        text.setText(WidgetName);
    }
}
}

0

Spinner 대신 버튼을 사용하여이를 처리합니다. GitHub에 샘플 프로젝트가 있습니다.

프로젝트에서 스피너와 버튼을 모두 표시하여 실제로 동일하게 보이도록 표시합니다. 버튼을 제외하고 원하는대로 초기 텍스트를 설정할 수 있습니다.

활동은 다음과 같습니다.

package com.stevebergamini.spinnerbutton;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Spinner;

public class MainActivity extends Activity {

    Spinner spinner1;
    Button button1;
    AlertDialog ad;
    String[] countries;

    int selected = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        spinner1 = (Spinner) findViewById(R.id.spinner1);
        button1 = (Button) findViewById(R.id.button1);

        countries = getResources().getStringArray(R.array.country_names);

        //  You can also use an adapter for the allert dialog if you'd like
        //  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, countries);        

        ad = new AlertDialog.Builder(MainActivity.this).setSingleChoiceItems(countries, selected,  
                new  DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            button1.setText(countries[which]);
                            selected = which;
                            ad.dismiss();

                        }}).setTitle(R.string.select_country).create(); 


        button1.setOnClickListener( new OnClickListener(){

            @Override
            public void onClick(View v) {
                ad.getListView().setSelection(selected);
                ad.show();              
            }});

    }

}

참고 : 예, 적용된 테마에 따라 다르며 Theme.Holo를 사용하면 모양이 약간 다를 수 있습니다. 그러나 Theme.Black과 같은 레거시 테마 중 하나를 사용하는 경우 좋습니다.


0

이 문제에 직면하는 경우 항목은 데이터베이스 커서에서 채워집니다이 때 ,

이 SO 답변 에서 찾은 가장 간단한 솔루션 :

커서 어댑터 쿼리에서 UNION을 사용 하고 실제로 DB에 추가하지 않고 id = -1 인 추가 항목을 쿼리 결과에 추가하십시오.

같은 :

db.rawQuery ( "_ id로 iWorkerId를 선택하고, 작업자에서 이름으로 nvLastName을 선택하십시오. w UNION SELECT -1을 _id로, ''를 이름으로", null);

선택한 항목이 -1이면 기본값입니다. 그렇지 않으면 테이블의 레코드입니다.


0

독창적 인 솔루션으로 보이지만 일반적으로 스피너 앞에 TextView를 넣습니다. 전체 Xml은 다음과 같습니다. (이봐들, 날 쏘지 마라. 나는 너희 중 누군가가 이런 종류의 결혼을 좋아하지 않는다는 것을 안다) :

<FrameLayout
    android:id="@+id/selectTypesLinear"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <Spinner
        android:id="@+id/spinnerExercises"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:entries="@array/exercise_spinner_entries"
        android:prompt="@string/exercise_spinner_prompt"
     />                         
    <TextView
        android:id="@+id/spinnerSelectText"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Hey! Select this guy!"
        android:gravity="center"
        android:background="#FF000000" />


</FrameLayout>

그런 다음 항목을 선택할 때 TextView를 숨 깁니다. 분명히 TextView의 배경색은 Spinner와 같아야합니다. 안드로이드 4.0에서 작동합니다. 이전 버전에서는 모릅니다.

예. Spinner가 처음에 setOnItemSelectedListener를 호출하기 때문에 textview를 숨기는 것이 약간 까다로울 수 있지만 다음과 같이 수행 할 수 있습니다.

    Boolean controlTouched;

    exerciseSpinner.setOnTouchListener(new OnTouchListener() {


        @Override
        public boolean onTouch(View v, MotionEvent event) {
            controlTouched = true; // I touched it but but not yet selected an Item.
            return false;
        }

    });
    exerciseSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> arg0, View arg1,
                int arg2, long arg3) {
            if (controlTouched) { // Are you sure that I touched it with my fingers and not someone else  ?
                spinnerSelText.setVisibility(View.GONE);
            }
        }

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

    });

0

나를 위해 그것은 이런 식으로 일했습니다. 일부 옵션의 텍스트 만 변경하는 기능이 향상되었습니다.

먼저 스피너의 이름을 사용하여 사용자 정의보기로 arrayadapter를 만들지 만 지금은 중요하지 않습니다. 키가 getView를 재정의하고 내부 변경 해야하는 값을 변경하십시오. 내 경우에는 첫 번째 사건이었고 나머지는 원본을 남겼습니다.

public void rellenarSpinnerCompeticiones(){
        spinnerArrayCompeticiones = new ArrayList<String>();
        for(Competicion c: ((Controlador)getApplication()).getCompeticiones()){
            spinnerArrayCompeticiones.add(c.getNombre());
        }
        //ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this,R.layout.spinner_item_competicion,spinnerArrayCompeticiones);
        ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this, R.layout.spinner_item_competicion, spinnerArrayCompeticiones){
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                final View v = vi.inflate(R.layout.spinner_item_competicion, null);
                final TextView t = (TextView)v.findViewById(R.id.tvCompeticion);
                if(spinnerCompeticion.getSelectedItemPosition()>0){
                    t.setText(spinnerArrayCompeticiones.get(spinnerCompeticion.getSelectedItemPosition()));
                }else{
                    t.setText("Competiciones");
                }
                return v;
            }
        };
        spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinnerCompeticion.setAdapter(spinnerArrayAdapter);
    }

0

여기 간단한 것이 있습니다

    private boolean isFirst = true;
private void setAdapter() {
    final ArrayList<String> spinnerArray = new ArrayList<String>();     
    spinnerArray.add("Select your option");
    spinnerArray.add("Option 1");
    spinnerArray.add("Option 2");
    spin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            TextView tv = (TextView)selectedItemView;
            String res = tv.getText().toString().trim();
            if (res.equals("Option 1")) {
            //do Something
        } else if (res.equals("Option 2")) {
            //do Something else
        }
        }

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

    });

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.my_spinner_style,spinnerArray) {
         public View getView(int position, View convertView, ViewGroup parent) {
             View v = super.getView(position, convertView, parent);
             int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, getResources().getDisplayMetrics());                  
             ((TextView) v).setTypeface(tf2);
             ((TextView) v).getLayoutParams().height = height;
             ((TextView) v).setGravity(Gravity.CENTER);
             ((TextView) v).setTextSize(TypedValue.COMPLEX_UNIT_SP, 19);
             ((TextView) v).setTextColor(Color.WHITE);
             return v;
         }

         public View getDropDownView(int position, View convertView,
                 ViewGroup parent) {
             if (isFirst) {
                 isFirst = false;
                 spinnerArray.remove(0);
             }
             View v = super.getDropDownView(position, convertView, parent);                  
             ((TextView) v).setTextColor(Color.argb(255, 70, 70, 70));
             ((TextView) v).setTypeface(tf2);
             ((TextView) v).setGravity(Gravity.CENTER);
             return v;
         }
     };
     spin.setAdapter(adapter);
}

0

위의 답변 중 하나를 참조하십시오 : https://stackoverflow.com/a/23005376/1312796

약간의 버그를 수정하기 위해 코드를 추가했습니다. 데이터가 검색되지 않은 곳 .. 프롬프트 텍스트를 표시하는 방법 ..!

여기 내 트릭이 있습니다 ... 나와 잘 작동합니다. !

스피너를 Relative_layout에 놓고 스피너와 Textview를 정렬하고 스피너의 어댑터가로드되거나 비어있을 때마다 Textview (SHOW / HIDE)의 가시성을 가지고 놀아보십시오.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="20dp"
android:background="#ededed"
android:orientation="vertical">



    <TextView
        android:id="@+id/txt_prompt_from"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:textColor="@color/gray"
        android:textSize="16sp"
        android:layout_alignStart="@+id/sp_from"
        android:text="From"
        android:visibility="gone"/>

    <Spinner
        android:id="@+id/sp_from"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        />

코드는 다음과 같습니다.

  txt__from = (TextView) rootView.findViewById(R.id.txt_prompt_from);

스피너 어댑터를로드 한 후 비우기 전과 후에이 메소드를 호출하십시오.

setPromptTextViewVisibility (); //True or fales 

public void setPromptTextViewVisibility (boolean visible )
{
    if (visible)
    {
        txt_from.setVisibility(View.VISIBLE);
    }
    else
    {
        txt_from.setVisibility(View.INVISIBLE);
    }

}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.