We continue
the series of articles on the development of applications for planning cases.
Today, we will improve the usability of our list due to comfortable and
animated removing items.
Practice
In today's
article we will solve two problems:
- swipe detection on the item;
- view animating.
1. Swipe
detection.
In order to
determine what movement made by the user, developed class SwipeDetector,
which will implement the interface View.OnTouchListener. This class will be
universal, that is possible to determine the swipe in all four directions (top
to bottom, bottom to top, left to right, right to left).
The minimum
distance for swipe establish the following:
- horizontal
swipe: 100 px;
- vertical swipe:
80 px.
All the
idea is to determine the difference between the start and end coordinates and
compared with a minimum distance.
Source code
(SwipeDetector):
/**
* Class swipe detection to View
*/
public class SwipeDetector implements View.OnTouchListener {
public static enum Action {
LR, // Left to right
RL, // Right to left
TB, // Top to bottom
BT, // Bottom to top
None // Action not found
}
private static final int HORIZONTAL_MIN_DISTANCE = 100; // The minimum distance for horizontal swipe
private static final int VERTICAL_MIN_DISTANCE = 80; // The minimum distance for vertical swipe
private float downX, downY, upX, upY; // Coordinates
private Action mSwipeDetected = Action.None; // Last action
public boolean swipeDetected() {
return mSwipeDetected != Action.None;
}
public Action getAction() {
return mSwipeDetected;
}
/**
* Swipe detection
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
mSwipeDetected = Action.None;
return false;
}
case MotionEvent.ACTION_MOVE: {
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
// Detection of horizontal swipe
if (Math.abs(deltaX) > HORIZONTAL_MIN_DISTANCE) {
// Left to right
if (deltaX < 0) {
mSwipeDetected = Action.LR;
return true;
}
// Right to left
if (deltaX > 0) {
mSwipeDetected = Action.RL;
return true;
}
} else
// Detection of vertical swipe
if (Math.abs(deltaY) > VERTICAL_MIN_DISTANCE) {
// Top to bottom
if (deltaY < 0) {
mSwipeDetected = Action.TB;
return false;
}
// Bottom to top
if (deltaY > 0) {
mSwipeDetected = Action.BT;
return false;
}
}
return true;
}
}
return false;
}
}
Following
the development of the class, this Listener must be set for View.
final SwipeDetector swipeDetector = new SwipeDetector(); listview.setOnTouchListener(swipeDetector);
2. Animation remove items
For
animation, we will use the class Animation (android.view.animation. Animation).
This class allows you to animate View, using a variety of information such as
the start and end position of the item, size, rotation, and more.
Develop a
method in our Activity, that will perform the movement of our element from its
present location at the edge of the screen. TranslateAnimation class allows you
to animate moving from one point to another.
/**
* Starting animation remove
*/
private Animation getDeleteAnimation(float fromX, float toX, int position)
{
Animation animation = new TranslateAnimation(fromX, toX, 0, 0);
animation.setStartOffset(100);
animation.setDuration(800);
animation.setAnimationListener(new DeleteAnimationListenter(position));
animation.setInterpolator(AnimationUtils.loadInterpolator(this,
android.R.anim.anticipate_overshoot_interpolator));
return animation;
}
Our task is
to keep track of the ending animation, and then removing item and updating the list.
It uses an interface Animation.AnimationListener. It allows you to keep track
of the beginning, the end and repeat the animation.
Add the
following code in our Activity. Position attribute is used to store the
position of the deleted item.
/**
* Listenter used to remove an item after the animation has finished remove
*/
public class DeleteAnimationListenter implements Animation.AnimationListener
{
private int position;
public DeleteAnimationListenter(int position)
{
this.position = position;
}
@Override
public void onAnimationEnd(Animation arg0) {
removeItem(position);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
}
}
Now add the
main logic for removing an element of animation in our Activity.
Add
additional static attribute - message to Handler:
public static final int MSG_ANIMATION_REMOVE = 2;
In Handler
add additional case (msg.arg2 shows in which direction you want to animate
View):
case MSG_ANIMATION_REMOVE: // Start animation removing
View view = (View)msg.obj;
view.startAnimation(getDeleteAnimation(0, (msg.arg2 == 0) ? -view.getWidth() : 2 * view.getWidth(), msg.arg1));
break;
We extend
the method of OnItemClickListener() for Listview. If swipe been made, the item
is removed, or his choice:
listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position,
long id) {
// If there is a tap on the Header or Footer, do not do anything
if (position == 0 || position == list.size() + 1)
return;
Message msg = new Message();
msg.arg1 = position - 1;// If was detected swipe we delete an item
if (swipeDetector.swipeDetected()){
if (swipeDetector.getAction() == SwipeDetector.Action.LR ||
swipeDetector.getAction() == SwipeDetector.Action.RL)
{
msg.what = MSG_ANIMATION_REMOVE;
msg.arg2 = swipeDetector.getAction() == SwipeDetector.Action.LR ? 1 : 0;
msg.obj = view;
}
}
// Otherwise, select an item
else
msg.what = MSG_CHANGE_ITEM;
handler.sendMessage(msg); }
});
Just do not
forget the context menu. When you remove an item from the context menu of the
direction in which the View will have to move, set at random:
case MSG_REMOVE_ITEM: // Remove an item Message msg = new Message(); msg.arg1 = index; msg.arg2 = (new Random()).nextInt(2); msg.obj = listview.getChildAt(index + 1); msg.what = MSG_ANIMATION_REMOVE; getHandler().sendMessage(msg); //removeItem(index); return true;
Links


No comments:
Post a Comment