Spinnerにフローティングラベルを追加する方法


87

Androidデザインサポートライブラリを使用してTextInputLayoutフローティングラベルをEditTextコンポーネントの上に配置した後、フローティングラベルをコンポーネントに追加する方法Spinner(デザインライブラリを使用する必要はない)があるかどうか疑問に思いました。

これは、の上にTextView配置されたようなものを意味しますSpinner(明らかにのようなアニメーションはありませんTextInputLayout)が、テキストサイズ、フォント、および色をTextInputLayoutのフローティングラベルのそれに一致させる必要があります。

たとえば、次のようになります(Spinnersの上にあるラベルを参照)。

ここに画像の説明を入力してください

前に述べたように、私の主な目的はとSpinner同じようにの上にラベルを付けることです。つまり、TextInputLayoutテキストサイズ、フォント、色、ラベルとコンポーネント間の距離は同じになります。

上のラベルのテキストフィールドを浮動に関するGoogleのデザインのページ、コンポーネントに対するラベルの寸法を示す図がありますが、ラベルテキストの色や大きさの兆候はありません。

ここに画像の説明を入力してください

要約すると、私は次のように質問し
ています。
-そうでない場合は、ので、私は置くことができることを何浮動ラベルテキストのサイズ、色、フォントがあり、TextView私の上のSpinner上の画像に示すレイアウト寸法で。


編集:

テキストフィールドのGoogleデザインガイドラインから、フローティングラベルには次のようになります。

ヒントと入力フォント:Roboto Regular 16sp
ラベルフォント:Roboto Regular 12sp
タイルの高さ:72dp
テキストの上下のパディング:16dp
テキストフィールドの仕切りのパディング:8dp

上記の画像と同様に。

したがって、フローティングラベルフォントはRoboto Regular 12spです。したがって、使用できるカスタムsや特別なコンポーネントがわからないため、a TextViewを使用してSpinnerラベルを表示Viewできます。

ただし、試してみたところ、図に示す例ほどよく見えません。カスタムビューは、より良い、このためかもしれそれはよりよいを見ることができるように、しかし、上記の溶液は近い私が最初に何を望むかに何かを達成するためのひとつの方法です。

回答:


44

テキストサイズ、フォント、色を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同じ画面でラベル付きビューもある場合、これはおそらく少し奇妙に見えます。

最後に、スタイルを適用しTextViewSpinner(またはその他の要素)の上に配置できます。

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/category"
    style="@style/InputLabel" />

結果

次のスクリーンショットは、2つの通常のTextInputLayoutビューの後にラベルとが続く単純な例を示していSpinnerます。私は8dpそれらをさらに分離するために追加の間隔を適用しませんでしたが、これはサイズ、フォント、色が反映されていることを示しています。

内部の要素にはSpinner別のパディングがありますが、より均一な外観を得るために、他のすべてのラベルと垂直方向の配置を維持することを好みます。

ここに画像の説明を入力してください


1
はい、外部ライブラリなしでこれを達成することは完全に可能です。実際、カスタムビューを作成するときにも同じアプローチを使用しました。カスタムビューは、実際にはスタイル付きのTextView、Spinner、およびDivider Viewで構成される複合ビューです。カスタムビューを作成したのは、2つまたは3つのビューを管理するよりも、レイアウト階層内の1つのビューとして管理する方が簡単だからです。
Farbod Salamat-Zadeh

3
おそらく<item name="android:textColor">?android:textColorHint</item>フォーカスされていない状態でTextInputLayoutで使用されているのと同じラベルの色をカスタムラベルで取得するために、スタイルを追加する必要があります。
se.solovyev 2017

「しかし、同じ画面でEditTextビューにもラベルを付けている場合、これはおそらく少し奇妙に見えるでしょう。」... スピナーにのみ使用するように、具体的に指定してスタイルSpinnerLabelに名前を付けることができInputLabelます。
ロビンフッド

34

私はあなたと同じ問題を解決するために自分で作った要点があります。

見てみな:

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

今、私はスピナーを必要としません。アニメーションが含まれた状態でも、フローティングラベル効果があります。


1
「スピナーは必要ない」とはどういう意味ですか。また、要旨の中で、「スピナーよりもEditTextを優れたオプションにするために使用しました」とはどういう意味ですか。UIは単なるEditTextですか?
Farbod Salamat-Zadeh、2015

スピナーの代わりとしてEditTextをTextInput Layoutと一緒に使用します。ユーザーがこのカスタムEditTextをクリックすると、オプションを選択できるダイアログが開きます。もちろん、もっと良いかもしれないし、スピナーのように別の種類のビューでオプションを表示するような改善を受け入れる。
Rodrigo Henriques 2015

