简体   繁体   English

Android字体ttf或otf字体呈现随机symblols /字母

[英]Android font ttf or otf typeface rendering random symblols/letters

I have a custom View in which I am drawing some text. 我有一个自定义View ,我正在绘制一些文本。 I am using various free otf/ttf font files which are available in the assets folder 我正在使用资产文件夹中提供的各种免费otf / ttf字体文件

public class ProjectView extends View {
    private final Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    private void init(Context context) {
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setAntiAlias(true);

        typeface = Typeface.createFromAsset(context.getAssets(), "fonts" + File.separator + fontFileName);
        textPaint.setTypeface(typeface);
    }
}

Everything seems to be working fine except one thing: The words I am drawing get randomly messed up, meaning the letters are randomly replaced with other letters or symbols. 一切似乎工作得很好,除了一件事:我正在绘制的单词随机乱搞,意味着字母随机替换为其他字母或符号。

Here is an example: 这是一个例子:

在此输入图像描述

The correct word is in the left image but sometimes it gets drawn like in the right image. 正确的单词位于左侧图像中,但有时会像右图中一样绘制。 Calling invalidate() again everything gets rendered correctly again fixes the problem. 再次调用invalidate()再次正确呈现所有内容可以解决问题。

This effect is more obvious in a ListView , it happens more often there because of the frequent redraws as I call notifyDatasetChanged() on each item click. 这个效果在ListView更明显,因为频繁的重绘,因为我在每个项目点击时调用notifyDatasetChanged() In the adapter I use it like this: 在适配器中我使用它像这样:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View view = convertView;
        ViewHolder holder;
        if (convertView == null) {
            view = inflater.inflate(R.layout.list_item_fonts, null);

            holder = new ViewHolder();
            holder.txtFont = (TextView) view.findViewById(R.id.txtFont);
            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }

        //tried this two but no success
        holder.txtFont.setPaintFlags(holder.txtFont.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG | Paint.DEV_KERN_TEXT_FLAG);
        holder.txtFont.getPaint().setSubpixelText(true);

        holder.txtFont.setTextSize(TypedValue.COMPLEX_UNIT_SP, fonts.get(position).getSize());

        holder.txtFont.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts" + File.separator + font.getFileName()));
}

To be honest, I have no idea what causes this or how I could prevent it. 说实话,我不知道是什么导致这种情况或如何阻止它。 Any help is appreciated! 任何帮助表示赞赏!

You are creating the typeface every time getView is called. 每次调用getView时都会创建字体。 This is inefficient, and could cause races while loading and parsing the typeface files. 这是低效的,并且可能在加载和解析字体文件时引起竞争。

Instead have in the activity a map of all loaded typefaces, and load each one only once. 而是在活动中具有所有加载的字体的映射,并且仅加载每个字体。

I would even try to manage the typefaces on the Application class, if many activities and views use the same typefaces. 如果许多活动和视图使用相同的字体,我甚至会尝试管理Application类上的字体。

May be this might help somebody. 可能这可能对某人有所帮助。 I got the same problem. 我遇到了同样的问题。 I solved it using lru cache. 我用lru缓存解决了它。

import android.content.Context;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.text.style.MetricAffectingSpan;
import android.util.LruCache;

public class TypefaceSpan extends MetricAffectingSpan {
    private static LruCache<String, Typeface> sTypefaceCache = new LruCache<>(12);
    private Typeface mTypeface;

    public TypefaceSpan(Context context, String typefaceName) {
        mTypeface = sTypefaceCache.get(typefaceName);

        if (mTypeface == null) {
            mTypeface = Typeface.createFromAsset(context.getApplicationContext().getAssets(),
                    String.format("fonts/%s", typefaceName));
            sTypefaceCache.put(typefaceName, mTypeface);
        }
    }

    @Override
    public void updateMeasureState(TextPaint p) {
        p.setTypeface(mTypeface);
        p.setFlags(p.getFlags() | Paint.SUBPIXEL_TEXT_FLAG);
    }

    @Override
    public void updateDrawState(TextPaint tp) {
        tp.setTypeface(mTypeface);
        tp.setFlags(tp.getFlags() | Paint.SUBPIXEL_TEXT_FLAG);
    }
}

example: 例:

private TypefaceSpan typefaceSpan;

constructor: 构造函数:

typefaceSpan = new TypefaceSpan(context, "name_of_font.otf");

getView: getView:

typefaceSpan.updateDrawState(holder.title.getPaint());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM