Bagaimana cara mengatur font kustom font ke teks Spinner secara terprogram?

93

Saya memiliki file font ttf di folder aset saya. Saya tahu cara menggunakannya untuk tampilan teks dengan:

Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
textview1.setTypeface(externalFont);

Saya telah mendefinisikan pencarian teks spinner saya di file xml itu sendiri (seperti biasa di android):

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:textColor="#ffffff"
android:gravity="center" 
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee" />

Saya tidak bisa mereferensikan textview ini dari kode, saya selalu mendapatkan pengecualian pointer nol. Misalnya saya mencoba:

TextView spinner_text=(TextView)findViewById(R.id.text1);
spinner_text.setTypeface(externalFont);

Apakah mungkin untuk memilih font eksternal saya bahkan untuk teks spinner saya yang ditentukan dalam xml itu sendiri?

Terima kasih.

EDIT dengan jawaban:

Ini bekerja:

String [] items = new String[2];
    items[0]="Something1";
    items[1]="Something2";

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                    R.layout.spinaca, items) {

         public View getView(int position, View convertView, ViewGroup parent) {
                 View v = super.getView(position, convertView, parent);

                 Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
                 ((TextView) v).setTypeface(externalFont);

                 return v;
         }


         public View getDropDownView(int position,  View convertView,  ViewGroup parent) {
                  View v =super.getDropDownView(position, convertView, parent);

                 Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
                 ((TextView) v).setTypeface(externalFont);
                 v.setBackgroundColor(Color.GREEN);

                 return v;
         }
 };


     adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);                                 
     spinner.setAdapter(adapter);

Mungkin perlu ditambahkan

import android.view.ViewGroup;

Ke daftar impor Anda di bagian atas file Anda. Untuk beberapa alasan Eclipse tidak membuat saran ini ketika tidak mengenali kelas ViewGroup yang terlibat dalam kode.

DixieFlatline
sumber
2
Terima kasih banyak teman .. Setelah perjuangan panjang, saya telah menemukan ini. Ini menyelamatkan hari terakhir saya
Andro Selva
terima kasih telah menambahkan jawaban!
CommonSenseCode
Pertanyaan yang sangat bagus ...
Rahul Kushwaha

Jawaban:

81

Inilah yang berhasil bagi saya (menggunakan ide dari jawaban CommonsWare dan gsanllorente ):

private static class MySpinnerAdapter extends ArrayAdapter<String> {
    // Initialise custom font, for example:
    Typeface font = Typeface.createFromAsset(getContext().getAssets(),
                        "fonts/Blambot.otf");

    // (In reality I used a manager which caches the Typeface objects)
    // Typeface font = FontManager.getInstance().getFont(getContext(), BLAMBOT);

    private MySpinnerAdapter(Context context, int resource, List<String> items) {
        super(context, resource, items);
    }

    // Affects default (closed) state of the spinner
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        TextView view = (TextView) super.getView(position, convertView, parent);
        view.setTypeface(font);
        return view;
    }

    // Affects opened state of the spinner
    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        TextView view = (TextView) super.getDropDownView(position, convertView, parent);
        view.setTypeface(font);
        return view;
    }
}

Jika Anda, seperti saya, awalnya mengisi Spinner menggunakan ArrayAdapter.createFromResource()dan sumber daya array (seperti dalam dokumentasi Spinner ), maka Anda akan menggunakan MySpinnerAdapter seperti ini:

MySpinnerAdapter<String> adapter = new MySpinnerAdapter(
        getContext(),
        R.layout.view_spinner_item,
        Arrays.asList(getResources().getStringArray(R.array.my_array))
);
spinner.setAdapter(adapter);
Jonik
sumber
1
Bagus! Saya melangkah lebih jauh dan membuat assignAdapterWithOptions(Spinner spinner, int textArrayResId)metode, mendapatkan konteks dari spinner.getContext()dan menetapkan adaptor ke pemintal di dalamnya (tata letak pemintal adalah stander untuk seluruh aplikasi saya)
IG Pascual
Ini sangat membantu saya. Terima kasih ... @ Jonik
Rahul Kushwaha
24

Anda akan menerapkan font melalui kustom Anda sendiri SpinnerAdapter, dalam getView()dan getDropDownView().

