Подтвердить что ты не робот

Плавающая этикетка 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 или специальных компонентов, которые вы могли бы использовать.

Однако, после проверки, это выглядит не так хорошо, как пример, показанный на изображении. пользовательский вид может быть лучше для этого, поскольку он может выглядеть лучше, но решение выше - это всего лишь один из способов достижения чего-то близкого к тому, что я изначально хотел.

4b9b3361

Ответ 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 (как пример приложения, так и руководство по использованию).

Ответ 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) {

        }
    });

если у вас есть вопросы Спросите меня

Ответ 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/