package com.example.barnes.ummoqmasterdashboard.Dq;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorListenerAdapter;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.view.ViewHelper;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static com.nineoldandroids.view.ViewHelper.setAlpha;
import static com.nineoldandroids.view.ViewHelper.setTranslationX;
import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
/**
* Created by barnes on 11/29/15.
*/
public class ContextualUndoAdapter extends BaseAdapterDecorator implements ContextualUndoListViewTouchListener.Callback
{
private final int mUndoLayoutId;
private final int mUndoActionId;
private final int mAnimationTime = 150;
private ContextualUndoView mCurrentRemovedView;
private long mCurrentRemovedId;
private Map<View, Animator> mActiveAnimators = new ConcurrentHashMap<View, Animator>();
private DeleteItemCallback mDeleteItemCallback;
/**
* Create a new ContextualUndoAdapter based on given parameters.
*
* @param baseAdapter The BaseAdapter to wrap
* @param undoLayoutId The layout resource id to show as undo
* @param undoActionId The id of the component which undoes the dismissal
*/
public ContextualUndoAdapter(BaseAdapter baseAdapter, int undoLayoutId, int undoActionId)
{
super(baseAdapter);
mUndoLayoutId = undoLayoutId;
mUndoActionId = undoActionId;
mCurrentRemovedId = -1;
}
@Override
public final View getView(int position, View convertView, ViewGroup parent)
{
ContextualUndoView contextualUndoView = (ContextualUndoView) convertView;
if (contextualUndoView == null)
{
contextualUndoView = new ContextualUndoView(parent.getContext(), mUndoLayoutId);
contextualUndoView.findViewById(mUndoActionId).setOnClickListener(new UndoListener(contextualUndoView));
}
View contentView = super.getView(position, contextualUndoView.getContentView(), parent);
contextualUndoView.updateContentView(contentView);
long itemId = getItemId(position);
if (itemId == mCurrentRemovedId)
{
contextualUndoView.displayUndo();
mCurrentRemovedView = contextualUndoView;
}
else
{
contextualUndoView.displayContentView();
}
contextualUndoView.setItemId(itemId);
return contextualUndoView;
}
@Override
public void setAbsListView(AbsListView listView)
{
super.setAbsListView(listView);
ContextualUndoListViewTouchListener contextualUndoListViewTouchListener = new ContextualUndoListViewTouchListener(listView, this);
listView.setOnTouchListener(contextualUndoListViewTouchListener);
listView.setOnScrollListener(contextualUndoListViewTouchListener.makeScrollListener());
listView.setRecyclerListener(new RecycleViewListener());
}
@Override
public void onViewSwiped(View dismissView, int dismissPosition)
{
ContextualUndoView contextualUndoView = (ContextualUndoView) dismissView;
if (contextualUndoView.isContentDisplayed())
{
restoreViewPosition(contextualUndoView);
contextualUndoView.displayUndo();
removePreviousContextualUndoIfPresent();
setCurrentRemovedView(contextualUndoView);
}
else
{
if (mCurrentRemovedView != null)
{
performRemoval();
}
}
}
private void restoreViewPosition(View view)
{
setAlpha(view, 1f);
setTranslationX(view, 0);
}
private void removePreviousContextualUndoIfPresent()
{
if (mCurrentRemovedView != null)
{
performRemoval();
}
}
private void setCurrentRemovedView(ContextualUndoView currentRemovedView)
{
mCurrentRemovedView = currentRemovedView;
mCurrentRemovedId = currentRemovedView.getItemId();
}
private void clearCurrentRemovedView()
{
mCurrentRemovedView = null;
mCurrentRemovedId = -1;
}
@Override
public void onListScrolled()
{
if (mCurrentRemovedView != null)
{
performRemoval();
}
}
private void performRemoval()
{
ValueAnimator animator = ValueAnimator.ofInt(mCurrentRemovedView.getHeight(), 1).setDuration(mAnimationTime);
animator.addListener(new RemoveViewAnimatorListenerAdapter(mCurrentRemovedView));
animator.addUpdateListener(new RemoveViewAnimatorUpdateListener(mCurrentRemovedView));
animator.start();
mActiveAnimators.put(mCurrentRemovedView, animator);
clearCurrentRemovedView();
}
/**
* Set the DeleteItemCallback for this ContextualUndoAdapter. This is called when an item should be deleted from your collection.
*/
public void setDeleteItemCallback(DeleteItemCallback deleteItemCallback)
{
mDeleteItemCallback = deleteItemCallback;
}
public Parcelable onSaveInstanceState()
{
Bundle bundle = new Bundle();
bundle.putLong("mCurrentRemovedId", mCurrentRemovedId);
return bundle;
}
public void onRestoreInstanceState(Parcelable state)
{
Bundle bundle = (Bundle) state;
mCurrentRemovedId = bundle.getLong("mCurrentRemovedId", -1);
}
/**
* A callback interface which is used to notify when items should be removed from the collection.
*/
public interface DeleteItemCallback
{
/**
* Called when an item should be removed from the collection.
* @param position the position of the item that should be removed.
*/
public void deleteItem(int position);
}
private class RemoveViewAnimatorListenerAdapter extends AnimatorListenerAdapter
{
private final View mDismissView;
private final int mOriginalHeight;
public RemoveViewAnimatorListenerAdapter(View dismissView)
{
mDismissView = dismissView;
mOriginalHeight = dismissView.getHeight();
}
@Override
public void onAnimationEnd(Animator animation)
{
mActiveAnimators.remove(mDismissView);
restoreViewPosition(mDismissView);
restoreViewDimension(mDismissView);
deleteCurrentItem();
}
private void restoreViewDimension(View view)
{
ViewGroup.LayoutParams lp;
lp = view.getLayoutParams();
//lp.height = mOriginalHeight;
view.setLayoutParams(lp);
}
private void deleteCurrentItem()
{
ContextualUndoView contextualUndoView = (ContextualUndoView) mDismissView;
int position = getAbsListView().getPositionForView(contextualUndoView);
mDeleteItemCallback.deleteItem(position);
}
}
private class RemoveViewAnimatorUpdateListener implements ValueAnimator.AnimatorUpdateListener
{
private final View mDismissView;
private final ViewGroup.LayoutParams mLayoutParams;
public RemoveViewAnimatorUpdateListener(View dismissView)
{
mDismissView = dismissView;
mLayoutParams = dismissView.getLayoutParams();
}
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator)
{
mLayoutParams.height = (Integer) valueAnimator.getAnimatedValue();
mDismissView.setLayoutParams(mLayoutParams);
}
}
;
private class UndoListener implements View.OnClickListener
{
private final ContextualUndoView mContextualUndoView;
public UndoListener(ContextualUndoView contextualUndoView)
{
mContextualUndoView = contextualUndoView;
}
@Override
public void onClick(View v)
{
clearCurrentRemovedView();
mContextualUndoView.displayContentView();
moveViewOffScreen();
animateViewComingBack();
}
private void moveViewOffScreen()
{
ViewHelper.setTranslationX(mContextualUndoView, mContextualUndoView.getWidth());
}
private void animateViewComingBack()
{
animate(mContextualUndoView).translationX(0).setDuration(mAnimationTime).setListener(null);
}
}
private class RecycleViewListener implements AbsListView.RecyclerListener
{
@Override
public void onMovedToScrapHeap(View view)
{
Animator animator = mActiveAnimators.get(view);
if (animator != null)
{
animator.cancel();
}
}
}
}