ฉันต้องใช้แบบอักษรบางอย่างสำหรับแอปพลิเคชันทั้งหมดของฉัน ฉันมีไฟล์. ttf เหมือนกัน เป็นไปได้ไหมที่จะตั้งค่านี้เป็นฟอนต์เริ่มต้นเมื่อเริ่มต้นแอปพลิเคชันแล้วใช้ที่อื่นในแอปพลิเคชันหรือไม่ เมื่อตั้งค่าฉันจะใช้งานใน XML เลย์เอาต์ของฉันได้อย่างไร
ฉันต้องใช้แบบอักษรบางอย่างสำหรับแอปพลิเคชันทั้งหมดของฉัน ฉันมีไฟล์. ttf เหมือนกัน เป็นไปได้ไหมที่จะตั้งค่านี้เป็นฟอนต์เริ่มต้นเมื่อเริ่มต้นแอปพลิเคชันแล้วใช้ที่อื่นในแอปพลิเคชันหรือไม่ เมื่อตั้งค่าฉันจะใช้งานใน XML เลย์เอาต์ของฉันได้อย่างไร
คำตอบ:
ใช่พร้อมการสะท้อนกลับ งานนี้ ( ตามคำตอบนี้ ):
(หมายเหตุ: นี่เป็นวิธีแก้ปัญหาเนื่องจากไม่มีการสนับสนุนแบบอักษรที่กำหนดเองดังนั้นหากคุณต้องการเปลี่ยนสถานการณ์นี้โปรดทำเครื่องหมายดาวเพื่อโหวตปัญหา Android ที่นี่ ) หมายเหตุ:อย่าแสดงความคิดเห็น "ฉันด้วย" ในปัญหานั้นทุกคนที่ได้รับมันจะได้รับอีเมลเมื่อคุณทำเช่นนั้น ดังนั้นโปรด "ดาว" โปรด
import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.Typeface;
public final class FontsOverride {
public static void setDefaultFont(Context context,
String staticTypefaceFieldName, String fontAssetName) {
final Typeface regular = Typeface.createFromAsset(context.getAssets(),
fontAssetName);
replaceFont(staticTypefaceFieldName, regular);
}
protected static void replaceFont(String staticTypefaceFieldName,
final Typeface newTypeface) {
try {
final Field staticField = Typeface.class
.getDeclaredField(staticTypefaceFieldName);
staticField.setAccessible(true);
staticField.set(null, newTypeface);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
จากนั้นคุณจำเป็นต้องใช้แบบอักษรเริ่มต้นจำนวนมากเกินไปตัวอย่างเช่นในคลาสแอปพลิเคชัน :
public final class Application extends android.app.Application {
@Override
public void onCreate() {
super.onCreate();
FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
}
}
หรือแน่นอนถ้าคุณใช้ไฟล์แบบอักษรเดียวกันคุณสามารถปรับปรุงได้เพื่อโหลดไฟล์เพียงครั้งเดียว
อย่างไรก็ตามฉันมักจะเขียนทับพูด"MONOSPACE"
แล้วตั้งค่าสไตล์เพื่อบังคับใช้แบบอักษรแบบอักษรกว้าง:
<resources>
<style name="AppBaseTheme" parent="android:Theme.Light">
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:typeface">monospace</item>
</style>
</resources>
android:Theme.Material.Light
เราได้ตรวจสอบรายงานในการแสดงความคิดเห็นว่ามันไม่ได้ทำงานและมันดูเหมือนจะไม่เข้ากันกับชุดรูปแบบ
หากชุดรูปแบบนั้นไม่สำคัญสำหรับคุณให้ใช้ชุดรูปแบบที่เก่ากว่าเช่น:
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<item name="android:typeface">monospace</item>
</style>
TextView
ไปทุกที่เพื่อใช้แบบอักษรที่กำหนดเองหรือใช้วิธีแก้ปัญหาแบบสะท้อนกลับเช่นนี้ เมื่อรวมกับชุดแบบอักษรที่ จำกัด ที่มีอยู่ใน Android มันทำให้การพัฒนาแอพที่ดูดีเป็นงานที่หนักมาก ฉันได้เพิ่มคำขอคุณสมบัติไปยังตัวติดตามปัญหา Android หากคุณต้องการที่จะเห็นคุณลักษณะนี้คุณสามารถดาวปัญหาที่นี่: code.google.com/p/android/issues/...
มีห้องสมุดที่ยอดเยี่ยมสำหรับแบบอักษรที่กำหนดเองใน Android: การประดิษฐ์ตัวอักษร
นี่คือตัวอย่างวิธีการใช้งาน
ใน Gradle คุณต้องใส่บรรทัดนี้ลงในไฟล์ build.gradle ของแอปของคุณ:
dependencies {
compile 'uk.co.chrisjenx:calligraphy:2.2.0'
}
จากนั้นสร้างคลาสที่ขยายApplication
และเขียนรหัสนี้:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath("your font path")
.setFontAttrId(R.attr.fontPath)
.build()
);
}
}
และในคลาสกิจกรรมให้ใส่เมธอดนี้ก่อน onCreate:
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
และสิ่งสุดท้ายที่ไฟล์ Manifest ของคุณควรมีหน้าตาดังนี้:
<application
.
.
.
android:name=".App">
และมันจะเปลี่ยนกิจกรรมทั้งหมดเป็นแบบอักษรของคุณ! มันง่ายและสะอาด!
<b></b>
, <u></u>
และ<i></i>
ในstrings.xml
ไฟล์และจนถึงขณะนี้ก็ทำงาน
แม้ว่าสิ่งนี้จะไม่สามารถใช้ได้กับแอปพลิเคชั่นทั้งหมด แต่มันก็ใช้ได้กับกิจกรรมและสามารถนำมาใช้ใหม่สำหรับกิจกรรมอื่นได้ ฉันได้อัปเดตรหัสของฉันด้วย @ FR073N เพื่อรองรับการดูอื่น ๆ ผมไม่แน่ใจว่าเกี่ยวกับปัญหาต่างๆButtons
, RadioGroups
ฯลฯ เพราะการเรียนเหล่านั้นขยายTextView
เพื่อให้พวกเขาควรจะทำงานได้ดี ฉันเพิ่มบูลีนแบบมีเงื่อนไขสำหรับการใช้การสะท้อนเนื่องจากดูเหมือนว่าแฮ็คมากและอาจลดประสิทธิภาพลงอย่างเห็นได้ชัด
หมายเหตุ: ตามที่ระบุไว้สิ่งนี้จะไม่ทำงานสำหรับเนื้อหาแบบไดนามิก! ด้วยเหตุนี้จึงเป็นไปได้ที่จะเรียกวิธีนี้ด้วยการพูดonCreateView
หรือgetView
วิธีการ แต่ต้องใช้ความพยายามเพิ่มเติม
/**
* Recursively sets a {@link Typeface} to all
* {@link TextView}s in a {@link ViewGroup}.
*/
public static final void setAppFont(ViewGroup mContainer, Typeface mFont, boolean reflect)
{
if (mContainer == null || mFont == null) return;
final int mCount = mContainer.getChildCount();
// Loop through all of the children.
for (int i = 0; i < mCount; ++i)
{
final View mChild = mContainer.getChildAt(i);
if (mChild instanceof TextView)
{
// Set the font if it is a TextView.
((TextView) mChild).setTypeface(mFont);
}
else if (mChild instanceof ViewGroup)
{
// Recursively attempt another ViewGroup.
setAppFont((ViewGroup) mChild, mFont);
}
else if (reflect)
{
try {
Method mSetTypeface = mChild.getClass().getMethod("setTypeface", Typeface.class);
mSetTypeface.invoke(mChild, mFont);
} catch (Exception e) { /* Do something... */ }
}
}
}
จากนั้นเพื่อใช้งานคุณจะทำสิ่งนี้:
final Typeface mFont = Typeface.createFromAsset(getAssets(),
"fonts/MyFont.ttf");
final ViewGroup mContainer = (ViewGroup) findViewById(
android.R.id.content).getRootView();
HomeActivity.setAppFont(mContainer, mFont);
หวังว่าจะช่วย
สรุป:
ตัวเลือก # 1: ใช้การไตร่ตรองเพื่อใช้แบบอักษร (รวมคำตอบของWeston & Roger Huang ):
import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.Typeface;
public final class FontsOverride {
public static void setDefaultFont(Context context,
String staticTypefaceFieldName, String fontAssetName) {
final Typeface regular = Typeface.createFromAsset(context.getAssets(),
fontAssetName);
replaceFont(staticTypefaceFieldName, regular);
}
protected static void replaceFont(String staticTypefaceFieldName,final Typeface newTypeface) {
if (isVersionGreaterOrEqualToLollipop()) {
Map<String, Typeface> newMap = new HashMap<String, Typeface>();
newMap.put("sans-serif", newTypeface);
try {
final Field staticField = Typeface.class.getDeclaredField("sSystemFontMap");
staticField.setAccessible(true);
staticField.set(null, newMap);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
try {
final Field staticField = Typeface.class.getDeclaredField(staticTypefaceFieldName);
staticField.setAccessible(true);
staticField.set(null, newTypeface);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
การใช้งานในระดับแอปพลิเคชัน:
public final class Application extends android.app.Application {
@Override
public void onCreate() {
super.onCreate();
FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
}
}
ตั้งค่าสไตล์เพื่อบังคับให้แอปพลิเคชันแบบอักษรแบบตัวกว้าง (ขึ้นอยู่กับlovefish ):
Pre-Lollipop:
<resources>
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:typeface">monospace</item>
</style>
</resources>
Lollipop (API 21):
<resources>
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:textAppearance">@style/CustomTextAppearance</item>
</style>
<style name="CustomTextAppearance">
<item name="android:typeface">monospace</item>
</style>
</resources>
ตัวเลือกที่ 2: ซับคลาสแต่ละอันและทุกมุมมองที่คุณต้องการปรับแต่งแบบอักษรเช่น ListView, EditTextView, ปุ่มและอื่น ๆ ( คำตอบของPalani ):
public class CustomFontView extends TextView {
public CustomFontView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public CustomFontView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomFontView(Context context) {
super(context);
init();
}
private void init() {
if (!isInEditMode()) {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "Futura.ttf");
setTypeface(tf);
}
}
ตัวเลือกที่ 3: ใช้ตัวรวบรวมมุมมองที่สำรวจผ่านลำดับชั้นการดูของหน้าจอปัจจุบันของคุณ:
รูปแบบ # 1 ( คำตอบของTom ):
public static final void setAppFont(ViewGroup mContainer, Typeface mFont, boolean reflect)
{
if (mContainer == null || mFont == null) return;
final int mCount = mContainer.getChildCount();
// Loop through all of the children.
for (int i = 0; i < mCount; ++i)
{
final View mChild = mContainer.getChildAt(i);
if (mChild instanceof TextView)
{
// Set the font if it is a TextView.
((TextView) mChild).setTypeface(mFont);
}
else if (mChild instanceof ViewGroup)
{
// Recursively attempt another ViewGroup.
setAppFont((ViewGroup) mChild, mFont);
}
else if (reflect)
{
try {
Method mSetTypeface = mChild.getClass().getMethod("setTypeface", Typeface.class);
mSetTypeface.invoke(mChild, mFont);
} catch (Exception e) { /* Do something... */ }
}
}
}
การใช้งาน:
final ViewGroup mContainer = (ViewGroup) findViewById(
android.R.id.content).getRootView();
HomeActivity.setAppFont(mContainer, Typeface.createFromAsset(getAssets(),
"fonts/MyFont.ttf"));
การเปลี่ยนแปลง # 2: https://coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere
ตัวเลือก # 4: ใช้ 3 พรรค Lib เรียกว่าการเขียนพู่กัน
โดยส่วนตัวฉันขอแนะนำตัวเลือก # 4 เนื่องจากมันช่วยประหยัดอาการปวดหัวได้มาก
"sans-serif"
ในnewMap.put(
และmonospace
ในstyles
! barana.ttf
ฉันต้องการใช้อักษรที่กำหนดเองที่มีชื่อว่า
ฉันต้องการปรับปรุงคำตอบของwestonสำหรับ API 21 Android 5.0
ภายใต้ API 21 สไตล์ข้อความส่วนใหญ่รวมถึงการตั้งค่า fontFamily เช่น:
<style name="TextAppearance.Material">
<item name="fontFamily">@string/font_family_body_1_material</item>
</style>
ซึ่งใช้แบบอักษรเริ่มต้นปกติของ Roboto:
<string name="font_family_body_1_material">sans-serif</string>
คำตอบเดิมไม่สามารถใช้แบบอักษร monospace ได้เนื่องจาก android: fontFamily มีความสำคัญมากกว่าสำหรับ Android: แอตทริบิวต์ typeface ( อ้างอิง ) ใช้ Theme.Holo. * เป็นวิธีแก้ปัญหาที่ถูกต้องเนื่องจากไม่มี android: การตั้งค่า fontFamily ภายใน
ตั้งแต่ Android 5.0 ใส่ตัวอักษรของระบบในตัวแปรแบบคงที่ Typeface.sSystemFontMap ( อ้างอิง ) เราสามารถใช้เทคนิคการสะท้อนเดียวกันเพื่อแทนที่:
protected static void replaceFont(String staticTypefaceFieldName,
final Typeface newTypeface) {
if (isVersionGreaterOrEqualToLollipop()) {
Map<String, Typeface> newMap = new HashMap<String, Typeface>();
newMap.put("sans-serif", newTypeface);
try {
final Field staticField = Typeface.class
.getDeclaredField("sSystemFontMap");
staticField.setAccessible(true);
staticField.set(null, newMap);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
try {
final Field staticField = Typeface.class
.getDeclaredField(staticTypefaceFieldName);
staticField.setAccessible(true);
staticField.set(null, newTypeface);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
Button
ชื่อเรื่องและแถบเครื่องมือของฉัน ฉันเอาชนะแบบอักษรเริ่มต้นใน MainApplication FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
ดังนี้ ฉันใช้ Nexus 5, v5.1.1
Build.VERSION.SDK_INT == 21
- นั่นเป็นเพียงการAPI 21
ทดสอบ I ที่ Nexus กับ API 22
มันง่ายมาก ... 1. ดาวน์โหลดและใส่ฟอนต์ที่กำหนดเองในสินทรัพย์ .. จากนั้นเขียนคลาสแยกต่างหากสำหรับการดูข้อความดังนี้: ที่นี่ฉันใช้ฟอนต์ฟอนต์
public class CusFntTextView extends TextView {
public CusFntTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public CusFntTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CusFntTextView(Context context) {
super(context);
init();
}
private void init() {
if (!isInEditMode()) {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "Futura.ttf");
setTypeface(tf);
}
}
}
และทำสิ่งต่อไปนี้ใน xml:
<com.packagename.CusFntTextView
android:id="@+id/tvtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hi Android"
android:textAppearance="?android:attr/textAppearanceLarge"
/>
ฉันขอแนะนำให้ขยาย TextView และส่วนควบคุมอื่น ๆ ด้วย แต่มันจะดีกว่าถ้าฉันพิจารณาตั้งค่าแบบอักษรในโครงสร้าง
public FontTextView(Context context) {
super(context);
init();
}
public FontTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FontTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
protected void init() {
setTypeface(Typeface.createFromAsset(getContext().getAssets(), AppConst.FONT));
}
ฉันต้องการที่จะปรับปรุงเวสตัน 's และโรเจอร์ Huang ' s คำตอบมานานกว่า 21 API Android อมยิ้มกับรูปแบบ ' Theme.AppCompat '
ด้านล่าง Android 4.4
<resources>
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:typeface">monospace</item>
</style>
</resources>
API (สูงกว่า) เกิน 5.0
<resources>
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:textAppearance">@style/CustomTextAppearance</item>
</style>
<style name="CustomTextAppearance">
<item name="android:typeface">monospace</item>
</style>
</resources>
และไฟล์ util FontsOverrideก็เหมือนกับคำตอบของweston ฉันได้ทดสอบในโทรศัพท์เหล่านี้:
Nexus 5 (Android 5.1 ระบบ Android หลัก)
ZTE V5 (android 5.1 CM12.1)
XIAOMI note (android 4.4 MIUI6)
HUAWEI C8850 (android 2.3.5 UNKNOWN)
วิธีการแก้ปัญหาที่ยอดเยี่ยมสามารถพบได้ที่นี่: https://coderwall.com/p/qxxmaa/android-use-a-custom-font-everywhere
เพียงขยายกิจกรรมจาก BaseActivity และเขียนวิธีการเหล่านั้น นอกจากนี้คุณควรจะดีกว่าแบบอักษรแคชตามที่อธิบายไว้ที่นี่: https://stackoverflow.com/a/16902532/2914140
หลังจากการวิจัยบางอย่างฉันเขียนโค้ดที่ใช้งานได้กับ Samsung Galaxy Tab A (Android 5.0) รหัสมือสองของเวสตันและโรเจอร์ Huang เช่นเดียวกับhttps://stackoverflow.com/a/33236102/2914140 ทดสอบด้วย Lenovo TAB 2 A10-70L ด้วยซึ่งไม่สามารถใช้งานได้ ฉันแทรกตัวอักษร 'Comic Sans' ที่นี่เพื่อดูความแตกต่าง
import android.content.Context;
import android.graphics.Typeface;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class FontsOverride {
private static final int BOLD = 1;
private static final int BOLD_ITALIC = 2;
private static final int ITALIC = 3;
private static final int LIGHT = 4;
private static final int CONDENSED = 5;
private static final int THIN = 6;
private static final int MEDIUM = 7;
private static final int REGULAR = 8;
private Context context;
public FontsOverride(Context context) {
this.context = context;
}
public void loadFonts() {
Map<String, Typeface> fontsMap = new HashMap<>();
fontsMap.put("sans-serif", getTypeface("comic.ttf", REGULAR));
fontsMap.put("sans-serif-bold", getTypeface("comic.ttf", BOLD));
fontsMap.put("sans-serif-italic", getTypeface("comic.ttf", ITALIC));
fontsMap.put("sans-serif-light", getTypeface("comic.ttf", LIGHT));
fontsMap.put("sans-serif-condensed", getTypeface("comic.ttf", CONDENSED));
fontsMap.put("sans-serif-thin", getTypeface("comic.ttf", THIN));
fontsMap.put("sans-serif-medium", getTypeface("comic.ttf", MEDIUM));
overrideFonts(fontsMap);
}
private void overrideFonts(Map<String, Typeface> typefaces) {
if (Build.VERSION.SDK_INT == 21) {
try {
final Field field = Typeface.class.getDeclaredField("sSystemFontMap");
field.setAccessible(true);
Map<String, Typeface> oldFonts = (Map<String, Typeface>) field.get(null);
if (oldFonts != null) {
oldFonts.putAll(typefaces);
} else {
oldFonts = typefaces;
}
field.set(null, oldFonts);
field.setAccessible(false);
} catch (Exception e) {
Log.e("TypefaceUtil", "Cannot set custom fonts");
}
} else {
try {
for (Map.Entry<String, Typeface> entry : typefaces.entrySet()) {
final Field staticField = Typeface.class.getDeclaredField(entry.getKey());
staticField.setAccessible(true);
staticField.set(null, entry.getValue());
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
private Typeface getTypeface(String fontFileName, int fontType) {
final Typeface tf = Typeface.createFromAsset(context.getAssets(), "fonts/" + fontFileName);
return Typeface.create(tf, fontType);
}
}
ในการเรียกใช้รหัสในแอปพลิเคชันทั้งหมดคุณควรเขียนในบางคลาสเช่น Application ดังต่อไปนี้
new FontsOverride(this).loadFonts();
สร้างโฟลเดอร์ 'แบบอักษร' ภายใน 'สินทรัพย์' และใส่แบบอักษรที่ต้องการที่นั่น การเรียนการสอนที่ง่ายอาจจะพบได้ที่นี่: https://stackoverflow.com/a/31697103/2914140
อุปกรณ์ Lenovo ยังได้รับค่าของแบบอักษรอย่างไม่ถูกต้อง ในครั้งส่วนใหญ่จะส่งกลับ Typeface.NORMAL บางครั้งก็เป็นโมฆะ แม้ว่า TextView จะเป็นตัวหนา (ในรูปแบบ xml-file) ดูที่นี่: TextView isBold ส่งคืน NORMALเสมอ วิธีนี้ข้อความบนหน้าจอจะเป็นแบบอักษรปกติไม่ใช่ตัวหนาหรือตัวเอียง ดังนั้นฉันคิดว่ามันเป็นข้อบกพร่องของผู้ผลิต
ทำงานกับ Xamarin และ Android:
ประเภท:
public class FontsOverride
{
public static void SetDefaultFont(Context context, string staticTypefaceFieldName, string fontAssetName)
{
Typeface regular = Typeface.CreateFromAsset(context.Assets, fontAssetName);
ReplaceFont(staticTypefaceFieldName, regular);
}
protected static void ReplaceFont(string staticTypefaceFieldName, Typeface newTypeface)
{
try
{
Field staticField = ((Java.Lang.Object)(newTypeface)).Class.GetDeclaredField(staticTypefaceFieldName);
staticField.Accessible = true;
staticField.Set(null, newTypeface);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
การใช้งานแอปพลิเคชัน:
namespace SomeAndroidApplication
{
[Application]
public class App : Application
{
public App()
{
}
public App(IntPtr handle, JniHandleOwnership transfer)
: base(handle, transfer)
{
}
public override void OnCreate()
{
base.OnCreate();
FontsOverride.SetDefaultFont(this, "MONOSPACE", "fonts/Roboto-Light.ttf");
}
}
}
สไตล์:
<style name="Theme.Storehouse" parent="Theme.Sherlock">
<item name="android:typeface">monospace</item>
</style>
ในฐานะที่เป็น Android O ตอนนี้เป็นไปได้ที่จะกำหนดโดยตรงจาก XML และข้อผิดพลาดของฉันตอนนี้ปิด!
TL; DR:
ก่อนอื่นคุณต้องเพิ่มแบบอักษรของคุณในโครงการ
ที่สองคุณเพิ่มตระกูลแบบอักษรเช่น:
<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
<font
android:fontStyle="normal"
android:fontWeight="400"
android:font="@font/lobster_regular" />
<font
android:fontStyle="italic"
android:fontWeight="400"
android:font="@font/lobster_italic" />
</font-family>
สุดท้ายคุณสามารถใช้แบบอักษรในเลย์เอาต์หรือสไตล์:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/lobster"/>
<style name="customfontstyle" parent="@android:style/TextAppearance.Small">
<item name="android:fontFamily">@font/lobster</item>
</style>
สนุก!
คุณสามารถตั้งค่าฟอนต์ที่กำหนดเองสำหรับทุกเลย์เอาท์ทีละคนด้วยการเรียกใช้ฟังก์ชั่นเพียงครั้งเดียวจากทุกเลย์เอาท์โดยผ่านรูทของ View.First สร้างแนวทาง Singelton สำหรับการเข้าถึงวัตถุฟอนต์เช่นนี้
public class Font {
private static Font font;
public Typeface ROBO_LIGHT;
private Font() {
}
public static Font getInstance(Context context) {
if (font == null) {
font = new Font();
font.init(context);
}
return font;
}
public void init(Context context) {
ROBO_LIGHT = Typeface.createFromAsset(context.getAssets(),
"Roboto-Light.ttf");
}
}
คุณสามารถกำหนดแบบอักษรที่แตกต่างกันในระดับบนตอนนี้กำหนดระดับตัวอักษรตัวช่วยเหลือที่จะใช้แบบอักษร:
public class FontHelper {
private static Font font;
public static void applyFont(View parentView, Context context) {
font = Font.getInstance(context);
apply((ViewGroup)parentView);
}
private static void apply(ViewGroup parentView) {
for (int i = 0; i < parentView.getChildCount(); i++) {
View view = parentView.getChildAt(i);
//You can add any view element here on which you want to apply font
if (view instanceof EditText) {
((EditText) view).setTypeface(font.ROBO_LIGHT);
}
if (view instanceof TextView) {
((TextView) view).setTypeface(font.ROBO_LIGHT);
}
else if (view instanceof ViewGroup
&& ((ViewGroup) view).getChildCount() > 0) {
apply((ViewGroup) view);
}
}
}
}
ในโค้ดด้านบนฉันใช้ฟอนต์กับ textView และ EditText เท่านั้นคุณสามารถใช้ฟอนต์กับอิลิเมนต์มุมมองอื่นเช่นเดียวกันคุณต้องส่งรหัสของกลุ่มมุมมองรูทของคุณไปยังวิธีฟอนต์ข้างต้น เช่นเลย์เอาต์ของคุณคือ:
<RelativeLayout 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"
android:orientation="vertical"
android:id="@+id/mainParent"
tools:context="${relativePackage}.${activityClass}" >
<RelativeLayout
android:id="@+id/mainContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/homeFooter"
android:layout_below="@+id/edit" >
<ImageView
android:id="@+id/PreviewImg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/abc_list_longpressed_holo"
android:visibility="gone" />
<RelativeLayout
android:id="@+id/visibilityLayer"
android:layout_width="match_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="@+id/UseCamera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:src="@drawable/camera" />
<TextView
android:id="@+id/tvOR"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/UseCamera"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="OR"
android:textSize="30dp" />
<TextView
android:id="@+id/tvAND"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="OR"
android:textSize="30dp" />
</RelativeLayout>
ในเค้าโครงด้านบนรหัสผู้ปกครองหลักคือ "ผู้ปกครองหลัก" ตอนนี้ให้ใช้แบบอักษร
public class MainActivity extends BaseFragmentActivity {
private EditText etName;
private EditText etPassword;
private TextView tvTitle;
public static boolean isHome = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Font font=Font.getInstance(getApplicationContext());
FontHelper.applyFont(findViewById(R.id.mainParent), getApplicationContext());
}
}
ไชโย :)
ฉันขอแนะนำให้ขยาย TextView และใช้ TextView แบบกำหนดเองของคุณภายในโครงร่าง XML ของคุณหรือทุกที่ที่คุณต้องการ TextView ใน TextView ที่กำหนดเองของคุณให้แทนที่setTypeface
@Override
public void setTypeface(Typeface tf, int style) {
//to handle bold, you could also handle italic or other styles here as well
if (style == 1){
tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans700.otf");
}else{
tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "MuseoSans500.otf");
}
super.setTypeface(tf, 0);
}
โซลูชันของทอมใช้งานได้ดี แต่ใช้ได้กับ TextView และ EditText เท่านั้น
หากคุณต้องการครอบคลุมมุมมองส่วนใหญ่ (RadioGroup, TextView, ช่องทำเครื่องหมาย ... ) ฉันได้สร้างวิธีการดังนี้:
protected void changeChildrenFont(ViewGroup v, Typeface font){
for(int i = 0; i < v.getChildCount(); i++){
// For the ViewGroup, we'll have to use recursivity
if(v.getChildAt(i) instanceof ViewGroup){
changeChildrenFont((ViewGroup) v.getChildAt(i), font);
}
else{
try {
Object[] nullArgs = null;
//Test wether setTypeface and getTypeface methods exists
Method methodTypeFace = v.getChildAt(i).getClass().getMethod("setTypeface", new Class[] {Typeface.class, Integer.TYPE});
//With getTypefaca we'll get back the style (Bold, Italic...) set in XML
Method methodGetTypeFace = v.getChildAt(i).getClass().getMethod("getTypeface", new Class[] {});
Typeface typeFace = ((Typeface)methodGetTypeFace.invoke(v.getChildAt(i), nullArgs));
//Invoke the method and apply the new font with the defined style to the view if the method exists (textview,...)
methodTypeFace.invoke(v.getChildAt(i), new Object[] {font, typeFace == null ? 0 : typeFace.getStyle()});
}
//Will catch the view with no such methods (listview...)
catch (Exception e) {
e.printStackTrace();
}
}
}
}
วิธีนี้จะกลับสไตล์ของชุดมุมมองใน XML (ตัวหนาตัวเอียง ... ) และนำไปใช้หากมีอยู่
สำหรับ ListView ฉันจะสร้างอะแดปเตอร์เสมอและฉันจะตั้งค่าแบบอักษรภายใน getView
ฉันเขียนคลาสที่กำหนดแบบอักษรให้กับมุมมองในลำดับชั้นมุมมองปัจจุบันและยึดตามคุณสมบัติแบบอักษรปัจจุบัน (ตัวหนาปกติคุณสามารถเพิ่มสไตล์อื่น ๆ ได้ถ้าคุณต้องการ):
public final class TypefaceAssigner {
public final Typeface DEFAULT;
public final Typeface DEFAULT_BOLD;
@Inject
public TypefaceAssigner(AssetManager assetManager) {
DEFAULT = Typeface.createFromAsset(assetManager, "TradeGothicLTCom.ttf");
DEFAULT_BOLD = Typeface.createFromAsset(assetManager, "TradeGothicLTCom-Bd2.ttf");
}
public void assignTypeface(View v) {
if (v instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) v).getChildCount(); i++) {
View view = ((ViewGroup) v).getChildAt(i);
if (view instanceof ViewGroup) {
setTypeface(view);
} else {
setTypeface(view);
}
}
} else {
setTypeface(v);
}
}
private void setTypeface(View view) {
if (view instanceof TextView) {
TextView textView = (TextView) view;
Typeface typeface = textView.getTypeface();
if (typeface != null && typeface.isBold()) {
textView.setTypeface(DEFAULT_BOLD);
} else {
textView.setTypeface(DEFAULT);
}
}
}
}
ตอนนี้ในแฟรกเมนต์ทั้งหมดใน onViewCreated หรือ onCreateView ในกิจกรรมทั้งหมดใน onCreate และในอะแด็ปเตอร์มุมมองทั้งหมดใน getView หรือ newView เพียงเรียกใช้:
typefaceAssigner.assignTypeface(view);
ใน api 26 ที่มี build.gradle 3.0.0 และสูงกว่าคุณสามารถสร้างไดเรกทอรีฟอนต์ใน res และใช้บรรทัดนี้ในสไตล์ของคุณ
<item name="android:fontFamily">@font/your_font</item>
สำหรับการเปลี่ยนแปลง build.gradle ใช้สิ่งนี้ในการพึ่งพา build.gradle ของคุณ
classpath 'com.android.tools.build:gradle:3.0.0'
item
เพียงอย่างเดียวไม่ได้ตั้งค่าแบบอักษรสำหรับทั้งแอป เบาะแสใด ๆ
ในที่สุด Google ก็ตระหนักถึงความรุนแรงของปัญหานี้ (การใช้แบบอักษรที่กำหนดเองกับองค์ประกอบ UI) และพวกเขาได้คิดค้นวิธีการแก้ปัญหาที่สะอาด
ก่อนอื่นคุณต้องอัปเดตเพื่อรองรับไลบรารี 26+ (คุณอาจต้องอัปเดต gradle ของคุณ {4.0+}, android studio) จากนั้นคุณสามารถสร้างโฟลเดอร์ทรัพยากรใหม่ที่เรียกว่าแบบอักษร ในโฟลเดอร์นี้คุณสามารถใส่ทรัพยากรแบบอักษร (.tff, ... ) จากนั้นคุณต้องแทนที่แอพเริ่มต้นและบังคับให้ฟอนต์ที่คุณกำหนดไว้เอง :)
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:fontFamily">@font/my_custom_font</item>
</style>
หมายเหตุ: ถ้าคุณต้องการสนับสนุนอุปกรณ์ที่มี API เก่ากว่า 16 คุณต้องใช้เนมสเปซแอพแทน android!
ฉันต้องการปรับปรุงคำตอบของ Weston สำหรับ API 21 Android 5.0
ฉันมีปัญหาเดียวกันกับ Samsung s5 ของฉันเมื่อใช้แบบอักษร DEFAULT (ด้วยแบบอักษรอื่น ๆ มันใช้งานได้ดี)
ฉันจัดการเพื่อให้มันทำงานได้โดยการตั้งค่าแบบอักษร ("sans" เป็นต้น) ในไฟล์ XML สำหรับแต่ละ Textview หรือปุ่ม
<TextView
android:layout_width="match_parent"
android:layout_height="39dp"
android:textColor="@color/abs__background_holo_light"
android:textSize="12sp"
android:gravity="bottom|center"
android:typeface="sans" />
และใน MyApplication Class:
public class MyApplication extends Application {
@Override
public void onCreate() {
TypefaceUtil.overrideFont(getApplicationContext(), "SANS_SERIF",
"fonts/my_font.ttf");
}
}
หวังว่ามันจะช่วย
นี้การแก้ปัญหาทำงานไม่ถูกต้องในบางสถานการณ์
ดังนั้นฉันจะขยาย:
FontsReplacer.java
public class MyApplication extends Application {
@Override
public void onCreate() {
FontsReplacer.replaceFonts(this);
super.onCreate();
}
}
https://gist.github.com/orwir/6df839e3527647adc2d56bfadfaad805
การประดิษฐ์ตัวอักษรใช้งานได้ดี แต่ไม่เหมาะสำหรับฉันเนื่องจากมันไม่รองรับน้ำหนักที่แตกต่าง (ตัวหนาตัวเอียง ฯลฯ ) สำหรับตระกูลฟอนต์
ดังนั้นฉันจึงลองใช้Fontainซึ่งช่วยให้คุณกำหนดมุมมองที่กำหนดเองและใช้ตระกูลแบบอักษรที่กำหนดเองได้
ในการใช้ Fontain คุณควรเพิ่มสิ่งต่อไปนี้ในโมดูลแอปของคุณ build.gradle:
compile 'com.scopely:fontain:1.0.0'
จากนั้นแทนที่จะใช้ TextView ปกติคุณควรใช้ FontTextView
ตัวอย่างของ FontTextView พร้อมเนื้อหาตัวพิมพ์ใหญ่และตัวหนา:
<com.scopely.fontain.views.FontTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/black"
android:textColor="@android:color/white"
android:textSize="11dp"
android:gravity="center"
android:id="@+id/tv1"
app:font_family="myCustomFont"
app:caps_mode="characters"
app:font_weight="BOLD"/>
package com.theeasylearn.demo.designdemo;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
public class MyButton extends TextView {
public MyButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyButton(Context context) {
super(context);
init();
}
private void init() {
Typeface tf =
Typeface.createFromAsset(
getContext().getAssets(), "angelina.TTF");
setTypeface(tf);
}
}
TextView
s
สำหรับการเปลี่ยนตระกูลฟอนต์เริ่มต้นของ TextViews ให้แทนที่ textViewStyle ในธีมแอพของคุณ
สำหรับการใช้แบบอักษรที่กำหนดเองใน fontFamily ให้ใช้ทรัพยากรแบบอักษรที่อยู่ในห้องสมุดสนับสนุน
ฟีเจอร์นี้ถูกเพิ่มเข้ามาใน Android 26 แต่กลับไปเป็นเวอร์ชั่นเก่าผ่านทาง supportlib
https://developer.android.com/guide/topics/resources/font-resource.html https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html # ใช้สนับสนุน-lib
ตั้งแต่เปิดตัว Android Oreo และห้องสมุดสนับสนุน (26.0.0) คุณสามารถทำได้อย่างง่ายดาย อ้างถึงคำตอบนี้ในคำถามอื่น
โดยทั่วไปสไตล์สุดท้ายของคุณจะมีลักษณะเช่นนี้:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="fontFamily">@font/your_font</item> <!-- target android sdk versions < 26 and > 14 -->
</style>
ฉันพบว่าการผสมผสานของห้องสมุด 3 ตัวอักษรและโพสต์ของ coderwallเป็นผลลัพธ์ที่ดีที่สุดของฉัน
ใช่เป็นไปได้ที่จะตั้งค่าแบบอักษรเป็นแอปพลิเคชันทั้งหมด
วิธีที่ง่ายที่สุดในการทำเช่นนี้คือจัดแพคเกจตัวอักษรที่ต้องการด้วยแอปพลิเคชันของคุณ
ในการทำสิ่งนี้เพียงแค่สร้างสินทรัพย์ / โฟลเดอร์ในรูทโปรเจ็กต์และวางฟอนต์ของคุณ (ใน TrueType หรือ TTF แบบฟอร์ม) ในเนื้อหา
ตัวอย่างเช่นคุณอาจสร้างสินทรัพย์ / แบบอักษร / และวางไฟล์ TTF ของคุณลงในนั้น
public class FontSampler extends Activity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
TextView tv=(TextView)findViewById(R.id.custom);
Typeface face=Typeface.createFromAsset(getAssets(), "fonts/HandmadeTypewriter.ttf");
tv.setTypeface(face);
}
}