CommonsWare
sumber
Saya mengedit pertanyaan saya dengan masalah terbaru saya, dapatkah Anda memberi tahu apa yang saya lakukan salah. Tnx
DixieFlatline
1
@DixieFlatline: Anda perlu menambahkan impor untuk android.view.ViewGroup, mungkin
CommonsWare
15

Jika Anda mengimplementasikan Adapter Anda di file lain, Anda bisa mengakses fungsi "getAssets ()" dari konstruktor Adapter, karena Anda memiliki Context sebagai parameter.

public class YourItemAdapter extends ArrayAdapter<String> {
int recurso;
Typeface tf;

public YourItemAdapter(Context _context, int _resource,
        List<String> _items) {

    super(_context, _resource, _items);
    recurso=_resource;
    tf=Typeface.createFromAsset(_context.getAssets(),"font/digital-7.ttf");
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    //You can use the new tf here.
    TextView spinner_text=(TextView)findViewById(R.id.text1);
    spinner_text.setTypeface(tf);
    }
}
gsanllorente.dll
sumber
yang satu ini sangat membantu, Terima Kasih :)
Jashan PJ
Ini agak berguna, meskipun tidak berhasil untuk saya: findViewById(R.id.text1)sepertinya tidak menemukan TextView, meskipun ID-nya benar. Beberapa masalah lain dalam kode ini: 1) pernyataan return yang hilang dalam getView(), 2) bidang yang tidak digunakan recurso, 3) beberapa masalah gaya seperti penamaan variabel spinner_text(seharusnya spinnerText). Inilah yang berhasil untuk saya .
Jonik
4

Coba ini buat custom_spinner.xml kustom

<?xml version="1.0" encoding="utf-8"?>

<com.xxxx.xxxx.CheckedTextViewC

    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1"
    style="?android:attr/spinnerDropDownItemStyle"
    android:singleLine="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:textAlignment="center"
    android:paddingTop="5dp"
    android:paddingBottom="5dp"
    android:textSize="18sp"

    />

Buat CheckedtextView kustom seperti ini

import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.CheckedTextView;

public class CheckedTextViewC extends CheckedTextView {

    public CheckedTextViewC(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
    }
    public CheckedTextViewC(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }
    public CheckedTextViewC(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
    public void setTypeface(Typeface tf, int style) {
        if(!this.isInEditMode()){
        Typeface normalTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Roboto-Light.ttf");
        Typeface boldTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Roboto-Light.ttf");

        if (style == Typeface.BOLD) {
            super.setTypeface(boldTypeface/*, -1*/);
        } else {
            super.setTypeface(normalTypeface/*, -1*/);
        }
        }

    }
}

menerapkan tata letak baru

adapter= new ArrayAdapter <String>(Menu.this,R.layout.custom_spinner, list);
joe1327
sumber
Saya pikir ini akan lebih baik, karena Anda tidak perlu mengotori adaptor, dan Anda dapat menggunakan CustomTextview ini di mana pun di Aplikasi Anda.
Milad
2

Ini adalah kelanjutan dari jawaban saya sebelumnya: https://stackoverflow.com/a/51100507/787399

Untuk alasan kompatibilitas, Anda dapat menggunakan gaya dan kelas yang disesuaikan dengan widget di Android. Meskipun di atas Android level 15, /res/fontfolder sumber daya baru diperkenalkan:

Sumber Daya Font di Android

Langkah 1: nyatakan item_spinner.xml

<?xml version="1.0" encoding="utf-8"?>
<com.my_package.custom_views.FontTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tv_spinner"
    style="@style/App_TextViewStyleSmall"
    android:layout_gravity="start|bottom"
    android:layout_marginLeft="@dimen/dp_5"
    android:layout_marginStart="@dimen/dp_5"
    android:ellipsize="marquee"
    android:gravity="start|bottom"
    android:padding="@dimen/dp_10"
    android:singleLine="true"
    android:textAlignment="inherit" />
    <!--declared in layout: item_spinner.xml-->
    <!-- removed attributes:  android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:textColor="@color/text_grey_light"
               android:textSize="@dimen/sp_14" -->
    <!--style="?android:attr/spinnerItemStyle"-->

langkah 2: nyatakan item_spinner_dropdown.xml:

<?xml version="1.0" encoding="utf-8"?>
<com.my_package.custom_views.FontTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tv_spinner"
    style="@style/App_TextViewStyleSmall"
    android:layout_gravity="start|bottom"
    android:layout_marginLeft="@dimen/dp_5"
    android:layout_marginStart="@dimen/dp_5"
    android:ellipsize="marquee"
    android:gravity="start|bottom"
    android:padding="@dimen/dp_10"
    android:singleLine="true" />
    <!--declared in layout: item_spinner_dropdown.xml -->
    <!--removed: ?android:attr/dropdownListPreferredItemHeight-->
    <!--style="?android:attr/spinnerDropDownItemStyle"-->

Langkah 3: Gunakan spinner dalam tata letak:

<LinearLayout
            android:id="@+id/ll_my_spinner"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/fet_bus_entity"
            android:layout_marginTop="@dimen/dp_12"
            android:orientation="horizontal">

