2

I am asking this rather complex question hoping that i would get an idea from you.

Here is the thing: I have created a custom list view class, the one above:

public class FolderListView extends ListView {

    private float xDistance, yDistance, lastX, lastY;
    private int folder_index;
    private FolderViewInterface openFolder;

    // private boolean swiping = false;

    // If built programmatically
    public FolderListView(Context context) {
        super(context);
    }

    // This example uses this method since being built from XML
    public FolderListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    // Build from XML layout
    public FolderListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {

        case MotionEvent.ACTION_UP:
            // if (swiping == false) {

            //if (xDistance > yDistance)
            //  return false;
        //  else {
                folder_index = pointToPosition((int) lastX, (int) lastY);
            //  Toast.makeText(getContext(),
            //          "You pressed a folder with index: " + folder_index,
            //          Toast.LENGTH_SHORT).show();
        //  }
            HomeScreenFragment f = new HomeScreenFragment();
            openFolder = (FolderViewInterface) f;
            openFolder.onFolderOpened(folder_index);
            // }
            // swiping = false;
            break;

        case MotionEvent.ACTION_DOWN:
            // swiping = false;
            xDistance = yDistance = 0f;
            lastX = ev.getX();
            lastY = ev.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            // swiping = true;
            final float curX = ev.getX();
            final float curY = ev.getY();
            xDistance += Math.abs(curX - lastX);
            yDistance += Math.abs(curY - lastY);
            lastX = curX;
            lastY = curY;
            if (xDistance > yDistance)
                return false;
        }

        return super.onInterceptTouchEvent(ev);

    }

}

thing is here i am looking to properly detect the touch event. I want on touch to open the other fragment, but right now the fragment is opened both on touch and on swipe.

I have used the onInterceptTouchEvent because the elements of my list are viewpagers and they were not behaving properly when scrolling.

I need some kind of logic here to detect the swiping and not perform this part:

HomeScreenFragment f = new HomeScreenFragment();
            openFolder = (FolderViewInterface) f;
            openFolder.onFolderOpened(folder_index);

Only if the event is a touch event, not a swipe one.

Any kind of suggestion/help is highly appreciated, please let me know if you need any more details.

Thanks!

Adrian Olar
  • 2,883
  • 4
  • 35
  • 63
  • Why don't you just add `onClickListener` to your item view? – Desert Aug 05 '13 at 12:30
  • tried that, not working... – Adrian Olar Aug 05 '13 at 12:32
  • Can you post code of your try? – Desert Aug 05 '13 at 12:33
  • `folder_list.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView> arg0, View arg1, int arg2, long arg3) { System.out.println("TOUCHED!"); } });` Yet nothing gets printed. folder_list is a FolderListView item object, not null. – Adrian Olar Aug 05 '13 at 12:40
  • Be aware of this : http://stackoverflow.com/questions/2220547/why-doesnt-system-out-println-work-in-android. Also, can we see the xml layout you are using please ? – mithrop Aug 05 '13 at 12:45
  • it's okay, i don't have a custom ROM and the XML is okay... i get no null pointers, it's just it's not the functionality that i need – Adrian Olar Aug 05 '13 at 12:54

3 Answers3

2

I am taking time 125 based on PRESSED_STATE_DURATION

Try this

//Declare as instance variables
int oldX,oldY,newX,newY;
//State the minimum distance of swipe that you forgive the user for ;)
int distance = 10;
int time = 125;
boolean cancel = false;
case MotionEvent.ACTION_DOWN:
cancel = false;
//Get x and y of touch
oldX = ev.getX();
oldY = ev.getY();
startActionTimer();

case MotionEvent.ACTION_MOVE:
//Get x and y of touch
newX = ev.getX();
newY = ev.getY();

case MotionEvent.ACTION_UP:
cancel = true;

