Como fazer um Android Spinner com o texto inicial "Select One"?

569

Eu quero usar um Spinner que inicialmente (quando o usuário ainda não fez uma seleção) exibe o texto "Selecionar um". Quando o usuário clica no botão giratório, a lista de itens é exibida e o usuário seleciona uma das opções. Depois que o usuário faz uma seleção, o item selecionado é exibido no Spinner em vez de "Select One".

Eu tenho o seguinte código para criar um 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);

Com este código, inicialmente o item "Um" é exibido. Eu poderia apenas adicionar um novo item "Selecionar um" aos itens, mas, em seguida, "Selecionar um" também seria exibido na lista suspensa como primeiro item, o que não é o que eu quero.

Como posso resolver este problema?

Pieter Kuijpers
fonte
6
A solução perfeita está nesta pergunta: stackoverflow.com/questions/9863378/… Basta substituir o método getDropDownView ().
Sourab Sharma
Você já tentou definir o primeiro elemento do seu adaptador para "Selecionar um"?
IgorGanapolsky
[Aqui está outra ótima solução interessante!] [1] [1]: stackoverflow.com/questions/9863378/…
AirtonCarneiro
spinner reutilizável: github.com/henrychuangtw/ReuseSpinner
HenryChuang

Respostas:

255

Aqui está uma solução geral que substitui a Spinnerexibição. Substitui setAdapter()para definir a posição inicial como -1 e proxies do fornecido SpinnerAdapterpara exibir a sequência de prompt para a posição menor que 0.

Isso foi testado no Android 1.5 a 4.2, mas cuidado com o comprador! Porque esta solução depende de reflexão para chamar o privado AdapterView.setNextSelectedPositionInt()e AdapterView.setSelectedPositionInt(), não é garantido que funcione em futuras atualizações do sistema operacional. Parece provável que sim, mas não é de forma alguma garantido.

Normalmente, eu não toleraria algo assim, mas essa pergunta já foi feita várias vezes e parece uma solicitação razoável o suficiente para que eu pensasse em publicar minha solução.

