What I want to do is to click a space on the screen, get the coordinates and paint the image here. I did this using paintIcon and mouseListener in eclipse but how to do the same thing in android studio? Thanks!
public static Game game = new Game();
public Control(){
this.setLayout(null);
this.setBounds(0, 0, 780, 780);
addMouseListener(this);
}
public void paint(Graphics g){
setBackground(Color.GREEN);
board.paintIcon(this, g, 0, 0);
for(int i = 0; i < 19; i++){
for(int j = 0; j < 19; j++){
if(game.gameBoard.board[i][j] != 'E'){
if(game.gameBoard.board[i][j] == 'B'){
black.paintIcon(this, g, j * 40, i * 40);
}
if(game.gameBoard.board[i][j] == 'W'){
white.paintIcon(this, g, j * 40, i * 40);
}
}
}
}
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
mouseX = e.getX();
mouseY = e.getY();
int targetX = mouseX / 40;
int targetY = mouseY / 40;
game.move(targetX, targetY);
repaint();
}
In Android you use a different system than in "Java"(you know Android is Java), for instance as is clear from your code you do not have a Mouse but a Touch event.
The first thing you should do is to study this official link that explains the concept of Canvas. Then you will learn how to integrate the "tap" into your app that is instead this official link
This is an excellent post to learn ho to do it.
You begin extending the View and overriding the method onDraw(Canvas canvas) then you need to override a listener that say you when the user clicked the screen onTouchEvent(MotionEvent event) usually there are three motion events you want to cover MotionEvent ACTION_DOWN(you tap and the screen recognizes the X,Y coordinates, that is the one you need),ACTION_MOVE(if you drag your finger maintaining pressure on the screen) and ACTION_UP(when you release your finger)
Just remember you need to call invalidate() if you have an animation or something changes on the screen. Basically is a "forced" call to the "onDraw" method. On the basis of the three links I sent you can cover all thebasis of the 2d graphics in Android that is a bit different by Java because of the different features but also the Android dependency on the specific SDK classes
what I want to do is to click a space on the screen, get the coordinates and paint the image here
Here is an example of how you can obtain that in Android instead of "just" Java, please see the notes comments I did below with the double slashes //
public class YourBoard extends View {//EXTENDS VIEW this is important because you override methods
Drawable editIcon = getResources().getDrawable(R.drawable.icon);
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.background);
float xPos = 0;
float yPos = 0;
public YourBoard (Context context) {//HERE THE CONSTRUCTOR YOU CAN INITIALIZE THINGS HERE
super (context);
}
#Override
protected void onDraw (Canvas canvas) {//This was your paint(Graphics g)
super.onDraw(canvas);
canvas.save();
canvas.drawBitmap(mBitmap, 0, 0, null);
canvas.translate(xPos, yPos);
editIcon.draw(canvas);
canvas.restore();
}
#Override
public boolean onTouchEvent (MotionEvent event) {//THIS WAS YOUR MOUSE LISTENER
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :
xPos = event.getX();
yPos = event.getY();
invalidate();//NOTICE THE INVALIDATE I MENTIONED
break;
}
return true;
}
}
}
Related
Hi I'm developing a game in android, for that I have draw 8*8 rectangles using canvas.drawRect() method, now what I need is when user touches on any of the rect, its color has to change. For this I have done as follows.
public boolean onTouchEvent(final MotionEvent event) {
handleTouches(event.getX(), event.getY());
return false;
}
public void handleTouches(float x, float y) {
xLocTouch = (int) x;
yLocTouched = (int) y;
outerLoop: for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (GameView.tiles[i][j].rect.contains(xLocTouch, yLocTouched)) {
touched = true;
xTouched = i;
yTouched = j;
break outerLoop;
}
}
}
}
protected void onDraw(Canvas canvas) {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
canvas.drawRect(tiles[i][j].rect, paint);
canvas.drawRect(tiles[i][j].rect, p);
if(touched && i==xTouched && j == yTouched) {
Paint touchedColor = new Paint();
touchedColor.setColor(Color.BLUE);
canvas.drawRect(tiles[i][j].rect, touchedColor);
}
}
}
This code is works properly, but the problem is when I touch first time that rect's color changes, but for the second touch it erases old touches position. I need to keep all the touched rect as different color. Is there any way for this?
A Boolean array that tracks the touch state of each rectangle would do the trick. I can't see the external code, but this could be an additional field in your GameView class, and updated appropriately in your handleTouches method.
A perhaps less efficient, less elegant solution would be to just not set the color of the rectangle in onDraw if it's already Color.BLUE (modify your if statement appropriately). You can get the color of the touched pixel using this SE answer, but be forewarned you have to first turn the canvas into a bitmap in order to sample the color (hence the inefficiency).
As is, 100 pink circles (same bitmap) appear scattered randomly over the phone screen (as is supposed to). When I tap one of the circles, that circle should disappear (change to the background color). I think I have a fundamental misunderstanding of Android and View in general.I think I have a couple obvious errors (that are not so obvious to me, but I've been staring at it so long that I figured I needed some help). Currently, the screen shows the random circles but nothing more. Touching the screen does nothing. Any better ideas to make the circles disappear? It recently reorganized all the bitmaps when you touched it, but I did something recently, and it stopped. The bitmap is 30px by 30px.
public class DrawV extends View {
private Bitmap bit_dot;
private int width;
private int height;
public int[] width_array = new int[100];
public int[] height_array = new int[100];
private View dotV = (View)findViewById(R.id.bigdocpic);//bitmap
Random rand = new Random();
public DrawV(Context context) {
super(context);
bit_dot = BitmapFactory.decodeResource(getResources(), R.drawable.dot_catch);
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
width = metrics.widthPixels;
height = metrics.heightPixels;
}
#Override
//draws 100 randomly placed similar bitmaps
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int height_dimension;
int width_dimension;
for (int i = 0; i < 100; i++){
height_dimension = rand.nextInt(height) + 1;
width_dimension = rand.nextInt(width) + 1;
canvas.drawBitmap(bit_dot, width_dimension, height_dimension, null);
width_array[i] = width_dimension;//
height_array[i] = height_dimension;//
}
}
#Override
public boolean onTouchEvent(MotionEvent event){
Paint p = new Paint();
p.setColor(Color.WHITE);
Path path = new Path();
Canvas c = new Canvas();
for (int i = 0; i < 100; i++){
if ((event.getX() == width_array[i]) && (event.getY() == height_array[i]))
c.drawCircle(width_array[i], height_array[i], 15, p);
}
invalidate();
return false;//false or true?
}
//set visibility of bitmap to invisible
public boolean onTouch(View v, MotionEvent event) {
dotV.setVisibility(View.INVISIBLE);
invalidate();
return false;//false or true? not understanding
}}
Help?
Your onTouchEvent isn't really doing anything important as-is, and you don't have the concept of a circle object.
onDraw should really be drawing these circles from an array/list created earlier - say a List<MyCircles> or MyCircles[]. On touch, you could iterate through all of your circles until you find one that is closest, remove that circle from the array or list, then invalidate.
The reason nothing is happening at all is even though you're drawing those circles again in onTouchEvent, you're redrawing everything yet again in onDraw (invalidate() calls draw/onDraw).
Ideally, create your list of circles in your initializer, draw them in onDraw, and update them in onTouch (That is, delete). There may be a simpler way to do this but this is, at the very least, a more proper approach.
I am trying to check collisions between lines and a circle, if the circle hits the line, it would work change a boolean to true and once its not touched, it would change it back to false. I am using canvas and surface view.
Here is my code for checking collision which didn't work and ended up in error:
#Override
public void run() {
while(runnable)
{
if(!holder.getSurface().isValid()){
continue;
}
Canvas mCanvas = holder.lockCanvas();
update(mCanvas);
values = new Values(mCanvas);
createPaints();
drawBackground(mCanvas);
drawObjects(mCanvas);
holder.unlockCanvasAndPost(mCanvas);
}
}
Now the collision is processed in the update:
private void update(Canvas c) {
ball.update(c, checkLinesCollision(values.level1, ball.getX(), ball.getY()));
//takes a canvas, and a boolean
}
boolean checkLinesCollision(float[] f,float x,float y){
int c = 0;
for(int i = 0; i < f.length; i+=4){
float x1 = f[i];
float y1 = f[i+1];
float x2 = f[i+2];
float y2 = f[i+3];
if (x> x1 && x<x2 && y>y1 && y>y2){
c++;
}
}
if(c>0){return true;}else{return false;}
}
the values for the level
float yLow = c.getHeight()-c.getHeight()/4;
level1 = new float[]{0,yLow,c.getWidth(),yLow,
40,c.getHeight()/2,300,c.getHeight()/2};
ball update function:
public void update(Canvas c, boolean b) {
if(b){
dy=-dy;
b = false;
}
y -= dy;
dy--;
}
Now according to the logcat the problem is in the main update function.
I think that I am using the wrong function, what can I do to fix it?
Thanks!
I have found the solution. Apparently the problem was with the float array; in my app, i declared the float array in a constructor. After a long time of researching on the web and rechecking my logcat, i found that you cannot declare an array in the constructor. all i did was moving the float array outside of the constructor and everything was alright, even though i found the solution, i am not sure why you cannot declare it in the constructor..
I want to make a small app. You will touch the screen and draw something and it will list points you pass and draw small green 3x3 rectangles for each fifth point. I use onTouchEvent for listing points using TextView and send it to setContentView. However, I have problem in drawing. I checked examples for drawing (onDraw) but I am not able to get it working for both printing point plus drawing green dots. Any help would be great, thanks.
Here you are, a quick sample of drawing on SurfaceView.
public class FunPanel extends SurfaceView {
class Point {
int X;
int Y;
public Point() {
X = Y = -1;
}
}
private ArrayList<Point> mPoints = new ArrayList<Point>();
private Point mCurPoint = new Point();
private Bitmap mBitmap = ....// your desired image
#Override
public void doDraw(Canvas canvas) {
if( !(mPoints.size() % 5) ) {
canvas.drawBitmap(mBitmap, mCurPoint.X, mCurPoint.Y, null);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mCurPoint.X = (int) event.getX() - mBitmap.getWidth() / 2;
mCurPoint.Y = (int) event.getY() - mBitmap.getHeight() / 2;
mPoints.add(mCurPoint);
return super.onTouchEvent(event);
}
}
It's not entirely clear what you're trying to do, but have a look at this It should get you started in the right direction. Basically extend a View and override the onDraw(Canvas) to draw the Rectangles and override the onTouchEvent(MotionEvent) to grab the touch points from the screen.
I have displayed images from resource in my application as rows and columns randomly.
From those rows and columns i would like to swap the two images when user click on beside of images only.The following code will display the images in rows and columns as randomly.
private void rand(int imagesList[][])
{
Random generator = new Random();
int temp;
for (int i = 0; i < MAX_ROWS; i++)
for(int j = 0; j < MAX_COLS; j++)
{
int randRowPos = generator.nextInt(MAX_ROWS);
int randColPos = generator.nextInt(MAX_COLS);
temp = imagesList[i][j];
imagesList[i][j] = imagesList[randRowPos][randColPos];
imagesList[randRowPos][randColPos]= temp;
}
}
by using the above code i have displayed images as rows and columns.
Here how can i swap the two beside images from rows and columns?
please any body help me.....
I don't have privilege to add comment, so I am posting this as answer.
What do you mean by beside images ?
Is it when user will click on one image , it should get swapped with the image next to it ?
Can you also share the code where you have binned these images to view or any adapterview ?
EDIT :
I too had similar situation at the times when absolute layouts were alive.
What I had done is as follows:
Class:
public class PlayScreen extends Activity implements OnTouchListener
private Panel mainPanel; // Panel for out display
boolean firstClick = false;
OnCreate :
main = new Panel(this);
// Display the panel (calls the ondraw and updates the display)
setContentView(main,new ViewGroup.LayoutParams(screenwidth,screenheight));
// Listen for touchevents on the panel
main.setOnTouchListener(this);
Panel :
class Panel extends View
{
/*
* Init a Panel to draw on and a paint to paint with
*/
Paint mBitmapPaint;
public Panel(Context context)
{
super(context);
mBitmapPaint = new Paint();
}
#Override
protected void onDraw(Canvas canvas)
{
drawImages(canvas);
}
}
drawImages :
private void drawImages(Canvas canvas)
{
for(int i = 0; i<MAX_ROWS; i++){
for(int j=0; j<MAX_COLS; j++)
{
int xpos = j*bmp.getWidth()+j*2;
int ypos = i*bmp.getHeight()+i*2;
bmp = BitmapFactory.decodeResource(mContext.getResources(), items[i][j],opts);
canvas.drawBitmap(bmp,xpos,ypos,mBitmapPaint);
clickzonex.add(xpos);
clickzoney.add(ypos);
clickzonei.add(i);
clickZonej.add(j);
}
}
}
OnTouch:
onTouch(View v, MotionEvent event) :
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
// imply logic
x = (int) event.getX();
y = (int) event.getY();
for(int i = 0; i < clickzonex.size();i++)
{
if((x>clickzonex[i]) && (x<(clickzonex[i]+ bmp.getwidth())) && (y>(clickzoney[i])) && (y<(clickzoney[i]+bmp.getHeight())))
{
// we have a click in a zone so we get the card-number in that zone
if(firstClick == false)
{
itemAti=clickzonei[i];
itemAtj = clickzonej[i];
firstclick = false;
}
else
{
FirstItemToSwap = items[clickzonei[i]][clickzonej[i]];
SecondItemToSwap = items[itemAti][itemAtj];
// Now do the swaping using any algo you like.
main.postInvalidate();
firstclick = true;
}
break;
}
}
return true;
}
else
{
return false;
}
I have just tried to show you the logic using my own example and mixing it with your code. The main point is that in ondraw method just call drawcanvas and on touch just swap the items[][] and call postinvalidate method of Panel class.
I had to do something like this once. I just swapped the image references in the array and did a redraw(invalidate()) on the whole thing.
void swap(int x1, int y1, int x2, int y2) {
// swap items[x1][y1] and items[x2][y2]
........
invalidate();
}
Not quite sure what you are actually asking here, so please try to clarify the question.
One approach could be to use a ViewAnimator as a parent for each of the drawable ImageViews.
<ViewAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/slideshow_animator"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
Then once you capture the event that should trigger the swap, you can use the ViewAnimator to swap the View (in your case ImageView) it uses. You can even easily add an animation effect
http://developer.android.com/reference/android/widget/ViewAnimator.html