Android में एक कस्टम टाइपफेस का उपयोग करना


111

मैं अपने एंड्रॉइड एप्लिकेशन के लिए एक कस्टम फ़ॉन्ट का उपयोग करना चाहता हूं जो मैं बना रहा हूं।
मैं व्यक्तिगत रूप से कोड से प्रत्येक वस्तु के टाइपफेस को बदल सकता हूं, लेकिन मेरे पास उनमें से सैकड़ों हैं।

इसलिए,

  • क्या एक्सएमएल से ऐसा करने का कोई तरीका है? [एक कस्टम टाइपफेस सेट करना]
  • क्या कोड से एक स्थान पर ऐसा करने का कोई तरीका है, यह कहने के लिए कि संपूर्ण अनुप्रयोग और सभी घटकों को डिफ़ॉल्ट एक के बजाय कस्टम टाइपफेस का उपयोग करना चाहिए?

stackoverflow.com/questions/5541058/… इस पोस्ट को देखो मैंने इस मुद्दे के बारे में पूरा कोड यहाँ पोस्ट किया
मनीष सिंगला

आप एम्बेडेड फोंट के संदर्भ रखने के लिए अपनी मुख्य गतिविधि पर स्थिर चर का उपयोग कर सकते हैं। यह फोंट का एक लगातार सेट होगा जो जीसी द्वारा नहीं उठाया जाएगा।
जैक्सनक्राट

फैक्टरी विधि। या एक विधि जो आपका दृष्टिकोण लेती है और सभी फ़ॉन्ट और टाइपफेस सेटिंग्स सेट करती है।
mtmurdock

नई समर्थन लाइब्रेरी 26 अब आपको XML में फोंट का उपयोग करने की अनुमति देती है। यहां बताया गया है कि XML में
फॉन्ट्स

जवाबों:


80

क्या एक्सएमएल से ऐसा करने का कोई तरीका है?

कोई खेद नहीं। आप केवल XML के माध्यम से अंतर्निहित टाइपफेस निर्दिष्ट कर सकते हैं।

क्या कोड से एक स्थान पर ऐसा करने का कोई तरीका है, यह कहने के लिए कि संपूर्ण अनुप्रयोग और सभी घटकों को डिफ़ॉल्ट एक के बजाय कस्टम टाइपफेस का उपयोग करना चाहिए?

ऐसा नहीं कि मुझे पता नहीं।

आजकल इन के लिए कई विकल्प हैं:

  • यदि आप उपयोग कर रहे हैं, तो एंड्रॉइड एसडीके में फ़ॉन्ट संसाधन और बैकपॉट appcompat

  • उपयोग न करने वालों के लिए तृतीय-पक्ष पुस्तकालयappcompat , हालांकि सभी लेआउट संसाधनों में फ़ॉन्ट को परिभाषित करने का समर्थन नहीं करेंगे


4
@ कोडवेल्ली: कई मायनों में, बेहतर जवाब कस्टम फोंट के साथ उपद्रव नहीं करना है। वे बड़े होते हैं, आपके डाउनलोड को बड़ा बनाते हैं और उन लोगों की संख्या को कम करते हैं जो आपके ऐप का उपयोग और डाउनलोड करते रहेंगे।
कॉमन्सवेअर

22
@CommonsWare: मैं जरूरी सहमत नहीं हूँ। टाइपफेस यूआई स्टाइलिंग का एक अभिन्न अंग है जैसे आप पृष्ठभूमि छवियों आदि के साथ करते हैं और आकार हमेशा बड़ा नहीं होता है। उदाहरण के लिए, मेरे मामले में फ़ॉन्ट सिर्फ 19.6KB है :)
कोडवल्ले

2
@Amit: इस मुद्दे पर कोई बदलाव नहीं हुआ है। जावा में अपने यूआई के लिए एक टाइपफेस लागू करने में मदद करने के लिए कोड स्निपेट बहुत सारे हैं, लेकिन एक्सएमएल से ऐसा करने का कोई तरीका नहीं है।
कॉमन्सवेयर

