【问题标题】:canvas.drawText with pixel perfect text on a canvascanvas.drawText 与画布上的像素完美文本
【发布时间】:2016-05-09 02:55:26
【问题描述】:

这与 AntiAlias 无关,请在回答之前阅读问题,谢谢。

将赏金添加到--> android convert text width (in pixels) to percent of screen width/height

质量信息 --> https://stackoverflow.com/a/1016941/1815624

尝试在画布上绘制文本时,我得到的结果不一致。请帮忙,谢谢。

我希望文本在所有设备上占用相同数量的缩放空间

我不关心 ANTI_ALIAS 并添加了 paint.setFlags(Paint.ANTI_ALIAS_FLAG); 但问题是一样的......

在一个屏幕上,文本占用一半宽度,在另一个屏幕上仅占 1/3,甚至一个使用全宽。

我希望他们都使用相同数量的屏幕空间。

举例

1600X900 7寸平板奇巧实物:

1920.1080 5.2 kitkat 物理

模拟 1600x900 20 英寸棒棒糖

1280x720 4.7 英寸

这些是使用http://www.gkproggy.com/2013/01/draw-text-on-canvas-with-font-size.html的指南创建的

该教程在哪里显示一致的结果

这里要彻底的是出处:

public class MainActivity extends Activity
{
    Paint paint;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        paint = new Paint();
        View test = new TestView(this);

        setContentView(test);
    }

    public class TestView extends View
    {

        public TestView(Context context)
        {
            super(context);
            setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        }

        public float pixelsToSp(Context context, float px) {
            float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
            return px/scaledDensity;
        }

        public float spToPixels(float sp) {
            Context context = getContext();
            float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
            return scaledDensity*sp;
        }

        @Override
        protected void onDraw(Canvas canvas)
        {
            int size = getResources().getDimensionPixelSize(R.dimen.sp20);
            int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics());
            Log.v("intSize", Integer.toString(size));
            Log.v("intSize", Integer.toString(px));
            Log.v("intSize", Float.toString(spToPixels(20f)));
            if(true) {
                Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/Ultra.ttf");
                paint.setTypeface(myTypeface);
            }
            paint.setColor(Color.BLACK);
            paint.setTextSize(size);
            paint.setFlags(Paint.ANTI_ALIAS_FLAG);
            canvas.drawText("HELLOOOOOOOOOOOOOO!", 0, size, paint);
            super.onDraw(canvas);
        }
    }
}

我尝试过来自 https://stackoverflow.com/a/5369766/1815624

调查一下

https://stackoverflow.com/a/21895626/1815624

https://stackoverflow.com/a/14753968/1815624

https://stackoverflow.com/a/21895626/1815624

【问题讨论】:

  • 我真的不知道你在问什么,但要获得“平滑”边缘,你可以在绘制对象上将抗锯齿设置为 true
  • 我希望文本在所有设备上占用相同数量的缩放空间
  • 看起来确实如此。如果您用尺子测量它们,您是否希望它们跨越屏幕宽度/高度的相同 百分比,或者它们的尺寸相同?
  • 是的,这就是我想要做的。百分比
  • 文本似乎与您提供的每个屏幕截图上的状态栏大小相同......它可以正确缩放。

标签: android android-canvas drawtext android-typeface pixel-perfect


【解决方案1】:

使用的资源:

https://stackoverflow.com/a/4847027/1815624

https://stackoverflow.com/a/21895626/1815624

得到屏幕宽度,一些文本大小与屏幕比例的参考,并计算。所以结果是:

注意第二个 HELLOOOOOOOOOOOOOOOO!

public class MainActivity extends Activity
{
    Paint paint;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        paint = new Paint();
        View test = new TestView(this);

        setContentView(test);
    }

    public class TestView extends View
    {

        public TestView(Context context)
        {
            super(context);
            setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        }

        public float pixelsToSp(float px) {
            Context context = getContext();
            float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
            return px/scaledDensity;
        }

        public float spToPixels(float sp) {
            Context context = getContext();
            float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
            return scaledDensity*sp;
        }

        @Override
        protected void onDraw(Canvas canvas)
        {
            int size = getResources().getDimensionPixelSize(R.dimen.sp20);
            int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics());
            Log.v("intSize", Integer.toString(size));
            Log.v("intSize", Integer.toString(px));
            Log.v("intSize", Float.toString(spToPixels(20f)));

            DisplayMetrics metrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(metrics);

            Log.v("intSize hm", Integer.toString(metrics.heightPixels));
            Log.v("intSize wm", Integer.toString(metrics.widthPixels));

            if(true) {
                Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/Ultra.ttf");
                paint.setTypeface(myTypeface);
            }
            paint.setColor(Color.BLACK);
            paint.setTextSize(size);
            paint.setFlags(Paint.ANTI_ALIAS_FLAG);
            canvas.drawText("HELLOOOOOOOOOOOOOO!", 0, size, paint);
            setTextSizeForWidth(paint, metrics.widthPixels * 0.5f, "HELLOOOOOOOOOOOOOO!");
            canvas.drawText("HELLOOOOOOOOOOOOOO!", 0, size*3, paint);
            super.onDraw(canvas);
        }
        /**
         * Sets the text size for a Paint object so a given string of text will be a
         * given width.
         *
         * @param paint
         *            the Paint to set the text size for
         * @param desiredWidth
         *            the desired width
         * @param text
         *            the text that should be that width
         */
        private void setTextSizeForWidth(Paint paint, float desiredWidth,
                                                String text) {

            // Pick a reasonably large value for the test. Larger values produce
            // more accurate results, but may cause problems with hardware
            // acceleration. But there are workarounds for that, too; refer to
            // https://stackoverflow.com/questions/6253528/font-size-too-large-to-fit-in-cache
            final float testTextSize = 48f;

            // Get the bounds of the text, using our testTextSize.
            paint.setTextSize(testTextSize);
            Rect bounds = new Rect();
            paint.getTextBounds(text, 0, text.length(), bounds);

            // Calculate the desired size as a proportion of our testTextSize.
            float desiredTextSize = testTextSize * desiredWidth / bounds.width();

            // Set the paint for that size.
            paint.setTextSize(desiredTextSize);
        }

    }
}

如果您不扩展 Activity 使用,请注意

    DisplayMetrics metrics = new DisplayMetrics();
    WindowManager windowManager = (WindowManager) context
            .getSystemService(Context.WINDOW_SERVICE);
    windowManager.getDefaultDisplay().getMetrics(metrics);

而不是

    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);

【讨论】:

    猜你喜欢
    • 2012-08-10
    • 1970-01-01
    • 2015-06-20
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 2019-05-20
    • 2020-01-30
    • 2012-10-01
    相关资源
    最近更新 更多