Android, GridView and onTouchListener - android

My application have three pages (three tabs) and I want to switch beetween two gridviews by moving finger horizontaly. The touch code works fine but I can't click anymore on the grid items! I use the method onItemClickListener (onClickListener don't works on Gridview) but the grid item is not clicked.
Thanks for your help!
The code is :
myGrid.setOnTouchListener(this);
myGrid.setOnItemClickListener(this);
....
public boolean onTouch(View v, MotionEvent event) {
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
xStart = event.getX();
break;
case MotionEvent.ACTION_UP:
xEnd = event.getX();
if (xEnd - xStart > 20){
//switch to previous tab
}
if (xEnd - xStart < -20){
//switch to next tab
}
return true;
default:
break;
}
return true;
}

What view is that onTouch code in? You could try changing that last return true to return false so that if the action wasn't a motionevent, the event is not consumed by the view.

Related

How to draw a 5*5 array and move images on it

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;
}
}
});

Adding onClickListener inside ViewPager Makes the Swipe not Smooth Android

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.

Android trigger onTouch after onLongPress

I am currently trying to implement Drag and Drop in Android. The draging should be done on an item from a ListView. The thing is that the elements(items) in this ListView should have some sort of action when they are touched (single taped) and they should be dragable after the user perform a long press on one of the items. I got the code for draging from a tutorial but the problem that i cannot solve is:
After the user holds his finger on an item from the ListView the onTouch(MotionEvent ev) is called at the beginning and after a second GestureDetector.onLongPress is called.
My draging logic is implemented in the onTouch methods. What i currently do is set a boolean (isLongPressed) to true after LongPress is enabled and in the onTouch methods i check if this boolean is true - if yes then perform the draging.
Here is my code :
public class DragNDropListView extends ListView implements GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener
{
private boolean isLongPressed
#Override
public boolean onTouchEvent(MotionEvent ev)
{
mGestureDetector.onTouchEvent(ev);
if (!isLongPressed)
{
Log.e("Not Long", "Its Not Longpressed yet");
return super.onTouchEvent(ev);
}
final int action = ev.getAction();
final int x = (int) ev.getX();
final int y = (int) ev.getY();
if (action == MotionEvent.ACTION_DOWN && isLongPressed)
{
mDragMode = true;
}
if (!mDragMode)
return super.onTouchEvent(ev);
switch (action)
{
case MotionEvent.ACTION_DOWN:
Log.e("Action down", "Down");
break;
case MotionEvent.ACTION_MOVE:
Log.e("ACTION MOVE", "Move");
drag()
break;
case MotionEvent.ACTION_UP:
{
isLongPressed = false;
}
}
#Override
public void onLongPress(MotionEvent ev)
{
Log.e("LongPress", "LongPressed");
isLongPressed = true;
mGestureDetector.setIsLongpressEnabled(isLongPressed);
super.onTouchEvent(ev);
}
What happens is that i get "isNotLongPressed" if i just tab the items (desired behavior), After a long press i get "LongPressed" but then if i start draging i get nothing. If i release my finger and then start the drag everything is ok but i want to be able to drag immediately after the long press is registered.

OnTouch event on Screen

I have xml in which I have 2 relative layouts, the first one is map(using map fragments) and the second one is ViewPager layout. I added button to map to hide map when clicked, now I want a method to get back the map layout by sweep down the screen.
I tried setting onTouchListener to relative layout but it is not working, also tried implementing OnTouchListener
public class MainActivity extends FragmentActivity implements OnTouchListener
it is not working! how to achieve this?
#Override
public boolean onTouch(View v, MotionEvent event) {
x= event.getX();
y=event.getY();
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
sX = event.getX();
sY = event.getY();
break;
case MotionEvent.ACTION_UP:
fX = event.getX();
fY = event.getY();
if(fX-sX == 0 || fX-sX > 0 || fX-sX <0)
if(fY-sY < 0)
{
if(mapview.getVisibility()==View.GONE)
{
mapview.setVisibility(View.VISIBLE);
}
}
break;
}
return true;
}
Post your code, btw in simple way, ACTION_DOWN is when you touch the screen, ACTION_UP is when you finger release the screen. Look here

Correctly detecting a swipe on a GridView placed inside a ViewPager in Android

I have a ViewPager which uses GridViews for pages. I would like the ViewPager to switch pages when I swipe across the screen.
The problem is that swipes are not detected when they are made across the GridView. Outside of the GridView, the swipes work correctly; it seems that the GridView is trapping all touch events without passing it to ViewPager first.
While fiddling with the source code, I did this to a custom class extended from GridView:
#Override
public boolean onTouchEvent(MotionEvent event) {
return pager.onInterceptTouchEvent(event);
}
-- where pager refers to the ViewPager class. With this, ViewPager will correctly detect swipes and move pages accordingly, but it doesn't allow GridView to accept any events, so I can't click on the items.
What I would like to be able to do is correctly detect swipes in ViewPager and item clicks on GridView.
I had trouble with colig's implementation, but I was able to get it to work by subclassing ViewPager and overriding the onInterceptTouchEvent() method. I only checked for swipes in the X direction to allow for vertical scrolling if necessary.
private static final int minSwipeDistance = 30;
private float mTouchX;
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
boolean response = super.onInterceptTouchEvent(event);
float x = event.getX();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mTouchX = x;
break;
case MotionEvent.ACTION_MOVE:
float dX = Math.abs(x - mTouchX);
if (dX > minSwipeDistance)
return true;
break;
}
return response;
}
Alix is on the right track. I managed to come up with this simple-looking fix. I'm not entirely sure of how it works, but it does! And for future reference, it works for other kinds of views too -- TableLayout, for example -- not just GridView.
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
x = event.getX();
y = event.getY();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
downX = x;
downY = y;
return super.onInterceptTouchEvent(event);
}
case MotionEvent.ACTION_MOVE: {
deltaX = Math.abs(downX - x);
deltaY = Math.abs(downY - y);
return super.onTouchEvent(event);
}
case MotionEvent.ACTION_UP: {
if (deltaX > 4 && deltaY > 4) {
super.onTouchEvent(event);
}
}
}
return super.onInterceptTouchEvent(event);
}
You can override onInterceptTouchEvent for dispatch evenement where you want

Categories

Resources