Custom fonts and XML layouts (Android)

后端 未结 18 1876
执念已碎
执念已碎 2020-11-22 07:21

I\'m trying to define a GUI layout using XML files in Android. As far as I can find out, there is no way to specify that your widgets should use a custom font (e.g. one you\

相关标签:
18条回答
  • 2020-11-22 07:30

    I might have a simple answer for the question without extending the TextView and implementing a long code.

    Code :

     TextView tv = (TextView) findViewById(R.id.textview1);
        tv.setTypeface(Typeface.createFromAsset(getAssets(), "font.ttf"));
    

    Place the custom font file in assets folder as usual and try this. It works for me. I just dont understand why peter has given such a huge code for this simple thing or he has given his answer in old version.

    0 讨论(0)
  • 2020-11-22 07:30

    Fontinator is an Android-Library make it easy, to use custom Fonts. https://github.com/svendvd/Fontinator

    0 讨论(0)
  • 2020-11-22 07:35

    Also can be defined in the xml without creating custom classes

    style.xml

    <style name="ionicons" parent="android:TextAppearance">
        <!-- Custom Attr-->
        <item name="fontPath">fonts/ionicons.ttf</item>
    </style>
    

    activity_main.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  xmlns:app="http://schemas.android.com/apk/res-auto"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:orientation="vertical" >
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="@style/ionicons"
            android:text=""/>
    </LinearLayout>
    

    A quick note, because I just always forgot where to put the fonts, its that the font must be inside assets and this folder resides in the same level that res and src, in my case its assets/fonts/ionicons.ttf

    Updated Added root layout because this method needs xmlns:app="http://schemas.android.com/apk/res-auto" to work

    Update 2 Forgot about a library that I've installed before called Calligraphy

    0 讨论(0)
  • 2020-11-22 07:36

    You can extend TextView to set custom fonts as I learned here.

    TextViewPlus.java:

    package com.example;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Typeface;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.widget.TextView;
    
    public class TextViewPlus extends TextView {
        private static final String TAG = "TextView";
    
        public TextViewPlus(Context context) {
            super(context);
        }
    
        public TextViewPlus(Context context, AttributeSet attrs) {
            super(context, attrs);
            setCustomFont(context, attrs);
        }
    
        public TextViewPlus(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            setCustomFont(context, attrs);
        }
    
        private void setCustomFont(Context ctx, AttributeSet attrs) {
            TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.TextViewPlus);
            String customFont = a.getString(R.styleable.TextViewPlus_customFont);
            setCustomFont(ctx, customFont);
            a.recycle();
        }
    
        public boolean setCustomFont(Context ctx, String asset) {
            Typeface tf = null;
            try {
            tf = Typeface.createFromAsset(ctx.getAssets(), asset);  
            } catch (Exception e) {
                Log.e(TAG, "Could not get typeface: "+e.getMessage());
                return false;
            }
    
            setTypeface(tf);  
            return true;
        }
    
    }
    

    attrs.xml: (in res/values)

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="TextViewPlus">
            <attr name="customFont" format="string"/>
        </declare-styleable>
    </resources>
    

    main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:foo="http://schemas.android.com/apk/res/com.example"
        android:orientation="vertical" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    
        <com.example.TextViewPlus
            android:id="@+id/textViewPlus1"
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:text="@string/showingOffTheNewTypeface"
            foo:customFont="saxmono.ttf">
        </com.example.TextViewPlus>
    </LinearLayout>
    

    You would put "saxmono.ttf" in the assets folder.

    UPDATE 8/1/13

    There are serious memory concerns with this method. See chedabob's comment below.

    0 讨论(0)
  • 2020-11-22 07:37

    This might be a little late, but you need to create a singleton class that returns the custom typeface to avoid memory leaks.

    TypeFace class:

    public class OpenSans {
    
    private static OpenSans instance;
    private static Typeface typeface;
    
    public static OpenSans getInstance(Context context) {
        synchronized (OpenSans.class) {
            if (instance == null) {
                instance = new OpenSans();
                typeface = Typeface.createFromAsset(context.getResources().getAssets(), "open_sans.ttf");
            }
            return instance;
        }
    }
    
    public Typeface getTypeFace() {
        return typeface;
    }
    }
    

    Custom TextView:

    public class NativelyCustomTextView extends TextView {
    
        public NativelyCustomTextView(Context context) {
            super(context);
            setTypeface(OpenSans.getInstance(context).getTypeFace());
        }
    
        public NativelyCustomTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
            setTypeface(OpenSans.getInstance(context).getTypeFace());
        }
    
        public NativelyCustomTextView(Context context, AttributeSet attrs,
                int defStyle) {
            super(context, attrs, defStyle);
            setTypeface(OpenSans.getInstance(context).getTypeFace());
        }
    
    }
    

    By xml:

    <com.yourpackage.views.NativelyCustomTextView
                android:id="@+id/natively_text_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_margin="20dp"
                android:text="@string/natively"
                android:textSize="30sp" /> 
    

    Programmatically:

    TextView programmaticallyTextView = (TextView) 
           findViewById(R.id.programmatically_text_view);
    
    programmaticallyTextView.setTypeface(OpenSans.getInstance(this)
                    .getTypeFace());
    
    0 讨论(0)
  • 2020-11-22 07:37

    You can make easily custom textview class :-

    So what you need to do first, make Custom textview class which extended with AppCompatTextView.

    public class CustomTextView extends AppCompatTextView {
        private int mFont = FontUtils.FONTS_NORMAL;
        boolean fontApplied;
    
        public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init(attrs, context);
        }
    
        public CustomTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(attrs, context);
        }
    
        public CustomTextView(Context context) {
            super(context);
            init(null, context);
        }
    
        protected void init(AttributeSet attrs, Context cxt) {
            if (!fontApplied) {
                if (attrs != null) {
                    mFont = attrs.getAttributeIntValue(
                            "http://schemas.android.com/apk/res-auto", "Lato-Regular.ttf",
                            -1);
                }
                Typeface typeface = getTypeface();
                int typefaceStyle = Typeface.NORMAL;
                if (typeface != null) {
                    typefaceStyle = typeface.getStyle();
                }
                if (mFont > FontUtils.FONTS) {
                    typefaceStyle = mFont;
                }
                FontUtils.applyFont(this, typefaceStyle);
                fontApplied = true;
            }
        }
    }
    

    Now , every time Custom text view call and we will get int value from attribute int fontValue = attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto","Lato-Regular.ttf",-1).

    Or

    We can also get getTypeface() from view which we set in our xml (android:textStyle="bold|normal|italic"). So do what ever you want to do.

    Now, we make FontUtils for set any .ttf font into our view.

    public class FontUtils {
    
        public static final int FONTS = 1;
        public static final int FONTS_NORMAL = 2;
        public static final int FONTS_BOLD = 3;
        public static final int FONTS_BOLD1 = 4;
    
        private static Map<String, Typeface> TYPEFACE = new HashMap<String, Typeface>();
    
        static Typeface getFonts(Context context, String name) {
            Typeface typeface = TYPEFACE.get(name);
            if (typeface == null) {
                typeface = Typeface.createFromAsset(context.getAssets(), name);
                TYPEFACE.put(name, typeface);
            }
            return typeface;
        }
    
        public static void applyFont(TextView tv, int typefaceStyle) {
    
            Context cxt = tv.getContext();
            Typeface typeface;
    
            if(typefaceStyle == Typeface.BOLD_ITALIC) {
                typeface = FontUtils.getFonts(cxt, "FaktPro-Normal.ttf");
            }else if (typefaceStyle == Typeface.BOLD || typefaceStyle == SD_FONTS_BOLD|| typefaceStyle == FONTS_BOLD1) {
                typeface = FontUtils.getFonts(cxt, "FaktPro-SemiBold.ttf");
            } else if (typefaceStyle == Typeface.ITALIC) {
                typeface = FontUtils.getFonts(cxt, "FaktPro-Thin.ttf");
            } else {
                typeface = FontUtils.getFonts(cxt, "FaktPro-Normal.ttf");
            }
            if (typeface != null) {
                tv.setTypeface(typeface);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题