I have a project which i'm required to develop Android game that display a 5*5 table and and image for each player which each one of them can move the image in place inside the 5*5 table.
ex:
Note : I need to know the exact coordinates (or anything relative) so i can save the position in array and move the image to that new place (eg : re-draw it on the new position).
Any ideas ?
Thanks in advance.
Just use a RelativeLayout with 5x5 ImageViews (set to not visible).
And on the images that the user can move to the place, use Drag and Drop.
In onDrag you set the visibility of the image to Gone.
For all ImageView (5x5 Table), you set the onDragListener.
After that, in the overwritten method OnDrop, you can receive the view that is dropped and can determine which drawable to show.
edit:
Oh well, in this case I would use GridView as said in the comments. And make usage of drag and drop. You don't need to attach a DragListener to every image then. You can simply let the GridView listen to the drop events and determine by the x and y where to drop.
Little example (just as a hint)
gameStoneView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
DragShadowBuilder shadowBuilder = new DragShadowBuilder(gameStoneView);
gameStoneView.startDrag(null, shadowBuilder, gameStoneView, 0);
if (dragListener != null) {
dragListener.onDragStart();
}
break;
default:
LOG.v("Motion event reorderIcon: DEFAULT - not action down");
}
return true;
}
});
gridView.setOnDragListener(new OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_LOCATION:
currentY = event.getY();
currentX = event.getX();
break;
case DragEvent.ACTION_DROP:
final Point position = getPositionOfItem(currentX, currentY);
dropItemAt(position);
break;
case DragEvent.ACTION_DRAG_EXITED:
//BORDER DRAGEVENT: ACTION_DRAG_EXITED
viewDraggedOutSide = true;
break;
case DragEvent.ACTION_DRAG_ENDED:
//BORDER DRAGEVENT: ACTION_DRAG_ENDED
if (viewDraggedOutSideList) {
reinsertDraggedItem();
update();
}
viewDraggedOutSideList = false;
return true;
default:
return true;
}
}
});
Related
In a Custom ListView extending Cursoradapter, I need both Listview and image button to get focussed. How to do it?
Implement your own OnTouchListener for ListView which conditional return values. If you return TRUE from onTouch, the system will assume that the onTouch was handled and it won't handle it by itself. If you return FALSE from onTouch, system will assume that the OnTouchListener did not handle the touch events and will do further processing. This way you can manage how the touch / click should work with ImageButton in a ListView.
I don't know what exactly your implementation is. But it may give you a little idea...
boolean pressedImageButton = false;
myListView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(action)
{
case MotionEvent.ACTION_DOWN:
float positionX = event.getRawX();
float positionY = event.getRawY();
if(some conditions with positionX and positionY)
pressedImageButton = true;
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
if(pressedImageButton)
myImageButton.performClick(); // or whatever action you want to perform on that ImageButton
pressedImageButton = false;
break;
}
}
});
I hope this helps. :)
Im using view.startDrag() to start dragging operation. While dragging, events are received in OnDragListener. Also im using DragShadowBuilder to show the last image of View B while dragging.
Is there a way to stop or cancel or abort dragging from some external events or operation? for example, there are 2 view, View A and View B, i'm dragging View B over View A. While dragging, due to some external event or operation, i want to cancel dragging operations or cancel OnDragListener (without removing my finger from the view B).
Code Snippet for DragShadowBuilder:
DragShadowBuilder shadowBuilder = new DragShadowBuilder(view) {
#Override
public void onDrawShadow(Canvas canvas) {
canvas.drawBitmap(b, 0, 0, new Paint());
super.onDrawShadow(canvas);
}
};
boolean dragSuccess = false;
dragSuccess = view.startDrag(null, shadowBuilder, view, 0);
Code Snippet for OnDragListener:
private final class ViewDragListener implements OnDragListener {
#Override
public boolean onDrag(View v, DragEvent event) {
int action = event.getAction();
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
log("ACTION_DRAG_STARTED");
break;
case DragEvent.ACTION_DRAG_ENTERED:
log("ACTION_DRAG_ENTERED");
break;
case DragEvent.ACTION_DRAG_EXITED:
log("ACTION_DRAG_EXITED");
case DragEvent.ACTION_DROP:
log("ACTION_DROP");
mX = (int) event.getX();
mY = (int)event.getY();
break;
case DragEvent.ACTION_DRAG_ENDED:
log("ACTION_DRAG_ENDED");
//Doing some cleanup operations.
break;
case DragEvent.ACTION_DRAG_LOCATION:
log("ACTION_DRAG_LOCATION");
break;
default:
break;
}
return true;
}
}
I couldn't find any trick for this. I tried sending a motion event of ACTION_UP and it did nothing. As long as the user's finger is held down, there's no interrupting the event hierarchy, it seems. I found nothing to help with a google search.
I just set a global and waited until the drag ended, then proceeded.
The swipe of ViewPager is smooth inside the vertical scrollview when I add this code into my ViewPager.
mPager.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
But when I add onClickListener to my ImageView [which is found in the Fragment added to the Adapter of the Viewpager], the swipe of my ViewPager is incorrect. Incorrect wherein I need to have a STRAIGHT HORIZONTAL LINE swipe for it to go to another page unlike before [when I did not add the onClickListener], the viewpager goes to the next page even I do DIAGONAL swiping. Any help is much appreciated. Thanks.
I just used setontouchlistener to my imageview and set conditions there.
Here's the code:
imgCarousel.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
pStart = new Point((int) event.getX(), (int) event.getY());
break;
}
case MotionEvent.ACTION_UP: {
break;
}
case MotionEvent.ACTION_MOVE:{
break;
}
case MotionEvent.ACTION_CANCEL:{
Point pCancel = new Point((int) event.getX(), (int) event.getY());
int difference = pStart.x - pCancel.x;
if(difference > 10){
mPager.setCurrentItem(HomeCarousel.currentPage+1);
}
}
default:
break;
}
return true;
}
});
I think, it happens because ImageView intercept touchEvent using onClickListener.
You can use GestureOverlayView with your ImageView - http://developer.android.com/reference/android/gesture/GestureOverlayView.html
It could handle touch events without intercepting them.
I have on my activity several ImageView's that the user can move around the screen. How can I identify which ImageView is actually selected by the user? In Xcode I can assign a unique Tag to each ImageView and than onTouch get the Tag number. Is there a similar way on Android?
this is Xcode:
UITouch *touch = [[event allTouches] anyObject];
if ([touch view].tag == 901)
{
iTouchObject = 901;
[self.view bringSubviewToFront:imgRojo1];
}
In Android Activity I have so far done: in onCreate I can assign an ID to each ImageView
ImageView selImage = (ImageView)findViewById(R.id.i904);
selImage.setId(904);
and in onTouch.MOVED I can use the ImageView with a directly assigned ID. In this case the image moves smooth below the finger on the screen.
iID = 904;
ImageView selImage = (ImageView)findViewById(iID);
BUT, how can I get the ID from the ImageView that the user has touched?
I have tried to use setOnTouchListener:
ImageView selImage = (ImageView)findViewById(R.id.i904);
selImage.setId(904);
selImage.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
iID = v.getId();
ImageView selImage = (ImageView)findViewById(iID);
int eventaction = event.getAction();
int X = (int)event.getX();
int Y = (int)event.getY();
switch (eventaction ) {
case MotionEvent.ACTION_DOWN: // touch down so check if the finger is on a ball
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
// move the balls the same as the finger
selImage.setX(X-25);
selImage.setY(Y-25);
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
return true;
}});
By this I can select each ImageView and it moves, BUT, it doesn't move smooth and also the ImageView is duplicated on the screen.
Is it possible to get in the first case in the onTouch.MOVED the View and use it to get the ID with: iID = v.getId();
You can check what id your current view has and compare it with the actual resource Id.
For example:
switch (v.getId()) {
case R.id.image1:
// Do this
break;
case R.id.image2:
// ..
break;
case R.id.image3:
// ..
break;
}
You may also check out this page to read a bit more about drag-and-drop with the ChoiceDragListener instead.
UPDATE:
I have found a solution, maybe not the best optimized, but great working. Hope that it helps others of you in similar situations:
For each ImageView I am assigning an ID (setID) and setOnTouchListener. Only thing I am doing in setOnTouchListener is to assign to an integer the same number as I have used for the ID. Important is to put RETURN FALSE, this will stop the setOnTouchListener.
ImageView selImage = (ImageView)findViewById(R.id.i904);
selImage.setId(904);
selImage.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
iID = 904;
return false;
}
});
I have put added the following onTouchEvent(). First thing here is to select the ImageView with the ID that was set in the integer before.
public boolean onTouchEvent(MotionEvent event) {
ImageView selImage = (ImageView)findViewById(iID);
int eventaction = event.getAction();
int X = (int)event.getX();
int Y = (int)event.getY();
switch (eventaction ) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
selImage.setX(X-25);
selImage.setY(Y-25);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
Now I can touch any of the ImageView's and move them around on the screen. Hope it helps!
How can I listen the move events after the LongPress is caled in my GestureDetector?
When the user LongClick he starts the selection mode, and can drag a square into the screen. But I noticed that the onScroll is not called after LongPress is consumed.
Tried to do fight this for a while, and for now the solution is:
Disable the longpress using setIsLongpressEnabled(isLongpressEnabled) on your gestureDetector
Here is my OnTouch method of my View:
public boolean onTouchEvent(MotionEvent event) {
if (mGestureDetector.onTouchEvent(event)== true)
{
//Fling or other gesture detected (not logpress because it is disabled)
}
else
{
//Manually handle the event.
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
//Remember the time and press position
Log.e("test","Action down");
}
if (event.getAction() == MotionEvent.ACTION_MOVE)
{
//Check if user is actually longpressing, not slow-moving
// if current position differs much then press positon then discard whole thing
// If position change is minimal then after 0.5s that is a longpress. You can now process your other gestures
Log.e("test","Action move");
}
if (event.getAction() == MotionEvent.ACTION_UP)
{
//Get the time and position and check what that was :)
Log.e("test","Action down");
}
}
return true;
}
My device returned ACTION_MOVE whenever I hold finger on the screen. If your doesnt, just check the state of some pressed flag after 0.5s using a timer or thread.
Hope that helps!
I have done this task by using the following concepts:
Suppose I have the Image View and on long press on it, image inside this image View would be drag-able and placed inside the another view(e.g. Relative Layout)
Set MyClickListner on Image View's setOnLongClickListener() method.
private final class MyClickListener implements View.OnLongClickListener {
// called when the item is long-clicked
#Override
public boolean onLongClick(View view) {
// TODO Auto-generated method stub
// create it from the object's tag
ClipData.Item item = new ClipData.Item((CharSequence)view.getTag());
String[] mimeTypes = { ClipDescription.MIMETYPE_TEXT_PLAIN };
ClipData data = new ClipData(view.getTag().toString(), mimeTypes, item);
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag( data, //data to be dragged
shadowBuilder, //drag shadow
view, //local data about the drag and drop operation
0 //no needed flags
);
// view.setVisibility(View.INVISIBLE);
return true;
}
}
Then set MyDragListner on Relative Layout(e.g. bigImageRelativeLayoutVw.setOnDragListener(new MyDragListener());)
class MyDragListener implements View.OnDragListener {
#Override
public boolean onDrag(View v, DragEvent event) {
int X=(int)event.getX();
int Y=(int)event.getY();
int touchX = 0,touchY=0;
// Handles each of the expected events
switch (event.getAction()) {
//signal for the start of a drag and drop operation.
case DragEvent.ACTION_DRAG_STARTED:
// do nothing
break;
//the drag point has entered the bounding box of the View
case DragEvent.ACTION_DRAG_ENTERED:
break;
//the user has moved the drag shadow outside the bounding box of the View
case DragEvent.ACTION_DRAG_EXITED:
// v.setBackground(normalShape); //change the shape of the view back to normal
break;
//drag shadow has been released,the drag point is within the bounding box of the View
case DragEvent.ACTION_DROP:
// if the view is the bottomlinear, we accept the drag item
if(v == bigImageRelativeLayoutVw) {
View view = (View) event.getLocalState();
touchX=X-viewCoords[0]-20;
touchY=Y-viewCoords[1]-20;
View view1=new View(getActivity());
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(30,30);
layoutParams.leftMargin =touchX;
layoutParams.topMargin = touchY;
view1.setBackgroundResource(R.drawable.heavy_damage);
view1.setLayoutParams(layoutParams);
RelativeLayout containView = (RelativeLayout) v;
containView.addView(view1);
view.setVisibility(View.VISIBLE);
} else {
View view = (View) event.getLocalState();
view.setVisibility(View.VISIBLE);
break;
}
break;
//the drag and drop operation has concluded.
case DragEvent.ACTION_DRAG_ENDED:
// v.setBackground(normalShape); //go back to normal shape
default:
break;
}
return true;
}
}