2015-10-30 2 views
0

Я написал небольшой класс, который можно использовать для создания пользовательских чертежей. По большей части все работает так, как ожидалось, но когда дело доходит до отображения чертежей, почти «идеальных пикселей», я действительно не знаю, как получить правильное решение. Правильным решением было бы получить 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

+0

Он еще не сконцентрирован? – Nanoc

+0

Да, но не так полностью центрирован. В других плотностях вы узнаете более узнаваемую разницу. –

+2

use 'Paint # getTextBounds' – pskink

ответ

1

Если вы хотите, чтобы отцентрировать текст в основной форме, что вам нужно сделать текст в нужном месте и для этого вам нужно использовать Paint.getTextBounds (String text, int start, int end, Rect bounds)

общественных недействительные getTextBounds (текстовая строка, Int начала, внутр конечные, Rect )

Возвращает в границах (выделенных вызывающим) наименьший прямоугольник, который охватывает все символы с подразумеваемым началом в (0,0).

После того, как вы выполните этот метод, вы получите информацию в bounds. Все, что вам нужно сделать, это написать логику в методе draw вашего Drawable, где вы вычисляете координаты x/y для выполнения drawText() (на основании этого bounds rect).

+1

не нужно «переводить», так как вы можете указать 'x' и' y' coords непосредственно в 'drawText' call – pskink

+0

Да, это имеет смысл. Благодарю. – Henry