在PreferenceScreen中为文本设置自定义字体

10

我PreferenceActivity的外观如下:

import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.widget.TextView;

public class Settings extends PreferenceActivity {

    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
            super.onCreate(savedInstanceState);

            //setContentView(R.layout.about);

            Typeface timesFont = Typeface.createFromAsset(getAssets(), "fonts/times.ttf");

            TextView about_txt = (TextView) findViewById(R.id.about_txt);        
            about_txt.setTypeface(timesFont);
            about_txt.setText(R.string.about_txt);


            if (Build.VERSION.SDK_INT<Build.VERSION_CODES.HONEYCOMB)
            {
                addPreferencesFromResource(R.xml.preferences);
            } else {
                // Display the fragment as the main content.
                getFragmentManager().beginTransaction().replace(android.R.id.content,
                        new PrefsFragment()).commit();
            }
    }

    public static class PrefsFragment extends PreferenceFragment 
    {
            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);

                // Load the preferences from an XML resource
                addPreferencesFromResource(R.xml.preferences);
            }
        }
}

并且 preference.xml

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

        <ListPreference
            android:dialogTitle="@string/size_dialog"
            android:entries="@array/size_list"
            android:entryValues="@array/entry_size"
            android:key="size_list"
            android:summary="@string/size_summary"
            android:title="@string/pref4title"
            />

    </PreferenceCategory>

    <PreferenceCategory
        android:title="@string/pref_about"
        android:layout="@layout/about"
        >

    </PreferenceCategory>

</PreferenceScreen>

@layout/about(about.xml):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:tools="http://schemas.android.com/tools"
         android:layout_width="match_parent"
         android:layout_height="match_parent"> 

          <TextView
            android:id="@+id/about_txt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="some text here"   
            />

</LinearLayout>

我有特定的语言,因此在about.xml中的文本应该使用特定的字体。通常我会使用以下代码来设置TextView的字体:

 Typeface timesFont = Typeface.createFromAsset(getAssets(), "fonts/times.ttf");

 TextView about_txt = (TextView) findViewById(R.id.about_txt);        
 about_txt.setTypeface(timesFont);
 about_txt.setText(R.string.about_txt);

但我应该使用什么来访问添加到首选项屏幕中的 about.xml 文本?

谢谢!

4个回答

7

改变PreferenceScreen中所有TextViews的字体最简单的方法是:

public class WallpaperSettings extends PreferenceActivity {

  private View tryInflate(String name, Context context, AttributeSet attrs) {
    LayoutInflater li = LayoutInflater.from(context);
    View v = null;
    try {
        v = li.createView(name, null, attrs); 
    } catch (Exception e) {
        try {
            v = li.createView("android.widget." + name, null, attrs);
        } catch (Exception e1) {
        }
    }
    return v;
  }

  protected void onCreate(Bundle savedInstanceState) {
    //CHANGE TYPEFACE FOR ALL TEXTVIEWS
    final Typeface font = Typeface.createFromAsset(getAssets(), "fonts/cabal.ttf");     
    getLayoutInflater().setFactory(new Factory() {
        @Override
        public View onCreateView(String name, Context context,
                AttributeSet attrs) {
            View v = tryInflate(name, context, attrs);
            if (v instanceof TextView) {                    
                ((TextView) v).setTypeface(font);
            }
            return v;
        }
    });

    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.prefs);
  }
}

就是这样了!


6

也许编写自己的Preference并将其添加到xml中更容易
只需通过Spannable为设置字段设置自定义字体:
(看起来很长,但很快完成 :))

完整解决方案:

private void convertPreferenceToUseCustomFont(Preference somePreference) {
    CustomTypefaceSpan customTypefaceSpan = new CustomTypefaceSpan("", net.mikekober.myMory.utils.Utils.getUsedTypeFace(getActivity()));

    SpannableStringBuilder ss;
    if (somePreference.getTitle() != null) {
        ss = new SpannableStringBuilder(somePreference.getTitle().toString());
        ss.setSpan(customTypefaceSpan, 0, ss.length(),Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
        somePreference.setTitle(ss);
    }

    if (somePreference.getSummary() != null) {
        ss = new SpannableStringBuilder(somePreference.getSummary().toString());
        ss.setSpan(customTypefaceSpan, 0, ss.length(),Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
        somePreference.setSummary(ss);
    }
}

为每个偏好调用它,就完成了 :)
愉快并祝好运
顺便说一下:更改文本时,请再次调用!
顺带一提:已检查、查看、应用、完善 ;) 来自:https://dev59.com/AGw15IYBdhLWcg3wcbWy#10741161 顺带一提,差点忘了:
static private class CustomTypefaceSpan extends TypefaceSpan {

    private final Typeface newType;

    public CustomTypefaceSpan(String family, Typeface type) {
        super(family);
        newType = type;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        applyCustomTypeFace(ds, newType);
    }

    @Override
    public void updateMeasureState(TextPaint paint) {
        applyCustomTypeFace(paint, newType);
    }

    private static void applyCustomTypeFace(Paint paint, Typeface tf) {
        int oldStyle;
        Typeface old = paint.getTypeface();
        if (old == null) {
            oldStyle = 0;
        } else {
            oldStyle = old.getStyle();
        }

        int fake = oldStyle & ~tf.getStyle();
        if ((fake & Typeface.BOLD) != 0) {
            paint.setFakeBoldText(true);
        }

        if ((fake & Typeface.ITALIC) != 0) {
            paint.setTextSkewX(-0.25f);
        }

        paint.setTypeface(tf);
    }
}

