laminatefish
laminatefish

Reputation: 5246

Best way to determine screen dimensions for signature capture stroke width?

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;
    }   
}

Upvotes: 0

Views: 827

Answers (1)

Jose L Ugia
Jose L Ugia

Reputation: 6250

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);

}

Upvotes: 1

Related Questions