0

Help solve my problem, please. Googling does not give results.
I have a custom SurfaceView, on the canvas of which, through a separate thread, I draw various shapes and text. This SurfaceView is wrapped in a custom FrameLayout that implements pinch-zoom for a child. So, at the zoom, the quality of the figures is lost, although if you use the usual View with canvas, everything is ok. TextureView has the same problem. I'd love to use the regular View, but I need a constant redraw of the canvas.
Does anyone have any thoughts?

For example, I draw a grid with numbers:

PixelGridSurfaceView

public class PixelGridSurfaceView extends SurfaceView
        implements SurfaceHolder.Callback {

private DrawThread drawThreadSV;
private float pixelRadius = 0;
private int numColumns = 90, numRows = 90;

public PixelGridSurfaceView(Context context) {
    super(context);
    getHolder().addCallback(this);
}

public PixelGridSurfaceView (Context context, AttributeSet attributeSet) {
    super(context, attributeSet);
    getHolder().addCallback(this);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // Add padding to maximum width calculation.
    final int desiredWidth = Math.round(getPaddingLeft() + getPaddingRight());


    final int desiredHeight = Math.round(getPaddingTop() +
            getPaddingBottom());

    // Reconcile size that this view wants to be with the size the parent will let it be.
    final int measuredWidth = reconcileSize(desiredWidth, widthMeasureSpec);
    final int measuredHeight = reconcileSize(desiredHeight, heightMeasureSpec);

    // calculate best pixel size
    float cellWidth = (float) measuredWidth / numColumns;
    float cellHeight = (float) measuredHeight / numRows;

    pixelRadius = cellHeight < cellWidth ? cellHeight : cellWidth;
    pixelRadius = (float) Math.floor(pixelRadius);

    // Store the final measured dimensions.
    setMeasuredDimension((int) pixelRadius * numColumns, measuredHeight);
}

private int reconcileSize(int contentSize, int measureSpec) {
    final int mode = MeasureSpec.getMode(measureSpec);
    final int specSize = MeasureSpec.getSize(measureSpec);
    switch (mode) {
        case MeasureSpec.EXACTLY:
            return specSize;
        case MeasureSpec.AT_MOST:
            if (contentSize < specSize) {
                return contentSize;
            } else {
                return specSize;
            }
        case MeasureSpec.UNSPECIFIED:
        default:
            return contentSize;
    }
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    drawThreadSV = new DrawThread(new SurfaceViewHolder(getHolder()));
    drawThreadSV.setPixelRadius(getContext(), pixelRadius);
    drawThreadSV.setNumRowsColumns(numColumns, numRows);
    drawThreadSV.setRunning(true);
    drawThreadSV.start();
}



@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    boolean retry = true;
    drawThreadSV.setRunning(false);

    while(retry) {
        try {
            drawThreadSV.join();
            retry = false;
        }
        catch (InterruptedException e) {
        }
    }
}
}

DrawThread

public class DrawThread extends Thread {

    private boolean running = false;
    private ISurfaceHolder surfaceHolder;
    private int numColumns, numRows;
    private Paint linePaint, cellsPaint;
    private TextPaint fontPaint;
    private float pixelRadius = 0;
    private float baselineX, baselineY;
    private String number = "4";

    DrawThread(ISurfaceHolder surfaceHolder) {
        this.surfaceHolder = surfaceHolder;
        linePaint = new Paint();
        cellsPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        fontPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        linePaint.setColor(Color.BLACK);
        cellsPaint.setColor(Color.WHITE);
        linePaint.setStyle(Paint.Style.STROKE);
    }

    void setPixelRadius(Context context, float pixelRadius) {
        this.pixelRadius = pixelRadius;
        fontPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, pixelRadius / 2.5f, context.getResources().getDisplayMetrics()));
    }

    void setNumRowsColumns(int numColumns, int numRows) {
        this.numColumns = numColumns;
        this.numRows = numRows;
    }

    void setRunning(boolean running) {
        this.running = running;
    }


    @Override
    public void run() {
        Canvas canvas;
        while (running) {
            canvas = null;
            try {
                canvas = surfaceHolder.lockCanvas();
                if (canvas == null)
                    continue;
                drawPath(canvas);

            } finally {
                if (canvas != null) {
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }

    private void drawPath(Canvas canvas) {
        canvas.drawColor(Color.WHITE);
        for (int i = 0; i < numColumns; i++) {
            for (int j = 0; j < numRows; j++) {
                drawPixel(canvas, cellsPaint, i, j);
            }

        }
        for (int i = 0; i < numColumns; i++) {
            for (int j = 0; j < numRows; j++) {
                numberSizeAndPosition(i, j);
                drawPixel(canvas, linePaint, i, j);
                canvas.drawText(number, baselineX, baselineY, fontPaint);
            }

        }
    }

    private void drawPixel(Canvas canvas, Paint paint, int i, int j) {
        canvas.drawRect(i * pixelRadius, j * pixelRadius,
                (i + 1) * pixelRadius, (j + 1) * pixelRadius,
                paint);
    }

    private void numberSizeAndPosition(int i, int j) {

        float centerX = (i * pixelRadius) + pixelRadius / 2.0f;
        float centerY = (j * pixelRadius) + pixelRadius / 2.0f;

        Rect bounds = new Rect();
        fontPaint.getTextBounds(number, 0, number.length(), bounds);
        float textWidth = bounds.width();
        float textHeight = bounds.height();

        baselineY = centerY + textHeight * 0.5f;
        baselineX = centerX - textWidth * 0.5f;
    }
}

coloring.xml

...
<ZoomLayout
        android:id="@+id/zoomLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentBottom="true"
        android:scrollbars="vertical|horizontal"
        android:background="@color/colorWhite"
        app:hasClickableChildren="true"
        app:horizontalPanEnabled="true"
        app:maxZoom="9.0"
        app:maxZoomType="zoom"
        app:minZoom="1.0"
        app:minZoomType="zoom"
        app:overPinchable="false"
        app:overScrollHorizontal="false"
        app:overScrollVertical="false"
        app:verticalPanEnabled="true"
        app:zoomEnabled="true">

        <PixelGridSurfaceView
            android:id="@+id/gridSurfaceView"
            android:layout_width="1000dp"
            android:layout_height="1000dp"
            android:layout_centerInParent="true"/>
    </ZoomLayout>
...

With zoom, low quality

0 Answers0