【问题标题】:Android font ttf or otf typeface rendering random symblols/lettersAndroid 字体 ttf 或 otf 字体呈现随机符号/字母
【发布时间】:2014-07-23 01:56:30
【问题描述】:

我有一个自定义的View,我正在其中绘制一些文本。我正在使用 assets 文件夹中提供的各种免费 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);
    }
}

除了一件事之外,一切似乎都运行良好:我画的字被随机弄乱了,这意味着这些字母被随机替换为其他字母或符号。

这是一个例子:

正确的单词在左图中,但有时它会像右图一样绘制。再次调用 invalidate() 一切都会再次正确呈现,从而解决了问题。

这种效果在ListView 中更为明显,因为我在每次点击项目时都调用notifyDatasetChanged() 时频繁重绘,所以这种效果更频繁地发生在那里。在适配器中,我这样使用它:

@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()));
}

说实话,我不知道是什么原因造成的,也不知道如何预防。任何帮助表示赞赏!

【问题讨论】:

  • 您能告诉我们您使用的是哪些字体吗?尤其是那些引起问题的可能很重要。
  • 这在我使用的所有字体上随机发生。 ttf 文件来自 Google 字体。
  • 您能否发布一个链接,指向您遇到问题的至少一种字体?我想尝试重现问题。
  • 我建议您将字体作为静态变量或其他东西保存,并且只加载一次。

标签: android fonts android-custom-view text-rendering android-typeface


【解决方案1】:

每次调用 getView 时,您都在创建字体。这是低效的,并且在加载和解析字体文件时可能会导致竞争。

而是在活动中包含所有已加载字体的地图,并且每个字体仅加载一次。

如果许多活动和视图使用相同的字体,我什至会尝试管理 Application 类上的字体。

【讨论】:

  • 虽然这是一个很好的建议,但我真的不明白它与问题有什么关系。 Typeface.createFromAsset() 不是同步的吗?而这些调用都来自 UI 线程。为什么会产生竞争条件?
  • 为每种字体创建字体(我使用大约 100 个字体文件)似乎减少了这种情况发生的频率,几乎看不到它,所以绝对是一种改进。问题是,拥有所有这 100 个字体对象不会占用太多内存吗?用户可能永远不会滚动整个列表。确实,我在 getView 上创建字体
  • @Alin 在类似的应用程序(大约 50 种字体)中,加载所有字体时我没有看到显着的内存使用。如果字体文件很小,它占用的内存也应该很小。您也可以只缓存第一次使用时实际使用的字体。
  • @matiash 加载字体文件需要读取文件、解析文件并为其创建内存数据结构。我假设一些工作是在另一个线程中完成的,可能是本机线程。不是 100% 确定,因为我没有查看 Android 代码。
  • @yoah 这个怎么样:我在 getView 上创建字体但我也将它存储在缓存中,所以下次加载项目时,我只需从那里获取字体?
【解决方案2】:

这可能对某人有帮助。我遇到了同样的问题。我使用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);
    }
}

示例:

private TypefaceSpan typefaceSpan;

构造函数:

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

获取视图:

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

【讨论】:

    猜你喜欢
    • 2011-12-05
    • 2011-07-15
    • 2016-03-22
    • 2021-06-08
    • 2011-04-14
    • 2017-02-02
    • 2014-06-04
    • 2019-07-22
    • 2014-04-27
    相关资源
    最近更新 更多