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
2D Array grid on drawing 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 Activity
for 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_frame
is frame layout in xml
id_frame
是 xml 中的框架布局
回答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;
}
}
}