I have the following problem.
I am trying to code a Tetris Game for Android. Therefore I need to put a Grid on the GameView (a self coded class, which extends the SurfaceVieW).
Unfortunately I do not know how to draw the Grid on the GameView.
I already implemented a Grid class, which sets the width and height of the rows and columns.
My Grid Class
package com.example.tetris;
import android.content.Context;
import android.graphics.Paint;
import android.widget.GridView;
public class Grid extends GridView
{
private int rowsWidth;
private int columnsHeight;
private int rowsNum;
private int columnsNum;
private Paint gridcolor;
private GameView gameview;
public Grid(Context context)
{
super(context);
}
public void drawGrid(GameView gameview)
{
this.gameview = gameview;
rowsWidth = gameview.getWidth() / 10;
rowsNum = gameview.getWidth() / rowsWidth;
columnsHeight = gameview.getHeight()/rowsWidth;
columnsNum = gameview.getHeight() / columnsHeight;
setHorizontalSpacing(1);
setColumnWidth(rowsWidth);
setNumColumns(columnsNum);
}
}
My GameView Class
package com.example.tetris;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.GridView;
public class GameView extends SurfaceView {
private SurfaceHolder surfaceHolder;
private Tetriminos[] tetriminos[];
private GridView grid;
public GameView(Context context)
{
super(context);
final GameLoopThread gameloop = new GameLoopThread(this); // warum er final erzwingt, ka
surfaceHolder = getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback()
{
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
gameloop.setRunning(true);
gameloop.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
gameloop.setRunning(false);
}
});
}
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
drawBorders(canvas);
// grid.drawGrid(this);
}
public boolean onTouchEvent(MotionEvent event) {
return false;
}
public void drawBorders(Canvas canvas)
{
int borderwidth = 10;
int screenWidth = getWidth();
int screenHeight = getHeight();
Paint bordercolor = new Paint();
bordercolor.setARGB(255, 236, 27, 36);
canvas.drawRect(0, 0, borderwidth, getHeight(), bordercolor);
canvas.drawRect(0, getHeight()-borderwidth, getWidth(), getHeight(), bordercolor);
canvas.drawRect(getWidth()-borderwidth, 0, getWidth(), getHeight(), bordercolor);
canvas.drawRect(0, 0, getWidth(), borderwidth, bordercolor);
}
}
Related
I want to draw black dots when I touch the screen and its work, but when I start the activity for the first time the screen is black and after the touch is going white.I want to be white from the beggining. How can I fix it? Here is my code:
package com.inveitix.android.clue.ui.views;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
/**
* Created by Tito on 3.2.2016 г..
*/
public class DrawingView extends SurfaceView {
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas canvas;
int width;
int height;
private SurfaceHolder surfaceHolder;
private WindowManager wm;
public DrawingView(Context context) {
super(context);
init();
}
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DrawingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
surfaceHolder = getHolder();
wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
getScreenSize();
}
private void getScreenSize() {
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
width = size.x;
height = size.y;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (surfaceHolder.getSurface().isValid()) {
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
canvas.drawCircle(event.getX(), event.getY(), 10, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
return false;
}
}
In your init method add:
holder.addCallback(new SurfaceHolder.Callback() {
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void surfaceCreated(SurfaceHolder holder) {
canvas = holder.lockCanvas();
canvas.drawColor(Color.WHITE);
holder.unlockCanvasAndPost(canvas);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
});
change this
paint.setColor(Color.BLACK);
to
paint.setColor(Color.WHITE);
in your init() put this
paint.setColor(Color.WHITE);
Hello :) I created a yellow canvas with a ball on it, now i'm trying to move the ball but I don't know how, it's the first time i'm using an accelerometer and it's my first time using canvas and draw.. So can you help me moving it?
Here is my code so far:
package com.example.theball;
import android.support.v4.widget.DrawerLayout.LayoutParams;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.SensorEvent;
import android.os.Bundle;
import android.view.Display;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class MainActivity extends Activity {
private int c = Color.YELLOW;
private Canvas g;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_main);
draw();
}
#SuppressWarnings("deprecation")
public void draw ()
{
Display display = getWindowManager().getDefaultDisplay();
int width = display.getHeight();
int height = display.getWidth();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
g = new Canvas(bitmap);
g.drawColor(c);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
g.drawCircle(50, 10, 25, paint);
ImageView imageView = new ImageView(this);
imageView.setImageBitmap(bitmap);
RelativeLayout layout = new RelativeLayout(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
layout.addView(imageView, params);
layout.setBackgroundColor(Color.BLACK);
setContentView(layout);
}
public void onSensorChanged(SensorEvent event)
{
}
}
SOLVED: here is the new code, thanks to someone here from stackoverflow:
package com.example.theball;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ImageView;
#SuppressWarnings("deprecation") public class MainActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private Sensor accelerometer;
private long lastUpdate;
AnimatedView animatedView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public static int x;
public static int y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
lastUpdate = System.currentTimeMillis();
animatedView = new AnimatedView(this);
setContentView(animatedView);
}
#Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
x -= (int) event.values[0];
y += (int) event.values[1];
}
}
public class AnimatedView extends ImageView {
static final int width = 50;
static final int height = 50;
public AnimatedView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xffffAC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
#Override
protected void onDraw(Canvas canvas) {
mDrawable.setBounds(x, y, x + width, y + height);
mDrawable.draw(canvas);
invalidate();
}
}
}
When I try to run this code I get an error in the view activity stating that void is an invalid type for the function "protected void onDraw(Canvas canvas)".
This is the main activity
package com.example.crazyeights;
import android.app.Activity;
import android.os.Bundle;
public class CrazyEightsActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
CrazyEightsView myView = new CrazyEightsView(this);
setContentView(myView);
}
}
This is the View activity
package com.example.crazyeights;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class CrazyEightsView extends View
{
private Paint redPaint;
private int circleX;
private int circleY;
private float radius;
public CrazyEightsView(Context context)
{
super(context);
redPaint = new Paint();
redPaint.setAntiAlias(true);
redPaint.setColor(Color.RED);
circleX = 100;
circleY = 100;
radius = 30;
This is where the error occurs.
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawCircle(circleX, circleY, radius, redPaint);
}
}
}
Move onDraw out of the constructor.
public CrazyEightsView(Context context)
{
super(context);
redPaint = new Paint();
redPaint.setAntiAlias(true);
redPaint.setColor(Color.RED);
circleX = 100;
circleY = 100;
radius = 30;
} // <-- put } here
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawCircle(circleX, circleY, radius, redPaint);
}
//} <-- used to be here
I'm using SurfaceView for driving sprites.
For performance, I only redraw canvas partially, so I lock the Canvas with dirty rect. In general, it works good, but SurfaceView lost initial drawing in surfaceCreated method.
I suppose it's related to SurfaceView internal double buffering.
Any ideas how to correctly initialize SurfaceView?
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class TestView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = TestView.class.getSimpleName();
SurfaceHolder holder;
public TestView(Context context) {
super(context);
holder = getHolder();
holder.addCallback(this);
setFocusable(true);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
drawBg();
drawPoint(100, 120);
}
private void drawBg() {
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
synchronized (holder) {
canvas.drawRGB(255, 128, 128);
Paint paint = new Paint();
paint.setColor(Color.GREEN);
canvas.drawCircle(100, 100, 10, paint);
}
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
private void drawPoint(int x, int y) {
int radius = 10;
Rect dirty = new Rect(x - radius, y - radius, x + radius, y + radius);
Canvas canvas = null;
try {
canvas = holder.lockCanvas(dirty);
synchronized (holder) {
Paint paint = new Paint();
paint.setColor(Color.BLUE);
canvas.drawCircle(x, y, radius, paint);
}
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
drawPoint((int) event.getX(), (int) event.getY());
}
return super.onTouchEvent(event);
}
}
My custom view does not display entirely. Please see my screenshot:
And the source code
package com.dots;
import android.graphics.Color;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class Dots1Activity extends Activity
{
private static final String TAG = "DotsActivity";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
CustomDrawableView view1 = new CustomDrawableView(this, 50, 50, Constants.DOTS_RADIUS, Constants.DOTS_COLOR);
CustomDrawableView view2 = new CustomDrawableView(this, 150, 150, Constants.DOTS_RADIUS, Constants.DOTS_COLOR);
CustomDrawableView view3 = new CustomDrawableView(this, 300, 300, Constants.DOTS_RADIUS, Constants.DOTS_COLOR);
ll.addView(view1, layoutParams);
ll.addView(view2, layoutParams);
ll.addView(view3, layoutParams);
setContentView(ll);
}
}
class CustomDrawableView extends View implements View.OnClickListener{
private Context context;
private int x, y, radius, color;
public CustomDrawableView(Context context, int x, int y, int radius, int color) {
super(context);
this.context = context;
this.x = x;
this.y =y;
this.radius = radius;
this.color = color;
setOnClickListener(this);
}
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
canvas.drawCircle(x, y, radius, paint);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(View.MeasureSpec.makeMeasureSpec(Constants.DOTS_RADIUS*2, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(Constants.DOTS_RADIUS*2, View.MeasureSpec.EXACTLY));
}
public void onClick(View v) {
Toast.makeText(this.context,
x+"-"+y+"-"+radius,
Toast.LENGTH_SHORT).show();
}
}
public interface Constants
{
public static final int DOTS_RADIUS = 50;
public static final int DOTS_COLOR = Color.GREEN;
public static final int NUM_DOTS_ROWS = 5;
public static final int NUM_DOTS_COLS = 5;
public static final int WIDTH_BETWEEN_DOTS = 100;
public static final int HEIGHT_BETWEEN_DOTS = 100;
}
Making the assumption that you don't want the clipping you see in your screenshot. Your problem is that the values you return in onMeasure don't account for your x, y offsets:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(View.MeasureSpec.makeMeasureSpec(Constants.DOTS_RADIUS*2 + x, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(Constants.DOTS_RADIUS*2 + y, View.MeasureSpec.EXACTLY));
}
What exactly do you want to Achieve? if you want to be fullscreen then use the FILL_PARENT flag instead of WRAP_CONTENT at least for the width of your view. also for the height there is a weight parameter that might help even the height of your view. but since its a custom drawing i cant help you further if there are any adjustments needed in your view code. you have to figure that out for yourself.
The radius of each of your "dots" is identical, and this directly translates into the answer you return in onMeasure(). You're changing the x and y location of the center, getting further from the actual View canvas.