代码之家  ›  专栏  ›  技术社区  ›  Ads

Android ListView中的手势

  •  13
  • Ads  · 技术社区  · 15 年前

    嗨,我必须向ListView添加一个手势,我想实现联系人应用程序的相同功能。 当我向左滑动时,它应该发送一条消息,向右滑动它应该呼叫。有人能帮我做手势检测吗?我已经在各种其他视图中实现了它…但我不能为ListView做…我不知道怎么回事… 我的代码是`

    /** 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;
        }
    }
    
    2 回复  |  直到 9 年前
        1
  •  46
  •   Omid Nazifi    14 年前

    根据帖子[937313][1]中的答案(感谢gav和paiego),我快速编写了以下代码来识别ListView上的简单手势(水平滑动)。

    然而,在一次抛出操作之后,ListView的 onItemClick() 听众也会被呼叫!因此,您最终会得到一个fling和一个额外的oniteclick()。我认为这是因为Android在每个按钮上都会发送一个项目点击事件,不管用户移动手指有多远。为了弥补这一点,而不是注册一个 OnItemClickListener() ,我提供了自己的方法 myOnItemClick() . 然后我重写 SimpleOnGestureListener.onSingleTapUp() 方法,这样当手指向上时,此方法将手动调用myoniteclick()。

    到目前为止,这种方法对我来说还可以。无投诉:—)。

    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"
        };
    }
    
        2
  •  3
  •   golfadas    9 年前

    --编辑--- 如果您是从Google来的,只想告诉您,尽管这个解决方案仍然有效,但是GestureDetector的特定构造函数已被弃用。

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

    或者这个(像Gmail一样刷卡): https://github.com/nhaarman/ListViewAnimations

    推荐文章