Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

2D Array grid on drawing canvas

I am writing an pixel art app that paints images the user draws on the screen to pixel look. There are two ways to approach it. Either pixelate the image after saving or have a grid before hand so the user draws the pixel image. I don't find anything on the later method. So my issue with the first is drawing a grid where if a cell is touched I would change the color of it. I tried drawing rectangles on a canvas but that was pointless because i couldn't control the cells.

I was thinking about nested for loops that creates a bitmap at each cell?

like image 224
user3856296 Avatar asked Jul 19 '14 16:07

user3856296


2 Answers

public class PixelGridView extends View {


//number of row and column 

    int horizontalGridCount = 2;


    private Drawable horiz;
    private Drawable vert;
    private final float width;



    public PixelGridView(@NonNull Context context) {
        this(context, null);
    }

    public PixelGridView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        horiz = new ColorDrawable(Color.WHITE); horiz.setAlpha(160);
        vert = new ColorDrawable(Color.WHITE); vert.setAlpha(160);
        width = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0.9f, context.getResources().getDisplayMetrics());
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        horiz.setBounds(left, 0, right, (int) width);
        vert.setBounds(0, top, (int) width, bottom);
    }





    private float getLinePosition(int lineNumber) {
        int lineCount = horizontalGridCount;

            return (1f / (lineCount + 1)) * (lineNumber + 1f);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
       // drawTask.start();
        int count = horizontalGridCount;
        for (int n = 0; n < count; n++) {
            float pos = getLinePosition(n);

            // Draw horizontal line
            canvas.translate(0, pos * getHeight());
            horiz.draw(canvas);
            canvas.translate(0, - pos * getHeight());

            // Draw vertical line
            canvas.translate(pos * getWidth(), 0);
            vert.draw(canvas);
            canvas.translate(- pos * getWidth(), 0);
        }
        //drawTask.end(count);
    }
}

and in your main activity:

//inside on create method

        val myView = PixelGridView(this)

        id_frame.addView(myView)

id_frame is frame layout in xml

example

like image 165
Rohit Singh Avatar answered Oct 10 '22 11:10

Rohit Singh


The following is just a simple, illustrative example. It is not optimized, implements no exception handling, etc.

public class PixelGridView extends View {
    private int numColumns, numRows;
    private int cellWidth, cellHeight;
    private Paint blackPaint = new Paint();
    private boolean[][] cellChecked;

    public PixelGridView(Context context) {
        this(context, null);
    }

    public PixelGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
        blackPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    }

    public void setNumColumns(int numColumns) {
        this.numColumns = numColumns;
        calculateDimensions();
    }

    public int getNumColumns() {
        return numColumns;
    }

    public void setNumRows(int numRows) {
        this.numRows = numRows;
        calculateDimensions();
    }

    public int getNumRows() {
        return numRows;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        calculateDimensions();
    }

    private void calculateDimensions() {
        if (numColumns < 1 || numRows < 1) {
            return;
        }

        cellWidth = getWidth() / numColumns;
        cellHeight = getHeight() / numRows;

        cellChecked = new boolean[numColumns][numRows];

        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.WHITE);

        if (numColumns == 0 || numRows == 0) {
            return;
        }

        int width = getWidth();
        int height = getHeight();

        for (int i = 0; i < numColumns; i++) {
            for (int j = 0; j < numRows; j++) {
                if (cellChecked[i][j]) {

                    canvas.drawRect(i * cellWidth, j * cellHeight,
                                    (i + 1) * cellWidth, (j + 1) * cellHeight,
                                    blackPaint);
                }
            }
        }

        for (int i = 1; i < numColumns; i++) {
            canvas.drawLine(i * cellWidth, 0, i * cellWidth, height, blackPaint);
        }

        for (int i = 1; i < numRows; i++) {
            canvas.drawLine(0, i * cellHeight, width, i * cellHeight, blackPaint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            int column = (int)(event.getX() / cellWidth);
            int row = (int)(event.getY() / cellHeight);

            cellChecked[column][row] = !cellChecked[column][row];
            invalidate();
        }

        return true;
    }
}

Here's a simple Activity for demonstration:

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        PixelGridView pixelGrid = new PixelGridView(this);
        pixelGrid.setNumColumns(4);
        pixelGrid.setNumRows(6);

        setContentView(pixelGrid);
    }
}
like image 26
Mike M. Avatar answered Oct 10 '22 12:10

Mike M.