Après avoir utilisé la variable TextInputLayout
de la bibliothèque de conception Android pour placer une étiquette flottante au-dessus d’un composant EditText
, je me demandais s’il existait un moyen d’ajouter une étiquette flottante au composant Spinner
(pas nécessairement en utilisant la bibliothèque de conception).
Par cela, je veux dire quelque chose comme un TextView
placé au-dessus de Spinner
(évidemment pas d’animations comme le TextInputLayout
), mais je veux que la taille du texte , la police et la couleur correspondent à celles de l’étiquette flottante de TextInputLayout
.
Par exemple, cela ressemblerait à quelque chose comme ceci (voir les étiquettes au dessus de la Spinner
s):
Comme je l’ai déjà mentionné, mon objectif principal est d’avoir une étiquette au-dessus de Spinner
, comme dans TextInputLayout
- afin que la taille du texte, la police, la couleur et les distances entre l’étiquette et le composant soient identiques.
Dans la page Google Design sur les champs de texte d'étiquette flottants , il existe un diagramme indiquant les dimensions de l'étiquette par rapport au composant, mais aucune indication de la couleur ou de la taille du texte de l'étiquette:
Donc, pour résumer, je demande:
- S'il y a un composant spécial pour réaliser ce que je demande ou une vue personnalisée que je peux utiliser, de quoi s'agit-il et comment puis-je l'utiliser.
- Si non, quelle est la taille, la couleur et la police du texte de l'étiquette flottante, de sorte que je puisse placer une TextView
au-dessus de ma Spinner
avec les dimensions de la mise en page indiquées dans l'image ci-dessus.
Le Consignes de conception de Google relatives aux champs de texte , présente les caractéristiques suivantes pour les étiquettes flottantes:
Astuce et police de saisie: Roboto Regular 16sp
Label police: Roboto Regular 12sp
Hauteur de la tuile: 72dp
Rembourrage en haut et en bas du texte: 16dp
Rembourrage du séparateur de champ de texte: 8dp
ainsi que les images montrées ci-dessus.
La police de l'étiquette flottante est donc: Roboto Regular 12sp. Vous pouvez donc utiliser une variable TextView
pour afficher l’étiquette Spinner
, étant donné que je ne connais aucune View
s personnalisée ni aucun composant spécial que vous pourriez utiliser.
Cependant, après l'avoir essayé, il n'a pas l'air aussi bon que l'exemple montré dans l'image. Une vue custom peut être meilleure pour cela, car cela pourrait sembler plus joli, mais la solution ci-dessus n'est qu'un moyen de réaliser quelque chose de proche de ce que je voulais à l'origine.
Je veux que la taille, la police et la taille du texte correspondent à celles de l'étiquette flottante de la
TextInputLayout
.
Ceci peut être réalisé facilement sans aucune bibliothèque externe. Après avoir essayé de pirater la TextInputLayout
et même de créer ma propre vue personnalisée, je me suis rendu compte que l'utilisation d'une simple TextView
prenait beaucoup moins de code et était probablement plus efficace.
Le style de texte peut être copié à partir de la bibliothèque AppCompat
.
Les directives de conception des matériaux fournissent les informations suivantes:
8dp
Voici ce que les directives ne mentionnent pas à propos de Material EditText
:
4dp
16dp
au-dessus, cela revient au concepteur d'interface: c'est logique, car si vous la placez sous une autre EditText
, vous n'aurez besoin que d'un 8dp
d'espace supplémentaire.De plus, la bibliothèque de support de conception contient ce style pour l’étiquette d’un élément ciblé:
<style name="TextAppearance.Design.Hint" parent="TextAppearance.AppCompat.Caption">
<item name="Android:textColor">?attr/colorControlActivated</item>
</style>
Les éléments inactifs utilisent simplement TextAppearance.AppCompat.Caption
.
Ajoutez les éléments suivants à votre fichier dimens.xml
:
<dimen name="input_label_vertical_spacing">8dp</dimen>
<dimen name="input_label_horizontal_spacing">4dp</dimen>
Ajoutez ensuite ceci à 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 vous souhaitez que l'étiquette ait toujours la couleur mise en surbrillance (accent), remplacez TextAppearance.AppCompat.Caption
par TextAppearance.Design.Hint
dans la bibliothèque de support technique de Google Design. Cependant, cela semblera probablement un peu étrange si vous avez également étiqueté les vues EditText
sur le même écran.
Enfin, vous pouvez mettre une TextView
au-dessus de votre Spinner
(ou de tout autre élément) avec le style appliqué:
<TextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="@string/category"
style="@style/InputLabel" />
La capture d'écran suivante montre un exemple simple avec deux vues TextInputLayout
normales, suivies d'une étiquette et d'une Spinner
. Je n'ai pas appliqué l'espacement supplémentaire 8dp
pour les séparer davantage, mais cela vous indique que la taille, la police et la couleur sont reflétées.
Les éléments à l'intérieur de la variable Spinner
ont un rembourrage différent, mais je préfère conserver l'alignement vertical avec toutes les autres étiquettes pour obtenir un aspect plus uniforme.
J'ai un Gist fait par moi-même pour résoudre le même problème que vous avez.
Vérifiez-le:
https://Gist.github.com/rodrigohenriques/77398a81b5d01ac71c3b
Maintenant, je n'ai plus besoin de fileuses. Vous aurez toujours un effet d'étiquette flottante avec des animations incluses.
J'ai atteint cet objectif en utilisant une AutoCompleteTextView, en désactivant le clavier et en affichant les options au toucher.
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;
}
});
J'ai créé un composant composé View
qui affiche une étiquette au-dessus de Spinner
. Le texte de l'étiquette peut être défini à l'aide de XML ou en Java.
Le composant présente les caractéristiques principales d'une Spinner
(pas toutes d'entre elles) ainsi qu'un aspect similaire au composant TextInputLayout
.
Je l'ai nommé LabelledSpinner
, et il est disponible dans la bibliothèque UsefulViews Android sur GitHub sous la licence Apache 2.0 .
Pour l'utiliser, ajoutez la dépendance de la bibliothèque dans votre fichier build.gradle
:
compile 'com.satsuware.lib:usefulviews:+'
Des exemples de son utilisation sont disponibles sur le référentiel GitHub (à la fois un exemple d'application et un guide d'utilisation).
J'ai une solution alternative qui utilise le comportement de TextInputLayout et un DialogFragment personnalisé (AlertDialog) pour émuler une popup de dialogue de rotation.
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>
Créer une spinner personnalisée via 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();
}
}
Activité.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");
}
Résultat
Lorsque vous cliquez sur le style spinner TextInputLayout, une boîte de dialogue d'alerte contenant votre liste de sélections s'ouvrira. Une fois la sélection choisie, le texte EditText sera renseigné avec votre sélection et l’étiquette flottera comme vous le souhaitez.
J'ai modifié la solution de Rodrigo pour utiliser un adaptateur, c'est-à-dire plus comme un Spinner standard https://Gist.github.com/smithaaron/d2acd57937d7a4201a79
Voici mon tour
les bonnes choses sont que tout fonctionnera comme vous le souhaitez,
mais le problème, c'est que cela augmente la hiérarchie des dispositions et que vous devez gérer les fonctionnalités dans le code. C'est une solution laide:
<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>
et remplacez l'adaptateur pour spinner, pour rendre transparentes les valeurs sélectionnées
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;
}
}
et après avoir sélectionné Spinner, récupérez simplement le texte sélectionné et réglez-le sur EditText. Il aura le même effet avec l'animation.
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 tu as une question demande moi
Voici une bibliothèque que j’utilise pour l’étiqueteuse flottante rey5137 Bibliothèque de matériaux
Aussi, pour référence future, voici une liste de quelques bonnes bibliothèques . Bibliothèques UIBibliothèques principales
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>
Avec les nouveaux styles de bibliothèque de matériaux comme ceci:
<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>
pour plus d'informations: https://material.io/develop/Android/components/menu/