Practice
To animate
flying cells need to change the layout main.xml, which is our ListView. Add the
ImageView, which will act as a flying cell. We will use this idea on because
animate View the item itself, as we did in the previous article, we did not
succeed. Because each cell of the list Is located under each other, and when you
move down the upper cells, they will overlap the bottom cell.
Исходный код (main.xml)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white" >
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="@android:color/transparent" />
<ImageView
android:id="@+id/flyingCell"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
</FrameLayout>
Add the
necessary attributes in Activity.
// Messages for Handler public static final int MSG_ANIMATION_FLY = 3; // Stores the size of the screen private DisplayMetrics dm = new DisplayMetrics(); // Flying cell private ImageView flying_cell;
In the method onCreate() add initialization ImageView and DisplayMetrics.
flying_cell = (ImageView)findViewById(R.id.flyingCell); getWindowManager().getDefaultDisplay().getMetrics(dm);
Develop a method in our Activity, that will perform the movement of the selected item from its current position to a specified.
/** * Starting animation flying cell */ private void startFly(Bitmap cellBitmap, Point start, Point end, ToDoItem item) { flying_cell.setVisibility(View.VISIBLE); flying_cell.setImageBitmap(cellBitmap); TranslateAnimation translateAnimation = new TranslateAnimation(start.x, end.x, start.y, end.y); translateAnimation.setStartOffset(100); translateAnimation.setDuration(700); translateAnimation.setInterpolator(AnimationUtils.loadInterpolator(this, android.R.anim.accelerate_decelerate_interpolator)); /* This uses AnimationSet, so you can add some moreanimation (for example, first to zoom in the cell, and then move to reduce normal size) */ AnimationSet spriteAnimation = new AnimationSet(true); spriteAnimation.addAnimation(translateAnimation); spriteAnimation.setAnimationListener(new FlyAnimationListenter()); flying_cell.startAnimation(spriteAnimation); }
Our task is to keep track of the ending animation, and then update the list.
/** * Listenter used to update the list after the cell has arrived to the desired position */ public class FlyAnimationListenter implements Animation.AnimationListener { @Override public void onAnimationEnd(Animation arg0) { getHandler().sendEmptyMessage(MSG_CHANGE_ITEM); } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } }
As well add a method that allows you to determine whether the animation is running or not. This is to ensure that same time can be done only one animation.
/** * Animation is running or not */ public boolean isAnimationStarted() { return flying_cell.isShown(); }
В In Handler add additional case. The idea of flying cells is the following algorithm.When you select a cell, we obtain its image (Bitmap). Next are counting the initial position of the cell as the top point of list + height of the first cell + total height of all the cells that go to the selected cell. Then you sort the list and calculate the same formula the final position. After correct the end point with the size of the screen and execute the animation.
... case MSG_CHANGE_ITEM: // Animation is complete of flying cells flying_cell.setVisibility(View.GONE); adapter.notifyDataSetChanged(); setCountPurchaseProduct(); break; ... case MSG_ANIMATION_FLY: // Start animation flying cells Bitmap cellBitmap = (Bitmap)msg.obj; ToDoItem item = list.get(msg.arg1); item.setCheck(!item.isCheck()); Point startPoint, endPoint; /* We need the following values to find the position: height = Height of one cell header_height = Height Header's list (just the height of the first cell in the list) listTop = highest point of the list - the size of scroll area */ int height = listview.getChildAt(1).getHeight(); int header_height = listview.getChildAt(0).getBottom(); int listTop = listview.getTop() - height * listview.getFirstVisiblePosition(); /* Searching for the starting and the end point is the following algorithm: 1. The starting point: the top point of list + height of the first cell + total height of all the cells that go to the selected cell 2. Sort the list according to the new position of the selected cell 3. Find the end point: high point list + height of the first cell + total height of all the cells that go to the selected cell */ startPoint = new Point(0, listTop + header_height + height * getPositionInList(item.getIndex())); Utils.sorting(list, 0); saveList(); endPoint = new Point(0, listTop + header_height + height * getPositionInList(item.getIndex())); // Correct the end point with the size of the screen if (endPoint.y > dm.heightPixels) endPoint.y = dm.heightPixels; else if (endPoint.y < -1*height) endPoint.y = -1*height; // If the cell changes position, the start animation if (endPoint.y != startPoint.y) startFly(cellBitmap, startPoint, endPoint, item); else handler.sendEmptyMessage(MSG_CHANGE_ITEM); break;
Now you need to change all the methods that are used to select the item in accordance with the new changes:
- method onItemClickListener() for Listview:
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 or animation is running, do not do anything if (position == 0 || position == list.size() + 1 || isAnimationStarted()) 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 { view.setDrawingCacheEnabled(true); Bitmap cellBitmap = view.getDrawingCache().copy(Config.ARGB_8888, false); view.setVisibility(View.INVISIBLE); msg.obj = cellBitmap; msg.what = MSG_ANIMATION_FLY; } handler.sendMessage(msg); } });
- method OnClickListener() for CheckBox in the class CustomListAdapter:
final View tmp = v; listitem_check.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (((MainActivity)context).isAnimationStarted()) return; tmp.setDrawingCacheEnabled(true); Bitmap cellBitmap = tmp.getDrawingCache().copy(Config.ARGB_8888, false); tmp.setVisibility(View.INVISIBLE); Message msg = new Message(); msg.obj = cellBitmap; msg.arg1 = position; msg.what = MainActivity.MSG_ANIMATION_FLY; ((MainActivity)context).getHandler().sendMessage(msg); } });
No comments:
Post a Comment