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