Жест в списке 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