Android库中的字体

时间:2011-09-30 12:28:34

标签: android

在以下链接

Android Dev Guide

写道:

图书馆项目不能包含原始资产 这些工具不支持在库项目中使用原始资产文件(保存在assets /目录中)。应用程序使用的任何资产资源都必须存储在应用程序项目本身的assets /目录中。但是,支持保存在res /目录中的资源文件。

因此,如果我想创建一个使用自定义字体的自定义视图组件,我该如何访问该资源?我不能用我最喜欢的字体重新分发我的组件!!!!

祝你好运

9 个答案:

答案 0 :(得分:24)

这是从实际工作的资源加载字体的方法;-) 归功于第一版的mr32bit。

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

答案 1 :(得分:7)

好的,我找到了解决问题的方法。您需要将文件复制到外部目录,然后从Typeface.createFromFile的文件加载字体,然后删除临时文件。我知道这不是一种干净的工作方式,而是在努力工作。

1 - 您需要将字体放在“/res/raw/font.ttf”

2 - 在您的代码中使用以下方法

3 - 输入您的代码Typeface mFont = FileStreamTypeface(R.raw.font);

4 - 一切都已完成

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

如果有人有替代方案,我很高兴看到它。 您是否必须记住此解决方法仅适用于Android库

祝你好运

答案 2 :(得分:2)

Intellij Idea(和android studio一样,它基于intellij)有一个功能,可以让你将库模块的资产文件包含到应用程序模块中,我不了解其他环境。

转到文件菜单中的项目结构,然后进入facet,选择应用程序模块,在编译器选项卡中选中“将资源从依赖项包含到进入APK”复选框。

由于intellij比Eclipse好得多,我认为迁移是合理的。

修改

android studio中完全支持资产和清单合并。

答案 3 :(得分:1)

如果扩展TextView并想要使用许多此视图,则此视图中只应有一个Typeface实例。将* .ttf文件复制到res / raw /并使用以下代码:

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是一个静态变量,因此引用不会被销毁,可以在其他MyTextViews中重用。 这段代码与其他答案几乎相同,但我觉得如果你在ListView或其它东西中使用它,效率会提高并消耗更少的内存。

答案 4 :(得分:0)

  

因此,如果我想创建一个使用自定义字体的自定义视图组件,我该如何访问该资源?

您的代码将以不同的方式访问它。您只需告诉自定义视图的重用者将字体文件包含在其资产中。

  

我不能用我最喜欢的字体重新发布我的组件!!!!

当然可以。将字体与库项目的其余部分一起放在ZIP文件中,以及将其放在项目中的位置说明。但是请务必使用您有权以这种方式重新分发的字体。

答案 5 :(得分:0)

即使你将你的字体放在assets / fonts文件夹中,这个库也可以运行,而且非常容易使用:https://github.com/neopixl/PixlUI。我已经在Android 2.3上成功测试过了。 以及4.4

答案 6 :(得分:0)

只需使用@ bk138的响应,这对我有用的小改动

在清单

中添加此内容
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

并在创建Buffered

之前添加它
        File f2 = new File(outPath);
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outPath));

答案 7 :(得分:0)

下面的代码修改了@ bk138的解决方案,并包含了@Jason Robinson的建议,即不删除文件并首先检查先前缓存的文件。此外,它在字体后面命名临时文件而不是创建时间。

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

答案 8 :(得分:0)

这是我在@ Mr32Bit的答案中修改后的版本/改进。在第一次调用时,我将字体复制到app private dir / custom_fonts。将来读取检查是否存在,如果是,则读取现有副本(每次在复制文件上节省时间)。

注意:这假定只有一个自定义字体。

 /**
     * Helper method to load (and cache font in app private folder) typeface from raw dir this is needed because /assets from library projects are not merged in Eclipse
     * @param c
     * @param resource ID of the font.ttf in /raw
     * @return
     */
    public static Typeface loadTypefaceFromRaw(Context c, int resource)
    {
        Typeface tf = null;

        InputStream is = c.getResources().openRawResource(resource);
        String path = c.getFilesDir() + "/custom_fonts";
        File f = new File(path);
        if (!f.exists())
        {
            if (!f.mkdirs())
                return null;
        }

        String outPath = path + "/myfont.ttf";

        File fontFile = new File(outPath);
        if (fontFile.exists()) {
            tf = Typeface.createFromFile(fontFile);
        }else{
            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);
            }
            catch (IOException e)
            {
                return null;
            }
        }
        return tf;
    }