it-swarm.com.de

Wie kann ich programmgesteuert eine benutzerdefinierte Schriftart für Spinner-Text festlegen?

Ich habe eine Ttf-Schriftdatei in meinem Assets-Ordner. Ich weiß, wie man es für Textansichten verwendet:

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

Ich habe den Look für meinen Spinner-Text in seiner eigenen XML-Datei (wie üblich in Android) definiert:

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

Ich kann diese Textansicht einfach nicht aus dem Code referenzieren, ich bekomme immer Nullzeigerausnahmen. Z.B. Ich habe es versucht:

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

Kann ich meine externe Schriftart auch für meinen Spinner-Text auswählen, der in seiner eigenen XML definiert ist?

Vielen Dank.

BEARBEITEN mit Antwort:

Das funktioniert:

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

Es kann notwendig sein, hinzuzufügen

import Android.view.ViewGroup;

Zu Ihrer Importliste oben in Ihrer Datei. Aus irgendeinem Grund schlägt Eclipse diesen Vorschlag nicht vor, wenn es die im Code enthaltene ViewGroup-Klasse nicht erkennt.

82
DixieFlatline

Das hat bei mir funktioniert (mit Ideen sowohl aus CommonsWares und gsanllorentes antworten):

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

Wenn Sie, wie ich, den Spinner ursprünglich mit ArrayAdapter.createFromResource() und einer Array-Ressource (wie in Spinner-Dokumentation ) gefüllt haben, würden Sie MySpinnerAdapter folgendermaßen verwenden: 

MySpinnerAdapter<String> adapter = new MySpinnerAdapter(
        getContext(),
        R.layout.view_spinner_item,
        Arrays.asList(getResources().getStringArray(R.array.my_array))
);
spinner.setAdapter(adapter);
75
Jonik

Sie würden die Schriftart über Ihre eigenen benutzerdefinierten SpinnerAdapter in getView() und getDropDownView() anwenden.

23
CommonsWare

Wenn Sie Ihren Adapter in einer anderen Datei implementieren, können Sie vom Konstruktor des Adapters aus auf die Funktion "getAssets ()" zugreifen, da Sie den Kontext als Parameter verwenden.

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

Versuchen Sie dies, um benutzerdefinierte custom_spinner.xml zu erstellen

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

    />

Erstellen Sie eine benutzerdefinierte CheckedtextView wie diese

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

    }
}

implementieren Sie das neue Layout 

adapter= new ArrayAdapter <String>(Menu.this,R.layout.custom_spinner, list);
4
joe1327

Dies ist die Fortsetzung meiner vorherigen Antwort: https://stackoverflow.com/a/51100507/787399

Aus Gründen der Kompatibilität können Sie die Stile und das angepasste .__ verwenden. Klassen gegen die Widgets in Android. Obwohl über dem Android-Level 15, neue /res/font-Ressourcenordner wurden eingeführt:

Fontressourcen in Android

Schritt 1: item_spinner.xml deklarieren

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

schritt 2: item_spinner_dropdown.xml deklarieren:

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

Schritt 3: Spinner im Layout verwenden:

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

[Hinweis: Die ID von FontTextView ist in beiden Layouts, Spinner-Elementen und Dropdown-Elementen identisch.]

Schritt 4: Verwenden Sie es in der Aktivität/im 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);
    }

[Weitere Hinweise finden Sie in meinem anderen Beitrag: https://stackoverflow.com/a/51077569/787399 und https://stackoverflow.com/a/22164007/787399 ]

2
Abhinav Saxena

Bitte folgen Sie den grundlegenden Anpassungen von FontTextView, FontEditView, FontRadioButton, FontCheckBox und FontButton.

[Die genaue Antwort finden Sie nach dem Lesen dieser Anleitung unter: https://stackoverflow.com/a/51113022/787399 ]

Verwenden Sie im ArrayAdapter-Elementlayout das benutzerdefinierte FontTextView wie folgt:

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

verwenden Sie den Code:

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

    }

Beschreiben Sie den Stil und die Attribute in den jeweiligen XML-Dateien:

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

und

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

einige weitere Stile definieren:

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

erwähne Schriftarten in deiner strings.xml:

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

und in den Layouts verwenden, um etwas Code und Zeit zu sparen:

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

Ab Android-Version 16 ist dies alles vereinfacht, da Sie jetzt TTF- und andere Schriftartressourcen im /res/font-Ordner statt in Assets behalten können. Dadurch werden die meisten benutzerdefinierten Klassen, Stile und Attribute entfernt, siehe:

Fontressourcen in Android

Happy Coding mit Stil !! :-)

2
Abhinav Saxena

Jungs, ich fand eine tolle Lösung, ich wickle orignal Adapter per Helfer gerne ein

Verwenden Sie diese Klasse SpinnerViewHelper und ein glückliches Programmieren mit Android

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

Lambda-Ausdruck wird verwendet.

0
Qamar4P