Cara menambahkan label mengambang di Spinner

88

Setelah menggunakan Pustaka Dukungan Desain Android TextInputLayoutuntuk menempatkan label mengambang di atas EditTextkomponen, saya bertanya-tanya apakah ada cara untuk menambahkan label mengambang ke Spinnerkomponen (tidak harus menggunakan Pustaka Desain).

Dengan ini, maksud saya sesuatu seperti TextViewditempatkan di atas Spinner(jelas tidak ada animasi seperti itu TextInputLayout), tapi saya ingin ukuran teks, font dan warna cocok dengan TextInputLayoutlabel mengambang itu .

Misalnya, akan terlihat seperti ini (lihat label di atas Spinner):

masukkan deskripsi gambar di sini

Seperti yang saya sebutkan sebelumnya, tujuan utama saya adalah memiliki label di atas Spinner, seperti pada TextInputLayout- sehingga ukuran teks, font, warna, dan jarak antara label dan komponen akan sama.

Pada halaman Google Design tentang bidang teks label mengambang , terdapat diagram yang menunjukkan dimensi label relatif terhadap komponen, tetapi tidak ada indikasi warna atau ukuran teks label:

masukkan deskripsi gambar di sini

Jadi, untuk meringkas, saya bertanya:
- Jika ada komponen khusus untuk mencapai apa yang saya minta atau tampilan kustom yang dapat saya gunakan, apakah itu, dan bagaimana saya bisa menggunakannya.
- Jika tidak, berapa ukuran teks floating label, warna dan fontnya, sehingga saya dapat menempatkan di TextViewatas my Spinnerdengan dimensi tata letak yang ditunjukkan pada gambar di atas.


EDIT:

Dari pedoman Desain Google untuk bidang teks , ini memiliki yang berikut untuk label mengambang:

Font petunjuk dan masukan: Roboto Reguler 16sp
Font label: Roboto Reguler 12sp
Tinggi ubin: 72dp Padding
teks atas dan bawah: 16dp
Padding pembagi bidang teks: 8dp

serta gambar yang ditunjukkan di atas.

Jadi font label mengambang adalah: Roboto Regular 12sp . Oleh karena itu, Anda dapat menggunakan a TextViewuntuk menampilkan Spinnerlabel karena saya tidak tahu ada Viewkomponen khusus atau khusus yang dapat Anda gunakan.

Namun , setelah mencobanya, tidak terlihat sebagus contoh yang ditunjukkan pada gambar. Tampilan kustom mungkin lebih baik untuk ini , karena mungkin terlihat lebih bagus, tetapi solusi di atas hanyalah salah satu cara untuk mencapai sesuatu yang mendekati apa yang awalnya saya inginkan.

Farbod Salamat-Zadeh
sumber

Jawaban:

44

Saya ingin ukuran teks, jenis huruf dan warna sesuai dengan TextInputLayoutlabel mengambang .

Ini dapat dicapai dengan mudah tanpa pustaka eksternal. Setelah mencoba meretas TextInputLayoutdan bahkan membuat tampilan khusus saya sendiri, saya menyadari bahwa menggunakan TextViewkode sederhana membutuhkan lebih sedikit kode dan mungkin lebih efisien.

Gaya teks dapat disalin dari AppCompatperpustakaan.

Gaya

Dari pedoman Desain Material kami mendapatkan informasi berikut:

  • label harus memiliki margin bawah 8dp
  • label harus sejajar vertikal dengan teks masukan

Inilah yang tidak disebutkan oleh pedoman tentang Materi EditText:

  • itu memiliki bantalan kiri 4dp
  • labelnya sebenarnya tidak memiliki spasi 16dpdi atasnya, ini diserahkan kepada perancang antarmuka: ini masuk akal karena jika Anda meletakkannya di bawah yang lain EditText, Anda hanya akan membutuhkan tambahan 8dpruang

Selain itu, Pustaka Dukungan Desain berisi gaya ini untuk label elemen fokus:

<style name="TextAppearance.Design.Hint" parent="TextAppearance.AppCompat.Caption">
    <item name="android:textColor">?attr/colorControlActivated</item>
</style>

Elemen tidak aktif cukup gunakan TextAppearance.AppCompat.Caption.

Penerapan

Tambahkan berikut ini ke dimens.xmlfile Anda :

<dimen name="input_label_vertical_spacing">8dp</dimen>
<dimen name="input_label_horizontal_spacing">4dp</dimen>

Kemudian tambahkan ini ke 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>

