【问题标题】:How to set font custom font to Spinner text programmatically?如何以编程方式将字体自定义字体设置为 Spinner 文本?
【发布时间】:2023-03-20 18:00:02
【问题描述】:

我的资产文件夹中有一个 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_width="fill_parent"
android:layout_height="wrap_content"
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 类时,它不会提出此建议。

【问题讨论】:

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

标签: android fonts spinner android-spinner android-fonts


【解决方案1】:

这对我有用(使用来自 CommonsWare'sgsanllorente'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_width="match_parent"
    android:layout_height="wrap_content"
    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://stackoverflow.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_width="match_parent"
               android:layout_height="wrap_content"
               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_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>

[注意: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://stackoverflow.com/a/51077569/787399https://stackoverflow.com/a/22164007/787399]

【讨论】:

    【解决方案6】:

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

    [ 确切答案,看过本指南后,请看: https://stackoverflow.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 表达式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-02
      • 1970-01-01
      • 1970-01-01
      • 2014-10-17
      • 2018-02-26
      • 1970-01-01
      相关资源
      最近更新 更多