Удалить просмотр списка элементов с помощью Slide - Like Gmail
Я разрабатываю приложение со списком магазинов в виде списка. Мне нужно это, когда я провожу предмет listview
справа (или слева) этот элемент должен быть удален из списка.
У меня есть мой список и мне нужна только функция, чтобы сделать это.
Заранее спасибо.
4 ответа
Вот как я понимаю этот эффект. У нас есть ListView lvSimple
и мы добавляем onTouchListener к нашему lvSimple
, Это мой рабочий код.
float historicX = Float.NaN, historicY = Float.NaN;
static final int DELTA = 50;
enum Direction {LEFT, RIGHT;}
...
ListView lvSimple = (ListView) findViewById(R.id.linLayout);
...
lvSimple.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
historicX = event.getX();
historicY = event.getY();
break;
case MotionEvent.ACTION_UP:
if (event.getX() - historicX < -DELTA) {
FunctionDeleteRowWhenSlidingLeft();
return true;
}
else if (event.getX() - historicX > DELTA) {
FunctionDeleteRowWhenSlidingRight();
return true;
}
break;
default:
return false;
}
return false;
}
});
где функция FunctionDeleteRowWhenSlidingLeft()
звонит, когда мы скользим влево, FunctionDeleteRowWhenSlidingRight()
- вправо соответственно. В этой функции вам нужно вставить код для анимации.
Ответ от Android-разработчика указывает на код Романа Нурика в gist.github.com. Этот код устарел. Он использует этот Swipe to Dismiss в своем проекте с открытым исходным кодом Dash Clock.
Есть некоторые вещи, которые вы должны знать, прежде чем использовать код в Gist.github.com.
- Устаревший код в gist.Github очень чувствителен к прикосновениям. Если вы продолжите нажимать на элемент в ListView, он будет удален. В обновленном коде он исправил чувствительность к бросанию.
- Этот слушатель не работает, если у вас есть разделители, объявленные в ListView. Если вы хотите разделители, объявите их в макете ListItem.
- Этот код все еще находится в бета-версии. Пусть покупатель будет бдителен.
Поэтому я рекомендую использовать обновленный код. Вы можете найти обновленный источник здесь.
Другой вариант, который вы должны рассмотреть, это использовать библиотеку Тима Роуса EnhancedListView. [Обновление - 01.08.2015] С введением RecycleView эта библиотека устарела.
Для вышеупомянутого слушателя Романа Нурика SwipeToDismiss требуется уровень API 12 или выше. Джейк Уортон портировал этот код для поддержки всех уровней API в SwipeToDismissNOA.
Тим Роус расширил эту библиотеку, чтобы также поддерживать функцию отмены.
Я сделал ответ, используя то, что написал Макловинг. Пока это работает, но это работает, только если все ваши дети имеют одинаковый рост.
listView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
historicX = event.getX();
historicY = event.getY();
return false;
case MotionEvent.ACTION_UP:
if (listView.getChildAt(0) != null) {
int heightOfEachItem = haveListView.getChildAt(0).getHeight();
int heightOfFirstItem = -haveListView.getChildAt(0).getTop() + haveListView.getFirstVisiblePosition()*heightOfEachItem;
//IF YOU HAVE CHILDS IN LIST VIEW YOU START COUNTING
//listView.getChildAt(0).getTop() will see top of child showed in screen
//Dividing by height of view, you get how many views are not in the screen
//It needs to be Math.ceil in this case because it sometimes only shows part of last view
final int firstPosition = (int) Math.ceil(heightOfFirstItem / heightOfEachItem); // This is the same as child #0
//Here you get your List position, use historic Y to get where the user went first
final int wantedPosition = (int) Math.floor((historicY - haveListView.getChildAt(0).getTop()) / heightOfEachItem) + firstPosition;
//Here you get the actually position in the screen
final int wantedChild = wantedPosition - firstPosition;
//Depending on delta, go right or left
if (event.getX() - historicX < -DELTA) {
//If something went wrong, we stop it now
if (wantedChild < 0 || wantedChild >= List.size()|| wantedChild >= listView.getChildCount()) {
return true;
}
//Start animation with 500 miliseconds of time
listView.getChildAt(wantedChild).startAnimation(outToLeftAnimation(500));
//after 500 miliseconds remove from List the item and update the adapter.
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
public void run() {
List.remove(wantedPosition);
updateAdapter();
}
},
500
);
return true;
} else if (event.getX() - historicX > DELTA) {
//If something went wrong, we stop it now
if (wantedChild < 0 || wantedChild >= List.size() || wantedChild >= listView.getChildCount()) {
return true;
}
//Start animation with 500 miliseconds of time
listView.getChildAt(wantedChild).startAnimation(outToRightAnimation(500));
//after 500 miliseconds remove from List the item and update the adapter.
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
public void run() {
List.remove(wantedPosition);
updateAdapter();
}
},
500
);
return true;
}
}
return true;
default:
return false;
}
}
});
Анимации имеют эту функцию:
private Animation outToLeftAnimation(int duration) {
Animation outtoLeft = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, -1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
outtoLeft.setDuration(duration);
outtoLeft.setInterpolator(new AccelerateInterpolator());
return outtoLeft;
}
private Animation outToRightAnimation(int duration) {
Animation outtoRight = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, +1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
outtoRight.setDuration(duration);
outtoRight.setInterpolator(new AccelerateInterpolator());
return outtoRight;
}
Я пытаюсь это сделать, и до сих пор я не видел ошибок, если бы кто-то мог попробовать, было бы хорошо.