Nachdem ich die TextInputLayout
der Android Design Support Library verwendet habe, um ein Floating-Label über einer EditText
-Komponente zu platzieren, fragte ich mich, ob es eine Möglichkeit gibt, ein Floating-Label der Spinner
-Komponente hinzuzufügen (nicht unbedingt Verwenden der Design Library).
Damit meine ich so etwas wie eine TextView
, die über der Spinner
platziert ist (offensichtlich keine Animationen wie die TextInputLayout
), aber ich möchte, dass Textgröße, Schriftart und Farbe mit der des Floating-Labels der TextInputLayout
übereinstimmen.
Zum Beispiel würde es ungefähr so aussehen (siehe die Beschriftungen über der Spinner
s):
Wie bereits erwähnt, besteht mein Hauptziel darin, über der Variablen Spinner
eine Beschriftung zu haben, genau wie in der Variable TextInputLayout
. Textgröße, Schriftart, Farbe und Abstände zwischen der Beschriftung und der Komponente wären also gleich.
Auf der Google Design-Seite zu schwebenden Beschriftungstextfeldern gibt es ein Diagramm, das die Abmessungen der Beschriftung relativ zur Komponente zeigt, jedoch keine Angabe der Farbe oder Größe des Beschriftungstextes:
Zusammenfassend frage ich:
- Wenn es eine spezielle Komponente gibt, um zu erreichen, was ich frage, oder eine benutzerdefinierte Ansicht, die ich verwenden kann, was wäre sie und wie kann ich sie verwenden?.
- Wenn nicht, wie groß ist die Größe, Farbe und Schriftart des Floating-Labels, so dass ich eine TextView
über meiner Spinner
mit den im obigen Bild angezeigten Layoutabmessungen platzieren kann.
Aus den Google Design-Richtlinien für Textfelder ergibt sich Folgendes für Floating-Labels:
Hinweis und Eingabeschriftart: Roboto Regular 16sp
Etikettenschrift: Roboto Regular 12sp
Fliesenhöhe: 72dp
Textabdeckung oben und unten: 16dp
Textfeldtrennerfüllung: 8dp
sowie die oben gezeigten Bilder.
Die Floating-Label-Schrift lautet also: Roboto Regular 12sp. Sie können daher eine TextView
verwenden, um das Label Spinner
anzuzeigen, da mir keine benutzerdefinierten View
s oder spezielle Komponenten bekannt sind, die Sie verwenden könnten.
Allerdings sieht es nach dem Ausprobieren nicht ganz so gut aus wie das im Bild gezeigte Beispiel. Eine benutzerdefinierte Ansicht ist vielleicht besser für diese, da sie schöner aussehen könnte, aber die Lösung oben ist nur eine Möglichkeit, etwas zu erreichen, das dem entspricht, was ich ursprünglich wollte.
Ich möchte, dass die Textgröße, die Schriftart und die Farbe von derjenigen der
TextInputLayout
-Gleitmarke entsprechen.
Dies ist ohne externe Bibliotheken problemlos möglich. Nachdem ich versucht hatte, die TextInputLayout
zu hacken und sogar meine eigene benutzerdefinierte Ansicht zu erstellen, wurde mir klar, dass die Verwendung einer einfachen TextView
viel weniger Code erfordert und wahrscheinlich effizienter ist.
Der Textstil kann aus der Bibliothek AppCompat
kopiert werden.
Aus den Richtlinien für Materialdesign erhalten wir folgende Informationen:
8dp
habenFolgendes wird in den Richtlinien nicht über das Material EditText
erwähnt:
4dp
16dp
darüber, dies bleibt dem Interface-Designer überlassen: Dies ist sinnvoll, denn wenn Sie es unter einer anderen EditText
platzieren, benötigen Sie nur einen zusätzlichen 8dp
-PlatzDarüber hinaus enthält die Design Support Library diesen Stil für die Beschriftung eines fokussierten Elements:
<style name="TextAppearance.Design.Hint" parent="TextAppearance.AppCompat.Caption">
<item name="Android:textColor">?attr/colorControlActivated</item>
</style>
Inaktive Elemente verwenden einfach TextAppearance.AppCompat.Caption
.
Fügen Sie Ihrer dimens.xml
-Datei Folgendes hinzu:
<dimen name="input_label_vertical_spacing">8dp</dimen>
<dimen name="input_label_horizontal_spacing">4dp</dimen>
Dann füge dies zu styles.xml
hinzu:
<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>
Wenn das Etikett immer die hervorgehobene (Akzent-) Farbe haben soll, ersetzen Sie TextAppearance.AppCompat.Caption
durch TextAppearance.Design.Hint
aus der Google Design Support Library. Dies wird jedoch wahrscheinlich ein bisschen komisch aussehen, wenn Sie auf demselben Bildschirm auch EditText
-Ansichten beschriftet haben.
Schließlich können Sie eine TextView
über der Spinner
(oder einem anderen Element) mit dem angewendeten Stil platzieren:
<TextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="@string/category"
style="@style/InputLabel" />
Der folgende Screenshot zeigt ein einfaches Beispiel mit zwei normalen TextInputLayout
-Ansichten, gefolgt von einem Label und einer Spinner
. Ich habe den zusätzlichen 8dp
-Abstand nicht angewendet, um sie weiter voneinander zu trennen, aber dies zeigt Ihnen, dass Größe, Schriftart und Farbe wiedergegeben werden.
Die Elemente in der Variablen Spinner
haben eine andere Auffüllung, ich ziehe es jedoch vor, die vertikale Ausrichtung mit allen anderen Beschriftungen beizubehalten, um ein einheitlicheres Aussehen zu erzielen.
Ich habe eine Gist von mir gemacht, um das gleiche Problem zu lösen, das Sie haben.
Hör zu:
https://Gist.github.com/rodrigohenriques/77398a81b5d01ac71c3b
Jetzt brauche ich keine Spinner. Sie haben immer noch Floating-Label-Effekt mit enthaltenen Animationen.
Ich habe dies erreicht, indem ich ein AutoCompleteTextView verwendet habe, die Tastatur deaktiviert habe und die Optionen bei Berührung angezeigt habe.
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;
}
});
Ich habe eine zusammengesetzte View
-Komponente erstellt, die eine Beschriftung über der Spinner
anzeigt. Der Text für das Label kann über XML oder in Java festgelegt werden.
Die Komponente hat die Hauptmerkmale einer Spinner
(nicht alle davon) und ähnelt der TextInputLayout
-Komponente.
Ich habe es eine LabelledSpinner
genannt und ist als Teil meiner UsefulViews Android-Bibliothek auf GitHub unter der Apache 2.0-Lizenz verfügbar.
Um es zu verwenden, fügen Sie die Bibliotheksabhängigkeit in Ihre build.gradle
-Datei ein:
compile 'com.satsuware.lib:usefulviews:+'
Beispiele für seine Verwendung finden Sie im GitHub-Repository (sowohl eine Beispielanwendung als auch ein Verwendungshandbuch).
Ich habe eine alternative Lösung, die das Verhalten von TextInputLayout und ein benutzerdefiniertes DialogFragment (AlertDialog) verwendet, um ein Dialogfenster für ein Dialogfenster zu emulieren.
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>
Benutzerdefiniertes Spinner über DialogFragment erstellen (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();
}
}
Aktivität.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");
}
Ergebnis
Wenn Sie auf das Textfeld „TextInputLayout“ im Spinner-Stil klicken, wird ein Benachrichtigungsdialogfeld mit Ihrer Auswahlliste ausgelöst. Wenn Sie eine Auswahl ausgewählt haben, wird der EditText mit Ihrer Auswahl gefüllt, und die Beschriftung wird wie gewünscht verschoben.
Ich habe die Lösung von Rodrigo geändert, um einen Adapter zu verwenden, d. H. Eher wie ein Standard-Spinner https://Gist.github.com/smithaaron/d2acd57937d7a4201a79
Hier ist mein Trick,
das Gute ist, dass alles so funktioniert, wie Sie wollen,
das Schlimme ist jedoch, dass die Layout-Hierarchie zunimmt, und Sie müssen mit der Funktionalität im Code umgehen, und es ist eine hässliche Lösung:
<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>
und überschreiben Sie den Adapter für den Spinner, um die ausgewählten Werte transparent zu machen
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;
}
}
wenn Sie im Drehfeld ausgewählt haben, rufen Sie einfach den ausgewählten Text auf und setzen Sie ihn auf EditText. Dies hat dieselbe Wirkung wie bei der 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) {
}
});
wenn Sie Fragen haben, fragen Sie mich
Hier ist eine Bibliothek, die ich für den Floating-Label-Spinner verwende rey5137 Material Library
Zur späteren Bezugnahme finden Sie hier eine Liste einiger großartiger Bibliotheken . UI-BibliothekenCore Libraries
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>
Mit neuen Materialbibliotheksstilen wie folgt:
<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>
weitere Informationen: https://material.io/develop/Android/components/menu/