// ================================================================================ // ListView row animation helper // ================================================================================ /** * This method animates all other views in the ListView container (not including ignoreView) * into their final positions. It is called after ignoreView has been removed from the * adapter, but before layout has been run. The approach here is to figure out where * everything is now, then allow layout to run, then figure out where everything is after * layout, and then to run animations between all of those start/end positions. */ public void animateRemoval(ListView listview, View viewToRemove) { int firstVisiblePosition = listview.FirstVisiblePosition; for (int i = 0; i < listview.ChildCount; ++i) { View child = listview.GetChildAt(i); if (child != viewToRemove) { int pos = firstVisiblePosition + i; long itemId = adapter.GetGroupId(pos); if (!mItemIdTopMap.ContainsKey(itemId)) { mItemIdTopMap.Add(itemId, child.Top); } else { mItemIdTopMap[itemId] = child.Top; } } } // Delete the item from the adapter int position = listView.GetPositionForView(viewToRemove); dataSource.RemoveAt(position); adapter.NotifyDataSetChanged(); ViewTreeObserver observer = listview.ViewTreeObserver; observer.AddOnPreDrawListener(new CustomOnPreDrawListener(listview, observer, adapter, mItemIdTopMap, moveView)); }
private void Init() { Inflate(Context, Resource.Layout.tooltip, this); _topPointerView = FindViewById <ImageView>(Resource.Id.tooltip_pointer_up); _contentHolder = (ViewGroup)FindViewById(Resource.Id.tooltip_contentholder); _tooltipTextView = FindViewById <TextView>(Resource.Id.tooltip_contenttv); _bottomPointerView = FindViewById <ImageView>(Resource.Id.tooltip_pointer_down); _shadowView = FindViewById(Resource.Id.tooltip_shadow); SetOnClickListener(this); ViewTreeObserver.AddOnPreDrawListener(this); }
/** * This method determines whether the hover cell has been shifted far enough * to invoke a cell swap. If so, then the respective cell swap candidate is * determined and the data set is changed. Upon posting a notification of the * data set change, a layout is invoked to place the cells in the right place. * Using a ViewTreeObserver and a corresponding OnPreDrawListener, we can * offset the cell being swapped to where it previously was and then animate it to * its new position. */ void handleCellSwitch() { observeDeltaY = mLastEventY - mDownY; int deltaYTotal = mHoverCellOriginalBounds.Top + mTotalOffset + observeDeltaY; View belowView = getViewForID(mBelowItemId); View mobileView = getViewForID(mMobileItemId); View aboveView = getViewForID(mAboveItemId); bool isBelow = (belowView != null) && (deltaYTotal > belowView.Top); bool isAbove = (aboveView != null) && (deltaYTotal < aboveView.Top); if (isBelow || isAbove) { observeSwitchItemID = isBelow ? mBelowItemId : mAboveItemId; View switchView = isBelow ? belowView : aboveView; int originalItem = GetPositionForView(mobileView); if (switchView == null) { updateNeighborViewsForID(mMobileItemId); return; } swapElements(mCheeseList, originalItem, GetPositionForView(switchView)); ((BaseAdapter)Adapter).NotifyDataSetChanged(); mDownY = mLastEventY; observeSwitchViewStartTop = switchView.Top; mobileView.Visibility = ViewStates.Visible; switchView.Visibility = ViewStates.Invisible; updateNeighborViewsForID(mMobileItemId); observer = ViewTreeObserver; observer.AddOnPreDrawListener(this); } }