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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24842550/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 15:09:04  来源:igfitidea点击:

2D Array grid on drawing canvas

javaandroidbitmapandroid-canvas

提问by user3856296

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?

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

采纳答案by Mike M.

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 Activityfor demonstration:

这里有一个简单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);
    }
}

回答by Kiradien

One available option is to look into using the Android Gridviewas 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.

一种可用的选择是考虑使用Android Gridview作为绘图网格;我自己没有测试过这个,但是如果你用你想要的像素尺寸在每个单元格中创建一个要触摸的对象,你应该能够通过保存变量来创建一个基本的像素艺术应用程序。

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

请注意,网格视图单元格根据其内容调整大小,如如何在 Android 网格视图中设置单元格大小中所述?

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-19202is generally the best place to start and pull what you need from it.

此外,在绘制事物时,有许多不同的处理方法,但是请遵循指南或教程,例如http://code.tutsplus.com/tutorials/android-sdk-create-a-drawing-app- touch-interaction--mobile-19202通常是开始并从中提取所需内容的最佳位置。

Good luck!

祝你好运!

回答by Rohit Singh

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_frameis frame layout in xml

id_frame是 xml 中的框架布局

example

例子

回答by Hitesh Sahu

This view class will draw grid of equidistance lines in Canvas based on how much GAP_WIDTH_DP is allocated

该视图类将根据分配的 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;

        }

    }
}