Жест в списке Android

Привет, я должен добавить жест в мой список, я хочу реализовать ту же функциональность приложения контактов. Когда я оставляю нажатие, оно должно отправить сообщение, а вправо - вызвать. Может ли кто-нибудь помочь мне, как сделать это обнаружение жестов... я реализовал это в различных других представлениях... но я не мог сделать для 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 ответа

Основываясь на ответах из поста [#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"
    };
}

- Редакция --- Если вы пришли сюда из Google, просто хочу сказать, что, хотя это решение все еще работает, этот конкретный конструктор GestureDetector устарел.

Если вы хотите реализовать жесты смахивания в своем приложении для Android, вы можете использовать эту библиотеку: https://github.com/liuzc/android-swipelistview

Или этот (смахивание работает как gmail): https://github.com/nhaarman/ListViewAnimations

Другие вопросы по тегам