感谢提供简单的解决方案。自定义字体应用于除“ListPreference”的“summary”文本之外的所有文本。您知道如何更改“summary”字体吗? - Hiren Dabhi
@Nolesh的解决方案同样适用于摘要字段,并且是一个更好的解决方案。 - dasfima

4

随着Android O对字体的支持,我们现在可以在应用主题中设置font-family,这将自动反映在PreferenceFragment中(注意:我正在使用PreferenceFragmentCompat)。首先像这样向资源中添加font-family

<font-family xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<font
    android:fontStyle="normal"
    android:fontWeight="400"
    android:font="@font/nunito"

    app:fontStyle="normal"
    app:fontWeight="400"
    app:font="@font/nunito"/>

<font
    android:fontStyle="italic"
    android:fontWeight="400"
    android:font="@font/nunito_italic"

    app:fontStyle="italic"
    app:fontWeight="400"
    app:font="@font/nunito_italic" />

注意:目前需要同时使用appandroid命名空间声明链接

然后为文本视图添加一个style,并在其中指定font-family属性:

<style name="NunitoTextViewStyle" parent="android:Widget.TextView">
    <item name="android:fontFamily">@font/nunito_regular_font_family</item>
</style>

最后,只需按以下方式在您的AppTheme中引用上述style

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    ........
    <item name="android:textViewStyle">@style/NunitoTextViewStyle</item>
</style>

完成。这将在您的PreferenceFragmentCompat中显示自定义字体。


4
public class CustomPreference extends Preference 
    implements PreferenceStyle {

    private int style;

    public CustomPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

    public CustomPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomPreference(Context context) {
        super(context);
    }

    @Override
    protected void onBindView(View view) {
        super.onBindView(view);
        switch (style) {
        case STYLE_ALARMED:
            setStyleAlarmed(view);
            break;
        case STYLE_NORMAL:
            setStyleNormal(view);
            break;
        case STYLE_WARNING:
            setStyleWarning(view);
            break;
        case STYLE_SUMMARY_ALARM:
            setStyleSummaryAlarm(view);
            break;
        case STYLE_SUMMARY_WARNING:
            setStyleSummaryWarning(view);
            break;
        case STYLE_DISABLED:
            setStyleDisabled(view);
            break;
        default:
            break;
        }

    }

private void setStyleWarning(View view) {
    TextView titleView = (TextView) view.findViewById(android.R.id.title);
    titleView.setTextColor(Color.YELLOW);
            // add your FONT here
}

private void setStyleAlarmed(View view) {
    int alarmREDColor = view.getContext().getResources().getColor(R.color.alarmed_red);
    TextView titleView = (TextView) view.findViewById(android.R.id.title);
    titleView.setTextColor(alarmREDColor);
}

public void setStyle(int style) {
        switch (style) {
        case STYLE_ALARMED:
            this.style = STYLE_ALARMED;
            break;
        case STYLE_NORMAL:
            this.style = STYLE_NORMAL;
            break;
        default:
            this.style = STYLE_NORMAL;
        }
    }

public interface PreferenceStyle {

    public static final int STYLE_DISABLED = 0;
    public static final int STYLE_NORMAL = 10;
    public static final int STYLE_ALARMED = 20;
    public static final int STYLE_WARNING = 30;

    public static final int STYLE_SUMMARY_ALARM = 40;
    public static final int STYLE_SUMMARY_WARNING = 50;

    public void setStyle(int style);
    public Context getContext();
    public void setSummary(CharSequence summary);

}

public class YourActivity extends PreferenceActivity {

    private CustomPreference pref1;
    private CustomPreference pref2;
    private CustomPreference pref3;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);         
        addPreferencesFromResource(R.xml.prefence_xml);
        pref1 = findPreference();
                    pref1.setOnPreferenceClickListener(this);
                    pref1.setStyle(PreferenceStyle.STYLE_NORMAL);
               }
        }

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >


    <PreferenceCategory 
        android:title="category1">

        <com.project.main.preference.CustomPreference 
            android:key="key"
            android:title="title"
            />  

        <com.project.main.preference.CustomPreference 
            android:key="key"
            android:title="title"/>

    </PreferenceCategory>

</PreferenceScreen>

谢谢您的快速回复,但是当我使用“extends Preference”而不是“PreferenceActivity”时,就无法使用addPreferencesFromResource。或者我做错了什么吗? - Sever
在PreferenceActivity中的“super.onCreate(savedInstanceState)”之后,我加入了“new CustomPreference(this)”,但是没有任何变化。此外,我还在onBindView(View view)方法中添加了以下更改:{super.onBindView(view);Typeface timesFont =Typeface.createFromAsset(this.context.getAssets(), "fonts/times.ttf"); TextView about_txt = (TextView) view.findViewById(android.R.id.title); about_txt.setTypeface(timesFont);} 但是没有效果。 - Sever
请问您能否更新您的帖子,提供正确调用CustomPreference并更改字体的方法...因为我尝试的所有方法都无法生效。 - Sever
谢谢,非常感谢,你帮了我很多。感谢你花时间。我现在明白我犯了什么错误。 - Sever
在findPreference()中出现了ClassCastException错误,现在该怎么办? - Cyph3rCod3r
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接