Después de usar la biblioteca de compatibilidad de diseño de Android TextInputLayout
para colocar una etiqueta flotante sobre un EditText
componente, me preguntaba si hay una manera de agregar una etiqueta flotante al Spinner
componente (no necesariamente usando la biblioteca de diseño).
Con esto, me refiero a algo como un TextView
colocado encima de Spinner
(obviamente no hay animaciones como TextInputLayout
), pero quiero que el tamañoTextInputLayout
del texto, la fuente y el color coincidan con los de la etiqueta flotante de .
Por ejemplo, se vería así (vea las etiquetas sobre las Spinner
s):
Como mencioné antes, mi objetivo principal es tener una etiqueta encima del Spinner
, al igual que en el TextInputLayout
, por lo que el tamaño del texto, la fuente, el color y las distancias entre la etiqueta y el componente serían los mismos.
En la página de Google Design sobre campos de texto de etiquetas flotantes , hay un diagrama que muestra las dimensiones de la etiqueta en relación con el componente, pero no hay indicación del color o tamaño del texto de la etiqueta:
Entonces, para resumir, estoy preguntando:
- Si hay un componente especial para lograr lo que estoy pidiendo o una vista personalizada que pueda usar, cuál sería y cómo puedo usarla.
- Si no es así, ¿cuál es el tamaño, el color y la fuente del texto de la etiqueta flotante, para que pueda colocar una TextView
encima de mi Spinner
con las dimensiones del diseño que se muestran en la imagen de arriba?
EDITAR:
De las pautas de diseño de Google para campos de texto , tiene lo siguiente para etiquetas flotantes:
Sugerencia y fuente de entrada: Roboto Regular 16sp
Fuente de etiqueta: Roboto Regular 12sp
Altura del mosaico: 72dp Relleno
superior e inferior del
texto : 16dp Relleno del divisor del campo de texto: 8dp
así como las imágenes que se muestran arriba.
Entonces, la fuente de la etiqueta flotante es: Roboto Regular 12sp . Por lo tanto, puede usar a TextView
para mostrar la Spinner
etiqueta, ya que no conozco ningún View
componente especial o personalizado que pueda usar.
Sin embargo , después de probarlo, no se ve tan bien como el ejemplo que se muestra en la imagen. Una vista personalizada puede ser mejor para esto , ya que podría verse mejor, pero la solución anterior es solo una forma de lograr algo cercano a lo que quería originalmente.
fuente
<item name="android:textColor">?android:textColorHint</item>
su estilo para obtener el mismo color de texto en la etiqueta personalizada que se usa en TextInputLayout en estado desenfocado.SpinnerLabel
lugar deInputLabel
usarlo solo para hilanderos.Logré esto usando un AutoCompleteTextView, deshabilitando el teclado y mostrando las opciones al tacto.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, getResources().getStringArray(R.array.locations)); AutoCompleteTextView mTextView = (AutoCompleteTextView) findViewById(R.id.location); mTextView.setAdapter(adapter); mTextView.setKeyListener(null); mTextView.setOnTouchListener(new View.OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event){ ((AutoCompleteTextView) v).showDropDown(); return false; } });
fuente
TextInputLayout
, asegurando así que tendrá la apariencia correcta exacta.R.layout.support_simple_spinner_dropdown_item
lugar deandroid.R.layout.simple_spinner_item
mTextView.setText(...)
, no recibirá todos los valores del adaptador en el menú desplegable ... La llamadaadapter.getFilter().filter(null);
muestra nuevamente todas las sugerenciasTengo una esencia hecha por mí mismo para resolver el mismo problema que tienes.
Echale un vistazo:
https://gist.github.com/rodrigohenriques/77398a81b5d01ac71c3b
Ahora no necesito hilanderos. Seguirá teniendo efecto de etiqueta flotante con animaciones incluidas.
fuente
setInputType(InputType.TYPE_NULL);
alonDraw(canvas)
método para deshabilitar cualquier entrada en el texto de edición. De lo contrario, por ejemplo, los clics largos mostrarán un menú contextual y permitirán al usuario pegar texto.EditText
oAppCompatEditText
, ¡por favor!He creado un
View
componente compuesto que muestra una etiqueta sobre elSpinner
. El texto de la etiqueta se puede configurar mediante XML o en Java.El componente tiene las características clave de a
Spinner
( no todas ), además de tener un aspecto similar alTextInputLayout
componente.Lo he nombrado a
LabelledSpinner
, y está disponible como parte de mi biblioteca de Android UsefulViews en GitHub bajo la licencia Apache 2.0 .Para usarlo, agregue la dependencia de la biblioteca en su
build.gradle
archivo:compile 'com.satsuware.lib:usefulviews:+'
Los ejemplos de su uso están disponibles en el repositorio de GitHub (una aplicación de muestra y una guía de uso).
fuente
Spinner
, que es similar a cómo hay pequeñas etiquetas sobre losEditText
componentes, envueltosTextInputLayout
. ¿Cómo te lo imaginaste?Modifiqué la solución de Rodrigo para usar un adaptador, es decir, más como un Spinner estándar https://gist.github.com/smithaaron/d2acd57937d7a4201a79
fuente
Tengo una solución alternativa que usa el comportamiento de TextInputLayout y un DialogFragment personalizado (AlertDialog) para emular una ventana emergente de diálogo giratorio.
layout.xml:
<android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/your_et" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/your_label" android:maxLines="1" android:inputType="textNoSuggestions" android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:focusable="false" style="@style/Base.Widget.AppCompat.Spinner.Underlined"/> </android.support.design.widget.TextInputLayout>
Crear Spinner personalizado a través de DialogFragment (AlertDialog)
SpinnerFragment.java:
public class SpinnerFragment extends DialogFragment { private static final String TITLEID = "titleId"; private static final String LISTID = "listId"; private static final String EDITTEXTID = "editTextId"; public static SpinnerFragment newInstance(int titleId, int listId, int editTextId) { Bundle bundle = new Bundle(); bundle.putInt(TITLEID, titleId); bundle.putInt(LISTID, listId); bundle.putInt(EDITTEXTID, editTextId); SpinnerFragment spinnerFragment = new SpinnerFragment(); spinnerFragment.setArguments(bundle); return spinnerFragment; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final int titleId = getArguments().getInt(TITLEID); final int listId = getArguments().getInt(LISTID); final int editTextId = getArguments().getInt(EDITTEXTID); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); try { final String[] items = getResources().getStringArray(listId); builder.setTitle(titleId) .setItems(listId, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int pos) { EditText et = (EditText) getActivity().findViewById(editTextId); String selectedText = items[pos]; if (!TextUtils.isEmpty(selectedText)) { et.setText(selectedText); } else { et.getText().clear(); } } }); } catch (NullPointerException e) { Log.e(getClass().toString(), "Failed to select option in " + getActivity().toString() + " as there are no references for passed in resource Ids in Bundle", e); Toast.makeText(getActivity(), getString(R.string.error_failed_to_select), Toast.LENGTH_LONG).show(); } return builder.create(); }
}
Activity.java:
private void addCustomSpinner() { EditText yourEt = (EditText) findViewById(R.id.your_et); yourEt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showCustomSpinnerDialog(view); } }); } private void showCustomSpinnerDialog(View v) { int titleId = R.string.your_label; int listId = R.array.spinner_selections; int editTextId = R.id.your_et; SpinnerFragment spinnerFragment = SpinnerFragment.newInstance(titleId, listId, editTextId); spinnerFragment.show(getFragmentManager(), "customSpinner"); }
Resultado
Cuando haces clic en el TextInputLayout con estilo de ruleta, se activará un cuadro de diálogo de alerta que contiene tu lista de selecciones. Una vez que se elige una selección, EditText se completará con su selección y la etiqueta flotará como lo desee.
fuente
android:focusable="false"
hace que esta vista sea inaccesible para quienes usan el teclado o la voz para interactuar con la aplicación?android:focusable="false"
es para que el usuario no pueda ingresar una entrada que no esté entre la selección. Desafortunadamente, no tengo un teléfono Android físico para probar los comportamientos y avisarles.Puedes lograr esto:
Con nuevos estilos de biblioteca de materiales como este:
<com.google.android.material.textfield.TextInputLayout android:id="@+id/fullNameLay" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu" android:layout_width="wrap_content" android:layout_height="wrap_content"> <androidx.appcompat.widget.AppCompatAutoCompleteTextView android:id="@+id/fullNameEt" android:layout_width="match_parent" android:layout_height="wrap_content"/> </com.google.android.material.textfield.TextInputLayout>
para más información: https://material.io/develop/android/components/menu/
fuente
Aquí está mi truco
lo bueno es que todo saldrá como tu quieres,
pero lo malo es que está aumentando la jerarquía de diseño, y tienes que manejar la funcionalidad en el código, y es una solución fea:
<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.design.widget.TextInputLayout android:id="@+id/til" android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/edt" android:layout_width="match_parent" android:layout_height="@dimen/edt_height" android:hint="@string/create_gcc_visa_txt_step" /> </android.support.design.widget.TextInputLayout> <Spinner android:id="@+id/spn" style="@style/MyAppTheme.Base.Spinner" android:layout_height="@dimen/edt_height" android:layout_alignBottom="@id/til" /> </RelativeLayout>
y anular el adaptador para spinner, para hacer transparentes los valores seleccionados
public class MySpinnerAdapter extends SimpleAdapter { Context mContext; public MySpinnerAdapter(Context context, List<String> data, int resource, String[] from, int[] to) { super(context, data, resource, from, to); mContext = context; } @Override public View getView(int position, View convertView, ViewGroup parent) { convertView = super.getView(position, convertView, parent); TextView tv = (TextView) convertView.findViewById(android.R.id.text1); tv.setTextColor(ContextCompat.getColor(mContext, R.color.transparent)); return convertView; } }
y después de seleccionar en la ruleta, simplemente obtenga el texto seleccionado y configúrelo en EditText y tendrá el mismo efecto con la animación
yourSpinnerView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<String> adapterView, View view, int i, long l) { //get your selected text from adapter or from where you want String selectedText = adapterView.getItemAtPosition(i)); if (i != 0) { edt.setText(selectedText); } else { // if in case your spinner have first empty text, // then when spinner selected, just empty EditText. edt.setText(""); } } @Override public void onNothingSelected(AdapterView<?> adapterView) { } });
si tienes alguna duda pregúntame
fuente
Aquí hay una biblioteca que utilizo para el control giratorio de etiquetas flotantes rey5137 Biblioteca de materiales
Además, para referencia futura, aquí hay una lista de algunas bibliotecas excelentes. Bibliotecas de UI Bibliotecas principales
fuente
SpinnerCustom.java
package com.pozitron.tfkb.customviews; import android.content.Context; import android.content.res.TypedArray; import android.support.annotation.Nullable; import android.text.SpannableString; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; import com.pozitron.commons.customviews.TextViewFont; import com.pozitron.tfkb.R; import butterknife.BindView; import butterknife.ButterKnife; /** * Created by so12607 on 31/01/2018. */ public class SpinnerCustom extends LinearLayout { @BindView(R.id.layoutSpinnerCustomLabel) TextViewFont layoutSpinnerCustomLabel; @BindView(R.id.layoutSpinnerCustomSpinner) TextViewFont layoutSpinnerCustomSpinner; @BindView(R.id.layoutSpinner) LinearLayout layoutSpinner; private View v; public SpinnerCustom(Context context) { this(context, null); } public SpinnerCustom(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public SpinnerCustom(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); v = LayoutInflater.from(context).inflate(R.layout.layout_spinner_custom, this, true); ButterKnife.bind(this); if (!isInEditMode()) { TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SpinnerCustom, 0, 0); final String label = array.getString(R.styleable.SpinnerCustom_label); final boolean enable = array.getBoolean(R.styleable.SpinnerCustom_enabled, true); layoutSpinnerCustomLabel.setText(label); layoutSpinnerCustomLabel.setEnabled(enable); layoutSpinnerCustomSpinner.setEnabled(enable); layoutSpinner.setEnabled(enable); layoutSpinner.setClickable(enable); v.setEnabled(enable); v.setClickable(enable); array.recycle(); } } public void setText(String text) { layoutSpinnerCustomSpinner.setText(text); } public void setText(SpannableString text) { layoutSpinnerCustomSpinner.setText(text); } public void setText(CharSequence text) { layoutSpinnerCustomSpinner.setText(text); } public void setLabel(String text) { layoutSpinnerCustomLabel.setText(text); } public void setError(SpannableString text) { layoutSpinnerCustomSpinner.setError(text); } public void setEnabled(boolean enable) { layoutSpinnerCustomLabel.setEnabled(enable); layoutSpinnerCustomSpinner.setEnabled(enable); layoutSpinner.setEnabled(!enable); layoutSpinner.setClickable(!enable); } }
layout_spinner_custom.xml
<?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:id="@+id/layoutSpinner" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <com.pozitron.commons.customviews.TextViewFont android:id="@+id/layoutSpinnerCustomLabel" style="@style/TextLabel" tools:text="label" /> <com.pozitron.commons.customviews.TextViewFont android:id="@+id/layoutSpinnerCustomSpinner" style="@style/SpinnerText" android:clickable="false" /> </LinearLayout>
style.xml
<style name="TextLabel" parent="android:Widget.TextView"> <item name="font">@integer/font_GTEestiDisplay_Regular</item> <item name="android:layout_width">match_parent</item> <item name="android:textSize">14sp</item> <item name="android:layout_height">wrap_content</item> <item name="android:gravity">bottom</item> <item name="android:textColor">@color/greyLabel</item> </style> <style name="SpinnerText" parent="EditText"> <item name="font">@integer/font_GTEestiDisplay_Medium</item> <item name="android:gravity">bottom</item> <item name="android:textSize">17sp</item> <item name="android:minHeight">35dp</item> <item name="android:focusable">false</item> <item name="android:background">@drawable/spinner_selector</item> <item name="android:text">@string/select</item> <item name="android:textColor">@color/selector_spinner_text</item> </style>
fuente