How to detect when a drawable is touched - android

I'm working on an app that has a canvas with a bunch of little images that the user can drag around, and a "box" that the user will drag from to create new image objects or drag an existing image to it, and it will remove it.
What is the best way to detect if the user has touched an area, or an image on the screen? The first thing that comes to mind is obviously comparing the touch coordinates with each object's coordinates, but that seems a little cumbersome. Is there a better, or built in way?
Thanks

It depends on how complicated your interface is, but basically if you override onTouchEvent that will get you the coordinates you were referring to.
In order to find what was touched, without going through every object, you could find ways to simplify this, such as by splitting your screen into perhaps 8 grids, and know which grid(s) every object is in, so that when the screen is touched then you can find the objects that may be in that grid, and so you will have fewer items to look through.
For a brief answer on how to use onTouchEvent you can look at:
http://androidforums.com/android-games/210019-touch-event-image-made-canvas.html

The View class in Android has an onClickListener which you can use to detect when the user clicks on a View. If you implement your 'images' (as you call them) as Views you can simply add a click listener to each to find which view was clicked. Add the listener like this:
// Get a reference to the view from xml (or if you
// have created it dynamically, just use that)
View imageView = findViewById(R.id.my_view);
imageView.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// Do stuff with view (the View v that is passed is the View that was touched)
doStuff(v);
}
});

Related

Android detect tap or move - for chess piece interaction

I want to implement touch listener that detects
Click/tap on chess piece in order to select ot
Swipe/move of chess piece immediately.
How to do it?
Unfortunately, I am not sure what you mean by a "chess piece", but let's assume that the board is a view in the background, and inside you have inner views which are chess pieces.
To achieve the select/unselect given piece effect you should add a simple View.OnClickListener interface to your view. Each of your pieces should have a view class and some data connected to it (like a position, a type of piece, id, etc.). After clicking the piece update the state of some global variable, for example, selectedPiece with an ID assigned to a given piece. You should also change the UI of a given piece, for example change the border to show the selected piece to a user. Then after clicking a new field for moving the piece you should update the UI by moving your piece view to an appropriate position. Also, the data of a piece or a game should be updated - depending on the place of storing the pieces' positions.
For this you should implement the drag&drop feature which is described here: https://www.tutorialspoint.com/android/android_drag_and_drop.html. You should determine the places where the user can move a piece and in case of dropping the piece in the wrong place, cancel the move and go with the piece to a start position.
Basic response to touch events using event.x and event.y works:
https://developer.android.com/develop/ui/views/graphics/opengl/touch
https://suragch.medium.com/how-touch-events-are-delivered-in-android-eee3b607b038
...more info:
Android Touch Listener

Android - Waiting till view is laid on screen without any guesswork

