android - 스튜디오 - 안드로이드 커스텀 스피너




초기 텍스트가 '하나 선택'인 Android Spinner를 만드는 방법 (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;
    }
}

원본 소스

안드로이드에서 처음에는 Spinner를 사용하고 싶습니다. 사용자가 아직 선택하지 않은 경우에는 "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"도 첫 번째 항목으로 드롭 다운 목록에 표시됩니다. 이는 원하는 항목이 아닙니다.

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


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");

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


그래서 이것은 버튼 - 스피너에 대한 "all-in"의 마지막 예입니다.

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에 ​​감사드립니다.


나는 다음과 같이 시도했다. 버튼을 클릭하고 클릭 이벤트를 전달하십시오. 단추 배경을 변경하면 회 전자 인 것 같습니다.

글로벌 변수 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();
    }
});

나는이 해결책을 찾았다.

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


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

이 클래스에는 구현이 필요하지 않습니다.


대신 Button 을 사용하여 종료되었습니다. ButtonSpinner 가 아니지만 사용자 정의하기 쉽습니다.

먼저 어댑터를 작성하십시오.

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

레이아웃 ID로 simple_spinner_dropdown_item 을 사용하고 있습니다. 이렇게하면 경고 대화 상자를 작성할 때 더 나은 모양을 만들 수 있습니다.

내 단추에 대한 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();
}

그리고 그게 다야!


먼저, Spinner 클래스의 prompt 속성에 관심이있을 것입니다. 아래 그림을 보면 "Choose a Planet"은 android:prompt="" XML에 설정할 수있는 프롬프트입니다.

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

회 전자를 다른보기로 감싸고보기의 클릭을 차단 한 다음 CustomSpinner 에게 어댑터를 전환하라고 알려줄 수 있지만 무서운 해킹처럼 보일 수 있습니다.

"Select One"을 정말로 보여줄 필요가 있습니까?


빈 선택과 함께 스피너에 대해 동일한 문제가 발생했으며 더 나은 솔루션을 발견했습니다. 이 간단한 코드를 살펴보십시오.

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

여기에 많은 답변이 있지만 아무도 간단한 해결책을 제안한 것이 놀랍습니다. TextView를 Spinner 상단에 놓습니다. TextView에 클릭 리스너를 설정하면 TextView가 숨겨져 Spinner가 표시되고 spinner.performClick ()이 호출됩니다.


이게 내 방법이야:

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

텍스트보기로 변경하고 다음을 사용할 수 있습니다.

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

android:text 속성을 정의하십시오.


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

세 가지 옵션 만있는 경우 RadioButton을 사용하는 RadioGroup을 사용하면 처음에는 선택을 해제 할 수 있습니다.


항목이 데이터베이스 커서에서 채워지는 경우이 문제가 발생하는 경우 ,

this SO 답변 에서 찾은 가장 간단한 해결책은 다음과 같습니다.

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

뭔가 :

db.rawQuery ( "_id로 선택 iWorkerId, 이름으로 nvLastName 작업자와 UNION SELECT -1, _id로, ''이름으로", null);

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


나는 Spinner 대신 버튼을 사용하여 이것을 처리한다. 나는 샘플 프로젝트를 GitHub에 올려 놓았다.

프로젝트에서 Spinner와 버튼이 실제로 동일하게 보이는지 표시하고 있습니다. 버튼을 제외하고는 원하는대로 초기 텍스트를 설정할 수 있습니다.

활동 내용은 다음과 같습니다.

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과 같은 기존 테마 중 하나를 사용한다면 잘 할 수 있습니다.


나를 위해 그것은 이런 식으로 일했습니다. 모든 옵션이 아닌 일부 옵션의 텍스트 만 변경하는 개선 사항이 있습니다.

먼저 스피너의 이름을 가져 와서 사용자 정의 뷰가있는 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);
    }

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

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활성화되지 않을 첫 번째 요소로 나타나야합니다.

그래서 우리는 이런 기능을 구현할 수 있습니다. 안드로이드 스피너에 배열 목록 항목을로드해야하는 경우. 따라서 일부 어댑터를 사용해야합니다. 그래서 여기에 내가 사용할거야 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);

여기이 코드에서. 우리는 사용자 정의 스피너 레이아웃 ie를 사용하고 있습니다 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 메소드를 오버라이드하여 설정할 수도 있습니다. 이렇게해서 우리는 예상되는 회 전자를 얻을 수 있습니다.


이전에 제출 된 답변 중 아무 것도이 문제를 해결하고 싶지 않았습니다. 나에게 이상적인 솔루션은 회 전자가 처음 표시 될 때 "하나 선택"(또는 초기 텍스트가 무엇이든)을 제공합니다. 사용자가 회 전자를 누를 때 초기 텍스트는 표시되는 드롭 다운의 일부가 아니어야합니다.

내 특정 상황을 더욱 복잡하게 만들기 위해 회 전자 데이터가 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);
    }
}
}

진부한 솔루션으로 보였지만 대개 단순히 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와 동일해야합니다. Android 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) {
        }

    });






android-spinner