2010-10-13 44 views
13

您好我必须添加一个手势到我的列表视图,我想实现相同的功能的联系人应用程序。 当我离开时它应该发送一条消息,右击它应该调用。任何人都可以帮助我如何做这些手势检测...我已经在其他各种意见实施它...但我无法做listView ...我不会做什么... ...蠕虫 我的代码是`手势在列表视图android

/** Called when the activity is first created. */ 
public void onCreate(Bundle icicle) { 
    super.onCreate(icicle); 
    setContentView(R.layout.main); 
    // Create an array of Strings, that will be put to our ListActivity 
    String[] names = new String[] { "Linux", "Windows7", "Eclipse", "Suse", "Ubuntu", "Solaris", "Android", "iPhone"}; 
    // Create an ArrayAdapter, that will actually make the Strings above 
    // appear in the ListView 
    this.setListAdapter(new ArrayAdapter<String>(this, R.id.MyList, names)); 
    gestureListener = new ListView.OnTouchListener() { 
     public boolean onTouch(View v, MotionEvent event) { 
      if (gestureDetector.onTouchEvent(event)) { 
       return true; 
      } 
      return false; 
     } 
    };  
} 

@Override 
protected void onListItemClick(ListView l, View v, int position, long id) { 
    super.onListItemClick(l, v, position, id); 
    // Get the item that was clicked 
    Object o = this.getListAdapter().getItem(position); 
    String keyword = o.toString(); 
    Toast.makeText(this, "You selected: " + keyword, Toast.LENGTH_LONG).show(); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if (gestureDetector.onTouchEvent(event)) 
     return true; 
    else 
     return false; 
} 

class MyGestureDetector extends SimpleOnGestureListener { 

    @Override 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
     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) { 
       Context ctx = getApplicationContext(); 
       CharSequence txt = "Right to Left Swipe"; 
       int duration = Toast.LENGTH_LONG; 
       Toast toast = Toast.makeText(ctx, txt, duration); 
       toast.show(); 
       Toast.makeText(this.getItem(lv.pointToPosition((int)e1.getX(),(int) e1.getY()))); 
       // return super.onFling();           
      } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
       Context ctx = getApplicationContext(); 
       CharSequence txt = "Left to Right Swipe"; 
       int duration = Toast.LENGTH_LONG; 
       Toast toast = Toast.makeText(ctx, txt, duration); 
       toast.show(); 
      } 
     } catch (Exception e) { 
      // nothing 
     } 
     return false; 
    } 
} 
+0

[如何实现一扔可能重复在Android的列表视图](http://stackoverflow.com/questions/4030389/how-to-implement-fling-in-android-listview) – 2012-07-25 10:51:51

回答

46

基于从信息[#937313] [1](要感谢GAV和paiego)的答案,我刮起了下面的代码上的ListView识别简单的手势(水平刷卡)。

但是,在执行一次手动操作后,ListView的onItemClick()侦听器也会被调用!因此,你最终会碰到一个额外的onItemClick()。我认为这是因为Android在每个按钮上发送一个项目点击事件,无论用户移动手指的方式有多远。为了解决这个问题,我没有注册一个通常的OnItemClickListener(),而是提供了我自己的方法myOnItemClick()。然后我重写SimpleOnGestureListener.onSingleTapUp()方法,这样当手指启动时,此方法将手动调用myOnItemClick()。

到目前为止,这种方法对我来说工作正常。没什么好抱怨的 :-)。

public class PracticeActivity extends ListActivity { 

    private int REL_SWIPE_MIN_DISTANCE; 
    private int REL_SWIPE_MAX_OFF_PATH; 
    private int REL_SWIPE_THRESHOLD_VELOCITY; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // As paiego pointed out, it's better to use density-aware measurements. 
     DisplayMetrics dm = getResources().getDisplayMetrics(); 
     REL_SWIPE_MIN_DISTANCE = (int)(120.0f * dm.densityDpi/160.0f + 0.5); 
     REL_SWIPE_MAX_OFF_PATH = (int)(250.0f * dm.densityDpi/160.0f + 0.5); 
     REL_SWIPE_THRESHOLD_VELOCITY = (int)(200.0f * dm.densityDpi/160.0f + 0.5); 

     ListView lv = getListView(); 
     lv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, 
      m_Starbucks)); 

     final GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector()); 
     View.OnTouchListener gestureListener = new View.OnTouchListener() { 
      public boolean onTouch(View v, MotionEvent event) { 
       return gestureDetector.onTouchEvent(event); 
      }}; 
     lv.setOnTouchListener(gestureListener); 

     // Long-click still works in the usual way. 
     lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 
      public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { 
       String str = MessageFormat.format("Item long clicked = {0,number}", position); 
       Toast.makeText(PracticeActivity.this, str, Toast.LENGTH_SHORT).show(); 
       return true; 
      } 
     }); 
    } 

    // Do not use LitView.setOnItemClickListener(). Instead, I override 
    // SimpleOnGestureListener.onSingleTapUp() method, and it will call to this method when 
    // it detects a tap-up event. 
    private void myOnItemClick(int position) { 
     String str = MessageFormat.format("Item clicked = {0,number}", position); 
     Toast.makeText(this, str, Toast.LENGTH_SHORT).show(); 
    } 

    private void onLTRFling() { 
     Toast.makeText(this, "Left-to-right fling", Toast.LENGTH_SHORT).show(); 
    } 

    private void onRTLFling() { 
     Toast.makeText(this, "Right-to-left fling", Toast.LENGTH_SHORT).show(); 
    } 

    class MyGestureDetector extends SimpleOnGestureListener{ 

     // Detect a single-click and call my own handler. 
     @Override 
     public boolean onSingleTapUp(MotionEvent e) { 
      ListView lv = getListView(); 
      int pos = lv.pointToPosition((int)e.getX(), (int)e.getY()); 
      myOnItemClick(pos); 
      return false; 
     } 

     @Override 
     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
      if (Math.abs(e1.getY() - e2.getY()) > REL_SWIPE_MAX_OFF_PATH) 
       return false; 
      if(e1.getX() - e2.getX() > REL_SWIPE_MIN_DISTANCE && 
       Math.abs(velocityX) > REL_SWIPE_THRESHOLD_VELOCITY) { 
       onRTLFling(); 
      } else if (e2.getX() - e1.getX() > REL_SWIPE_MIN_DISTANCE && 
       Math.abs(velocityX) > REL_SWIPE_THRESHOLD_VELOCITY) { 
       onLTRFling(); 
      } 
      return false; 
     } 

    } 

    private static final String[] m_Starbucks = { 
     "Latte", "Cappuccino", "Caramel Macchiato", "Americano", "Mocha", "White Mocha", 
     "Mocha Valencia", "Cinnamon Spice Mocha", "Toffee Nut Latte", "Espresso", 
     "Espresso Macchiato", "Espresso Con Panna" 
    }; 
} 
+1

谢谢你分享:-) – Ads 2011-03-03 02:33:17

+0

不错的一个。谢谢。 – dierre 2012-09-09 18:19:40

+0

@wwyt,像魅力一样工作!谢谢你的朋友 但是,有什么办法没有扩展ListActivity?因为我必须扩展一些其他类 – 2012-12-26 13:40:39

2

--Edited --- 如果你来到这里,从谷歌,只是想告诉你的是,虽然这个解决方案仍然有效,GestureDetector的特定构造已被弃用。

如果你想实现你的Android应用滑动手势,你可以考虑使用这个库:https://github.com/liuzc/android-swipelistview

或者这一个(刷卡工作,就像Gmail中):https://github.com/nhaarman/ListViewAnimations

+0

此声明不正确。请阅读您链接的文档。 – carlrice 2013-04-17 01:57:05

+0

谢谢你刚刚编辑它 – golfadas 2013-04-17 11:43:57

+1

第一个链接不工作了,也许你的意思是这个https://github.com/liuzc/android-swipelistview – Mitro 2017-04-04 10:10:38