Font in Android Library

后端 未结 9 1618
南方客
南方客 2021-02-05 15:30

At the follow link

Android Dev Guide

is write:

Library projects cannot include raw assets The tools do not support the use of raw asset files (saved in t

相关标签:
9条回答
  • 2021-02-05 15:48

    Here's a method for loading fonts from resources that actually works ;-) Credit to mr32bit for the first version.

    private Typeface getFontFromRes(int resource)
    { 
        Typeface tf = null;
        InputStream is = null;
        try {
            is = getResources().openRawResource(resource);
        }
        catch(NotFoundException e) {
            Log.e(TAG, "Could not find font in resources!");
        }
    
        String outPath = getCacheDir() + "/tmp" + System.currentTimeMillis() ".raw";
    
        try
        {
            byte[] buffer = new byte[is.available()];
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath));
    
            int l = 0;
            while((l = is.read(buffer)) > 0)
                bos.write(buffer, 0, l);
    
            bos.close();
    
            tf = Typeface.createFromFile(outPath);
    
            // clean up
            new File(outPath).delete();
        }
        catch (IOException e)
        {
            Log.e(TAG, "Error reading in font!");
            return null;
        }
    
        Log.d(TAG, "Successfully loaded font.");
    
        return tf;      
    }
    
    0 讨论(0)
  • 2021-02-05 15:48

    Even though You put Your fonts in assets/fonts folder, somehow this library works and its very easy to use: https://github.com/neopixl/PixlUI . I've successfully tested it on Android 2.3. as well as 4.4

    0 讨论(0)
  • 2021-02-05 15:50

    The code below modifies the solution from @bk138 and includes @Jason Robinson recommendations for not deleting the file and checking for a previously cached file first. Also, it names the temp file after the font instead of the time created.

    public static Typeface getFontFromRes(Context context, int resId, boolean deleteAfterwards){ 
        String tag = "StorageUtils.getFontFromRes";
    
        String resEntryName = context.getResources().getResourceEntryName(resId);
        String outPath = context.getCacheDir() + "/tmp_" + resEntryName + ".raw";
    
        //First see if the file already exists in the cachDir
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(new File(outPath));
        } catch (FileNotFoundException e) {
            Log.d(tag,"fileNotFoundException outPath:"+outPath+e.getMessage());
        }
    
        if(fis != null){            
            try {
                Log.d(tag,"found cached fontName:"+resEntryName);
                fis.close();
            } catch (IOException e) {
                Log.d(tag,"IOException outPath:"+outPath+e.getMessage());
            }
    
            //File is already cached so return it now
            return Typeface.createFromFile(outPath);
        }       
    
        InputStream is = null;
        try {
            is = context.getResources().openRawResource(resId);
        }catch(NotFoundException e) {
            Log.e(tag, "Could not find font in resources! " + outPath);
        }
    
        try{
            byte[] buffer = new byte[is.available()];
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath));
    
            int l = 0;
            while((l = is.read(buffer)) > 0)
                bos.write(buffer, 0, l);
    
            bos.close();
        }catch (IOException e){
            Log.e(tag, "Error reading in font!");
            return null;
        }           
    
        Typeface tf = Typeface.createFromFile(outPath);
    
        if(deleteAfterwards){
            // clean up if desired
            new File(outPath).delete();
        }
    
        Log.d(tag, "Successfully loaded font.");
    
        return tf;      
    }
    
    0 讨论(0)
  • 2021-02-05 15:53

    Just use the response of @bk138 with this little change it works to me

    add this in the manifest

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    

    and add this before creating the Buffered

            File f2 = new File(outPath);
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath));
    
    0 讨论(0)
  • 2021-02-05 15:54

    If you extend a TextView and want to use many of this views you should have only one instance of the Typeface in this view. Copy the *.ttf file into res/raw/ and use the following code:

    public class MyTextView extends TextView {
        public static final String FONT = "font.ttf";
        private static Typeface mFont;
    
        private static Typeface getTypefaceFromFile(Context context) {
            if(mFont == null) {
                File font = new File(context.getFilesDir(), FONT);
                if (!font.exists()) {
                    copyFontToInternalStorage(context, font);
                }
                mFont = Typeface.createFromFile(font);
            }
            return mFont;
        }
    
        private static void copyFontToInternalStorage(Context context, File font) {
            try {
                InputStream is = context.getResources().openRawResource(R.raw.font);
                byte[] buffer = new byte[4096];
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(font));
                int readByte;
                while ((readByte = is.read(buffer)) > 0) {
                    bos.write(buffer, 0, readByte);
                }
                bos.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public MyTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
            setTypeface(getTypefaceFromFile(context));
        }
    }
    

    mFont is a static variable, so the reference will not be destroyed and can be reused in other MyTextViews. This code is nearly the same as the other answers but I guess mor efficient and consumes less memory if you are using it in a ListView or something.

    0 讨论(0)
  • 2021-02-05 15:57

    Ok I have found a workaround for the problem. You need to copy the file to an external directory then load a typeface from file with Typeface.createFromFile and then delete the temporary file. I know is not a clean mode of work but is working grate.

    1 - You need to put your font on "/res/raw/font.ttf"

    2 - Inser in your code the following method

    3 - put in your code Typeface mFont = FileStreamTypeface(R.raw.font);

    4 - All is done

     Typeface FileStreamTypeface(int resource)
    {
        Typeface tf = null;
    
        InputStream is = getResources().openRawResource(resource);
        String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/gmg_underground_tmp";
        File f = new File(path);
        if (!f.exists())
        {
            if (!f.mkdirs())
                return null;
        }
    
        String outPath = path + "/tmp.raw";
    
        try
        {
            byte[] buffer = new byte[is.available()];
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath));
    
            int l = 0;
            while((l = is.read(buffer)) > 0)
            {
                bos.write(buffer, 0, l);
            }
            bos.close();
    
            tf = Typeface.createFromFile(outPath);
    
            File f2 = new File(outPath);
            f2.delete();
        }
        catch (IOException e)
        {
            return null;
        }
    
        return tf;      
    }
    

    if someone have an alternative I'm pleased to read it. Do you have to remember that this workaround is only for Android Libraries

    Best regards

    0 讨论(0)
提交回复
热议问题