초기 텍스트“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.