1
@Amit: "लेकिन इसका मतलब है कि मुझे कस्टम फोंट के लिए अपनी .ttf या .otf फाइलें बनानी होंगी?" -- उम नहीं। आप मौजूदा टीटीएफ / ओटीएफ फोंट का उपयोग कर सकते हैं, हालांकि वे सभी काम नहीं कर सकते हैं। इस सवाल पर मुद्दा यह है कि उन फोंट को पूरे ऐप पर कैसे लागू किया जाए, जो अभी भी संभव नहीं है, और यही मैं अपनी टिप्पणी में उल्लेख कर रहा था।
कॉमन्सवेयर

1
यह स्वीकृत उत्तर अप्रचलित है, और इसे अद्यतन करने या इसे हटाने के लिए बहुत अच्छा होगा।
स्काई केल्सी

109

हाँ यह संभव है।

आपको एक कस्टम दृश्य बनाना होगा जो पाठ दृश्य का विस्तार करता है।

में attrs.xmlमें valuesफ़ोल्डर:

<resources>
    <declare-styleable name="MyTextView">
        <attr name="first_name" format="string"/>
        <attr name="last_name" format="string"/>
        <attr name="ttf_name" format="string"/>
    </declare-styleable>
</resources>

में main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:lht="http://schemas.android.com/apk/res/com.lht"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView  android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:text="Hello"/>
    <com.lht.ui.MyTextView  
        android:id="@+id/MyTextView"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:text="Hello friends"
        lht:ttf_name="ITCBLKAD.TTF"
        />   
</LinearLayout>

में MyTextView.java:

package com.lht.ui;

import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;

public class MyTextView extends TextView {

    Context context;
    String ttfName;

    String TAG = getClass().getName();

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;

        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            Log.i(TAG, attrs.getAttributeName(i));
            /*
             * Read value of custom attributes
             */

            this.ttfName = attrs.getAttributeValue(
                    "http://schemas.android.com/apk/res/com.lht", "ttf_name");
            Log.i(TAG, "firstText " + firstText);
            // Log.i(TAG, "lastText "+ lastText);

            init();
        }

    }

    private void init() {
        Typeface font = Typeface.createFromAsset(context.getAssets(), ttfName);
        setTypeface(font);
    }

    @Override
    public void setTypeface(Typeface tf) {

        // TODO Auto-generated method stub
        super.setTypeface(tf);
    }

}

4
यह काम करेगा, लेकिन केवल के लिए TextView। इसमें प्रत्येक विजेट वर्ग के लिए कस्टम उपवर्गों की आवश्यकता होगी जो कि TextViewउसी क्षमता से वांछित है जहां से विरासत में मिला है।
कॉमन्सवेयर

हाय मनीष, समाधान के लिए धन्यवाद। हालांकि Im को इसका उपयोग करने में समस्या का सामना करना पड़ रहा है। मुझे पैकेज कॉम में विशेषता ttf_name के लिए 'नो रिसोर्स आइडेंटिफायर' मिल रहा है।
क्षितिज अग्रवाल

17
यह काम करेगा, लेकिन पूर्व-आईसीएस यह आपके द्वारा देखे जाने वाले प्रत्येक दृश्य के लिए फोंट के लिए मेमोरी आवंटित करेगा: code.google.com/p/android/issues/detail?id=9904 इसे ठीक करने का एक तरीका विश्व स्तर पर सुलभ बनाना है सभी
त्वरित

हमें लूप की आवश्यकता क्यों है ?, क्या यह एक कॉल से काम नहीं करना चाहिए?
गुइलेर्मो टोबार

1
@AlaksiejN। मामले में आपको अलग-अलग TextViews के लिए अलग टाइपफेस सेट करने की आवश्यकता है ...
निक

49

मैंने इसे अधिक "ब्रूट फोर्स" तरीके से किया, जिसमें लेआउट xml या गतिविधियों में बदलाव की आवश्यकता नहीं है।

4.4 के माध्यम से Android संस्करण 2.1 पर परीक्षण किया गया। अपने एप्लिकेशन वर्ग में, ऐप स्टार्टअप पर इसे चलाएं:

