/* * Copyright 2013 Niek Haarman * * 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 com.marshalchen.common.uimodule.listviewanimations; import android.database.DataSetObserver; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.BaseAdapter; import android.widget.SectionIndexer; import com.marshalchen.common.uimodule.listviewanimations.widget.DynamicListView; import com.marshalchen.common.uimodule.listviewanimations.widget.DynamicListView.Swappable; /** * A decorator class that enables decoration of an instance of the BaseAdapter * class. * * Classes extending this class can override methods and provide extra * functionality before or after calling the super method. */ public abstract class BaseAdapterDecorator extends BaseAdapter implements SectionIndexer, DynamicListView.Swappable, ListViewSetter { protected final BaseAdapter mDecoratedBaseAdapter; private AbsListView mListView; private boolean mIsParentHorizontalScrollContainer; private int mResIdTouchChild; public BaseAdapterDecorator(final BaseAdapter baseAdapter) { mDecoratedBaseAdapter = baseAdapter; } @Override public void setAbsListView(final AbsListView listView) { mListView = listView; if (mDecoratedBaseAdapter instanceof ListViewSetter) { ((ListViewSetter) mDecoratedBaseAdapter).setAbsListView(listView); } if (mListView instanceof DynamicListView) { DynamicListView dynListView = (DynamicListView) mListView; dynListView.setIsParentHorizontalScrollContainer(mIsParentHorizontalScrollContainer); dynListView.setDynamicTouchChild(mResIdTouchChild); } } public AbsListView getAbsListView() { return mListView; } @Override public int getCount() { return mDecoratedBaseAdapter.getCount(); } @Override public Object getItem(final int position) { return mDecoratedBaseAdapter.getItem(position); } @Override public long getItemId(final int position) { return mDecoratedBaseAdapter.getItemId(position); } @Override public View getView(final int position, final View convertView, final ViewGroup parent) { return mDecoratedBaseAdapter.getView(position, convertView, parent); } @Override public boolean areAllItemsEnabled() { return mDecoratedBaseAdapter.areAllItemsEnabled(); } @Override public View getDropDownView(final int position, final View convertView, final ViewGroup parent) { return mDecoratedBaseAdapter.getDropDownView(position, convertView, parent); } @Override public int getItemViewType(final int position) { return mDecoratedBaseAdapter.getItemViewType(position); } @Override public int getViewTypeCount() { return mDecoratedBaseAdapter.getViewTypeCount(); } @Override public boolean hasStableIds() { return mDecoratedBaseAdapter.hasStableIds(); } @Override public boolean isEmpty() { return mDecoratedBaseAdapter.isEmpty(); } @Override public boolean isEnabled(final int position) { return mDecoratedBaseAdapter.isEnabled(position); } @Override public void notifyDataSetChanged() { if (!(mDecoratedBaseAdapter instanceof ArrayAdapter<?>)) { // fix #35 dirty trick ! // leads to an infinite loop when trying because ArrayAdapter triggers notifyDataSetChanged itself mDecoratedBaseAdapter.notifyDataSetChanged(); } } /** * Helper function if you want to force notifyDataSetChanged() */ @SuppressWarnings("UnusedDeclaration") public void notifyDataSetChanged(final boolean force) { if (force || !(mDecoratedBaseAdapter instanceof ArrayAdapter<?>)) { // leads to an infinite loop when trying because ArrayAdapter triggers notifyDataSetChanged itself mDecoratedBaseAdapter.notifyDataSetChanged(); } } @Override public void notifyDataSetInvalidated() { mDecoratedBaseAdapter.notifyDataSetInvalidated(); } @Override public void registerDataSetObserver(final DataSetObserver observer) { mDecoratedBaseAdapter.registerDataSetObserver(observer); } @Override public void unregisterDataSetObserver(final DataSetObserver observer) { mDecoratedBaseAdapter.unregisterDataSetObserver(observer); } @Override public int getPositionForSection(final int section) { if (mDecoratedBaseAdapter instanceof SectionIndexer) { return ((SectionIndexer) mDecoratedBaseAdapter).getPositionForSection(section); } return 0; } @Override public int getSectionForPosition(final int position) { if (mDecoratedBaseAdapter instanceof SectionIndexer) { return ((SectionIndexer) mDecoratedBaseAdapter).getSectionForPosition(position); } return 0; } @Override public Object[] getSections() { if (mDecoratedBaseAdapter instanceof SectionIndexer) { return ((SectionIndexer) mDecoratedBaseAdapter).getSections(); } return null; } public BaseAdapter getDecoratedBaseAdapter() { return mDecoratedBaseAdapter; } @Override public void swapItems(final int positionOne, final int positionTwo) { if (mDecoratedBaseAdapter instanceof Swappable) { ((Swappable) mDecoratedBaseAdapter).swapItems(positionOne, positionTwo); } } /** * If the adapter's list-view is hosted inside a parent(/grand-parent/etc) that can scroll horizontally, horizontal swipes won't * work, because the parent will prevent touch-events from reaching the list-view. * * Call this method with the value 'true' to fix this behavior. * Note that this will prevent the parent from scrolling horizontally when the user touches anywhere in a list-item. */ public void setIsParentHorizontalScrollContainer(final boolean isParentHorizontalScrollContainer) { mIsParentHorizontalScrollContainer = isParentHorizontalScrollContainer; if (mListView instanceof DynamicListView) { DynamicListView dynListView = (DynamicListView) mListView; dynListView.setIsParentHorizontalScrollContainer(mIsParentHorizontalScrollContainer); } } public boolean isParentHorizontalScrollContainer() { return mIsParentHorizontalScrollContainer; } /** * If the adapter's list-view is hosted inside a parent(/grand-parent/etc) that can scroll horizontally, horizontal swipes won't * work, because the parent will prevent touch-events from reaching the list-view. * * If a list-item view has a child with the given resource-ID, the user can still swipe the list-item by touching that child. * If the user touches an area outside that child (but inside the list-item view), then the swipe will not happen and the parent * will do its job instead (scrolling horizontally). * * @param childResId The resource-ID of the list-items' child that the user should touch to be able to swipe the list-items. */ public void setTouchChild(final int childResId) { mResIdTouchChild = childResId; if (mListView instanceof DynamicListView) { DynamicListView dynListView = (DynamicListView) mListView; dynListView.setDynamicTouchChild(mResIdTouchChild); } } public int getTouchChild() { return mResIdTouchChild; } }