Swipe Gesture inside ListView - Android

16.7k Views Asked by At

I am a newbie for Android. I got a tutorial on how to implement the `listView here:

I implemented it and it is working fine. I need to implement a ViewSwitcher for the same. Like when I swipe the song, I need to get some options like play, add to queue etc.,

Pls go through that tutorial and pls help. I'm struggling almost from 3 weeks.

Hope someone will help me.

Edit 1: The below code is the main Activity:

import java.util.ArrayList;
import java.util.HashMap;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.widget.ViewSwitcher;

public class CustomizedListView extends Activity implements OnGestureListener{
// All static variables
static final String URL = "http://api.androidhive.info/music/music.xml";
// XML node keys
static final String KEY_SONG = "song"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_ARTIST = "artist";
static final String KEY_DURATION = "duration";
static final String KEY_THUMB_URL = "thumb_url";


private ViewSwitcher switcher1;
private GestureDetector gesturedetector = null;
ListView list;
LazyAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();

    XMLParser parser = new XMLParser();
    String xml = parser.getXmlFromUrl(URL); // getting XML from URL
    Document doc = parser.getDomElement(xml); // getting DOM element

    NodeList nl = doc.getElementsByTagName(KEY_SONG);
    // looping through all song nodes <song>
    for (int i = 0; i < nl.getLength(); i++) {
        // creating new HashMap
        HashMap<String, String> map = new HashMap<String, String>();
        Element e = (Element) nl.item(i);
        // adding each child node to HashMap key => value
        map.put(KEY_ID, parser.getValue(e, KEY_ID));
        map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
        map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
        map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
        map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));

        // adding HashList to ArrayList
        songsList.add(map);

    }


    list=(ListView)findViewById(R.id.list);

    // Getting adapter by passing xml data ArrayList
    adapter=new LazyAdapter(this, songsList);        
    list.setAdapter(adapter);


    // Click event for single list row
    list.setOnItemClickListener(new OnItemClickListener() {

        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {


        }
    });



}   


@Override
public boolean onTouchEvent(MotionEvent event) {
        return gesturedetector.onTouchEvent(event);
}

public boolean onDown(MotionEvent e) {
    // TODO Auto-generated method stub
    return false;
}
int SWIPE_MIN_VELOCITY = 100;
int SWIPE_MIN_DISTANCE = 100;
//Sự kiện khi bạn vuốt màn hình đưa sang một bên nào đó

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
    //Get Position
    float ev1X = e1.getX();
    float ev2X = e2.getX();

    //Get distance of X (e1) to X (e2)
    final float xdistance = Math.abs(ev1X - ev2X);
    //Get veclocity of cusor
    //Vận tốc = số điểm ảnh (px) / giây
   final float xvelocity = Math.abs(velocityX);

   //Vận tốc chuyển đổi X > 100 và khoảng cách từ điểm kéo đầu đến điểm kéo cuối > 100
   if( (xvelocity > SWIPE_MIN_VELOCITY) && (xdistance > SWIPE_MIN_DISTANCE) )
   {
        if(ev1X > ev2X)//Switch Left
        {
            previousView();
        }
        else//Switch Right
        {
            nextView();
        }
   }

    return false;
}

public void onLongPress(MotionEvent e) {

}

public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY) {
    return false;
}

public void onShowPress(MotionEvent e) {

}

public boolean onSingleTapUp(MotionEvent e) {
    return false;
}

//Next, Previous Views
private void previousView() {
    switcher1.showPrevious();
}
private void nextView() {
    switcher1.showNext();
}

Below code the XML file.

<?xml version="1.0" encoding="utf-8"?>
  <ViewSwitcher xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/viewSwitcher1"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentLeft="true"
     android:layout_alignParentTop="true" >

   <include
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     layout="@layout/list_row_main" />

   <include
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     layout="@layout/list_row_swipe" />

</ViewSwitcher>
2

There are 2 best solutions below

4
On

As I understand your question, your problem is to detect the touch gesture within the ListView, right?

Therefore, you have to extend the ListView and detect horizontal touch gestures in the onInterceptTouchEvent method.

Heres is an example of a ListView, which does not react horizontally touch events. These events will be dispatched to you child view, which is in fact your list item view that has to catch these events (use gesture listener) and trigger the ViewSwitcher.

public class SampleListView extends ListView {

.
.
.

@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // reset difference values
                mDiffX = 0;
                mDiffY = 0;

                mLastX = ev.getX();
                mLastY = ev.getY();
                break;

            case MotionEvent.ACTION_MOVE:
                final float curX = ev.getX();
                final float curY = ev.getY();
                mDiffX += Math.abs(curX - mLastX);
                mDiffY += Math.abs(curY - mLastY);
                mLastX = curX;
                mLastY = curY;

                // don't intercept event, when user tries to scroll vertically
                if (mDiffX > mDiffY) {
                    return false; // do not react to horizontal touch events, these events will be passed to your list item view
                }
        }

        return super.onInterceptTouchEvent(ev);
    }

.
.
.

}
1
On

You can use motionevent to do it. You just need to trace the velocity.

for Example.

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
        float velocityY) {
    // TODO Auto-generated method stub
       try {
           if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
               return false;
           // right to left swipe
           if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {                  
              Toast.makeText(getApplicationContext(), "Left Swipe", 
              Toast.LENGTH_SHORT).show();                  
            }