可绘制(密度)的最佳实践

时间:2015-10-30 16:09:19

标签: android drawable paint pixel

我写了一个小类,可用于创建自定义drawable。在大多数情况下,一切都按预期工作,但是当谈到显示几乎“像素完美”的drawables时,我真的不知道如何得到一个合适的解决方案。一个合适的解决方案是在底层形状上获得100%居中的字符/文本。欢迎任何建议。提前谢谢。

这是班级:

public class DrawableSquareLetter extends Drawable {

    private final Paint paint;
    private Paint textPaint;
    private final Builder builder;


    public DrawableSquareLetter(Builder builder) {
        this.builder = builder;
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(builder.color);

        if (builder.applySurfaceShadow) {
            paint.setShadowLayer(
                    DeviceUtils.dp2px(4),
                    DeviceUtils.dp2px(2),
                    DeviceUtils.dp2px(2),
                    Color.parseColor(MaterialColor.GREY_900));
        }


        textPaint = new Paint();
        textPaint.setColor(builder.textColor);
        textPaint.setAntiAlias(true);
        textPaint.setFakeBoldText(builder.isBold);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setTypeface(builder.typeface);
        textPaint.setTextAlign(Paint.Align.CENTER);

        if (builder.applyTextShadow) {
            textPaint.setShadowLayer(
                    DeviceUtils.dp2px(2),
                    DeviceUtils.dp2px(1),
                    DeviceUtils.dp2px(1),
                    Color.parseColor(MaterialColor.GREY_800));
        }

    }


    @Override
    public void draw(Canvas canvas) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            canvas.drawRoundRect(0, 0, builder.size, builder.size, builder.rounded, builder.rounded, paint);
        } else canvas.drawRect(0, 0, builder.size, builder.size, paint);

        if (builder.textSize == -1) {
            textPaint.setTextSize(builder.size * .80f);
        } else textPaint.setTextSize(builder.textSize);

        float width = builder.size;
        float height = builder.size;

        String text = builder.isUpperCase ? builder.text.toUpperCase() : builder.text;
        canvas.drawText(text, width / 2f, height / 2f - (((textPaint.descent() + textPaint.ascent())) / 2f), textPaint);
    }


    @Override
    public void setAlpha(int alpha) {
        paint.setAlpha(alpha);
    }


    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        paint.setColorFilter(colorFilter);
    }


    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }


    public static class Builder {

        private final float size;
        private final int color;
        private String tag = "";
        private float rounded;
        private final String text;
        private int textColor = Color.BLACK;
        private float textSize = -1;
        private Typeface typeface = Typeface.DEFAULT;

        private boolean isUpperCase = true;
        private boolean isBold = true;
        private boolean applyTextShadow = true;
        private boolean applySurfaceShadow = true;


        public Builder(int sizeDp, int color, String text) {
            this.text = text;
            this.size = DeviceUtils.dp2px(sizeDp);
            this.color = color;
        }


        public Builder(int sizeDp, String color, String text) {
            this.text = text;
            this.size = DeviceUtils.dp2px(sizeDp);
            this.color = Color.parseColor(color);
        }


        public Builder textSize(float textSize) {
            this.textSize = DeviceUtils.sp2px(textSize);
            return this;
        }


        public Builder rounded(int radiusDp) {
            this.rounded = DeviceUtils.dp2px(radiusDp);
            return this;
        }


        public Builder textColor(int textColor) {
            this.textColor = textColor;
            return this;
        }


        public Builder textColor(String textColor) {
            this.textColor = Color.parseColor(textColor);
            return this;
        }


        public Builder typeface(Typeface typeface) {
            this.typeface = typeface;
            return this;
        }


        public Builder disableUpperCase() {
            this.isUpperCase = false;
            return this;
        }


        public Builder disableBold() {
            this.isBold = false;
            return this;
        }


        public Builder disableShadowOnSurface() {
            this.applySurfaceShadow = false;
            return this;
        }


        public Builder disableShadowOnText() {
            this.applyTextShadow = false;
            return this;
        }


        public Builder setTag(String tag) {
            this.tag = tag;
            return this;
        }


        public DrawableSquareLetter build() {
            return new DrawableSquareLetter(this);
        }


        public void show(ImageView imageView) {
            imageView.setImageDrawable(this.build());
        }
    }


    public String getTag() { return builder.tag; }

}

nexus 5 genymotion enter image description here

1 个答案:

答案 0 :(得分:1)

如果您希望将文本置于基础形状的中心,则需要在正确的位置绘制文本,为此您需要使用Paint.getTextBounds (String text, int start, int end, Rect bounds)

  

public void getTextBounds(String text,int start,int end,Rect   边界)

     

返回边界(由调用者分配)最小的矩形   包含所有字符,隐含的原点为(0,0)。

执行此方法后,您将获得bounds中的信息。您需要做的就是在draw的{​​{1}}方法中编写一个逻辑,您可以在其中计算执行Drawable的x / y坐标(基于此drawText() rect )。