private void setDefaultFont() {

    try {
        final Typeface bold = Typeface.createFromAsset(getAssets(), DEFAULT_BOLD_FONT_FILENAME);
        final Typeface italic = Typeface.createFromAsset(getAssets(), DEFAULT_ITALIC_FONT_FILENAME);
        final Typeface boldItalic = Typeface.createFromAsset(getAssets(), DEFAULT_BOLD_ITALIC_FONT_FILENAME);
        final Typeface regular = Typeface.createFromAsset(getAssets(),DEFAULT_NORMAL_FONT_FILENAME);

        Field DEFAULT = Typeface.class.getDeclaredField("DEFAULT");
        DEFAULT.setAccessible(true);
        DEFAULT.set(null, regular);

        Field DEFAULT_BOLD = Typeface.class.getDeclaredField("DEFAULT_BOLD");
        DEFAULT_BOLD.setAccessible(true);
        DEFAULT_BOLD.set(null, bold);

        Field sDefaults = Typeface.class.getDeclaredField("sDefaults");
        sDefaults.setAccessible(true);
        sDefaults.set(null, new Typeface[]{
                regular, bold, italic, boldItalic
        });

    } catch (NoSuchFieldException e) {
        logFontError(e);
    } catch (IllegalAccessException e) {
        logFontError(e);
    } catch (Throwable e) {
        //cannot crash app if there is a failure with overriding the default font!
        logFontError(e);
    }
}

अधिक पूर्ण उदाहरण के लिए, http://github.com/perchrh/FontOverrideExample देखें


यह मेरे लिए सबसे अच्छा समाधान है।
इगोर के

2
डिफ़ॉल्ट मेरे लिए काम नहीं करता है। अगर मैं मोनोस्पेस का उपयोग करता हूं और फिर code<style name = "AppTheme" parent = "AppBaseTheme"> <आइटम का नाम = "android: typeface"> monospace </ item> </ style> सेट codeकरता है, तो यह बोल्ड नहीं बल्कि काम करता है। मैंने इस कोड को एक वर्ग में जोड़ा है जो अनुप्रयोग का विस्तार करता है। क्या यह सही जगह है? @ पी-चान
क्रिस्टोफर रिवर

2
@ChristopherRivera हां, इसे अपने ऐप के एप्लिकेशन वर्ग में जोड़ें, सुनिश्चित करें कि यह ऑनक्रिएट पर चलता है। Grepcode.com/file/repository.grepcode.com/java/ext/… पर एक नज़र डालने के बाद, मैं आपको मानस के अतिरिक्त क्षेत्र के साथ-साथ मेरे नमूना कोड में एक को ओवरराइड करने का सुझाव दूंगा!
प्रति ईसाई हेन्डेन

2
ठीक है, मैं SERIF के क्षेत्र में बदल गया और इसने काम किया :)
अब्दुल्ला उमेर

3
यह उत्तर इस उत्तर को संदर्भित करता है, और एक क्लीनर दृष्टिकोण imho प्रदान करता है।
adamdport

36

हालाँकि मैं मनीष के उत्तर को सबसे तेज़ और सबसे लक्षित विधि के रूप में प्रस्तुत कर रहा हूँ, लेकिन मैंने भोले-भाले समाधान भी देखे हैं, जो केवल एक दृश्य पदानुक्रम के माध्यम से पुनरावृत्ति करते हैं और बदले में सभी तत्वों के टाइपफेस को अपडेट करते हैं। कुछ इस तरह:

public static void applyFonts(final View v, Typeface fontToSet)
{
    try {
        if (v instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) v;
            for (int i = 0; i < vg.getChildCount(); i++) {
                View child = vg.getChildAt(i);
                applyFonts(child, fontToSet);
            }
        } else if (v instanceof TextView) {
            ((TextView)v).setTypeface(fontToSet);
        }
    } catch (Exception e) {
        e.printStackTrace();
        // ignore
    }
}

लेआउट को फुलाकर और अपनी गतिविधि के onContentChanged()तरीकों से आपको इस फ़ंक्शन को अपने विचारों पर कॉल करने की आवश्यकता होगी ।


बहुत ज्यादा। उस समय, यह प्रोजेक्ट टाइमफ्रेम के भीतर करने का एकमात्र तरीका था। यदि आवश्यक हो तो एक आसान शॉर्टकट: (:
pospi

23

मैं इसे केंद्रीकृत तरीके से करने में सक्षम था, यहाँ परिणाम है:

यहां छवि विवरण दर्ज करें

मेरे पास निम्नलिखित हैं Activityऔर अगर मुझे कस्टम फोंट की आवश्यकता है तो मैं इसका विस्तार करता हूं:

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.LayoutInflater.Factory;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class CustomFontActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    getLayoutInflater().setFactory(new Factory() {

        @Override
        public View onCreateView(String name, Context context,
                AttributeSet attrs) {
            View v = tryInflate(name, context, attrs);
            if (v instanceof TextView) {
                setTypeFace((TextView) v);
            }
            return v;
        }
    });
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

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

private void setTypeFace(TextView tv) {
    tv.setTypeface(FontUtils.getFonts(this, "MTCORSVA.TTF"));
}
}