            <com.my_package.custom_views.FontTextView
                style="@style/App_TextViewStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="start|bottom"
                android:gravity="start|bottom"
                android:text="@string/are_you_a" />

            <Spinner
                android:id="@+id/sp_my_spinner"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/dp_5"
                android:layout_marginStart="@dimen/dp_5"
                android:layout_gravity="end|bottom"
                android:spinnerMode="dropdown" />
        </LinearLayout>

[Catatan: id dari FontTextView sama di kedua tata letak, item spinner dan item drop-down]

Langkah 4: Gunakan di Activity / Fragment:

private void initSpinnerBusinessType(View rootView) {
        String[] ar_dd_bus_type = getResources().getStringArray(R.array.ar_dd_bus_type);
        List<String> lst_bus_type = Arrays.asList(ar_dd_bus_type);
        ArrayList<String> ar_bus_type = new ArrayList<>(lst_bus_type);
        //==

        ArrayAdapter<String> adapter = new ArrayAdapter<>(activity, R.layout.item_spinner, R.id.tv_spinner, ar_bus_type);
        adapter.setDropDownViewResource(R.layout
                .item_spinner_dropdown);
        //=========
        Spinner sp_my_spinner= rootView.findViewById(R.id.sp_my_spinner);
        sp_my_spinner.setAdapter(adapter);
    }

[untuk panduan lebih lanjut lihat posting saya yang lain: https://stackoverflow.com/a/51077569/787399 dan https://stackoverflow.com/a/22164007/787399 ]

Abhinav Saxena
sumber
0

Silakan ikuti kustomisasi dasar FontTextView, FontEditView, FontRadioButton, FontCheckBox dan FontButton.

[Untuk jawaban yang tepat, setelah melihat panduan ini, silakan lihat: https://stackoverflow.com/a/51113022/787399 ]

Gunakan FontTextView kustom, dalam tata letak item ArrayAdapter, seperti ini:

public class FontEditText extends AppCompatEditText {

//    private String FONT = "fonts/roboto_regular.ttf";

    public FontEditText(Context context) {
        super(context, null);
//        setFontFromAsset(context, null, R.style.DefaultFontTextView);
//        FONT = getContext().getString(R.string.font_roboto_regular);
    }

    public FontEditText(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setFontFromAsset(context, attrs, R.attr.fetFontStyle);
    }

    public FontEditText(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setFontFromAsset(context, attrs, defStyleAttr);
    }

    private void setFontFromAsset(Context context, AttributeSet attrs, int defStyle) {
        BaseActivity activity = (BaseActivity)((MyApplication) context.getApplicationContext()).getCurrentActivity();
        FontAndLocaleManager fontAndLocaleManager = activity.getFontAndLocaleManager();
        fontAndLocaleManager.setFontFromAsset(this, R.styleable.FontEditText, R.styleable.FontEditText_fetFontFace, attrs, defStyle);
    }
}

gunakan kode:

public void setFontFromAsset(View view, int[] resViewStyleable, int resStyleableViewFontFace, AttributeSet attrs, int defStyle) {
        String strFont = null;
        Typeface tfFontFace = null;
        String strButton = FontButton.class.getCanonicalName(),
                strTextView = FontTextView.class.getCanonicalName(),
                strEditText = FontEditText.class.getCanonicalName(),
                strView = view.getClass().getCanonicalName();
        try {
            if (view.isInEditMode()) {
                return;
            }
            //R.string.font_roboto_regular
            strFont = context.getString(R.string.font_roboto_regular);
            tfFontFace = Typeface.createFromAsset(context.getAssets(), strFont);

            //AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes
            //R.styleable.FontButton
            TypedArray a = context.obtainStyledAttributes(attrs, resViewStyleable, defStyle, 0);
            //R.styleable.FontButton_btFontFace
            String derivedFont = a.getString(resStyleableViewFontFace);

            a.recycle();

            //==
            try {
                if (derivedFont != null) {
                    Typeface derivedFontFace = Typeface.createFromAsset(context.getAssets(), derivedFont);
                    if (strView.equals(strButton)) {
                        ((FontButton) view).setTypeface(derivedFontFace);
                    } else if (strView.equals(strTextView)) {
                        ((FontTextView) view).setTypeface(derivedFontFace);
                    } else if (strView.equals(strEditText)) {
                        ((FontEditText) view).setTypeface(derivedFontFace);
                    }
                    return;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            if (strFont != null && tfFontFace != null) {
                if (strView.equals(strButton)) {
                    ((FontButton) view).setTypeface(tfFontFace);
                } else if (strView.equals(strTextView)) {
                    ((FontTextView) view).setTypeface(tfFontFace);
                } else if (strView.equals(strEditText)) {
                    ((FontEditText) view).setTypeface(tfFontFace);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

Jelaskan gaya dan atribut di masing-masing xml:

<!--FontTextView-->
    <declare-styleable name="FontTextViewStyle">
        <!-- Style of the FontTextView. -->
        <attr name="ftvFontStyle" format="reference"/>

    </declare-styleable>
    <declare-styleable name="FontTextView">
        <!-- Font face of FontTextView. -->
        <attr name="ftvFontFace" format="reference"/>
    </declare-styleable>

dan

<!--FontTextView-->
<style name="StyledFontTextView" parent="@android:style/Theme.Light">
<item name="ftvFontStyle">@style/DefaultFontTextView</item>
</style>

<style name="DefaultFontTextView">
<item name="ftvFontFace">@string/font_roboto_regular</item>
</style>

tentukan beberapa gaya lagi:

<style name="App_TextViewStyle" parent="@android:style/Widget.TextView">
        <item name="android:textColor">@color/text_grey</item>
        <item name="android:textSize">@dimen/sp_20</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
    </style>
    <style name="App_TextViewStyleMedium" parent="@android:style/Widget.TextView">
        <item name="android:textColor">@color/text_hint</item>
        <item name="android:textSize">@dimen/sp_18</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
    </style>
    <style name="App_TextViewStyleSmall" parent="@android:style/Widget.TextView">
        <item name="android:textColor">@color/text_grey_light</item>
        <item name="android:textSize">@dimen/sp_14</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
    </style>

sebutkan font di strings.xml Anda:

...
<string name="font_roboto_regular">fonts/roboto_regular.ttf</string>
...

dan digunakan dalam tata letak menghemat beberapa kode dan waktu:

<com.mypackage.custom_views.FontTextView
                style="@style/App_TextViewStyleMedium"
                android:layout_gravity="start|bottom"
                android:gravity="start|bottom"
                app:fetFontFace="@string/font_roboto_regular"
                android:text="@string/are_you_a" />

Di Android level 16 ke atas, semua ini disederhanakan, karena sekarang Anda dapat tetap menggunakan TTF dan resource font lainnya /res/font folder, bukan di aset. Itu menghapus sebagian besar kelas, gaya, dan atribut khusus, lihat:

Sumber Daya Font di Android

Selamat Coding dengan gaya !! :-)

Abhinav Saxena
sumber
Jawaban panjang, tapi satu kali berhasil. Kemudian setelah itu dapat digunakan kembali.
Abhinav Saxena
-1

Guys Saya menemukan solusi yang luar biasa, saya membungkus adaptor orignal dengan pembantu seperti

Gunakan kelas ini SpinnerViewHelper dan selamat melakukan progamming dengan Android

new SpinnerViewHelper((Spinner)view.findViewById(R.id.labelSurveyNumber),(parent, v, position, id) -> UrduFontHelper.set(v));

Ekspresi lambda digunakan.

Qamar4P
sumber