0
votes

What would be the best way to determine screen size in an external class and then adjust the stroke width of a handwriting capture view, so that it scales nicely?

I've got this SignatureCanvas.java class, in an external library. As you can see I've set the stroke width to a constant, which works (nothing strange there!). However, as I've been testing on various devices and emaulators (of differing screen size), the stroke width isn't translated to any kind of under-the-hood pixel->dip (which is understandable!). So, on older/smaller screen sizes, this stroke width of 8, actually looks like it's 14, and the signature becomes unreadable.

I've brainstormed a bit and have come up with the idea of generalising screen resolutions and having a default stroke width for each 'bracket' (so to speak), and applying it as and when I need to. However, that seems a bit rubbish and I was wondering if anyone has had this dilemma previously and how you solved it?

The class is here purely for demonstration purposes, there is nothing wrong with the code per-se.

 package com.goosesys.gooselib.Views;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class SignatureCanvas extends View {
    private final float STROKE_WIDTH = 8f;
    private final boolean ANTI_ALIAS = true;
    private final int DEFAULT_PEN_COLOUR = 0xFF000000;

    private Path drawPath;
    private Paint drawPaint;
    private Paint canvasPaint;
    private int paintColour = DEFAULT_PEN_COLOUR;

    private Canvas drawCanvas;
    private Bitmap canvasBitmap;

    /*
     * Constructors
     */

    // Main in-code constructor //
    public SignatureCanvas(Context context) {
        super(context);
        setupDrawing();
    }

    // Constructor for use in UI layout tool - Custom Views
    public SignatureCanvas(Context context, AttributeSet attributeSet){
        super(context, attributeSet);
        setupDrawing();
    }   


    /*
     * Methods
     */
    private void setupDrawing(){
        drawPath = new Path();
        drawPaint = new Paint();

        // set initial colour for drawing
        drawPaint.setColor(paintColour);

        // setup paths
        drawPaint.setAntiAlias(ANTI_ALIAS);
        drawPaint.setStrokeWidth(STROKE_WIDTH);
        drawPaint.setStyle(Paint.Style.STROKE);
        drawPaint.setStrokeJoin(Paint.Join.ROUND);
        drawPaint.setStrokeCap(Paint.Cap.ROUND);

        // finally create a new canvas paint object
        canvasPaint = new Paint(Paint.DITHER_FLAG);
    }

    public void clearCanvas(){
        drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
        invalidate();   
    }

    public Bitmap saveSignature(){
        return Bitmap.createBitmap(canvasBitmap);
    }

    /*
     * (non-Javadoc)
     * @see android.view.View#onSizeChanged(int, int, int, int)
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh){
        super.onSizeChanged(w, h, oldw, oldh);
        // view given size

        canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        drawCanvas = new Canvas(canvasBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas){
        // draw view
        canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
        canvas.drawPath(drawPath, drawPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        // detect user touch
        float touchX = event.getX();
        float touchY = event.getY();

        switch(event.getAction()){
        case MotionEvent.ACTION_DOWN:
            drawPath.moveTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_MOVE:
            drawPath.lineTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_UP:
            drawCanvas.drawPath(drawPath, drawPaint);
            drawPath.reset();
            break;
        default:
            return false;
        }

        invalidate();
        return true;
    }   
}
1

1 Answers

1
votes
public static int convertDpsToPixels(Context context, int dps) {
    // http://developer.android.com/guide/practices/screens_support.html

    // Convert the dps to pixels
    final float scale = context.getResources().getDisplayMetrics().density;
    final float dpsFloat = dps;
    return (int) (dpsFloat * scale + 0.5f);

}