private void startActionTimer(){
        //time is pressed state duration
          new CountDownTimer(time, time) {
             public void onTick(long millisUntilFinished) {}

             public void onFinish() {
                //Time to do our action!!!
                // please consider
                if((Math.abs(newX - oldX )< distance) && (Math.abs(newY - oldY ) <distance)){
                    if(cancel == false){
                    // Now its a touch so do your action
                    }
                }
             }
          }.start();
     }

NOTE: Please use all the variables as class variables(instance variables) to avoid problems. Because sometimes i get weird situations where values are not updated properly

OR

Why don't you try the gesture detection

and override the onSingleTapUp method

Girish Nair
  • 5,148
  • 5
  • 40
  • 61
  • Sorry this is not working for me... i have tried your code but i am losing my initial functionality this way: which was not to intercept the list scrolling with the pager swiping, so now the scrolling is not allowing the pager to swipe... i need something based on what i have written already... but thank you so much for your hints, i will look more into what you proposed. – Adrian Olar Aug 05 '13 at 13:08
  • The code doesn't stop the scrolling in any manner, if you remove the above code then also it would work the same, What the code does is just waits for a few milliseconds before processing the request to find if its a touch or not, Anyway best of luck & if you find a solution please do post it so that others may find it helpful :) – Girish Nair Aug 05 '13 at 13:13
  • The scrolling works, the problem is the scrolling prevents the pager to swipe, that is why used onInterceptTouchEvent in the first place:) – Adrian Olar Aug 05 '13 at 13:15
0

If you just need to do something when an item is touched, you don't need a custom ListView, you just have to set a listener on the listView's adapter, .setOnItemClickListener().

bogdan
  • 782
  • 3
  • 7
  • That's the thing, i need to do 2 things: One when swiped and one when touched. The swiping is handled by the viewpager and the two events interfere, that is my problem... – Adrian Olar Aug 05 '13 at 12:41
  • well, the click will be handled by that listener, if you have problems with the swipe, then you should take a look at `requestDisallowInterceptTouchEvent()` – bogdan Aug 05 '13 at 12:46
  • So the thing is the swipe is covered by the implementation of the viewpager and works fine. the problem is here the new fragment is opened when i swipe AND when i touch, i only need it to open on simple touch.... – Adrian Olar Aug 05 '13 at 12:54
0

Here is the answer to my question, i have figured it out eventually. I just needed to use a boolean variable to check when the swiping was performed and do the appropriate thing when not swiping. it's not the best solution as it is very sensitive(detects even the slightest attempt of swipe) but still it's something.

Thanks guys for your help!

Here is my updated code:

package ro.gebs.captoom.utils;

import ro.gebs.captoom.fragments.HomeScreenFragment;
import ro.gebs.captoom.interfaces.FolderViewInterface;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView;

public class FolderListView extends ListView {

    private float xDistance, yDistance, lastX, lastY;
    private int folder_index;
    private FolderViewInterface openFolder;

    private boolean swiping = false;

    // If built programmatically
    public FolderListView(Context context) {
        super(context);
    }

    // This example uses this method since being built from XML
    public FolderListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    // Build from XML layout
    public FolderListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {

        case MotionEvent.ACTION_UP:
            folder_index = pointToPosition((int) lastX, (int) lastY);
            if (!swiping) {
                HomeScreenFragment f = new HomeScreenFragment();
                openFolder = (FolderViewInterface) f;
                openFolder.onFolderOpened(folder_index);
            }
            swiping = false;
            break;

        case MotionEvent.ACTION_DOWN:
            xDistance = yDistance = 0f;
            lastX = ev.getX();
            lastY = ev.getY();

            break;
        case MotionEvent.ACTION_MOVE:
            final float curX = ev.getX();
            final float curY = ev.getY();
            xDistance += Math.abs(curX - lastX);
            yDistance += Math.abs(curY - lastY);
            lastX = curX;
            lastY = curY;
            if (xDistance > yDistance) {
                swiping = true;
                System.out.println("I AM HEREEEEEE");
                return false;
            }

        }

        return super.onInterceptTouchEvent(ev);

    }

}
Adrian Olar
  • 2,883
  • 4
  • 35
  • 63