绘图画布上的2D阵列网格

时间:2014-07-19 16:33:28

标签: java android bitmap android-canvas

我正在编写一个像素艺术应用程序,用户将在屏幕上绘制的图像绘制成像素外观。有两种方法可以解决它。保存后对图像进行像素化或手头有网格,以便用户绘制像素图像。我在后面的方法上找不到任何东西。所以我的第一个问题是画一个网格,如果一个单元被触摸,我会改变它的颜色。我尝试在画布上绘制矩形但这没有意义,因为我无法控制细胞。

我在考虑在每个单元格中创建位图的嵌套for循环?

4 个答案:

答案 0 :(得分:23)

以下只是一个简单的说明性示例。它没有优化,没有实现异常处理等。

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

这是一个简单的Activity用于演示:

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

答案 1 :(得分:1)

example

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

以及您的主要活动中:

//inside on create method

        val myView = PixelGridView(this)

        id_frame.addView(myView)

id_frame是xml中的框架布局

答案 2 :(得分:0)

一个可用选项是使用Android Gridview作为绘图网格;我自己没有对此进行过测试,但是如果您使用所需的像素尺寸在每个单元格中创建要触摸的对象,则应该能够通过保存变量来创建基本的Pixel Art应用程序。

请注意,网格视图单元格的大小取决于其内容,如How to set a cell size in Android grid view?

中所述

此外,在绘制内容时,有许多不同的方法可以处理它,但是遵循指南或教程(如http://code.tutsplus.com/tutorials/android-sdk-create-a-drawing-app-touch-interaction--mobile-19202)通常是最好的起点和拉动所需的内容。< / p> 祝你好运!

答案 3 :(得分:0)

此视图类将根据分配的GAP_WIDTH_DP量在Canvas中绘制等距线的网格

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;

public class PixelGridView extends View {

    private int screenWidth;
    private int screenHeight;
    public static final int GAP_WIDTH_DP = 62;
    private float GAP_WIDTH_PIXEL;
    private  Paint paint = new Paint();

    public PixelGridView(Context context) {
        super(context);
        init(context);
    }

    public PixelGridView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);

    }

    public PixelGridView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);

    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public PixelGridView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }

    public static float convertDpToPixel(float dp, Context context){
        return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
    }

    public void init(Context context) {

        // set paint color
        paint.setColor(Color.GREEN);

        // get view dimentions
        getScreenDimensions();

    }

    private void getScreenDimensions() {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        screenWidth = displayMetrics.widthPixels;
        screenHeight = displayMetrics.heightPixels;

        //gap size in pixel
        GAP_WIDTH_PIXEL = convertDpToPixel(GAP_WIDTH_DP,  getContext());

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        getScreenDimensions();

    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // draw Horizontal line from Y= 0 -> Y+=Gap... till screen width
        float verticalPosition = 0;

        while (verticalPosition <= screenHeight) {

            canvas.drawLine(0, verticalPosition,
                           screenWidth, verticalPosition, paint);

            verticalPosition += GAP_WIDTH_PIXEL;

        }

        // draw Vertical line from X=0 -> X+=Gap... till screen Height 0|||hor+gap|||W
        float horizontalPosition = 0;

        while (horizontalPosition <= screenWidth) {

            canvas.drawLine(horizontalPosition, 0,
                    horizontalPosition, screenHeight,paint);

            horizontalPosition += GAP_WIDTH_PIXEL;

        }

    }
}