Jika Anda ingin label selalu memiliki warna yang disorot (aksen), ganti TextAppearance.AppCompat.Captiondengan TextAppearance.Design.Hintdari Pustaka Dukungan Desain Google. Namun, ini mungkin akan terlihat agak aneh jika Anda juga memiliki EditTexttampilan berlabel pada layar yang sama.

Terakhir, Anda dapat meletakkan di TextViewatas Spinner(atau elemen lainnya) dengan gaya yang diterapkan:

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

Hasil

Tangkapan layar berikut menunjukkan contoh sederhana dengan dua TextInputLayouttampilan normal diikuti oleh label dan Spinner. Saya tidak menerapkan 8dpspasi tambahan untuk memisahkannya lebih jauh, tetapi ini menunjukkan kepada Anda bahwa ukuran, font, dan warna tercermin.

Elemen-elemen di dalam Spinnermemiliki padding yang berbeda, namun saya lebih suka menjaga kesejajaran vertikal dengan semua label lain untuk mendapatkan tampilan yang lebih seragam.

masukkan deskripsi gambar di sini

Andrea Lazzarotto
sumber
1
Ya, sangat mungkin untuk mencapai ini tanpa perpustakaan eksternal. Faktanya, saya menggunakan pendekatan yang sama saat membuat tampilan kustom saya, yang sebenarnya merupakan tampilan gabungan yang terdiri dari TextView, Spinner, dan Tampilan pembagi bergaya. Alasan saya membuat tampilan kustom adalah karena lebih mudah mengelola sebagai satu tampilan dalam hierarki tata letak, daripada mencoba mengelola dua atau tiga tampilan.
Farbod Salamat-Zadeh
3
Anda mungkin ingin menambahkan <item name="android:textColor">?android:textColorHint</item>gaya Anda untuk mendapatkan warna teks yang sama di label kustom seperti yang digunakan di TextInputLayout dalam keadaan tidak fokus.
se.solovyev
"Namun, ini mungkin akan terlihat sedikit aneh jika Anda juga telah memberi label tampilan EditText pada layar yang sama." ... Anda hanya dapat spesifik dan nama gaya SpinnerLabelbukannya InputLabelsehingga Anda hanya menggunakannya untuk pemintal.
Robin Hood
35

Saya mencapai ini dengan menggunakan AutoCompleteTextView, menonaktifkan keyboard dan menampilkan opsi saat disentuh.

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;
    }
});
Sidney Veiga
sumber
Sejauh ini, ini adalah solusi terbaik. Ini adalah retasan kecil, dan memungkinkan untuk menggunakan standar TextInputLayout, sehingga memastikan Anda akan memiliki tampilan yang tepat dan tepat.
Direksi
3
Hanya peningkatan kecil: gunakan R.layout.support_simple_spinner_dropdown_itemsebagai penggantiandroid.R.layout.simple_spinner_item
BoD
Hack yang sangat pintar. Tapi itu masih hack.
Sevastyan Savanyuk
4
Jika Anda menggunakan mTextView.setText(...), Anda tidak akan menerima semua nilai dari adaptor di drop down ... Memanggil adapter.getFilter().filter(null);menampilkan lagi semua saran
maresmar
juga jika Anda mengatur teks, Anda tidak dapat menutup dropdown secara terprogram
Mike6679
34

Saya memiliki inti yang dibuat sendiri untuk memecahkan masalah yang sama yang Anda miliki.

Coba lihat:

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

Sekarang saya tidak membutuhkan pemintal. Anda masih akan memiliki efek label mengambang dengan animasi yang disertakan.

Rodrigo Henriques
sumber
1
Apa sebenarnya yang Anda maksud dengan "Saya tidak butuh pemintal" , dan di mana inti Anda, Anda mengatakan "Digunakan untuk membuat EditText Anda menjadi opsi yang lebih baik daripada Pemintal" ? Apakah UI hanyalah EditText?
Farbod Salamat-Zadeh
Saya menggunakan EditText dengan TextInput Layout sebagai alternatif untuk pemintal. Ketika pengguna mengklik di EditText kustom ini saya membuka dialog dengan opsi untuk dipilih. Tentu saja Ini bisa lebih baik dan saya menerima peningkatan apa pun seperti menampilkan opsi dengan jenis tampilan lain seperti spinner.
Rodrigo Henriques
1
Saya akan meningkatkan inti ini menjadi proyek github dengan sampel, lalu saya berharap mendapatkan bantuan untuk meningkatkan solusi ini.
Rodrigo Henriques
5
Tambahkan setInputType(InputType.TYPE_NULL);ke onDraw(canvas)metode untuk menonaktifkan masukan apa pun ke dalam teks editan. Jika tidak, misalnya klik lama akan memunculkan menu konteks dan memungkinkan pengguna untuk menempelkan teks.
Capricorn
1
nah ini luar biasa, tetapi jika Anda pernah memutuskan untuk meningkatkannya menjadi pustaka github, pastikan untuk memberikan opsi untuk memilih antara EditTextatau AppCompatEditText, tolong!
Muhammad Naderi
11

