/* * ****************************************************************************** * Copyright (c) 2013-2014 Gabriele Mariotti. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ***************************************************************************** */ package it.gmariotti.cardslib.library.internal.multichoice; /** * @author Gabriele Mariotti (gabri.mariotti@gmail.com) */ import android.app.Activity; import android.content.res.Resources; import android.util.SparseBooleanArray; import android.view.ActionMode; import android.view.Menu; import android.view.View; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ListView; import java.util.ArrayList; import it.gmariotti.cardslib.library.R; import it.gmariotti.cardslib.library.internal.Card; import it.gmariotti.cardslib.library.view.base.CardViewWrapper; public class MultiChoiceAdapterHelperBase implements AdapterView.OnItemLongClickListener,AdapterView.OnItemClickListener { protected static final String TAG = MultiChoiceAdapterHelperBase.class.getSimpleName(); protected AbsListView mAdapterView; protected BaseAdapter owner; protected AbsListView.MultiChoiceModeListener mMultiChoiceModeListener; /** * ActionMode */ protected ActionMode actionMode; private boolean ignoreCheckedListener; // ------------------------------------------------------------- // Constructors // ------------------------------------------------------------- public MultiChoiceAdapterHelperBase(BaseAdapter owner) { this.owner = owner; } // ------------------------------------------------------------- // View // ------------------------------------------------------------- /** * Sets the adapter and * @param adapterView */ public void setAdapterView(AbsListView adapterView) { mAdapterView=adapterView; //mAdapterView.setOnItemLongClickListener(this); mAdapterView.setMultiChoiceModeListener(mMultiChoiceModeListener); } /** * Used to setup some element events for multichoice * * @param view * @param mCard * @param mCardView * @param position */ public void setupMultichoice(View view, Card mCard, CardViewWrapper mCardView, long position) { final MultiChoiceAdapter adapter = (MultiChoiceAdapter) owner; View.OnClickListener advanceClickListener = new View.OnClickListener() { @Override public void onClick(View v) { final CardViewWrapper cardView = (CardViewWrapper) v; int position = adapter.getPosition(cardView.getCard()); onItemClick(mAdapterView, v, position, adapter.getItemId(position)); } }; //You need it to enable the CAB if (mCard.isCheckable()) { //mCardView.setLongClickable(true); mCardView.setOnClickListener(advanceClickListener); }else{ if (mCard.getOnClickListener()!=null){ mCardView.setOnClickListener(advanceClickListener); } } } /** * Checks and unchecks the items * * @param handle position * @param checked true if item is checked, false otherwise */ protected void setItemChecked(long handle, boolean checked) { if (checked) { checkItem(handle); } else { uncheckItem(handle); } } /** * Checks the item * * @param handle */ protected void checkItem(long handle) { mAdapterView.setItemChecked((int)handle,true); } /** * Unckecks the item * * @param handle */ protected void uncheckItem(long handle) { mAdapterView.setItemChecked((int)handle,false); } // ------------------------------------------------------------- // OnItemLongClickListener implementation // ------------------------------------------------------------- @Override public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) { //Check if the card is checkable if (!isCardCheckable(position)) { return false; } //Check the item int correctedPosition = correctPositionAccountingForHeader(adapterView, position); long handle = positionToSelectionHandle(correctedPosition); boolean wasChecked = mAdapterView.isItemChecked((int)handle); // invoke the contextual action mode by setting the respective list item to the checked setItemChecked(handle, !wasChecked); view.setActivated(!wasChecked); if (actionMode!=null){ //You need it to enable the CAB //((CardView)view).setLongClickable(false); } return true; } private int correctPositionAccountingForHeader(AdapterView<?> adapterView, int position) { ListView listView = (adapterView instanceof ListView) ? (ListView) adapterView : null; int headersCount = listView == null ? 0 : listView.getHeaderViewsCount(); if (headersCount > 0) { position -= listView.getHeaderViewsCount(); } return position; } protected long positionToSelectionHandle(int position) { return position; } /** * Indicates if the card is checkable * * @param position * @return */ public boolean isCardCheckable(int position) { MultiChoiceAdapter adapter = (MultiChoiceAdapter) owner; Card card = adapter.getItem(position); if (card != null) return card.isCheckable(); return false; } // ------------------------------------------------------------- // OnItemClickListener implementation // ------------------------------------------------------------- @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { MultiChoiceAdapter adapter = (MultiChoiceAdapter) owner; if (adapter.getOptionMultiChoice().isSelectItemClickInActionMode()){ if (adapter.isActionModeStarted()){ onItemLongClick(parent, view, position, id); return; }else{ //Default card onItemClick internal_onItemClick(parent, view, position, id); } }else{ //Default card onItemClick internal_onItemClick(parent, view, position, id); } } public void internal_onItemClick(AdapterView<?> parent, View view, int position, long id) { MultiChoiceAdapter adapter = (MultiChoiceAdapter) owner; Card mCard = adapter.getItem(position); if (mCard != null && mCard.getOnClickListener() != null) mCard.getOnClickListener().onClick(mCard, view); } // ------------------------------------------------------------- // ActionMode // ------------------------------------------------------------- public boolean startActionMode(Activity activity) { if (activity!=null){ if (!isActionModeStarted()) activity.startActionMode(mMultiChoiceModeListener); } return false; } /** * Called when action mode is first created. The menu supplied will be used to * generate action buttons for the action mode. * * @param mode ActionMode being created * @param menu Menu used to populate action buttons * @return true if the action mode should be created, false if entering this * mode should be aborted. */ public boolean onCreateActionMode(ActionMode mode, Menu menu) { actionMode = mode; onItemSelectedStateChanged(mode); //mAdapterView.setOnItemLongClickListener(null); //mAdapterView.setLongClickable(false); return false; } /** * Called when an action mode is about to be exited and destroyed. * * @param mode The current ActionMode being destroyed */ public void onDestroyActionMode(ActionMode mode) { actionMode = null; //mAdapterView.setOnItemLongClickListener(this); } /** * Called when an item is checked or unchecked during selection mode. * * @param mode The {@link ActionMode} providing the selection mode * @param position Adapter position of the item that was checked or unchecked * @param id Adapter ID of the item that was checked or unchecked * @param checked <code>true</code> if the item is now checked, <code>false</code> * if the item is now unchecked. */ public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { onItemSelectedStateChanged(mode); MultiChoiceAdapter adapter = (MultiChoiceAdapter) owner; Card card = adapter.getItem(position); adapter.onItemCheckedStateChanged(mode, position, id, checked, card.getCardView(), card); } /** * Manage the title when the items are selected * * @param mode */ protected void onItemSelectedStateChanged(ActionMode mode) { int count = mAdapterView.getCheckedItemCount(); if (count > 0) { Resources res = mAdapterView.getResources(); String mTitleSelected = res.getQuantityString(R.plurals.card_selected_items, count, count); mode.setTitle(mTitleSelected); } } /** * Indicate if action mode is started * * @return */ public boolean isActionModeStarted() { if (actionMode != null) { return true; } return false; } // ------------------------------------------------------------- // Utility methods // ------------------------------------------------------------- /** * Returns the selected cards * @return */ public ArrayList<Card> getSelectedCards() { SparseBooleanArray checked = mAdapterView.getCheckedItemPositions(); ArrayList<Card> items = new ArrayList<Card>(); MultiChoiceAdapter adapter = (MultiChoiceAdapter) owner; for (int i = checked.size()-1; i>=0; i--) { if (checked.valueAt(i) == true) { items.add( adapter.getItem((int) checked.keyAt(i))); } } return items; } // ------------------------------------------------------------- // Getters and setters // ------------------------------------------------------------- /** * Get the {@link android.widget.AbsListView.MultiChoiceModeListener} * @return */ public AbsListView.MultiChoiceModeListener getMultiChoiceModeListener() { return mMultiChoiceModeListener; } /** * Set the {@link android.widget.AbsListView.MultiChoiceModeListener} * * @param multiChoiceModeListener */ public void setMultiChoiceModeListener(AbsListView.MultiChoiceModeListener multiChoiceModeListener) { mMultiChoiceModeListener = multiChoiceModeListener; } }