I am creating a TutorialManager that handles all the user tutoring for app usage.
I have a ViewGroup that adds views to itself including a GridView that is filled with items after onMeasure() is called.
I am calling TutorialManagers method that's supposed to perform an action on the gridview but it needs to know when the gridview is filled in order to use any of it items
I added a callback method on the ViewGroup that is called right after all the view have been added
The problem is that the TutorialManager needs to know the X and Y coordinate of the views in order to highlight them using ShowCaseView
I've added a workaround using postDelayed(action, 100); which seems to work on my handset but what if on some device the view layout takes more than 100ms? It'll screw up the whole tutoring system.
I can't figure out any other way than creating a custom view that has a callback method which is called after the views position is known.
What's the common way of handling the issue that the laying view on screen is happening asynchronously?
You can try using an OnGlobalLayoutListener which fires whenever there is a layout change (Ie, your GridView and children have been added and measured. So where ever you initialize the GridView do this:
LayoutListener mLayoutListener = new LayoutListener;
mGridView.getViewTreeObserver().addOnGlobalLayoutListener(mLayoutListener);
private class LayoutListener implements OnGlobalLayoutListener {
#Override
public void onGlobalLayout() {
...Do your calculations here...
mGridView.getViewTreeObserver().removeOnGlobalLayoutListener(this); //If you only need this to execute once.
}
}
Note this will be called quite often. I'd recommend removing as soon as you don't need it.

Drawing custom view at runtime

Hi I'm having trouble understanding how to draw a custom view at runtime. For simplicity sake, say I have a custom view (Box) that extends the View class, and basically all it does is create a square which is configured to do in my onDraw() method. Now I want to be able to draw this custom view in an activity depending on if the user clicks a button on the activity.
So if the user clicks the button once, one box is drawn, clicks again another box is drawn maybe 10 pixels down etc. I searched for a solution but all I can find is people using a pre-made xml with the view and then using an inflator but I dont want to have a pre drawn box if the user hasn't pressed the button.
Also another quick question: When is onDraw() called or do I have to explicitly call
Box box = new Box();
box.onDraw(canvas);
Eclipse says that's a suspicious call, I agree.
To make a custom View you have to extend View class and override onDraw method. Then when you want to draw this view you have to add it to your view hierarchy. This is as simple view.add(new Box()), where view is your root view, this way Android system would invoke onDraw method by itself on every rendering cycle. For more information refer to official documentation.

Click button and that button waits for second button on activity to be pushed. Game board. How to accomplish?

I wasn't exactly sure how to briefly paraphrase my question in the title, so please forgive me as I never post questions until now. I am new to Android/Java for starters, as the main language I have used so far is C++. My question is that I have a game board layout (similar to checkers/chess). When it is the user’s turn, they are to click the piece they want to move on the board and then the blank location they would like to move it to. How can this be accomplished? Up until this point I have implemented onClickListeners that never rely on another button in the activity to be clicked afterwards and wait for the user to do so.
Brief information on my project currently (unsure if needed):
I am currently using an ImageButtons array (of size 36) and a two dimensional integer array to hold the information of each of the buttons, as they are displayed in a GridLayout in a 6 X 6 fashion. In my MainActivity class I have implemented the OnClickListener and created a switch statement in onClick() for each of the button ids.
I am not sure how much more information is needed on my code for help or if it is completly irrelevant. I tried looking on the internet before choosing to ask finding nothing. It is always possible though I was not correctly phrasing my issue. Thank you to everyone in advance!!! :)
Without any code it is hard to say what you are doing wrong/right. But if you have the images stored in an Array then when they click on one image that can be put into a variable which is used to place on the View that they click on next. If you have a more precise question then please post relevant code and error messages from what you have tried, if any. Hope this helps
after a user click's a piece store that info in a member variable like a current piece and then on second click check if the previous is not null, the current clicked space is empty and start your animation by posting to a runnable implementation. this is the simple logic part. where are you having problem exactly
To optimize your code to change images what you can do is custom animations on the imageview. You can change the position of the image with animation without having to create or store an image. (If you use images bitmap a lot you have a very good chance of running into OutOfMemory exceptions and this will happen on top end phones very easily
How to Move a Button and Change the Button Image
I would put a single Button on every GridView position.
Then, I would use button.setBackground() and button.setVisibility() to display and hide the buttons with various images. In this way, the buttons will appear to move, but you are really just displaying a different button.
I recommend this because it is easier to change the visibility and image properties of a button than it is to actually move the button, although both methods are possible.
You will maintain a 1 dimensional array of images[n] and a 2 dimensional array of buttons[6,6].
As an example, suppose you want to move image[5] from grid position (1,2) to position (3,4):
// Hide the button at (1,2);
button[1,2].setVisibility(Button.INVISIBLE);
// Display the button at (3,4) with image #5.
button[3,4].setBackground(image[5]);
button[3,4].setVisibility(Button.VISIBLE);
Additionally, if your button images are stored in your resources, you could efficiently use button.setBackgroundResource(R.drawable.image-5-id);
The instructions above discuss how to move a Button, but now how to trigger one Button to be moved and then trigger the location into which to move the Button.
To accomplish this, you will have to define two states, such as:
private final static int STATE_PICK_BUTTON = 0;
private final static int STATE_PICK_LOCATION = 1;
private int state;
Initialize state = STATE_PICK_BUTTON;
When the system is in the first state STATE_PICK_BUTTON, all button
presses identified in your onClick() function memorize a grid
position to move from, and in some cases transition the system into
the second state: STATE_PICK_LOCATION.
When the system is in the second state STATE_PICK_LOCATION, all
button presses actually move the button from the memorized grid
position to the grid position of this button press.
Of course, you will have to do all sorts of error checking to make
sure you are allowed to move a button before triggering the state
transition.
Finally, the above suggestion may not work, because it may be impossible to click an invisible button. If this is the case, instead of changing the visibility of Buttons in empty grid locations, leave all the buttons Button.VISIBLE and use a fully transparent Button image for the buttons representing empty grid spaces.

Delegating touch events

lets assume i have a LinearLayout , horizontal that contains a TextView and afterward a Spinner or another clicable TextView or an EditText.
I want that a click on any part of the line (if the layout has padding then the layout area as well!) will deleage the onTouchEvent to the Right part of the layout (EditText, TextView or Spinner) as if they were clicked themselves.
Doing it myself will require me either create my own versions of those widgets (too much work for little effect :-( ) or putting listeners on many items for the touch events and delegate them. I'm pretty sure Android has some methods or properties to do that, just didn't see any so far.
Can anyone help ?
I had to do something similar to this a while back, and ended up writing my own delegate and assigning the onclicklisteners for all of the components in my layout to that delegate. It's cumbersome, but not too painful to implement, and it turned out well.
Point being, I didn't see anything in the API to handle that sort of thing. The only other thing I might offer is that it is certainly possible to assign an onclicklistener to a component and simply send the event to another component's onclicklistener like so:
thislinearlayout.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getOtherComponent().performClick();
}
});
You can do the same thing with touch listeners.

Categories

Resources