लेकिन अगर मैं सपोर्ट पैकेज से किसी गतिविधि का उपयोग कर FragmentActivityरहा हूं, तो मैं इसका उपयोग करता हूं Activity:

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

public class CustomFontFragmentActivity extends FragmentActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

// we can't setLayout Factory as its already set by FragmentActivity so we
// use this approach
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
    View v = super.onCreateView(name, context, attrs);
    if (v == null) {
        v = tryInflate(name, context, attrs);
        if (v instanceof TextView) {
            setTypeFace((TextView) v);
        }
    }
    return v;
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public View onCreateView(View parent, String name, Context context,
        AttributeSet attrs) {
    View v = super.onCreateView(parent, name, context, attrs);
    if (v == null) {
        v = tryInflate(name, context, attrs);
        if (v instanceof TextView) {
            setTypeFace((TextView) v);
        }
    }
    return v;
}

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

private void setTypeFace(TextView tv) {
    tv.setTypeface(FontUtils.getFonts(this, "MTCORSVA.TTF"));
}
}

मैंने Fragmentअभी तक इस कोड का परीक्षण नहीं किया है, लेकिन उम्मीद है कि यह काम करेगा।

मेरा FontUtilsसरल है जो यहाँ वर्णित पूर्व ICS समस्या को हल करता है https://code.google.com/p/android/issues/detail?id=9904 :

import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.graphics.Typeface;

public class FontUtils {

private static Map<String, Typeface> TYPEFACE = new HashMap<String, Typeface>();

public static Typeface getFonts(Context context, String name) { 
    Typeface typeface = TYPEFACE.get(name);
    if (typeface == null) {
        typeface = Typeface.createFromAsset(context.getAssets(), "fonts/"
                + name);
        TYPEFACE.put(name, typeface);
    }
    return typeface;
}
}

2
इसे और वोट मिलना चाहिए। यह काम करता है और इसमें प्रदर्शन के लिए एक स्क्रीनशॉट है
ericn

10

अरे मुझे अलग-अलग विधवाओं के लिए अपने ऐप में 2 अलग-अलग फोंट चाहिए! मैं इस तरह से उपयोग करता हूं:

मेरे आवेदन वर्ग में मैं एक स्थिर विधि बनाता हूँ:

public static Typeface getTypeface(Context context, String typeface) {
    if (mFont == null) {
        mFont = Typeface.createFromAsset(context.getAssets(), typeface);
    }
    return mFont;
}

स्ट्रिंग टाइपफेस परिसंपत्ति फ़ोल्डर में xyz.ttf का प्रतिनिधित्व करता है। (मैंने एक कॉन्स्टेंट क्लास बनाया) अब आप इसे अपने ऐप में हर जगह इस्तेमाल कर सकते हैं:

mTextView = (TextView) findViewById(R.id.text_view);
mTextView.setTypeface(MyApplication.getTypeface(this, Constants.TYPEFACE_XY));

एकमात्र समस्या यह है कि, आपको हर उस विजेट की आवश्यकता है जहाँ आप फ़ॉन्ट का उपयोग करना चाहते हैं! लेकिन मुझे लगता है कि यह सबसे अच्छा तरीका है।


4

पोस्पी के सुझाव का उपयोग करना और रिचर्ड जैसी 'टैग' संपत्ति के साथ काम करना , मैंने एक कस्टम वर्ग बनाया जो मेरे कस्टम फोंट को लोड करता है और उनके टैग के अनुसार विचारों पर लागू होता है।

इसलिए मूल रूप से, टाइपफ़ेस को विशेषता एंड्रॉइड में सेट करने के बजाय: fontFamily आप एंड्रॉइड का उपयोग कर रहे हैं: एट्रीट्यूब को टैग करें और इसे परिभाषित एनाम में से एक पर सेट करें।

public class Fonts {
    private AssetManager mngr;

