not - spinner android developer
Etiqueta flotante Spinner? (10)
Después de usar
TextInputLayout
la Biblioteca de soporte de diseño de Android para colocar una etiqueta flotante sobre un componente
EditText
, me preguntaba si hay una manera de agregar una etiqueta flotante al componente
Spinner
(no necesariamente usando la Biblioteca de diseño).
Con esto, quiero decir algo así como un
TextView
colocado encima del
Spinner
(obviamente no hay animaciones como
TextInputLayout
), pero quiero que el
tamaño, la fuente y el color
del
texto coincidan con los de la etiqueta flotante de
TextInputLayout
.
Por ejemplo, se vería así (ver las etiquetas arriba del
Spinner
):
Como mencioné antes, mi objetivo principal es tener una etiqueta sobre el
Spinner
, al igual que en
TextInputLayout
, por lo que el tamaño, la fuente, el color y las distancias del texto entre la etiqueta y el componente serían los mismos.
En la página de Google Design sobre campos de texto de etiqueta flotante , 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 puedo usar, qué sería y cómo puedo usarlo.
- Si no, ¿cuál es el tamaño, el color y la fuente del texto de la etiqueta flotante, para que pueda colocar un
TextView
sobre mi
Spinner
con las dimensiones de 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 la etiqueta: Roboto Regular 12sp
Altura del azulejo: 72dp
Texto relleno superior e inferior: 16dp
Relleno divisor de campo de texto: 8dp
así como las imágenes que se muestran arriba.
Entonces la fuente de etiqueta flotante es:
Roboto Regular 12sp
.
Por lo tanto, puede usar un
TextView
para mostrar la etiqueta del
Spinner
, ya que no conozco ninguna
View
personalizada o componentes especiales 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 originalmente quería.
Quiero que el tamaño, la fuente y el color del texto coincidan con los de la etiqueta flotante
TextInputLayout
.
Esto se puede lograr fácilmente sin bibliotecas externas.
Después de intentar hackear
TextInputLayout
e incluso hacer mi propia vista personalizada, me di cuenta de que usar un
TextView
simple requiere mucho menos código y probablemente sea más eficiente.
El estilo de texto
se puede copiar
desde la biblioteca
AppCompat
.
El estilo
De las pautas de diseño de materiales obtenemos la siguiente información:
-
la etiqueta debe tener un margen inferior de
8dp
- la etiqueta debe estar alineada verticalmente con el texto de entrada
EditText
es lo que las pautas no mencionan sobre el Material
EditText
:
-
tiene un relleno izquierdo de
4dp
-
su etiqueta en realidad no tiene ningún espacio de
16dp
encima, esto se deja al diseñador de la interfaz: esto tiene sentido porque si lo coloca debajo de otroEditText
, solo necesitará8dp
adicionales de espacio
Además, la Biblioteca de soporte de diseño contiene este estilo para la etiqueta de un elemento enfocado:
<style name="TextAppearance.Design.Hint" parent="TextAppearance.AppCompat.Caption">
<item name="android:textColor">?attr/colorControlActivated</item>
</style>
Los elementos inactivos simplemente usan
TextAppearance.AppCompat.Caption
.
Implementación
Agregue lo siguiente a su archivo
dimens.xml
:
<dimen name="input_label_vertical_spacing">8dp</dimen>
<dimen name="input_label_horizontal_spacing">4dp</dimen>
Luego agregue esto a
styles.xml
:
<style name="InputLabel" parent="TextAppearance.AppCompat.Caption">
<item name="android:paddingBottom">@dimen/input_label_vertical_spacing</item>
<item name="android:paddingLeft">@dimen/input_label_horizontal_spacing</item>
<item name="android:paddingRight">@dimen/input_label_horizontal_spacing</item>
</style>
Si desea que la etiqueta siempre tenga el color resaltado (acento), reemplace
TextAppearance.AppCompat.Caption
con
TextAppearance.Design.Hint
de la Biblioteca de soporte de diseño de Google.
Sin embargo, esto probablemente se verá un poco extraño si también ha etiquetado
EditText
vistas
EditText
en la misma pantalla.
Finalmente, puede colocar un
TextView
sobre su
Spinner
(o cualquier otro elemento) con el estilo aplicado:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/category"
style="@style/InputLabel" />
Resultado
La siguiente captura de pantalla muestra un ejemplo simple con dos vistas normales
TextInputLayout
seguidas de una etiqueta y un
Spinner
.
No
8dp
espacio adicional de
8dp
para separarlos más, pero esto muestra que el tamaño, la fuente y el color se reflejan.
Los elementos dentro del
Spinner
tienen un relleno diferente, sin embargo, prefiero mantener la alineación vertical con todas las otras etiquetas para obtener un aspecto más uniforme.
Aquí está mi truco
Lo bueno es que todo funcionará como tú quieres,
pero lo malo es que está aumentando la jerarquía de diseño, y tiene 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 que los valores seleccionados sean transparentes
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, solo 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 pregunta pregúntame
Aquí hay una biblioteca que uso para la etiqueta flotante spinner rey5137 Biblioteca de materiales
Además, para referencia futura, aquí hay una lista de algunas excelentes bibliotecas. Bibliotecas de UI Bibliotecas principales
He creado un componente de
View
compuesto que muestra una etiqueta sobre el
Spinner
.
El texto para la etiqueta se puede establecer usando XML o en Java.
El componente tiene las características clave de un
Spinner
(
no todas
) y tiene un aspecto similar al componente
TextInputLayout
.
Lo he llamado
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 archivo
build.gradle
:
compile ''com.satsuware.lib:usefulviews:+''
Hay ejemplos de su uso disponibles en el repositorio de GitHub (una aplicación de muestra y una guía de uso).
Lo logré usando 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;
}
});
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
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/
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>
Tengo una idea esencial para resolver el mismo problema que tú tienes.
Echale un vistazo:
https://gist.github.com/rodrigohenriques/77398a81b5d01ac71c3b
Ahora no necesito hiladores. Seguirá teniendo un efecto de etiqueta flotante con animaciones incluidas.
Tengo una solución alternativa que utiliza el comportamiento de TextInputLayout y un DialogFragment (AlertDialog) personalizado para emular una ventana emergente de diálogo de flecha.
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 spinner con el estilo TextInputLayout, 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 desee.