如何以编程方式将字体自定义字体设置为 Spinner 文本?

Posted

技术标签:

【中文标题】如何以编程方式将字体自定义字体设置为 Spinner 文本?【英文标题】:How to set font custom font to Spinner text programmatically? 【发布时间】:2011-07-25 21:43:52 【问题描述】:

我的资产文件夹中有一个 ttf 字体文件。我知道如何将它用于文本视图:

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

我已经定义了在它自己的 xml 文件中查找我的微调器文本(就像在 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_
android:layout_
android:ellipsize="marquee" />

我只是不能从代码中引用这个文本视图,我总是得到空指针异常。例如。我试过了:

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

是否可以选择我的外部字体,即使是在它自己的 xml 中定义的微调器文本?

谢谢。

编辑答案:

这行得通:

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

可能需要添加

import android.view.ViewGroup;

到文件顶部的导入列表。由于某种原因,当 Eclipse 无法识别代码中涉及的 ViewGroup 类时,它不会提出此建议。

【问题讨论】:

非常感谢朋友。。经过长时间的努力,我找到了这个。这终于拯救了我的一天 感谢您添加答案! 非常好的问题... 【参考方案1】:

这对我有用(使用来自 CommonsWare's 和 gsanllorente's 答案的想法):

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;
    

如果您和我一样,最初使用 ArrayAdapter.createFromResource() 和数组资源(如 Spinner documentation)填充 Spinner,那么您应该像这样使用 MySpinnerAdapter:

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

【讨论】:

太棒了!我更进一步,创建了一个assignAdapterWithOptions(Spinner spinner, int textArrayResId) 方法,从spinner.getContext() 获取上下文并将适配器分配给其中的微调器(微调器布局与我的整个应用程序一致) 这对我有很大帮助。谢谢...@Jonik【参考方案2】:

您可以通过自己的自定义SpinnerAdaptergetView()getDropDownView() 应用字体。

【讨论】:

我用我最新的问题编辑了我的问题,你能告诉我我做错了什么吗? Tnx @DixieFlatline:你需要为android.view.ViewGroup添加一个导入,大概【参考方案3】:

如果你在另一个文件中实现你的适配器,你可以从适配器的构造函数中访问“getAssets()”函数,因为你有上下文作为参数。

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

【讨论】:

这个真的很有帮助,谢谢:) 这很有用,尽管它对我不起作用:findViewById(R.id.text1) 似乎没有找到 TextView,尽管 ID 是正确的。此代码中的其他一些问题:1)getView() 中缺少 return 语句,2)未使用的字段 recurso,3)一些样式问题,例如命名变量 spinner_text(应该是 spinnerText)。 Here's what worked for me.【参考方案4】:

试试这个创建自定义 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_
    android:layout_
    android:ellipsize="marquee"
    android:textAlignment="center"
    android:paddingTop="5dp"
    android:paddingBottom="5dp"
    android:textSize="18sp"

    />

像这样创建自定义 CheckedtextView

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

    

实现新布局

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

【讨论】:

我认为这样会更好,因为你不必在适配器上弄脏你的手,你可以在你的应用程序的任何其他地方使用这个 CustomTextview。【参考方案5】:

这是我之前回答的延续:https://***.com/a/51100507/787399

出于兼容性原因,您可以使用样式和自定义 针对 Android 中的小部件的类。虽然高于安卓水平 15、新增/res/font资源文件夹:

Font Resources in Android

第 1 步:声明 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_
               android:layout_
               android:textColor="@color/text_grey_light"
               android:textSize="@dimen/sp_14" -->
    <!--style="?android:attr/spinnerItemStyle"-->

第 2 步:声明 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"-->

第 3 步:在布局中使用微调器:

<LinearLayout
            android:id="@+id/ll_my_spinner"
            android:layout_
            android:layout_
            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_
                android:layout_
                android:layout_gravity="start|bottom"
                android:gravity="start|bottom"
                android:text="@string/are_you_a" />

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

[注意:FontTextView 的 id 在布局、微调项和下拉项中都是相同的]

第 4 步:在 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);
    

[如需进一步指导,请参阅我的另一篇帖子:https://***.com/a/51077569/787399 和 https://***.com/a/22164007/787399]

【讨论】:

【参考方案6】:

请按照 FontTextView、FontEditView、FontRadioButton、FontCheckBox 和 FontButton 的基本定制。

[ 确切答案,看过本指南后,请看: https://***.com/a/51113022/787399]

在ArrayAdapter项布局中使用自定义FontTextView,像这样:

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

使用代码:

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

    

在各自的 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>

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

定义更多样式:

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

在您的 strings.xml 中提及字体:

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

在布局中使用可以节省一些代码和时间:

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

在 Android 16 及更高级别,这一切都被简化了,因为现在您可以将 TTF 和其他字体资源保存在 /res/font 文件夹中,而不是资产中。这会删除大部分自定义类、样式和属性,请参阅:

Font Resources in Android

快乐的编码风格! :-)

【讨论】:

长答案,但一次工作。然后,这是一个可重复使用的。【参考方案7】:

伙计们,我找到了一个很棒的解决方案,我用助手包装了原始适配器

使用此类 SpinnerViewHelper 并愉快地使用 Android 进行编程

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

使用了 Lambda 表达式。

【讨论】:

以上是关于如何以编程方式将字体自定义字体设置为 Spinner 文本?的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式将 UILabel 字体设置为用户定义的运行时属性

如何在 iPhone SDK 中使用自定义字体? [复制]

如何将自定义字体设置为 android 工具栏的字幕?

如何以编程方式设置 wC hR 字体大小?

自定义字体仅在 Interface Builder 中设置时可用

以编程方式将 CFF 字体转换为 OpenType 字体