    public Fonts(Context context) {
        mngr = context.getAssets();
    }
    private enum AssetTypefaces {
        RobotoLight,
        RobotoThin,
        RobotoCondensedBold,
        RobotoCondensedLight,
        RobotoCondensedRegular
    }

    private Typeface getTypeface(AssetTypefaces font) {
        Typeface tf = null;
        switch (font) {
            case RobotoLight:
                tf = Typeface.createFromAsset(mngr,"fonts/Roboto-Light.ttf");
                break;
            case RobotoThin:
                tf = Typeface.createFromAsset(mngr,"fonts/Roboto-Thin.ttf");
                break;
            case RobotoCondensedBold:
                tf = Typeface.createFromAsset(mngr,"fonts/RobotoCondensed-Bold.ttf");
                break;
            case RobotoCondensedLight:
                tf = Typeface.createFromAsset(mngr,"fonts/RobotoCondensed-Light.ttf");
                break;
            case RobotoCondensedRegular:
                tf = Typeface.createFromAsset(mngr,"fonts/RobotoCondensed-Regular.ttf");
                break;
            default:
                tf = Typeface.DEFAULT;
                break;
        }
        return tf;
    }
    public void setupLayoutTypefaces(View v) {
        try {
            if (v instanceof ViewGroup) {
                ViewGroup vg = (ViewGroup) v;
                for (int i = 0; i < vg.getChildCount(); i++) {
                    View child = vg.getChildAt(i);
                    setupLayoutTypefaces(child);
                }
            } else if (v instanceof TextView) {
                if (v.getTag().toString().equals(AssetTypefaces.RobotoLight.toString())){
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoLight));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoCondensedRegular.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoCondensedRegular));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoCondensedBold.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoCondensedBold));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoCondensedLight.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoCondensedLight));
                }else if (v.getTag().toString().equals(AssetTypefaces.RobotoThin.toString())) {
                    ((TextView)v).setTypeface(getTypeface(AssetTypefaces.RobotoThin));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            // ignore
        }
    }
}

आपकी गतिविधि या फ्रैगमेंट में आप बस कॉल करते हैं

Fonts fonts = new Fonts(getActivity());
fonts.setupLayoutTypefaces(mainLayout);

4

मुझे लिसा रे के ब्लॉग पर एक अच्छा समाधान मिला । नए डेटा बाइंडिंग के साथ आपकी XML फ़ाइलों में फ़ॉन्ट सेट करना संभव है।

@BindingAdapter({"bind:font"})
public static void setFont(TextView textView, String fontName){
    textView.setTypeface(Typeface.createFromAsset(textView.getContext().getAssets(), "fonts/" + fontName));
}

XML में:

<TextView
app:font="@{`Source-Sans-Pro-Regular.ttf`}"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

क्या आप डेटा बाइंडिंग का उपयोग करके एक उदाहरण सुझा सकते हैं? यह बहुत सराहना की जाएगी।
श्रीकृष्ण

3

मुझे लगता है कि इसे करने का एक आसान तरीका हो सकता है। निम्न वर्ग आपके एप्लिकेशन के सभी घटकों (प्रति वर्ग सेटिंग के साथ) के लिए एक कस्टम प्रकार का चेहरा सेट करेगा।

/**
 * Base Activity of our app hierarchy.
 * @author SNI
 */
public class BaseActivity extends Activity {

    private static final String FONT_LOG_CAT_TAG = "FONT";
    private static final boolean ENABLE_FONT_LOGGING = false;

    private Typeface helloTypeface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        helloTypeface = Typeface.createFromAsset(getAssets(), "fonts/<your type face in assets/fonts folder>.ttf");
    }

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        View view = super.onCreateView(name, context, attrs);
        return setCustomTypeFaceIfNeeded(name, attrs, view);
    }

    @Override
    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
        View view = super.onCreateView(parent, name, context, attrs);
        return setCustomTypeFaceIfNeeded(name, attrs, view);
    }

    protected View setCustomTypeFaceIfNeeded(String name, AttributeSet attrs, View view) {
        View result = null;
        if ("TextView".equals(name)) {
            result = new TextView(this, attrs);
            ((TextView) result).setTypeface(helloTypeface);
        }

        if ("EditText".equals(name)) {
            result = new EditText(this, attrs);
            ((EditText) result).setTypeface(helloTypeface);
        }

        if ("Button".equals(name)) {
            result = new Button(this, attrs);
            ((Button) result).setTypeface(helloTypeface);
        }

        if (result == null) {
            return view;
        } else {
            if (ENABLE_FONT_LOGGING) {
                Log.v(FONT_LOG_CAT_TAG, "A type face was set on " + result.getId());
            }
            return result;
        }
    }

}

