package org.gscript; import java.util.ArrayList; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.Checkable; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemLongClickListener; import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.view.ActionMode; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; public abstract class GenericListFragment extends SherlockFragment { static final String LOG_TAG = FragmentLibraries.class.getSimpleName(); static final boolean DEBUG = false; ListAdapter mListAdapter; ActionMode mActionMode; View mFragmentView; ListView mListView; int mViewId; int mListId; int mChoiceMode = ListView.CHOICE_MODE_NONE; long[] mSavedCheckedIds; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mFragmentView = inflater.inflate(mViewId, container, false); mListView = ((ListView) mFragmentView.findViewById(mListId)); mListView.setAdapter(mListAdapter); mListView.setChoiceMode(mChoiceMode); mListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (mActionMode != null) { /* invalidate to update title count */ mActionMode.invalidate(); /* finish action mode if there is no selection */ if (getCheckedItemCount() == 0) mActionMode.finish(); } else { /* handle as normal click event */ GenericListFragment.this.onItemClick(parent, view, position, id); } } }); mListView.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { /* if null start the contextual action mode */ if (mActionMode == null) getSherlockActivity().startActionMode( mContextualCallback); if (mActionMode != null) { /* check long-pressed item */ ListView lv = (ListView) parent; lv.setItemChecked(position, !lv.isItemChecked(position)); /* invalidate to update title count */ mActionMode.invalidate(); /* finish action mode if there is no selection */ if (getCheckedItemCount() == 0) mActionMode.finish(); } return true; } }); return mFragmentView; } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (mActionMode != null && !isVisibleToUser) { /* invisible so hide the contextual actionbar */ if(DEBUG) Log.d(LOG_TAG, "became unvisible while contextual -> finish actionmode"); mActionMode.finish(); } if (mActionMode == null && isVisibleToUser) { int checkedItems = getCheckedItemCount(); if (checkedItems > 0) { /* * visible and we have items checked so show contextual * actionbar */ if(DEBUG) Log.d(LOG_TAG, String.format( "became visible while %d item(s) checked -> start actionmode", checkedItems)); getSherlockActivity().startActionMode( mContextualCallback); } } } private ActionMode.Callback mContextualCallback = new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { mActionMode = mode; GenericListFragment.this.onCreateActionMode(mode, menu); final ListView view = getListView(); if (view != null) { mChoiceMode = ListView.CHOICE_MODE_MULTIPLE; view.setChoiceMode(mChoiceMode); view.invalidateViews(); } return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { final ListView view = getListView(); if (view != null) { GenericListFragment.this.onPrepareActionMode(mode, menu); } /* store checked items so that we can restore the selection after an adapter change * eg in onLoadFinished (LoaderCallbacks<Cursor>) */ saveCheckedItems(); return true; } @Override public void onDestroyActionMode(ActionMode mode) { final ListView view = getListView(); if (view != null) { if (getUserVisibleHint()) { if(DEBUG) Log.d(LOG_TAG, "onDestroyActionMode while visible -> uncheck items"); for (int i = 0; i < view.getChildCount(); i++) { /* * manually uncheck views to make sure views are updated * properly */ View v = view.getChildAt(i); if (v instanceof Checkable) { ((Checkable) v).setChecked(false); } } /* clear choices and invalidate all views */ view.clearChoices(); } mChoiceMode = ListView.CHOICE_MODE_NONE; view.setChoiceMode(mChoiceMode); view.invalidateViews(); } mActionMode = null; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return GenericListFragment.this.onActionItemClicked(mode, item); } }; public void initListFragment(int viewResource, int listResource, ListAdapter adapter) { this.mViewId = viewResource; this.mListId = listResource; this.mListAdapter = adapter; } public void setListAdapter(ListAdapter adapter) { mListAdapter = adapter; } public ListAdapter getListAdapter() { return mListAdapter; } int getCheckedItemCount() { /* support SDK < 11 */ int itemCount = 0; final ListView view = getListView(); if (view != null) { /* switch to multiple choice so that we get the correct item count */ int prevMode = view.getChoiceMode(); view.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); itemCount = view.getCheckedItemIds().length; /* restore previous choicemode */ view.setChoiceMode(prevMode); } return itemCount; } long[] getCheckedItemIds() { long[] checkedIds = null; final ListView view = getListView(); if (view != null) { /* switch to multiple choice so that we get the correct item count */ int prevMode = view.getChoiceMode(); view.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); checkedIds = view.getCheckedItemIds(); /* restore previous choicemode */ view.setChoiceMode(prevMode); } return checkedIds; } void saveCheckedItems() { mSavedCheckedIds = getCheckedItemIds(); } void restoreCheckedItems() { final ListView view = this.getListView(); if ((mSavedCheckedIds != null && mSavedCheckedIds.length > 0) && view != null && mListAdapter != null) { ArrayList<Long> positions = new ArrayList<Long>(); int count = mListAdapter.getCount(); for (int pos = 0; pos < count; ++pos) positions.add(mListAdapter.getItemId(pos)); for (int idx = 0; idx < mSavedCheckedIds.length; ++idx) { int pos = -1; for(int y=0; y < positions.size(); ++y) { if(positions.get(y).longValue()==mSavedCheckedIds[idx]) { pos = y; break; } } if (pos >= 0) view.setItemChecked(pos, true); } if (mActionMode != null) mActionMode.invalidate(); } } View getFragmentView() { return mFragmentView; } ListView getListView() { return mListView; } public abstract void onItemClick(AdapterView<?> parent, View view, int position, long id); public abstract void onCreateActionMode(ActionMode mode, Menu menu); public abstract void onPrepareActionMode(ActionMode mode, Menu menu); public abstract boolean onActionItemClicked(ActionMode mode, MenuItem item); }