2D Array grid on drawing canvas

2019-01-23 00:13发布

问题:

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?

回答1:

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


回答2:

One available option is to look into using the Android Gridview as the drawing grid; I have not tested this myself, however if you create an object to be touched in each cell with your desired pixel dimensions, you should be able to create a rudimentary Pixel Art application by saving the variables.

Note, grid view cells are sized based on their contents, as noted in How to set a cell size in Android grid view?

Also, when it comes to drawing things, there are many different ways to handle it, however following a guide or tutorial such as http://code.tutsplus.com/tutorials/android-sdk-create-a-drawing-app-touch-interaction--mobile-19202 is generally the best place to start and pull what you need from it.

Good luck!



回答3:

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

    [enter image description here][1]val myView = PixelGridView(this)

    id_frame.addView(myView)

id_frame is frame layout in xml