2

LayoutInflater का डिफ़ॉल्ट कार्यान्वयन xml से फ़ॉन्ट टाइपफेस निर्दिष्ट करने का समर्थन नहीं करता है। हालाँकि मैंने इसे Xml में किया है लेआउट लेआउट के लिए एक कस्टम कारखाना प्रदान करके जो xml टैग से ऐसी विशेषताओं को पार्स करेगा।

मूल संरचना इस तरह होगी।

public class TypefaceInflaterFactory implements LayoutInflater.Factory {

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        // CUSTOM CODE TO CREATE VIEW WITH TYPEFACE HERE
        // RETURNING NULL HERE WILL TELL THE INFLATER TO USE THE
        // DEFAULT MECHANISMS FOR INFLATING THE VIEW FROM THE XML
    }

}

public class BaseActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater.from(this).setFactory(new TypefaceInflaterFactory());
    }
}

यह लेख इन तंत्रों की गहराई से व्याख्या करता है और लेखक इस तरह से टाइपफेस के लिए xml लेआउट समर्थन प्रदान करने का प्रयास करता है। लेखक के कार्यान्वयन के लिए कोड यहां पाया जा सकता है


1

एक रेगुलर प्रोग्रेसडायलॉग / AlertDialog में एक कस्टम फॉन्ट सेट करना:

font=Typeface.createFromAsset(getAssets(),"DroidSans.ttf");

ProgressDialog dialog = ProgressDialog.show(this, "titleText", "messageText", true);
((TextView)dialog.findViewById(Resources.getSystem().getIdentifier("message", "id", "android"))).setTypeface(font);
((TextView)dialog.findViewById(Resources.getSystem().getIdentifier("alertTitle", "id", "android"))).setTypeface(font);

1

हां यह डिफ़ॉल्ट टाइपफेस को ओवरराइड करके संभव है। मैंने इस समाधान का पालन ​​किया और इसने सभी TextViews और ActionBar टेक्स्ट के लिए एक बदलाव के साथ एक आकर्षण की तरह काम किया।

public class MyApp extends Application {

  @Override
  public void onCreate() {
    TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/Roboto-Regular.ttf"); // font from assets: "assets/fonts/Roboto-Regular.ttf
  }
}

styles.xml

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/pantone</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:windowTranslucentStatus" tools:targetApi="kitkat">true</item>
    <item name="android:windowDisablePreview">true</item>
    <item name="android:typeface">serif</item>
</style>

उपर्युक्त लिंक में बताए गए थीम.xml के बजाय, मैंने अपनी शैली में ओवरराइड करने के लिए डिफ़ॉल्ट फ़ॉन्ट का उल्लेख किया है। मेरे डिफ़ॉल्ट एप्लिकेशन टैग में एमएलएम। डिफ़ॉल्ट टाइपफ़ोर्स जिन्हें ओवरराइट किया जा सकता है वे सेरिफ़, सैंस, मोनोस्पेस और सामान्य हैं।

TypefaceUtil.java

public class TypefaceUtil {

    /**
     * Using reflection to override default typeface
     * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN
     * @param context to work with assets
     * @param defaultFontNameToOverride for example "monospace"
     * @param customFontFileNameInAssets file name of the font from assets
     */
    public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
        try {
            final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);

            final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
            defaultFontTypefaceField.setAccessible(true);
            defaultFontTypefaceField.set(null, customFontTypeface);
        } catch (Exception e) {
            Log.e("Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
        }
    }
}

प्रारंभ में, मुझे नहीं पता था कि टाइप किए जाने वाले टाइपफ़ोर्स को निर्धारित किया गया है और परिभाषित मूल्यों का सेट है, लेकिन अंततः इससे मुझे यह समझने में मदद मिली कि एंड्रॉइड फॉन्ट और टाइपफेस और उनके डिफ़ॉल्ट मानों के साथ कैसे व्यवहार करता है, जो कि एक अलग बिंदु है।


