web-dev-qa-db-fra.com

Comment définir une police personnalisée sur Spinner text par programme?

J'ai un fichier de police ttf dans mon dossier assets. Je sais comment l'utiliser pour les textviews avec:

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

J'ai défini l'apparence de mon texte dans son propre fichier XML (comme dans 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" />

Je ne peux tout simplement pas faire référence à cette textview à partir de code, je reçois toujours des exceptions null pointeur. Par exemple. j'ai essayé:

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

Est-il possible de sélectionner ma police externe même pour mon texte spinner défini dans son propre fichier XML?

Je vous remercie.

EDIT avec réponse:

Cela marche:

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

Il peut être nécessaire d'ajouter

import Android.view.ViewGroup;

À votre liste d'importations en haut de votre fichier. Pour une raison quelconque, Eclipse ne fait pas cette suggestion lorsqu'il ne reconnaît pas la classe ViewGroup impliquée dans le code.

82
DixieFlatline

C'est ce qui a fonctionné pour moi (en utilisant les idées des réponses de CommonsWare _ et de de 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;
    }
}

Si, comme moi, vous avez initialement rempli Spinner à l'aide de ArrayAdapter.createFromResource() et d'une ressource de tableau (comme dans documentation Spinner ), vous utiliseriez alors MySpinnerAdapter comme suit: 

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

Vous appliqueriez la police par l’intermédiaire de votre propre variable SpinnerAdapter, dans getView() et getDropDownView().

23
CommonsWare

Si vous implémentez votre adaptateur dans un autre fichier, vous pouvez accéder à la fonction "getAssets ()" à partir du constructeur de l'adaptateur, car vous avez le contexte comme paramètre.

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

Essayez cette création personnalisée custom_spinner.xml

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

    />

Créer un CheckedtextView personnalisé comme celui-ci

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

    }
}

implémenter la nouvelle mise en page 

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

Voici la suite de ma réponse précédente: https://stackoverflow.com/a/51100507/787399

Pour des raisons de compatibilité, vous pouvez utiliser les styles et personnalisé classes contre les widgets dans Android. Bien au-dessus du niveau Android 15 nouveaux dossiers de ressources /res/font ont été introduits:

Ressources de polices sous Android

Étape 1: déclarez 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"-->

étape 2: déclarez 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"-->

Étape 3: Utilisez spinner dans la mise en page:

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

[Remarque: l'id de FontTextView est le même dans les dispositions, l'élément de filtre et l'élément de menu déroulant]

Étape 4: utilisez-le dans l'activité/le 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);
    }

[pour plus de précisions, consultez mon autre article: https://stackoverflow.com/a/51077569/787399 et https://stackoverflow.com/a/22164007/787399 ]

2
Abhinav Saxena

Suivez la personnalisation de base de FontTextView, FontEditView, FontRadioButton, FontCheckBox et FontButton.

[Pour la réponse exacte, après avoir vu ce guide, veuillez consulter: https://stackoverflow.com/a/51113022/787399 ]

Utilisez FontTextView personnalisé, dans la disposition des éléments ArrayAdapter, comme ceci:

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

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

    }

Décrivez le style et les attributs dans les fichiers XML respectifs:

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

et

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

définir quelques styles supplémentaires:

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

mentionnez les polices dans votre strings.xml:

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

et utiliser dans les mises en page en économisant du code et du temps:

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

Au niveau 16 et supérieur d'Android, tout cela est simplifié, car vous pouvez maintenant conserver TTF et d'autres ressources de police dans le dossier /res/font, plutôt que dans les ressources. Cela supprime la plupart des classes, des styles et des attributs personnalisés, voir:

Ressources de polices sous Android

Happy Coding avec style !! :-)

2
Abhinav Saxena

Les gars, j'ai trouvé une solution géniale, j'emballe adaptateur orignal par aide comme

Utilisez cette classe SpinnerViewHelper et progamming avec Android

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

L'expression lambda est utilisée.

0
Qamar4P