1
この要点をサンプル付きのgithubプロジェクトにアップグレードしてから、このソリューションの改善に協力してもらいたいと思います。
Rodrigo Henriques、

5
メソッドに追加setInputType(InputType.TYPE_NULL);してonDraw(canvas)、edittextへの入力を無効にします。それ以外の場合は、たとえば長いクリックでコンテキストメニューが表示され、ユーザーがテキストを貼り付けることができます。
山羊座

1
これは素晴らしかったですが、githubライブラリにアップグレードすることを決定した場合は、EditTextまたはのどちらかを選択するオプションを必ず指定してAppCompatEditTextください。
ムハンマドナデリ

33

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;
    }
});

これは断然最良の解決策です。これは小さなハックであり、標準のを使用できるためTextInputLayout、正確な外観が得られます。
取締役会2017

3
ほんの少しの改善:R.layout.support_simple_spinner_dropdown_item代わりに使用android.R.layout.simple_spinner_item
BoD

非常に巧妙なハック。しかし、それはまだハックです。
Sevastyan Savanyuk 2017年

3
を使用する場合mTextView.setText(...)、ドロップダウンでアダプターからすべての値を受け取ることはできません...呼び出しにより、adapter.getFilter().filter(null);すべての提案が再度表示されます
mmrmartin

また、テキストを設定した場合、プログラムでドロップダウンを閉じることができません
Mike6679

11

の上にViewラベルを表示する複合コンポーネントを作成しましたSpinner。ラベルのテキストは、XMLまたはJavaを使用して設定できます。

コンポーネントには、aの主要な機能Spinnerすべてではない)があり、TextInputLayoutコンポーネントに似ています。

私はそれをa LabelledSpinnerと名付けました、そしてそれはApache 2.0ライセンスの下でGitHub上の私のUsefulViews Androidライブラリの一部として利用可能です。

これを使用するには、build.gradleファイルにライブラリの依存関係を追加します。

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

その使用例は、GitHubリポジトリ(サンプルアプリと使用ガイドの両方)にあります。


@LavekushAgrawalレポで正確に何が機能しないか、問題が発生するか教えてください
Farbod Salamat-Zadeh

1
実際には機能していますが、ラベルはedittextのようにフロートではありません
Lavekush Agrawal '20

@LavekushAgrawalの上に小さなラベルが配置されています。SpinnerこれはEditText、コンポーネントの上に小さなラベルがあり、でラップされているのと似ていますTextInputLayout。それをどう思いましたか?
Farbod Salamat-Zadeh 2016

@ FarbodSalamat-Zadehこれは使用するのに便利なライブラリですが、Lollipopでは動作しません。
ホルヘ、

2
Gradle 3.5では機能せず、Gradle 2.0のみの非常に古いライブラリ
Arthur Melo 2017


5

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>

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に選択内容が入力され、ラベルは希望どおりに浮動します。


android:focusable="false"キーボードや音声を使用してアプリを操作するユーザーは、このビューにアクセスできませんか?
sargas

スピナーと対話するためにキーボードや音声を使用したことがありませんが、設定した理由android:focusable="false"は、ユーザーが選択範囲外の入力を入力できないようにするためです。残念ながら、私はあなたに知らせるための動作をテストするための物理的なAndroidスマートフォンを持っていません。
ケニー・リー

4

ここに私のトリックがあります、

良いことは、すべてがあなたの望むように機能することです、

しかし、悪いのは、それがレイアウト階層を増やしており、コードで機能を処理する必要があることです。これは醜いソリューションです。

    <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;
    }
}

スピナーで選択した後、選択したテキストを取得して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) {

        }
    });

質問がある場合は私に尋ねてください


私が動けなくなるのを手伝ってくれませんか?複数の編集テキストがあるので、レイアウトのoncreateのフォーカスは最初のedittextに移動し、直接スピナーを押している間、edittextのコードの上にフォーカスがありませんが、スピナーのクリックにフォーカスを取得する必要があります
スニータ2017

@sunita私にビューの順序を教えてもらえますか。試してみるとスピナーに集中できたからです
Damir Mailybayev

2

あなたはこれを達成することができます: ここに画像の説明を入力してください

次のような新しいマテリアルライブラリスタイル:

<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/


それはスピナーではありません
user924

それはスピナーであり、デザインのみが異なります
アミンケシャヴァル


0

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>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.