Плавающая этикетка Spinner?
После использования библиотеки поддержки дизайна Android TextInputLayout
поместите плавающую метку над EditText
, мне было интересно, есть ли способ добавить плавающую метку к компоненту Spinner
(не обязательно используя библиотеку дизайна).
Под этим я подразумеваю нечто вроде TextView
, расположенное над Spinner
(очевидно, никаких анимаций, таких как TextInputLayout
), но я хочу, чтобы размер текста, шрифт и цвет в соответствии с плавающей меткой TextInputLayout
.
Например, он будет выглядеть примерно так (см. надписи над Spinner
s):
![введите здесь описание изображения]()
Как я уже упоминал ранее, моя главная цель - иметь надпись Spinner
, как и в TextInputLayout
, поэтому размер текста, шрифт, цвет и расстояния между меткой и компонентом будут одинаковыми.
На странице Google Design о плавающих текстовых полях с метками отображается диаграмма, показывающая размеры метки относительно компонента, но нет указателя на метку цвет текста или размер:
![введите описание изображения здесь]()
Итак, резюмируя, я спрашиваю:
- Если есть специальный компонент для достижения того, что я прошу, или пользовательский вид, который я могу использовать, что бы это было и как я могу его использовать.
- Если нет, каков размер текста, цвет и шрифт с плавающей меткой, чтобы я мог разместить TextView
выше моего Spinner
с размерами макета, показанными на приведенном выше изображении.
EDIT:
В Руководстве по дизайну Google для текстовых полей для плавающих меток оно имеет следующие значения:
Подсказка и шрифт ввода: Roboto Regular 16sp
Метка с надписью: Roboto Regular 12sp
Высота плитки: 72dp
Текстовое верхнее и нижнее заполнение: 16dp
Заполнение разделителя текстового поля: 8dp
а также изображения, показанные выше.
Таким образом, шрифт плавающей метки: Roboto Regular 12sp. Поэтому вы можете использовать TextView
для отображения метки Spinner
, поскольку я не знаю каких-либо пользовательских View
или специальных компонентов, которые вы могли бы использовать.
Однако, после проверки, это выглядит не так хорошо, как пример, показанный на изображении. пользовательский вид может быть лучше для этого, поскольку он может выглядеть лучше, но решение выше - это всего лишь один из способов достижения чего-то близкого к тому, что я изначально хотел.
Ответы
Ответ 1
Я хочу, чтобы размер, шрифт и цвет текста соответствовали размеру TextInputLayout
плавающей метки.
Это может быть легко достигнуто без каких-либо внешних библиотек. После попытки взломать TextInputLayout
и даже создания собственного пользовательского представления я понял, что использование простого TextView
занимает гораздо меньше кода и, вероятно, более эффективно.
Текстовый стиль можно скопировать из библиотеки AppCompat
.
Стиль
В Руководстве по материальному дизайну мы получаем следующую информацию:
- метка должна иметь нижнее поле
8dp
- метка должна быть выровнена по вертикали с текстом ввода
В этом руководстве не упоминаются материалы EditText
:
- у него есть левое дополнение
4dp
- На его ярлыке фактически нет пробела
16dp
над ним, это остается для дизайнера интерфейса: это имеет смысл, потому что если вы поместите его под другой EditText
, вам понадобится только дополнительный 8dp
пространства
Кроме того, библиотека поддержки дизайна содержит этот стиль для метки сфокусированного элемента:
<style name="TextAppearance.Design.Hint" parent="TextAppearance.AppCompat.Caption">
<item name="android:textColor">?attr/colorControlActivated</item>
</style>
Неактивные элементы просто используют TextAppearance.AppCompat.Caption
.
Реализация
Добавьте в свой файл dimens.xml
следующее:
<dimen name="input_label_vertical_spacing">8dp</dimen>
<dimen name="input_label_horizontal_spacing">4dp</dimen>
Затем добавьте это в 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>
Если вы хотите, чтобы на ярлыке всегда был выделенный (акцент) цвет, замените TextAppearance.AppCompat.Caption
на TextAppearance.Design.Hint
в Библиотеке поддержки дизайна Google. Тем не менее, это, вероятно, будет немного странно, если вы также отметили EditText
представления на одном экране.
Наконец, вы можете поместить TextView
над вашим Spinner
(или любым другим элементом) с применяемым стилем:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/category"
style="@style/InputLabel" />
Результат
На следующем скриншоте показан простой пример с двумя нормальными представлениями TextInputLayout
, за которыми следует метка, и Spinner
. Я не применял дополнительный интервал 8dp
, чтобы отделить их дальше, но это показывает, что размер, шрифт и цвет отражаются.
Элементы внутри Spinner
имеют разные дополнения, однако я предпочитаю сохранять вертикальное выравнивание со всеми другими метками, чтобы получить более равномерный вид.
![введите описание изображения здесь]()
Ответ 2
У меня есть сущность, сделанная мной для решения той же проблемы, что и у вас.
Проверьте:
https://gist.github.com/rodrigohenriques/77398a81b5d01ac71c3b
Теперь мне не нужны прядильщики. У вас все еще будет эффект плавающей метки с включенными анимациями.
Ответ 3
Я достиг этого, используя AutoCompleteTextView, отключив клавиатуру и показывая параметры при касании.
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;
}
});
Ответ 4
Я создал составной компонент View
, который отображает метку над Spinner
. Текст метки может быть задан с использованием XML или Java.
Компонент имеет ключевые функции Spinner
(не все из них), а также похож на компонент TextInputLayout
.
Я назвал его LabelledSpinner
, и он доступен как часть моего Полезные экраны Библиотека Android на GitHub под Apache 2.0 License.
Чтобы использовать его, добавьте зависимость библиотеки в свой файл build.gradle
:
compile 'com.satsuware.lib:usefulviews:+'
Примеры его использования доступны в репозитории GitHub (как пример приложения, так и руководство по использованию).
Ответ 5
Я изменил решение Rodrigo для использования адаптера, то есть больше похоже на стандартный Spinnerhttps://gist.github.com/smithaaron/d2acd57937d7a4201a79
Ответ 6
У меня есть альтернативное решение, которое использует поведение TextInputLayout и пользовательский диалог DialogFragment (AlertDialog) для эмуляции всплывающего диалогового окна spinner.
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>
Создать пользовательский счетчик с помощью диалогового окна (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");
}
Результат
Когда вы нажмете на TextInputLayout в стиле Spinner, он запустит диалоговое окно с предупреждением, содержащее ваш список выбранных. После выбора выбора EditText будет заполнен вашим выбором, и метка будет плавать так, как вы хотите.
Ответ 7
Вот мой трюк,
Хорошо, что все будет работать так, как вы хотите,
но плохо то, что он увеличивает иерархию раскладки, и вам приходится обрабатывать функциональность в коде, и это уродливое решение:
<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>
и переопределить адаптер для счетчика, чтобы сделать выбранные значения прозрачными
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;
}
}
и после выбора в spinner просто выберите выделенный текст и установите его в EditText, и он будет иметь тот же эффект с анимацией
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) {
}
});
если у вас есть вопросы Спросите меня
Ответ 8
Вот библиотека, которую я использую для плавающей метки Spinner
rey5137 Библиотека материалов
Кроме того, для дальнейшего использования здесь приведен список некоторых больших библиотек.
Библиотеки пользовательского интерфейса
Основные библиотеки
Ответ 9
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>
Ответ 10
Вы можете достичь этого:
![enter image description here]()
С новыми стилями библиотеки материалов, такими как это:
<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>
для получения дополнительной информации:https://material.io/develop/android/components/menu/