Saya telah membuat Viewkomponen gabungan yang menampilkan label di atas Spinner. Teks untuk label bisa disetel menggunakan XML atau di Java.

Komponen memiliki fitur utama Spinner( tidak semuanya ) serta terlihat mirip dengan TextInputLayoutkomponen.

Saya telah menamakannya a LabelledSpinner, dan ini tersedia sebagai bagian dari pustaka Android UsefulViews saya di GitHub di bawah Lisensi Apache 2.0 .

Untuk menggunakannya, tambahkan dependensi library di build.gradlefile Anda :

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

Contoh penggunaannya tersedia di repositori GitHub (baik aplikasi sampel, dan panduan penggunaan).

Farbod Salamat-Zadeh
sumber
@LavekushAgrawal Beri tahu saya apa yang sebenarnya tidak berhasil atau buka masalah di repo
Farbod Salamat-Zadeh
1
Sebenarnya ini berfungsi, tetapi label tidak mengapung seperti edittext
Lavekush Agrawal
@LavekushAgrawal Ada label kecil diposisikan di atas Spinner, yang mirip dengan label kecil di atas EditTextkomponen, dibungkus TextInputLayout. Bagaimana Anda membayangkannya?
Farbod Salamat-Zadeh
@ FarbodSalamat-Zadeh Ini adalah pustaka keren untuk digunakan, tetapi tidak berfungsi di Lollipop.
Jorge
2
tidak bekerja pada gradle 3.5, hanya perpustakaan gradle 2.0 yang sangat tua
Arthur Melo
6

Anda dapat mencapai ini: masukkan deskripsi gambar di sini

Dengan gaya pustaka Material baru seperti ini:

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

untuk informasi lebih lanjut: https://material.io/develop/android/components/menu/

Amin Keshavarzian
sumber
ini bukan pemintal
pengguna924
2
ini adalah pemintal, hanya dengan desain yang berbeda
Amin Keshavarzian
5

Saya memiliki solusi alternatif yang menggunakan perilaku TextInputLayout dan DialogFragment kustom (AlertDialog) untuk meniru popup dialog 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>

Buat Spinner Kustom melalui 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");
}

Hasil

Saat Anda mengklik TextInputLayout bergaya spinner, ini akan memicu dialog peringatan yang berisi daftar pilihan Anda. Setelah pilihan dipilih, EditText akan diisi dengan pilihan Anda dan label akan mengambang seperti yang Anda inginkan.

Kenny Li
sumber
Bukankah android:focusable="false"membuat tampilan ini tidak dapat diakses oleh mereka yang menggunakan keyboard atau suara untuk berinteraksi dengan aplikasi?
sargas
Saya tidak pernah menggunakan keyboard atau suara untuk berinteraksi dengan spinner, tetapi alasan mengapa saya menyetel android:focusable="false"adalah agar pengguna tidak dapat mengetikkan input yang tidak termasuk dalam pilihan. Sayangnya, saya tidak memiliki ponsel Android fisik untuk menguji perilaku tersebut untuk memberi tahu Anda.
Kenny Li
3

Ini trik saya,

hal baiknya adalah semuanya akan bekerja seperti yang Anda inginkan,

tetapi yang buruk adalah ini meningkatkan hierarki tata letak, dan Anda harus menangani fungsionalitas dalam kode, dan ini adalah solusi yang buruk:

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

dan ganti adaptor untuk pemintal, untuk membuat nilai yang dipilih transparan

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

dan setelah memilih di spinner, cukup pilih teks dan setel ke EditText dan itu akan memiliki efek yang sama dengan animasi

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

        }
    });

jika Anda memiliki pertanyaan Tanya saya

Damir Mailybayev
sumber
dapatkah kamu membantuku aku terjebak? Saya memiliki beberapa edit teks sehingga oncreate dari fokus tata letak pergi ke edittext pertama dan sementara secara langsung saya menekan spinner sehingga kode edittext di atas tidak mendapatkan fokus. tetapi saya perlu fokus pada klik spinner bagaimana saya bisa?
sunita
@sunita dapatkah Anda memberi tahu saya urutan tampilan, karena ketika saya mencoba saya bisa fokus pada pemintal
Damir Mailybayev
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>
Samet ÖZTOPRAK
sumber