/**
 * 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);
        }
    }
}
empapar
fonte
7
@emmby Você tem alguma idéia de como limpar a seleção depois que o usuário a definir? Tentei refatorar as duas chamadas invoke () em um método clearSelection (), mas na verdade não funciona. Embora a lista pop-up mostre o item selecionado anteriormente como desmarcado, o widget giratório ainda o mostra como selecionado e, se o usuário selecionar o mesmo item novamente, onItemSelected () não será chamado.
Qwertie 18/04
3
alguns poderiam explicar como usar a classe acima?
Bishan
4
Esta solução não é 100% perfeita no Android 4.2 (Cyanogenmod 10.1), usando entradas android:. A altura do TextView inflado é menor que a altura do recurso que o Adaptador padrão inflar. Então, quando você realmente seleciona uma opção, a altura aumenta em ~ 10px no meu Galaxy S, o que não é aceitável. Eu tentei várias coisas (gravidade, preenchimento, margem etc.) e nenhuma funcionou de maneira confiável em todos os dispositivos, por isso vou optar por uma solução diferente.
Maragues
3
@DavidDoria Você precisa usar a classe NoDefaultSpinner no seu arquivo de layout. Copie a fonte de cima para o seu projeto, por exemplo, no pacote com.example.customviews. Agora, no seu xml de layout, em vez de <Spinner ...> use <com.example.customviews.NoDefaultSpinner ...> O restante do código pode permanecer o mesmo. Não se esqueça de adicionar o atributo android: prompt à visualização <com.example.customviews.NoDefaultSpinner> no seu layout.
Ridcully
2
@emmby spinnerBrand.setSelection (-1); não está funcionando
Sachin C
291

O que você pode fazer é decorar SpinnerAdaptercom um que apresente uma exibição 'Selecionar opção ...' inicialmente para que o Spinner seja exibido sem nada selecionado.

Aqui está um exemplo de trabalho testado para Android 2.3 e 4.0 (ele não usa nada na biblioteca de compatibilidade, por isso deve ficar bom por um tempo) Como é um decorador, deve ser fácil atualizar o código existente e funciona bem com CursorLoaders também. (Trocar o cursor no embrulho, é cursorAdapterclaro ...)

Há um bug no Android que torna um pouco mais difícil reutilizar visualizações. (Portanto, você deve usar o setTagou qualquer outra coisa para garantir a sua convertViewcorreção.) O Spinner não suporta vários tipos de exibição

Notas de código: 2 construtores

Isso permite que você use um prompt padrão ou defina seu próprio 'nada selecionado' como a primeira linha, ou ambas, ou nenhuma. (Nota: alguns temas mostram um DropDown para um Spinner em vez de uma caixa de diálogo. O Dropdown normalmente não mostra o prompt)

Você define um layout para 'parecer' como um prompt, por exemplo, esmaecido ...

Nada inicial selecionado

Usando um prompt padrão (observe que nada está selecionado):

Com um prompt padrão

Ou com um prompt e algo dinâmico (poderia não ter nenhum prompt também):

Linha prompt e nada selecionado

Uso no exemplo acima

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

}
aaronvargas
fonte
52
Esta é uma solução elegante para o problema. O código funciona exatamente como copiado e copiado no meu projeto. +1 para nenhuma reflexão necessária.
Richard Le Mesurier
2
Esta é uma otima soluçao. Se alguém quiser saber como substituir o título não apenas antes de um item ser selecionado, mas a todo momento, na chamada getView (), retorne sempre getNothingSelectedView (ou qualquer outra visualização personalizada). A lista suspensa ainda será preenchida com itens do seu adaptador, mas agora você pode controlar o título APÓS que algo seja selecionado também.
OldSchool4664
6
Esta é uma solução realmente elegante para um problema que não deveria existir (tente o desenvolvimento do Iphone). Ótimo e obrigado! Fico feliz que alguém se lembrou de padrões etc.
user1700737:
3
@prashantwosti, o código foi atualizado para funcionar com o Lollipop. Especificamente getItemViewType () e getViewTypeCount ().
aaronvargas
3
@aaronvargas depois de selecionar um item do botão giratório, posso desfazer e selecionar "[Selecionar um planeta]"?
Modleckham
130

Acabei usando um em Buttonvez disso. Enquanto a Buttonnão é a Spinner, o comportamento é fácil de personalizar.

Primeiro, crie o adaptador como de costume:

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

Observe que estou usando o simple_spinner_dropdown_itemcomo o ID do layout. Isso ajudará a criar uma aparência melhor ao criar a caixa de diálogo de alerta.

No manipulador onClick do meu Button, tenho:

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

E é isso!

HRJ
fonte
10
Eu concordo com essa resposta. Além disso, um botão é muito mais fácil de estilizar do que um Spinner.
Romain Piel
@HRJ Eu implementei da maneira que você sugeriu, mas o item selecionado anteriormente não está sendo destacado (significa que o botão de opção deve ser destacado com um ponto verde no meio) .... Como posso obter isso no método OnClick () de botão. Por favor me ajude HRJ .....
Avadhani Y
2
O botão com esse layout é perfeito <Botão android: id = "@ + id / cidade" 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 12/01/14
Como você atualizaria o texto do botão para refletir a seleção, como aconteceria em um girador?
shim 28/01
3
solução do problema: apenas em vez de SetAdapter, use SetSingleChoiceItems
Grzegorz Dev
67

Primeiro, você pode estar interessado no promptatributo da Spinnerclasse. Veja a figura abaixo: "Escolha um planeta" é o prompt que pode ser definido no XML com android:prompt="".

insira a descrição da imagem aqui

Eu sugeriria a subclasse Spinner, onde você poderia manter dois adaptadores internamente. Um adaptador que possui a opção "Selecionar um" e o outro adaptador real (com as opções reais), usando o OnClickListenerpara alternar os adaptadores antes que a caixa de diálogo de opções seja mostrada. No entanto, depois de tentar implementar essa ideia, cheguei à conclusão de que você não pode receber OnClickeventos para o próprio widget.

Você pode envolver o botão giratório em uma visualização diferente, interceptar os cliques na visualização e solicitar que você CustomSpinnertroque o adaptador, mas parece um hack terrível.

Você realmente precisa mostrar "Select One"?

Casey
fonte
36
Não é apenas uma questão de mostrar "Selecionar um", mas também abordar o caso em que o valor do botão giratório pode opcionalmente ser deixado em branco.
Greg7gkb
5
Além disso, com esta opção, a Terra é mostrado como a selecção no Spinner antes de qualquer coisa foi escolhido, para meu aplicativo eu preferia o usuário será capaz de dizer que não tinha escolhido nada ainda
dylan murphy
2
isso realmente não responde à pergunta. as pessoas estão procurando uma maneira de ter o próprio girador por padrão mostrar "Select One", em vez do primeiro item na lista de planetas, neste exemplo
JMRboosties
58

Este código foi testado e funciona no Android 4.4

insira a descrição da imagem aqui

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);
Manos
fonte
getItem(getCount())está sublinhado em vermelho para mim? Não é possível resolver o método setHint
Zapnologica
Eu tenho uma dúvida, vi muitas soluções neste segmento .. mas por que todo mundo está adicionando dica para o último. É errado adicionar dica na primeira linha?
akashPatra
Não consigo definir 'setOnItemSelectedListener (this);' porque estou usando 'implementa NavigationView.OnNavigationItemSelectedListener', posso remover 'setOnItemSelectedListener (this);' sem problemas?
CGR
@akashpatra A razão pela qual eles adicionam uma última dica é que o ArrayAdapter for spinner pode obter seus valores de diferentes fontes em tempo de execução.
VinKrish
isso realmente me ajudou
Sunil
31

Encontrei esta solução:

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

Apenas mude a matriz [0] com "Selecionar uma" e, em seguida, no onItemSelected, renomeie para "Uma".

Não é uma solução elegante, mas funciona: D

Marco da Gualdo
fonte
5
Isto não funcionou para mim. Depois de escolher o item "Um", ele ainda diz "Selecionar um".
Leo Landau
Isso não funcionará, pois a interface onItemSelected chamará pela primeira vez sempre.
Vaibhav Kadam
20

Não existe uma API padrão para definir dicas no Spinner. Para adicioná-lo, precisamos de uma pequena solução alternativa, sem a implementação da reflexão de segurança

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

Fonte do adaptador:

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

Fonte original

Yakiv Mospan
fonte
o que é R.id.text1? é algum layout ou visão? por favor elabore sua resposta
Anand Savjani 31/03
Deveria serandroid.R.id.text1
Yakiv Mospan 31/03/16
Eu tenho uma dúvida, vi muitas soluções neste segmento .. mas por que todo mundo está adicionando dica para o último. É errado adicionar dica na primeira linha?
akashPatra
@akashpatra Não me lembro exatamente, mas parece que houve algum problema quando tentei fazê-lo como a primeira lista de itens. De qualquer forma você sempre pode experimentá-lo e comentar aqui, toda a magia aqui é em torno de getCountmétodo
Yakiv Mospan
@YakivMospan Recebo um NPE quando o uso, provavelmente devido ao Reflection ao usar o ProGuard. Você sabe como consertar isso?
Alan
17

Muitas respostas aqui, mas estou surpreso que ninguém tenha sugerido uma solução simples: Coloque um TextView em cima do Spinner. Defina um ouvinte de clique no TextView que oculta o TextView mostra o Spinner e chama spinner.performClick ().

mjancola
fonte
9

Eu tive o mesmo problema para o spinner, com uma seleção vazia, e encontrei uma solução melhor. Dê uma olhada neste código simples.

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

Aqui, spinneradapter é uma pequena personalização para o arrayadapter. Se parece com isso:

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);
    }
}
Rajasekhar
fonte
6
O problema dessa abordagem é que ela ainda seleciona o primeiro item da lista quando a lista é exibida. Como já está selecionado, você não pode tocá-lo para selecionar - ele age como se nenhum deles tivesse acontecido.
jwadsack
7

Você pode alterá-lo para uma exibição de texto e usar o seguinte:

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

e depois defina a android:textpropriedade

Christian Vielma
fonte
Funciona apenas para API 14 e superior.
Giulio Piancastelli 25/09
6

Arquivo XML:

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

Atividade:

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

Alguma função (adicione itens ao adaptador programaticamente)>

featuresAdapter.add("some string");

Agora você tem um botão giratório vazio e pode escrever um código para não abrir a caixa de diálogo se estiver vazio. Ou eles podem pressionar de volta. Mas você também a preenche com uma função ou outra lista durante o tempo de execução.

trgraglia
fonte
Também não há necessidade de notifyDataSetChanged (), pois deve ser definido como true por padrão.
trgraglia
4

Eu tentei como o seguinte. Pegue um botão e atribua o evento click. Ao alterar o plano de fundo do botão, parece ser um botão giratório.

Declarar como variáveis ​​globais alertdialog e valor padrão.

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();
    }
});
Ramesh Akula
fonte
4

Esse é meu jeito:

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
Cabezas
fonte
isso abre o spinner na posição inferior
SpyZip
3

Dê uma olhada no aplicativo iosched para obter uma solução de uso geral para adicionar um elemento ao topo de uma lista. Em particular, se você estiver usando um CursorAdapter, consulte TracksAdapter.java, que estende essa definição para fornecer um método "setHasAllItem" e código associado para gerenciar a contagem de listas e lidar com o item extra na parte superior.

Usando o adaptador personalizado, você pode definir o texto como "Selecionar um" ou o que mais você desejar.

Esporte
fonte
3

Eu tenho um botão giratório no meu main.xml e seu ID é @+id/spinner1

isto é o que eu escrevo na minha função 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) { }
});

Não precisa de nenhuma implementação na classe.

Cyril
fonte
3

Encontrei muitas boas soluções para isso. a maioria está funcionando adicionando um item ao final do adaptador e não exibe o último item na lista suspensa. O grande problema para mim foi que a lista suspensa giratória começará no final da lista. Assim, o usuário vê os últimos itens em vez dos primeiros (no caso de haver muitos itens para mostrar), depois de tocar no botão giratório pela primeira vez.

Então, eu coloquei o item de dica no início da lista. e oculte o primeiro item na lista suspensa.

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

defina o layout abaixo em @Override getDropDownView () quando position for 0, para ocultar a primeira linha de dica.

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>
Alireza Sobhani
fonte
3

Além disso, há um truque simples para mostrar o padrão:

Você pode adicionar um valor padrão à sua lista e adicionar toda a sua coleção usando list.addAll(yourCollection);

Exemplo de código viável aqui:

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

Espero que ele recupere sua complexidade. Feliz codificação!

Majedur Rahaman
fonte
2

Eu acho que a maneira mais fácil é criar um item fictício no índice 0 dizendo "selecione um" e, em seguida, salvar talvez verifique se a seleção não é 0.

Tobias
fonte
4
Que tal visualizar a lista de itens? Deseja ver a posição "selecione uma" na parte superior? Não é apenas a questão de economizar.
Krzysztof Wolny
@KrzysztofWolny Spinner, por padrão, exibe o item na posição 0
rds
2

Portanto, este é o meu exemplo final "all-in" para um botão giratório

Em 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>

Em 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>

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

    }

}   

Finalmente, obtive um tamanho de fonte configurável, sem o primeiro item selecionável por botão giratório !!! Graças a HRJ

selvagem
fonte
1

Ao estender SpinnerAdapter, você substitui dois Viewmétodos de produção getView(int, View, ViewGroup)e getDropDownView(int, View, ViewGroup). O primeiro fornece o Viewinserido no Spinnerpróprio; o segundo fornece a Viewlista suspensa (como o nome sugere). Você pode substituir o getView(...)item para que, até que um item seja selecionado, ele exiba um TextViewcontendo um prompt; quando detectar que um item foi selecionado, altere-o para exibir um TextViewcorrespondente a ele.

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

//...
}
Andrew Wyld
fonte
1
Descobri uma falha neste método: o Spinner seleciona automaticamente um item imediatamente. Vou encontrar uma maneira de contornar isso em breve.
precisa
Eu falei cedo demais. Eu não desisti, no entanto. Note-se que de acordo com o Spinnertutorial (que supostamente exibe uma Toastdepois de ter seleccionado um item) Isso deve funcionar: developer.android.com/resources/tutorials/views/...
Andrew Wyld
1

Para aqueles que usam Xamarin, aqui está o C # equivalente à resposta de aaronvargas acima.

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;
    }
  }
}
MPavlak
fonte
1

Também resolvi esse problema usando o código a seguir. Suponha que você esteja tendo uma lista de itens, por exemplo

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

Agora temos que fornecer as strings para o spinner, porque o spinner não consegue entender o objeto. Então, criaremos uma nova lista de array com itens de string como este ->

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

Agora temos uma itemStringArrayListlista de matrizes com dois itens de sequência. E temos que mostrar o texto "Selecionar item" como primeiro item. Portanto, temos que inserir uma nova string no itemStringArrayList.

itemStringArrayList.add("Select Item");

Agora temos uma lista de matrizes itemsArrayListe queremos mostrar dois elementos no menu suspenso. Mas a condição aqui é ... Se não selecionarmos nada, ele Select Itemdeverá aparecer como o primeiro elemento que não será ativado.

Portanto, podemos implementar essa funcionalidade assim. Se você precisar carregar os itens da lista de arrays no Android Spinner. Então você terá que usar algum adaptador. Então aqui eu vou usar o ArrayAdapter. Também podemos usar o adaptador de personalização.

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

Aqui neste código. estamos usando o layout giratório personalizado, ou seja R.layout.spinner_item. É uma visualização de texto simples

<?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"
    />

Precisamos desativar o primeiro texto no botão giratório. Portanto, para a posição 0, estamos desativando o texto. E também podemos definir cores substituindo o método getDropDownView. Portanto, dessa forma, obteremos o spinner esperado.

Shravan Jain
fonte
0

Eu usaria um RadioGroup com RadioButtons, se você tiver apenas três opções, poderá desmarcá-las primeiro.

stephane k.
fonte
0

Nenhuma das respostas enviadas anteriormente realmente funcionou da maneira que eu queria resolver esse problema. Para mim, a solução ideal forneceria o “Select One” (ou qualquer texto inicial) quando o botão giratório for exibido pela primeira vez. Quando o usuário toca no botão giratório, o texto inicial não deve fazer parte da lista suspensa exibida.

Para complicar ainda mais minha situação específica, meus dados giratórios estão chegando de um cursor carregado através dos retornos de chamada do LoaderManager.

Após considerável experimentação, vim com a seguinte solução:

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);
    }
}
}
Jed
fonte
0

Eu lido com isso usando um botão em vez de um Spinner. Eu tenho o projeto de amostra no GitHub.

No projeto, estou exibindo o Spinner e o botão para mostrar que eles realmente parecem idênticos. Exceto o botão, você pode definir o texto inicial para o que quiser.

Aqui está a aparência da atividade:

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

    }

}

NOTA: Sim, eu sei que isso depende do tema aplicado e a aparência será um pouco diferente se você usar o Theme.Holo. No entanto, se você estiver usando um dos temas herdados, como Theme.Black, estará pronto.

SBerg413
fonte
0

se você estiver enfrentando esse problema quando seus itens forem preenchidos a partir do cursor do banco de dados ,

a solução mais simples que encontrei nesta resposta SO:

use UNION na consulta do adaptador do cursor e adicione o item adicional com id = -1 ao resultado da consulta, sem realmente adicioná-lo ao banco de dados:

algo como:

db.rawQuery ("SELECT iWorkerId como _id, nvLastName como nome FROM Worker w UNION SELECT -1 como _id, '' como nome", nulo);

se o item selecionado for -1, será o valor padrão. Caso contrário, é um registro da tabela.

dvrm
fonte
0

Parece uma solução banal, mas geralmente coloco simplesmente um TextView na frente do botão giratório. O Xml inteiro fica assim. (ei pessoal, não atire em mim, eu sei que alguns de vocês não gostam desse tipo de casamento):

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

Então, oculto o TextView quando um item foi selecionado. Obviamente, a cor de fundo do TextView deve ser a mesma do Spinner. Funciona no Android 4.0. Não sei em versões mais antigas.

Sim. Como o Spinner chama setOnItemSelectedListener no início, a ocultação da visualização de texto pode ser um pouco complicada, mas pode ser feita desta maneira:

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

    });
Claudio Ferraro
fonte
0

para mim, funcionou algo assim. tem a melhoria que altera apenas o texto em algumas opções, não em todas.

Primeiro, pego os nomes do girador e crio o adaptador de matriz com uma visualização customizada, mas isso não importa agora, a chave é substituir o getView e, dentro, alterar os valores que você precisa alterar. No meu caso foi apenas o primeiro, o resto deixo o original

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);
    }
Rako
fonte
0

aqui está um simples

    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);
}
Sayka
fonte
0

Consulte uma das respostas acima: https://stackoverflow.com/a/23005376/1312796

Eu adicionei meu código para corrigir um pequeno bug. Que onde nenhum dado recuperado .. Como mostrar o texto do prompt ..!

Aqui está o meu truque ... Funciona bem comigo. !

Tente colocar seu botão giratório em um Relative_layout e alinhe um Textview com o botão giratório e brinque com a visibilidade do Textview (SHOW / HIDE) sempre que o adaptador do botão giratório estiver carregado ou vazio.

<?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"
        />

Aqui está o código:

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

chame esse método antes e antes do adaptador giratório carregado e vazio.

setPromptTextViewVisibility (); //True or fales 

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

}
Ibrahim AbdelGawad
fonte