0

मुझे नहीं पता कि यह पूरे ऐप को बदलता है, लेकिन मैंने कुछ घटकों को बदलने में कामयाबी हासिल की है जो अन्यथा ऐसा करने से नहीं बदले जा सकते हैं:

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/Lucida Sans Unicode.ttf");
Typeface.class.getField("DEFAULT").setAccessible(true);
Typeface.class.getField("DEFAULT_BOLD").setAccessible(true);
Typeface.class.getField("DEFAULT").set(null, tf);
Typeface.class.getField("DEFAULT_BOLD").set(null, tf);

2
दुर्भाग्य से यह किसी भी अधिक काम नहीं करता है: java.lang.IllegalAccessException: फ़ील्ड को java.lang.reflect.Field.setField (मूल विधि) पर java.lang.reflect.ield.set (फ़ील्ड.java: 'अंतिम' के रूप में चिह्नित किया गया है। 556)
BoD

0

मुझे पोस्पी का सुझाव पसंद है। किसी भी अतिरिक्त स्टाइल को निर्दिष्ट करने के लिए किसी भी दृश्य की 'टैग' संपत्ति का उपयोग न करें, जिसे आप XML में नहीं कर सकते हैं। मुझे JSON पसंद है इसलिए मैं एक कुंजी / मान सेट निर्दिष्ट करने के लिए JSON स्ट्रिंग का उपयोग करूँगा। यह वर्ग काम करता है - बस Style.setContentView(this, [resource id])अपनी गतिविधि में फोन करें ।

public class Style {

  /**
   * Style a single view.
   */
  public static void apply(View v) {
    if (v.getTag() != null) {
      try {
        JSONObject json = new JSONObject((String)v.getTag());
        if (json.has("typeface") && v instanceof TextView) {
          ((TextView)v).setTypeface(Typeface.createFromAsset(v.getContext().getAssets(),
                                                             json.getString("typeface")));
        }
      }
      catch (JSONException e) {
        // Some views have a tag without it being explicitly set!
      }
    }
  }

  /**
   * Style the passed view hierarchy.
   */
  public static View applyTree(View v) {
    apply(v);
    if (v instanceof ViewGroup) {
      ViewGroup g = (ViewGroup)v;
      for (int i = 0; i < g.getChildCount(); i++) {
        applyTree(g.getChildAt(i));
      }
    }
    return v;
  }

  /**
   * Inflate, style, and set the content view for the passed activity.
   */
  public static void setContentView(Activity activity, int resource) {
    activity.setContentView(applyTree(activity.getLayoutInflater().inflate(resource, null)));
  }
}

जाहिर है कि आप JSON का उपयोग करने के लिए केवल टाइपफेस से अधिक संभालना चाहते हैं।

'टैग' संपत्ति का एक लाभ यह है कि आप इसे एक आधार शैली पर सेट कर सकते हैं, जिसे आप एक थीम के रूप में उपयोग करते हैं और इस प्रकार यह आपके सभी विचारों पर स्वचालित रूप से लागू होता है। EDIT: Android 4.0.3 पर मुद्रास्फीति के दौरान एक दुर्घटना में यह परिणाम है। आप अभी भी एक शैली का उपयोग कर सकते हैं और इसे व्यक्तिगत रूप से पाठ विचारों पर लागू कर सकते हैं।

Google अनुवाद के अनुसार, एक चीज़ जो आप कोड में देखेंगे - कुछ विचारों में स्पष्ट रूप से सेट किए बिना एक टैग होता है - विचित्र रूप से यह स्ट्रिंग है κο'οΑπ ’- जो ग्रीक में 'कट’ है! क्या बकवास है...?


0

@ majinboo का उत्तर प्रदर्शन और स्मृति प्रबंधन के लिए संशोधित किया गया है। किसी भी एक से अधिक फ़ॉन्ट की जरूरत से संबंधित गतिविधि इस फॉन्ट क्लास का उपयोग कंस्ट्रक्टर को एक पैरामीटर के रूप में करके कर सकते हैं।

@Override
public void onCreate(Bundle savedInstanceState)
{
    Font font = new Font(this);
}

संशोधित फ़ॉन्ट्स वर्ग इस प्रकार है:

public class Fonts
{
    private HashMap<AssetTypefaces, Typeface> hashMapFonts;

