it-swarm.com.ru

Плавающая этикетка Spinner?

После использования TextInputLayout библиотеки поддержки дизайна Android для размещения плавающей метки над компонентом EditText , мне стало интересно, есть ли способ добавить плавающую метку в компонент Spinner (необязательно с использованием библиотеки дизайна).

Под этим я подразумеваю что-то вроде TextView , помещенное над Spinner (очевидно, нет анимации, такой как TextInputLayout), но я хочу, чтобы размер, шрифт и цвет текста соответствовали плавающему ярлыку TextInputLayout.

Например, это будет выглядеть примерно так (см. Метки над Spinners):

 enter image description here

Как я уже упоминал ранее, моя главная цель - разместить метку над Spinner, как и в TextInputLayout, чтобы размер текста, шрифт, цвет и расстояния между меткой и компонентом были бы одинаковыми.

На странице Google Design о плавающих текстовых полях метки есть диаграмма, показывающая размеры метки относительно компонента, но нет указания цвета или размера текста метки:

 enter image description here

Итак, подведу итог, я прошу:
- Если есть специальный компонент для достижения того, что я спрашиваю, или пользовательское представление, которое я могу использовать, что бы это было, и как я могу его использовать.
- Если нет, то каков размер текста, цвет и шрифт плавающей метки, чтобы я мог поместить TextView выше моей Spinner с размерами макета, показанными на изображении выше.


Правка:

Из руководящих принципов Google Design для текстовых полей , он имеет следующее для плавающих надписей:

Подсказка и шрифт ввода: Roboto Regular 16sp
Шрифт этикетки: Roboto Regular 12sp
Высота плитки: 72dp
Верхний и нижний отступ текста: 16dp
Заполнитель разделителя текстового поля: 8dp 

а также изображения, показанные выше. 

Итак, шрифт плавающей метки: Roboto Regular 12sp. Поэтому вы можете использовать TextView для отображения метки Spinner, так как я не знаю никаких пользовательских Views или специальных компонентов, которые вы могли бы использовать.

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

74
Farbod Salamat-Zadeh

Я хочу, чтобы размер текста, шрифт и цвет соответствовали плавающей метке 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 имеют разные отступы, однако я предпочитаю сохранять вертикальное выравнивание со всеми остальными метками, чтобы получить более однородный вид.

 enter image description here

36
Andrea Lazzarotto

У меня есть Gist, созданный мной для решения той же проблемы, что и у вас.

Проверьте это:

https://Gist.github.com/rodrigohenriques/77398a81b5d01ac71c3b

Теперь мне не нужны блесны. Вы по-прежнему будете иметь эффект плавающей метки с включенной анимацией. 

33
Rodrigo Henriques

Я добился этого, используя 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;
    }
});
24
Sidney Veiga

Я создал составной компонент View, который отображает метку над Spinner. Текст для метки может быть установлен с использованием XML или Java.

Компонент имеет ключевые функции Spinner (не все из них), а также похож на компонент TextInputLayout.

Я назвал его LabelledSpinner , и он доступен как часть моей библиотеки UsefulViews Android на GitHub под Лицензия Apache 2.0 .

Чтобы использовать его, добавьте библиотечную зависимость в ваш файл build.gradle:

compile 'com.satsuware.lib:usefulviews:+'

Примеры его использования доступны в репозитории GitHub (как пример приложения, так и руководство по использованию).

11
Farbod Salamat-Zadeh

У меня есть альтернативное решение, которое использует поведение TextInputLayout и пользовательский DialogFragment (AlertDialog), чтобы эмулировать всплывающее окно диалогового окна.

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>

Создать пользовательский Spinner с помощью 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");
}

Результат

Когда вы нажимаете на спиннер в стиле TextInputLayout, он запускает диалоговое окно с предупреждением, содержащим ваш список выбора. Как только выбор будет выбран, EditText будет заполнен вашим выбором, и метка будет плавать так, как вы хотите.

5
Kenny Li

Я изменил решение Родриго для использования адаптера, то есть больше похоже на стандартный Spinner https://Gist.github.com/smithaaron/d2acd57937d7a4201a79

5
aaronmarino

Вот мой трюк,

хорошо то, что все будет работать так, как вы хотите, 

но плохо в том, что это увеличивает иерархию компоновки, и вам приходится обрабатывать функциональность в коде, и это уродливое решение:

    <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) {

        }
    });

если у вас есть какие-либо вопросы, спросите меня

3
Damir Mailybayev

Вот библиотека, которую я использую для вращающегося плавающего ярлыка rey5137 Библиотека материалов

Кроме того, для дальнейшего использования, вот список некоторых замечательных библиотек . Библиотеки пользовательского интерфейсаОсновные библиотеки

1
Brandon Tripp

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>
0
Samet öztoprak