/* * COPYRIGHT NOTICE * Copyright (C) 2015, xyczero <xiayuncheng1991@gmail.com> * * http://www.xyczero.com/ * * @license under the Apache License, Version 2.0 * * @file CustomSwipeBaseAdapter.java * @brief Custom Swipe Abstract Adapter * * @version 1.0 * @author xyczero * @date 2015/01/12 */ package com.xyczero.customswipelistview; import android.content.Context; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.widget.AbsListView; import android.widget.BaseAdapter; import android.widget.RelativeLayout; import com.hoollyzhang.hlib.R; import java.util.ArrayList; import java.util.List; /** * Extended {@link android.widget.BaseAdapter} that for an {@link android.widget.Adapter} that can be used in * both {@link com.xyczero.customswipelistview.CustomSwipeListView} (by implementing the specialized * {@link com.xyczero.customswipelistview.OnUndoActionListener} interface. * * @param <T> The data type which is to be shown. * @author xyczero */ public abstract class CustomSwipeBaseAdapter<T> extends BaseAdapter implements OnUndoActionListener { /** * Default value represents the invalid position. */ private static final int INVALID_POSITION = -1; protected Context mContext; /** * Desgined to store the data which has been deleted. Can been used to * Restore the data when executing undo action. */ private T mObjectDeleted; /** * Contains the list of objects that represent the data of the adapter which * is extended the CustomSwipeBaseAdapter. */ private List<T> mObjects; /** * Records the position that the object has been deleted. */ private int mHasDeletedPosition; /** * Indicates the undo action has been exectued when is true,otherwise is * false. */ private boolean undoAnimationEnable; /** * Constructor * * @param context The current context. */ public CustomSwipeBaseAdapter(Context context) { mContext = context; mObjects = new ArrayList<T>(); } /** * remove the specified object by the position. * * @param position */ public T removeItemByPosition(int position) { if (position < mObjects.size() && position != INVALID_POSITION) { mObjectDeleted = mObjects.remove(position); mHasDeletedPosition = position; notifyDataSetChanged(); return mObjectDeleted; } else { throw new IndexOutOfBoundsException("The position is invalid!"); } } /** * Adds the specified object at the end of {@link #mObjects} and init the * {@link #mHasDeletedPosition} for {@link #INVALID_POSITION} * * @param object */ public void addAdapterData(T object) { if (object != null) { mObjects.add(object); mHasDeletedPosition = INVALID_POSITION; } notifyDataSetChanged(); } /** * Adds the specified list to {@link #mObjects} and init the * {@link #mHasDeletedPosition} for {@link #INVALID_POSITION} * * @param objects */ public void setAdapterData(List<T> objects) { if (objects != null) { mObjects = objects; mHasDeletedPosition = INVALID_POSITION; } notifyDataSetChanged(); } /** * set the animation {@link anim} to the specified view by * {@link #mHasDeletedPosition} when the specified view exectuing the undo * action. * * @param itemView * @param undoPosition */ private void setItemUndoActionAnimation(View itemView, int undoPosition) { if (undoPosition == mHasDeletedPosition && undoAnimationEnable) { itemView.startAnimation(AnimationUtils.loadAnimation(mContext, R.anim.undodialog_push_right_in)); clearDeletedObject(); } else { itemView.clearAnimation(); } } protected List<T> getAdapterData() { return mObjects; } private void clearDeletedObject() { mObjectDeleted = null; undoAnimationEnable = false; mHasDeletedPosition = INVALID_POSITION; } /** * Bind an existing item view to the data pointed to by position. * * @param view Existing item view, returned earlier by {@link #newItemView} * @param context Interface to application's global information * @param position The position from which to get the data. */ protected abstract void bindItemView(View view, Context context, int position); /** * Bind an existing swipe left view to the data pointed to by position. * SwipeLeftView is indicating the menu that will been shown when scroll * left the item view. * * @param view Existing item view, returned earlier by {@link #newItemView} * @param context Interface to application's global information * @param position The position from which to get the data. */ protected abstract void bindSwipeLeftView(View view, Context context, int position); private void bindView(View view, Context context, int position) { bindItemView(view, context, position); bindSwipeLeftView(view, context, position); } /** * Makes a new item view to hold the data pointed to by position. * * @param context Interface to application's global information * @param position The position from which to get the data. * @param parent The View to which the new view is attached to */ protected abstract View newItemView(Context context, int position, ViewGroup parent); /** * Makes a new swipe left view hold the data pointed to by position. * SwipeLeftView is indicating the menu that will been shown when scroll * left the item view. * * @param context Interface to application's global information * @param position The position from which to get the data. * @param parent The View to which the new view is attached to */ protected abstract View newSwipeLeftView(Context context, int position, ViewGroup parent); /** * Makes a new view that combines itemView and swipeLeftView to hold the * data pointed to by position. * * @param context Interface to application's global information * @param position The position from which to get the data. * @param parent The View to which the new view is attached to * @return */ private View newView(Context context, int position, ViewGroup parent) { // get a new itemView and init it. View itemView = newItemView(context, position, parent); if (itemView == null) throw new IllegalStateException("the itemView can't be null!"); // set a tag for the itemMainView which is used in CustomSwipeListView. itemView.setTag(CustomSwipeListView.ITEMMAIN_LAYOUT_TAG); // itemLayout indicates the outermost layout of the new view. RelativeLayout itemLayout = new RelativeLayout(context); itemLayout.setLayoutParams(new AbsListView.LayoutParams( itemView.getLayoutParams().width, itemView.getLayoutParams().height)); itemLayout.addView(itemView); // get a new swipeLeftView and init it. View swipeLeftView = newSwipeLeftView(context, position, parent); if (swipeLeftView == null) return itemLayout; // set a tag for the swipeLeftView which is used in CustomSwipeListView. swipeLeftView.setTag(CustomSwipeListView.ITEMSWIPE_LAYOUT_TAG); swipeLeftView.setVisibility(View.GONE); // itemSwipeLeftLayout indicates the layout of the swipeLeftView. RelativeLayout itemSwipeLeftLayout = new RelativeLayout(context); itemSwipeLeftLayout.setLayoutParams(new AbsListView.LayoutParams( itemView.getLayoutParams().width, itemView.getLayoutParams().height)); itemSwipeLeftLayout.setHorizontalGravity(Gravity.END); itemSwipeLeftLayout.setBackgroundColor(mContext.getResources() .getColor(android.R.color.transparent)); itemSwipeLeftLayout.addView(swipeLeftView); itemLayout.addView(itemSwipeLeftLayout); return itemLayout; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v; if (convertView == null) { v = newView(mContext, position, parent); } else { v = convertView; } bindView(v, mContext, position); // must ensure that the height of the CustemListview is a certain // value(like wrap_content is forbidden),otherwise the undo animation // will appear unexpectedly. setItemUndoActionAnimation(v, position); return v; } /** * Implments the {@link #noExecuteUndoAction} in * {@link com.xyczero.customswipelistview.OnUndoActionListener}. */ @Override public void noExecuteUndoAction() { if (!undoAnimationEnable) { clearDeletedObject(); } } /** * Implments the {@link #executeUndoAction} in {@link com.xyczero.customswipelistview.OnUndoActionListener}. */ @Override public void executeUndoAction() { if (mHasDeletedPosition <= mObjects.size() && mHasDeletedPosition != INVALID_POSITION) { mObjects.add(mHasDeletedPosition, mObjectDeleted); undoAnimationEnable = true; notifyDataSetChanged(); } } }