    private enum AssetTypefaces
    {
        RobotoLight,
        RobotoThin,
        RobotoCondensedBold,
        RobotoCondensedLight,
        RobotoCondensedRegular
    }

    public Fonts(Context context)
    {
        AssetManager mngr = context.getAssets();

        hashMapFonts = new HashMap<AssetTypefaces, Typeface>();
        hashMapFonts.put(AssetTypefaces.RobotoLight, Typeface.createFromAsset(mngr, "fonts/Roboto-Light.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoThin, Typeface.createFromAsset(mngr, "fonts/Roboto-Thin.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoCondensedBold, Typeface.createFromAsset(mngr, "fonts/RobotoCondensed-Bold.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoCondensedLight, Typeface.createFromAsset(mngr, "fonts/RobotoCondensed-Light.ttf"));
        hashMapFonts.put(AssetTypefaces.RobotoCondensedRegular, Typeface.createFromAsset(mngr, "fonts/RobotoCondensed-Regular.ttf"));
    }

    private Typeface getTypeface(String fontName)
    {
        try
        {
            AssetTypefaces typeface = AssetTypefaces.valueOf(fontName);
            return hashMapFonts.get(typeface);
        }
        catch (IllegalArgumentException e)
        {
            // e.printStackTrace();
            return Typeface.DEFAULT;
        }
    }

    public void setupLayoutTypefaces(View v)
    {
        try
        {
            if (v instanceof ViewGroup)
            {
                ViewGroup vg = (ViewGroup) v;
                for (int i = 0; i < vg.getChildCount(); i++)
                {
                    View child = vg.getChildAt(i);
                    setupLayoutTypefaces(child);
                }
            }
            else if (v instanceof TextView)
            {
                ((TextView) v).setTypeface(getTypeface(v.getTag().toString()));
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            // ignore
        }
    }
}

0

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>

0

ऐसा लगता है कि एंड्रॉइड O के साथ कस्टम फोंट का उपयोग करना आसान बना दिया गया है, आप इसे प्राप्त करने के लिए मूल रूप से xml का उपयोग कर सकते हैं। मैंने संदर्भ के लिए एंड्रॉइड आधिकारिक दस्तावेज के लिए एक लिंक संलग्न किया है, और उम्मीद है कि इससे उन लोगों को मदद मिलेगी, जिन्हें अभी भी इस समाधान की आवश्यकता है। एंड्रॉइड में कस्टम फोंट के साथ काम करना


0

यह जानना उपयोगी हो सकता है कि एंड्रॉइड 8.0 (एपीआई स्तर 26) से शुरू होकर आप एक्सएमएल में एक कस्टम फ़ॉन्ट का उपयोग कर सकते हैं

सीधे शब्दों में कहें, तो आप इसे निम्नलिखित तरीके से कर सकते हैं।

  1. फ़ॉन्ट को फ़ोल्डर में रखें res/font

  2. या तो एक विजेट की विशेषता में इसका इस्तेमाल करते हैं

<Button android:fontFamily="@font/myfont"/>

या में डाल दिया res/values/styles.xml

<style name="MyButton" parent="android:Widget.Button">
    <item name="android:fontFamily">@font/myfont</item>
</style>

और इसे एक शैली के रूप में उपयोग करें

<Button style="@style/MyButton"/>

0

सीधे xml फ़ाइल में "fontPath" विशेषता का उपयोग करें।

style.xml में उपयोग के लिए

<आइटम का नाम = "fontPath"> फोंट / ProximaNovaSemibold.ttf </ item>

प्रत्यक्ष लेआउट फ़ाइल में उपयोग के लिए

FontPath = "फोंट / ProximaNovaBold.ttf"

(नोट: उपसर्ग में ऐप / एंड्रॉइड विशेषता का उपयोग करने की आवश्यकता नहीं है)


-6

बिलकुल संभव है। इसे करने के कई तरीके। सबसे तेज़ तरीका, आज़माएँ - पकड़ने की विधि के साथ स्थिति बनाएँ .. अपनी निश्चित फ़ॉन्ट शैली स्थिति आज़माएँ, त्रुटि पकड़ें, और दूसरी फ़ॉन्ट शैली परिभाषित करें।


7
क्या आप उत्तर देने के लिए डेमो प्रदान कर सकते हैं?
मार्क
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.