diff --git a/extras/PullToRefreshListFragment/AndroidManifest.xml b/extras/PullToRefreshListFragment/AndroidManifest.xml index 89632e318..6745733d6 100644 --- a/extras/PullToRefreshListFragment/AndroidManifest.xml +++ b/extras/PullToRefreshListFragment/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="2110" + android:versionName="2.1.1" > diff --git a/extras/PullToRefreshListFragment/pom.xml b/extras/PullToRefreshListFragment/pom.xml index 61935d30e..06e9a13e8 100644 --- a/extras/PullToRefreshListFragment/pom.xml +++ b/extras/PullToRefreshListFragment/pom.xml @@ -10,7 +10,7 @@ com.github.chrisbanes.pulltorefresh extras - 2.1 + 2.1.1 diff --git a/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshBaseListFragment.java b/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshBaseListFragment.java new file mode 100644 index 000000000..4350f9257 --- /dev/null +++ b/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshBaseListFragment.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright 2011, 2012 Chris Banes. + * + * 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.handmark.pulltorefresh.extras.listfragment; + +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.ListView; + +import com.handmark.pulltorefresh.library.PullToRefreshBase; + +abstract class PullToRefreshBaseListFragment> extends ListFragment { + + private T mPullToRefreshListView; + + @Override + public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View layout = super.onCreateView(inflater, container, savedInstanceState); + + ListView lv = (ListView) layout.findViewById(android.R.id.list); + ViewGroup parent = (ViewGroup) lv.getParent(); + + // Remove ListView and add PullToRefreshListView in its place + int lvIndex = parent.indexOfChild(lv); + parent.removeViewAt(lvIndex); + mPullToRefreshListView = onCreatePullToRefreshListView(inflater, savedInstanceState); + parent.addView(mPullToRefreshListView, lvIndex, lv.getLayoutParams()); + + return layout; + } + + /** + * @return The {@link PullToRefreshBase} attached to this ListFragment. + */ + public final T getPullToRefreshListView() { + return mPullToRefreshListView; + } + + /** + * Returns the {@link PullToRefreshBase} which will replace the ListView + * created from ListFragment. You should override this method if you wish to + * customise the {@link PullToRefreshBase} from the default. + * + * @param inflater - LayoutInflater which can be used to inflate from XML. + * @param savedInstanceState - Bundle passed through from + * {@link ListFragment#onCreateView(LayoutInflater, ViewGroup, Bundle) + * onCreateView(...)} + * @return The {@link PullToRefreshBase} which will replace the ListView. + */ + protected abstract T onCreatePullToRefreshListView(LayoutInflater inflater, Bundle savedInstanceState); + +} \ No newline at end of file diff --git a/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshExpandableListFragment.java b/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshExpandableListFragment.java new file mode 100644 index 000000000..aca73a3e7 --- /dev/null +++ b/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshExpandableListFragment.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright 2011, 2012 Chris Banes. + * + * 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.handmark.pulltorefresh.extras.listfragment; + +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.view.LayoutInflater; + +import com.handmark.pulltorefresh.library.PullToRefreshExpandableListView; + +/** + * A sample implementation of how to use {@link PullToRefreshExpandableListView} + * with {@link ListFragment}. This implementation simply replaces the ListView + * that {@code ListFragment} creates with a new + * {@code PullToRefreshExpandableListView}. This means that ListFragment still + * works 100% (e.g. setListShown(...) ). + *

+ * The new PullToRefreshListView is created in the method + * {@link #onCreatePullToRefreshListView(LayoutInflater, Bundle)}. If you wish + * to customise the {@code PullToRefreshExpandableListView} then override this + * method and return your customised instance. + * + * @author Chris Banes + * + */ +public class PullToRefreshExpandableListFragment extends PullToRefreshBaseListFragment { + + protected PullToRefreshExpandableListView onCreatePullToRefreshListView(LayoutInflater inflater, + Bundle savedInstanceState) { + return new PullToRefreshExpandableListView(getActivity()); + } + +} \ No newline at end of file diff --git a/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshListFragment.java b/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshListFragment.java index 34909f53d..e544797f9 100644 --- a/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshListFragment.java +++ b/extras/PullToRefreshListFragment/src/com/handmark/pulltorefresh/extras/listfragment/PullToRefreshListFragment.java @@ -18,66 +18,25 @@ import android.os.Bundle; import android.support.v4.app.ListFragment; import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ListView; + import com.handmark.pulltorefresh.library.PullToRefreshListView; /** - * A sample implementation of how to the PullToRefreshListView with - * ListFragment. This implementation simply replaces the ListView that - * ListFragment creates with a new PullToRefreshListView. This means that - * ListFragment still works 100% (e.g. setListShown(...)). - * + * A sample implementation of how to use {@link PullToRefreshListView} with + * {@link ListFragment}. This implementation simply replaces the ListView that + * {@code ListFragment} creates with a new PullToRefreshListView. This means + * that ListFragment still works 100% (e.g. setListShown(...) ). + *

* The new PullToRefreshListView is created in the method - * onCreatePullToRefreshListView(). If you wish to customise the - * PullToRefreshListView then override this method and return your customised - * instance. + * {@link #onCreatePullToRefreshListView(LayoutInflater, Bundle)}. If you wish + * to customise the {@code PullToRefreshListView} then override this method and + * return your customised instance. * * @author Chris Banes * */ -public class PullToRefreshListFragment extends ListFragment { - - private PullToRefreshListView mPullToRefreshListView; - - @Override - public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View layout = super.onCreateView(inflater, container, savedInstanceState); - - ListView lv = (ListView) layout.findViewById(android.R.id.list); - ViewGroup parent = (ViewGroup) lv.getParent(); - - //Remove ListView and add PullToRefreshListView in its place - int lvIndex = parent.indexOfChild(lv); - parent.removeViewAt(lvIndex); - mPullToRefreshListView = onCreatePullToRefreshListView(inflater, savedInstanceState); - parent.addView(mPullToRefreshListView, lvIndex, lv.getLayoutParams()); - - return layout; - } - - /** - * @return The {@link PullToRefreshListView} attached to this ListFragment. - */ - public final PullToRefreshListView getPullToRefreshListView() { - return mPullToRefreshListView; - } +public class PullToRefreshListFragment extends PullToRefreshBaseListFragment { - /** - * Returns the {@link PullToRefreshListView} which will replace the ListView - * created from ListFragment. You should override this method if you wish to - * customise the {@link PullToRefreshListView} from the default. - * - * @param inflater - * - LayoutInflater which can be used to inflate from XML. - * @param savedInstanceState - * - Bundle passed through from - * {@link ListFragment#onCreateView(LayoutInflater, ViewGroup, Bundle) - * onCreateView(...)} - * @return The {@link PullToRefreshListView} which will replace the - * ListView. - */ protected PullToRefreshListView onCreatePullToRefreshListView(LayoutInflater inflater, Bundle savedInstanceState) { return new PullToRefreshListView(getActivity()); } diff --git a/extras/PullToRefreshViewPager/AndroidManifest.xml b/extras/PullToRefreshViewPager/AndroidManifest.xml index 8643bc964..eaffd6803 100644 --- a/extras/PullToRefreshViewPager/AndroidManifest.xml +++ b/extras/PullToRefreshViewPager/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="2110" + android:versionName="2.1.1" > diff --git a/extras/PullToRefreshViewPager/pom.xml b/extras/PullToRefreshViewPager/pom.xml index 0b1a8865f..46761a99c 100644 --- a/extras/PullToRefreshViewPager/pom.xml +++ b/extras/PullToRefreshViewPager/pom.xml @@ -10,7 +10,7 @@ com.github.chrisbanes.pulltorefresh extras - 2.1 + 2.1.1 diff --git a/extras/pom.xml b/extras/pom.xml index 6ad9d59b3..59ac6507b 100644 --- a/extras/pom.xml +++ b/extras/pom.xml @@ -10,7 +10,7 @@ com.github.chrisbanes.pulltorefresh parent - 2.1 + 2.1.1 diff --git a/library/AndroidManifest.xml b/library/AndroidManifest.xml index 28e0b3a47..c3db5673d 100644 --- a/library/AndroidManifest.xml +++ b/library/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="2110" + android:versionName="2.1.1" > diff --git a/library/pom.xml b/library/pom.xml index 40289a7e7..381eb5375 100644 --- a/library/pom.xml +++ b/library/pom.xml @@ -10,7 +10,7 @@ com.github.chrisbanes.pulltorefresh parent - 2.1 + 2.1.1 diff --git a/library/res/layout/pull_to_refresh_header_horizontal.xml b/library/res/layout/pull_to_refresh_header_horizontal.xml index 5e225c224..f05bb0338 100644 --- a/library/res/layout/pull_to_refresh_header_horizontal.xml +++ b/library/res/layout/pull_to_refresh_header_horizontal.xml @@ -1,19 +1,29 @@ - + android:layout_height="fill_parent" + android:paddingBottom="@dimen/header_footer_top_bottom_padding" + android:paddingLeft="@dimen/header_footer_left_right_padding" + android:paddingRight="@dimen/header_footer_left_right_padding" + android:paddingTop="@dimen/header_footer_top_bottom_padding" > - + + + + \ No newline at end of file diff --git a/library/res/layout/pull_to_refresh_header_vertical.xml b/library/res/layout/pull_to_refresh_header_vertical.xml index 8533c0b68..2185e2d6f 100644 --- a/library/res/layout/pull_to_refresh_header_vertical.xml +++ b/library/res/layout/pull_to_refresh_header_vertical.xml @@ -2,48 +2,58 @@ + android:paddingBottom="@dimen/header_footer_top_bottom_padding" + android:paddingLeft="@dimen/header_footer_left_right_padding" + android:paddingRight="@dimen/header_footer_left_right_padding" + android:paddingTop="@dimen/header_footer_top_bottom_padding" > - + android:layout_gravity="left|center_vertical" > - - + - + + - + android:layout_gravity="center" + android:gravity="center_horizontal" + android:orientation="vertical" > - - + + + + + \ No newline at end of file diff --git a/library/src/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java b/library/src/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java index ef26a2486..5f76645d2 100644 --- a/library/src/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java +++ b/library/src/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java @@ -9,15 +9,22 @@ public class LoadingLayoutProxy implements ILoadingLayout { - private final PullToRefreshBase mPullToRefreshView; private final HashSet mLoadingLayouts; - LoadingLayoutProxy(PullToRefreshBase pullToRefreshView) { - mPullToRefreshView = pullToRefreshView; + LoadingLayoutProxy() { mLoadingLayouts = new HashSet(); } - void addLayout(LoadingLayout layout) { + /** + * This allows you to add extra LoadingLayout instances to this proxy. This + * is only necessary if you keep your own instances, and want to have them + * included in any + * {@link PullToRefreshBase#createLoadingLayoutProxy(boolean, boolean) + * createLoadingLayoutProxy(...)} calls. + * + * @param layout - LoadingLayout to have included. + */ + public void addLayout(LoadingLayout layout) { if (null != layout) { mLoadingLayouts.add(layout); } @@ -28,8 +35,6 @@ public void setLastUpdatedLabel(CharSequence label) { for (LoadingLayout layout : mLoadingLayouts) { layout.setLastUpdatedLabel(label); } - - mPullToRefreshView.refreshLoadingViewsSize(); } @Override @@ -37,8 +42,6 @@ public void setLoadingDrawable(Drawable drawable) { for (LoadingLayout layout : mLoadingLayouts) { layout.setLoadingDrawable(drawable); } - - mPullToRefreshView.refreshLoadingViewsSize(); } @Override @@ -58,7 +61,7 @@ public void setPullLabel(CharSequence label) { @Override public void setReleaseLabel(CharSequence label) { for (LoadingLayout layout : mLoadingLayouts) { - layout.setRefreshingLabel(label); + layout.setReleaseLabel(label); } } @@ -66,7 +69,5 @@ public void setTextTypeface(Typeface tf) { for (LoadingLayout layout : mLoadingLayouts) { layout.setTextTypeface(tf); } - - mPullToRefreshView.refreshLoadingViewsSize(); } } diff --git a/library/src/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java b/library/src/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java index 26ee40753..b5132ed6a 100644 --- a/library/src/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java +++ b/library/src/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java @@ -19,7 +19,6 @@ import android.content.res.TypedArray; import android.util.AttributeSet; import android.util.Log; -import android.view.ContextMenu.ContextMenuInfo; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -30,6 +29,7 @@ import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.FrameLayout; +import android.widget.LinearLayout; import android.widget.ListAdapter; import com.handmark.pulltorefresh.library.internal.EmptyViewMethodAccessor; @@ -38,7 +38,23 @@ public abstract class PullToRefreshAdapterViewBase extends PullToRefreshBase implements OnScrollListener { - private int mSavedLastVisibleIndex = -1; + private static FrameLayout.LayoutParams convertEmptyViewLayoutParams(ViewGroup.LayoutParams lp) { + FrameLayout.LayoutParams newLp = null; + + if (null != lp) { + newLp = new FrameLayout.LayoutParams(lp); + + if (lp instanceof LinearLayout.LayoutParams) { + newLp.gravity = ((LinearLayout.LayoutParams) lp).gravity; + } else { + newLp.gravity = Gravity.CENTER; + } + } + + return newLp; + } + + private boolean mLastItemVisible; private OnScrollListener mOnScrollListener; private OnLastItemVisibleListener mOnLastItemVisibleListener; private View mEmptyView; @@ -69,8 +85,6 @@ public PullToRefreshAdapterViewBase(Context context, Mode mode, AnimationStyle a mRefreshableView.setOnScrollListener(this); } - abstract public ContextMenuInfo getContextMenuInfo(); - /** * Gets whether an indicator graphic should be displayed when the View is in * a state where a Pull-to-Refresh can happen. An example of this state is @@ -93,23 +107,12 @@ public final void onScroll(final AbsListView view, final int firstVisibleItem, f + ". Total Items:" + totalItemCount); } - // If we have a OnItemVisibleListener, do check... + /** + * Set whether the Last Item is Visible. lastVisibleItemIndex is a + * zero-based index, so we minus one totalItemCount to check + */ if (null != mOnLastItemVisibleListener) { - - // Detect whether the last visible item has changed - final int lastVisibleItemIndex = firstVisibleItem + visibleItemCount; - - /** - * Check that the last item has changed, we have any items, and that - * the last item is visible. lastVisibleItemIndex is a zero-based - * index, so we add one to it to check against totalItemCount. - */ - if (visibleItemCount > 0 && (lastVisibleItemIndex + 1) == totalItemCount) { - if (lastVisibleItemIndex != mSavedLastVisibleIndex) { - mSavedLastVisibleIndex = lastVisibleItemIndex; - mOnLastItemVisibleListener.onLastItemVisible(); - } - } + mLastItemVisible = (totalItemCount > 0) && (firstVisibleItem + visibleItemCount >= totalItemCount - 1); } // If we're showing the indicator, check positions... @@ -123,9 +126,17 @@ public final void onScroll(final AbsListView view, final int firstVisibleItem, f } } - public final void onScrollStateChanged(final AbsListView view, final int scrollState) { + public final void onScrollStateChanged(final AbsListView view, final int state) { + /** + * Check that the scrolling has stopped, and that the last item is + * visible. + */ + if (state == OnScrollListener.SCROLL_STATE_IDLE && null != mOnLastItemVisibleListener && mLastItemVisible) { + mOnLastItemVisibleListener.onLastItemVisible(); + } + if (null != mOnScrollListener) { - mOnScrollListener.onScrollStateChanged(view, scrollState); + mOnScrollListener.onScrollStateChanged(view, state); } } @@ -172,8 +183,14 @@ public final void setEmptyView(View newEmptyView) { ((ViewGroup) newEmptyViewParent).removeView(newEmptyView); } - refreshableViewWrapper.addView(newEmptyView, ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT); + // We need to convert any LayoutParams so that it works in our + // FrameLayout + FrameLayout.LayoutParams lp = convertEmptyViewLayoutParams(newEmptyView.getLayoutParams()); + if (null != lp) { + refreshableViewWrapper.addView(newEmptyView, lp); + } else { + refreshableViewWrapper.addView(newEmptyView); + } } if (mRefreshableView instanceof EmptyViewMethodAccessor) { @@ -231,7 +248,7 @@ public void setShowIndicator(boolean showIndicator) { ; @Override - void onPullToRefresh() { + protected void onPullToRefresh() { super.onPullToRefresh(); if (getShowIndicatorInternal()) { @@ -249,7 +266,7 @@ void onPullToRefresh() { } } - void onRefreshing(boolean doScroll) { + protected void onRefreshing(boolean doScroll) { super.onRefreshing(doScroll); if (getShowIndicatorInternal()) { @@ -258,7 +275,7 @@ void onRefreshing(boolean doScroll) { } @Override - void onReleaseToRefresh() { + protected void onReleaseToRefresh() { super.onReleaseToRefresh(); if (getShowIndicatorInternal()) { @@ -277,7 +294,7 @@ void onReleaseToRefresh() { } @Override - void onReset() { + protected void onReset() { super.onReset(); if (getShowIndicatorInternal()) { diff --git a/library/src/com/handmark/pulltorefresh/library/PullToRefreshBase.java b/library/src/com/handmark/pulltorefresh/library/PullToRefreshBase.java index ed76d2e56..a76b32891 100644 --- a/library/src/com/handmark/pulltorefresh/library/PullToRefreshBase.java +++ b/library/src/com/handmark/pulltorefresh/library/PullToRefreshBase.java @@ -46,7 +46,7 @@ public abstract class PullToRefreshBase extends LinearLayout imp // Constants // =========================================================== - static final boolean DEBUG = false; + static final boolean DEBUG = true; static final String LOG_TAG = "PullToRefresh"; @@ -91,9 +91,6 @@ public abstract class PullToRefreshBase extends LinearLayout imp private LoadingLayout mHeaderLayout; private LoadingLayout mFooterLayout; - private int mHeaderDimension; - private int mFooterDimension; - private OnRefreshListener mOnRefreshListener; private OnRefreshListener2 mOnRefreshListener2; private OnPullEventListener mOnPullEventListener; @@ -145,10 +142,10 @@ public void addView(View child, int index, ViewGroup.LayoutParams params) { @Override public final boolean demo() { if (mMode.showHeaderLoadingLayout() && isReadyForPullStart()) { - smoothScrollToAndBack(-mHeaderDimension * 2); + smoothScrollToAndBack(-getHeaderSize() * 2); return true; } else if (mMode.showFooterLoadingLayout() && isReadyForPullEnd()) { - smoothScrollToAndBack(mFooterDimension * 2); + smoothScrollToAndBack(getFooterSize() * 2); return true; } @@ -549,148 +546,6 @@ public final void setShowViewWhileRefreshing(boolean showView) { */ public abstract Orientation getPullToRefreshScrollDirection(); - /** - * Called when the UI has been to be updated to be in the - * {@link State#PULL_TO_REFRESH} state. - */ - void onPullToRefresh() { - switch (mCurrentMode) { - case PULL_FROM_END: - mFooterLayout.pullToRefresh(); - break; - case PULL_FROM_START: - mHeaderLayout.pullToRefresh(); - break; - default: - // NO-OP - break; - } - } - - /** - * Called when the UI has been to be updated to be in the - * {@link State#REFRESHING} or {@link State#MANUAL_REFRESHING} state. - * - * @param doScroll - Whether the UI should scroll for this event. - */ - void onRefreshing(final boolean doScroll) { - if (mMode.showHeaderLoadingLayout()) { - mHeaderLayout.refreshing(); - } - if (mMode.showFooterLoadingLayout()) { - mFooterLayout.refreshing(); - } - - if (doScroll) { - if (mShowViewWhileRefreshing) { - switch (mCurrentMode) { - case MANUAL_REFRESH_ONLY: - case PULL_FROM_END: - smoothScrollTo(mFooterDimension); - break; - default: - case PULL_FROM_START: - smoothScrollTo(-mHeaderDimension); - break; - } - } else { - smoothScrollTo(0); - } - } - } - - /** - * Called when the UI has been to be updated to be in the - * {@link State#RELEASE_TO_REFRESH} state. - */ - void onReleaseToRefresh() { - switch (mCurrentMode) { - case PULL_FROM_END: - mFooterLayout.releaseToRefresh(); - break; - case PULL_FROM_START: - mHeaderLayout.releaseToRefresh(); - break; - default: - // NO-OP - break; - } - } - - /** - * Called when the UI has been to be updated to be in the - * {@link State#RESET} state. - */ - void onReset() { - mIsBeingDragged = false; - mLayoutVisibilityChangesEnabled = true; - - // Always reset both layouts, just in case... - mHeaderLayout.reset(); - mFooterLayout.reset(); - - smoothScrollTo(0); - } - - /** - * Re-measure the Loading Views height, and adjust internal padding as - * necessary - */ - final void refreshLoadingViewsSize() { - final int maximumPullScroll = (int) (getMaximumPullScroll() * 1.2f); - - mHeaderDimension = mFooterDimension = 0; - - int pLeft, pTop, pRight, pBottom; - pLeft = pTop = pRight = pBottom = 0; - - if (mMode.showHeaderLoadingLayout()) { - mHeaderLayout.resetForMeasure(); - measureView(mHeaderLayout); - - switch (getPullToRefreshScrollDirection()) { - case HORIZONTAL: - mHeaderDimension = mHeaderLayout.getMeasuredWidth(); - pLeft = -maximumPullScroll; - mHeaderLayout.adjustWidthUsingLeftPadding(maximumPullScroll); - break; - case VERTICAL: - default: - mHeaderDimension = mHeaderLayout.getMeasuredHeight(); - pTop = -maximumPullScroll; - mHeaderLayout.adjustHeightUsingTopPadding(maximumPullScroll); - break; - } - - // We need to re-measure with the new padding... - measureView(mHeaderLayout); - } - - if (mMode.showFooterLoadingLayout()) { - mFooterLayout.resetForMeasure(); - measureView(mFooterLayout); - - switch (getPullToRefreshScrollDirection()) { - case HORIZONTAL: - mFooterDimension = mFooterLayout.getMeasuredWidth(); - pRight = -maximumPullScroll; - mFooterLayout.adjustWidthUsingRightPadding(maximumPullScroll); - break; - case VERTICAL: - default: - mFooterDimension = mFooterLayout.getMeasuredHeight(); - pBottom = -maximumPullScroll; - mFooterLayout.adjustHeightUsingBottomPadding(maximumPullScroll); - break; - } - - // We need to re-measure with the new padding... - measureView(mFooterLayout); - } - - setPadding(pLeft, pTop, pRight, pBottom); - } - final void setState(State state, final boolean... params) { mState = state; if (DEBUG) { @@ -750,7 +605,7 @@ protected LoadingLayout createLoadingLayout(Context context, Mode mode, TypedArr * Allows derivative classes to include any extra LoadingLayouts. */ protected LoadingLayoutProxy createLoadingLayoutProxy(final boolean includeStart, final boolean includeEnd) { - LoadingLayoutProxy proxy = new LoadingLayoutProxy(this); + LoadingLayoutProxy proxy = new LoadingLayoutProxy(); if (includeStart && mMode.showHeaderLoadingLayout()) { proxy.addLayout(mHeaderLayout); @@ -782,22 +637,22 @@ protected final void disableLoadingLayoutVisibilityChanges() { mLayoutVisibilityChangesEnabled = false; } - protected final int getFooterHeight() { - return mFooterDimension; - } - protected final LoadingLayout getFooterLayout() { return mFooterLayout; } - protected final int getHeaderHeight() { - return mHeaderDimension; + protected final int getFooterSize() { + return mFooterLayout.getContentSize(); } protected final LoadingLayout getHeaderLayout() { return mHeaderLayout; } + protected final int getHeaderSize() { + return mHeaderLayout.getContentSize(); + } + protected int getPullToRefreshScrollDuration() { return SMOOTH_SCROLL_DURATION_MS; } @@ -821,21 +676,21 @@ protected void handleStyledAttributes(TypedArray a) { /** * Implemented by derived class to return whether the View is in a state - * where the user can Pull to Refresh by scrolling from the start. + * where the user can Pull to Refresh by scrolling from the end. * - * @return true if the View is currently the correct state (for example, top - * of a ListView) + * @return true if the View is currently in the correct state (for example, + * bottom of a ListView) */ - protected abstract boolean isReadyForPullStart(); + protected abstract boolean isReadyForPullEnd(); /** * Implemented by derived class to return whether the View is in a state - * where the user can Pull to Refresh by scrolling from the end. + * where the user can Pull to Refresh by scrolling from the start. * - * @return true if the View is currently in the correct state (for example, - * bottom of a ListView) + * @return true if the View is currently the correct state (for example, top + * of a ListView) */ - protected abstract boolean isReadyForPullEnd(); + protected abstract boolean isReadyForPullStart(); /** * Called by {@link #onRestoreInstanceState(Parcelable)} so that derivative @@ -855,6 +710,89 @@ protected void onPtrRestoreInstanceState(Bundle savedInstanceState) { protected void onPtrSaveInstanceState(Bundle saveState) { } + /** + * Called when the UI has been to be updated to be in the + * {@link State#PULL_TO_REFRESH} state. + */ + protected void onPullToRefresh() { + switch (mCurrentMode) { + case PULL_FROM_END: + mFooterLayout.pullToRefresh(); + break; + case PULL_FROM_START: + mHeaderLayout.pullToRefresh(); + break; + default: + // NO-OP + break; + } + } + + /** + * Called when the UI has been to be updated to be in the + * {@link State#REFRESHING} or {@link State#MANUAL_REFRESHING} state. + * + * @param doScroll - Whether the UI should scroll for this event. + */ + protected void onRefreshing(final boolean doScroll) { + if (mMode.showHeaderLoadingLayout()) { + mHeaderLayout.refreshing(); + } + if (mMode.showFooterLoadingLayout()) { + mFooterLayout.refreshing(); + } + + if (doScroll) { + if (mShowViewWhileRefreshing) { + switch (mCurrentMode) { + case MANUAL_REFRESH_ONLY: + case PULL_FROM_END: + smoothScrollTo(getFooterSize()); + break; + default: + case PULL_FROM_START: + smoothScrollTo(-getHeaderSize()); + break; + } + } else { + smoothScrollTo(0); + } + } + } + + /** + * Called when the UI has been to be updated to be in the + * {@link State#RELEASE_TO_REFRESH} state. + */ + protected void onReleaseToRefresh() { + switch (mCurrentMode) { + case PULL_FROM_END: + mFooterLayout.releaseToRefresh(); + break; + case PULL_FROM_START: + mHeaderLayout.releaseToRefresh(); + break; + default: + // NO-OP + break; + } + } + + /** + * Called when the UI has been to be updated to be in the + * {@link State#RESET} state. + */ + protected void onReset() { + mIsBeingDragged = false; + mLayoutVisibilityChangesEnabled = true; + + // Always reset both layouts, just in case... + mHeaderLayout.reset(); + mFooterLayout.reset(); + + smoothScrollTo(0); + } + @Override protected final void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { @@ -901,9 +839,102 @@ protected final Parcelable onSaveInstanceState() { } @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { + protected final void onSizeChanged(int w, int h, int oldw, int oldh) { + if (DEBUG) { + Log.d(LOG_TAG, String.format("onSizeChanged. W: %d, H: %d", w, h)); + } + + super.onSizeChanged(w, h, oldw, oldh); + // We need to update the header/footer when our size changes refreshLoadingViewsSize(); + + // Update the Refreshable View layout + refreshRefreshableViewSize(w, h); + + /** + * As we're currently in a Layout Pass, we need to schedule another one + * to layout any changes we've made here + */ + post(new Runnable() { + @Override + public void run() { + requestLayout(); + } + }); + } + + /** + * Re-measure the Loading Views height, and adjust internal padding as + * necessary + */ + protected final void refreshLoadingViewsSize() { + final int maximumPullScroll = (int) (getMaximumPullScroll() * 1.2f); + + int pLeft = getPaddingLeft(); + int pTop = getPaddingTop(); + int pRight = getPaddingRight(); + int pBottom = getPaddingBottom(); + + switch (getPullToRefreshScrollDirection()) { + case HORIZONTAL: + if (mMode.showHeaderLoadingLayout()) { + mHeaderLayout.setWidth(maximumPullScroll); + pLeft = -maximumPullScroll; + } else { + pLeft = 0; + } + + if (mMode.showFooterLoadingLayout()) { + mFooterLayout.setWidth(maximumPullScroll); + pRight = -maximumPullScroll; + } else { + pRight = 0; + } + break; + + case VERTICAL: + if (mMode.showHeaderLoadingLayout()) { + mHeaderLayout.setHeight(maximumPullScroll); + pTop = -maximumPullScroll; + } else { + pTop = 0; + } + + if (mMode.showFooterLoadingLayout()) { + mFooterLayout.setHeight(maximumPullScroll); + pBottom = -maximumPullScroll; + } else { + pBottom = 0; + } + break; + } + + if (DEBUG) { + Log.d(LOG_TAG, String.format("Setting Padding. L: %d, T: %d, R: %d, B: %d", pLeft, pTop, pRight, pBottom)); + } + setPadding(pLeft, pTop, pRight, pBottom); + } + + protected final void refreshRefreshableViewSize(int width, int height) { + // We need to set the Height of the Refreshable View to the same as + // this layout + LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mRefreshableViewWrapper.getLayoutParams(); + + switch (getPullToRefreshScrollDirection()) { + case HORIZONTAL: + if (lp.width != width) { + lp.width = width; + mRefreshableViewWrapper.requestLayout(); + } + break; + case VERTICAL: + if (lp.height != height) { + lp.height = height; + mRefreshableViewWrapper.requestLayout(); + } + break; + } } /** @@ -913,6 +944,10 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { * @param value - New Scroll value */ protected final void setHeaderScroll(final int value) { + if (DEBUG) { + Log.d(LOG_TAG, "setHeaderScroll: " + value); + } + if (mLayoutVisibilityChangesEnabled) { if (value < 0) { mHeaderLayout.setVisibility(View.VISIBLE); @@ -999,17 +1034,8 @@ private void addRefreshableView(Context context, T refreshableView) { mRefreshableViewWrapper.addView(refreshableView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); - switch (getPullToRefreshScrollDirection()) { - case HORIZONTAL: - addViewInternal(mRefreshableViewWrapper, new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, - 1.0f)); - break; - case VERTICAL: - default: - addViewInternal(mRefreshableViewWrapper, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0, - 1.0f)); - break; - } + addViewInternal(mRefreshableViewWrapper, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT)); } @SuppressWarnings("deprecation") @@ -1097,29 +1123,6 @@ private boolean isReadyForPull() { } } - private void measureView(View child) { - ViewGroup.LayoutParams p = child.getLayoutParams(); - if (p == null) { - p = getLoadingLayoutLayoutParams(); - } - - int childWidthSpec, childHeightSpec; - - if (p.width == ViewGroup.LayoutParams.MATCH_PARENT) { - childWidthSpec = MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY); - } else { - childWidthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - } - - if (p.height == ViewGroup.LayoutParams.MATCH_PARENT) { - childHeightSpec = MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY); - } else { - childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - } - - child.measure(childWidthSpec, childHeightSpec); - } - /** * Actions a Pull Event * @@ -1146,12 +1149,12 @@ private void pullEvent() { switch (mCurrentMode) { case PULL_FROM_END: newScrollValue = Math.round(Math.max(initialMotionValue - lastMotionValue, 0) / FRICTION); - itemDimension = mFooterDimension; + itemDimension = getFooterSize(); break; case PULL_FROM_START: default: newScrollValue = Math.round(Math.min(initialMotionValue - lastMotionValue, 0) / FRICTION); - itemDimension = mHeaderDimension; + itemDimension = getHeaderSize(); break; } @@ -1380,14 +1383,14 @@ boolean permitsPullToRefresh() { /** * @return true if this mode wants the Loading Layout Header to be shown */ - boolean showHeaderLoadingLayout() { + public boolean showHeaderLoadingLayout() { return this == PULL_FROM_START || this == BOTH; } /** * @return true if this mode wants the Loading Layout Footer to be shown */ - boolean showFooterLoadingLayout() { + public boolean showFooterLoadingLayout() { return this == PULL_FROM_END || this == BOTH || this == MANUAL_REFRESH_ONLY; } @@ -1397,6 +1400,10 @@ int getIntValue() { } + // =========================================================== + // Inner, Anonymous Classes, and Enumerations + // =========================================================== + /** * Simple Listener that allows you to be notified when the user has scrolled * to the end of the AdapterView. See ( @@ -1413,10 +1420,6 @@ public static interface OnLastItemVisibleListener { } - // =========================================================== - // Inner and Anonymous Classes - // =========================================================== - /** * Listener that allows you to be notified when the user has started or * finished a touch event. Useful when you want to append extra UI events diff --git a/library/src/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java b/library/src/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java index 974618be5..649020c6d 100644 --- a/library/src/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java +++ b/library/src/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java @@ -20,7 +20,6 @@ import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.util.AttributeSet; -import android.view.ContextMenu.ContextMenuInfo; import android.view.View; import android.widget.ExpandableListView; @@ -44,11 +43,6 @@ public PullToRefreshExpandableListView(Context context, Mode mode, AnimationStyl super(context, mode, style); } - @Override - public ContextMenuInfo getContextMenuInfo() { - return ((InternalExpandableListView) getRefreshableView()).getContextMenuInfo(); - } - @Override public final Orientation getPullToRefreshScrollDirection() { return Orientation.VERTICAL; @@ -74,10 +68,6 @@ public InternalExpandableListView(Context context, AttributeSet attrs) { super(context, attrs); } - public ContextMenuInfo getContextMenuInfo() { - return super.getContextMenuInfo(); - } - @Override public void setEmptyView(View emptyView) { PullToRefreshExpandableListView.this.setEmptyView(emptyView); diff --git a/library/src/com/handmark/pulltorefresh/library/PullToRefreshGridView.java b/library/src/com/handmark/pulltorefresh/library/PullToRefreshGridView.java index e1db44977..f9506889a 100644 --- a/library/src/com/handmark/pulltorefresh/library/PullToRefreshGridView.java +++ b/library/src/com/handmark/pulltorefresh/library/PullToRefreshGridView.java @@ -20,7 +20,6 @@ import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.util.AttributeSet; -import android.view.ContextMenu.ContextMenuInfo; import android.view.View; import android.widget.GridView; @@ -44,11 +43,6 @@ public PullToRefreshGridView(Context context, Mode mode, AnimationStyle style) { super(context, mode, style); } - @Override - public ContextMenuInfo getContextMenuInfo() { - return ((InternalGridView) getRefreshableView()).getContextMenuInfo(); - } - @Override public final Orientation getPullToRefreshScrollDirection() { return Orientation.VERTICAL; @@ -74,11 +68,6 @@ public InternalGridView(Context context, AttributeSet attrs) { super(context, attrs); } - @Override - public ContextMenuInfo getContextMenuInfo() { - return super.getContextMenuInfo(); - } - @Override public void setEmptyView(View emptyView) { PullToRefreshGridView.this.setEmptyView(emptyView); diff --git a/library/src/com/handmark/pulltorefresh/library/PullToRefreshListView.java b/library/src/com/handmark/pulltorefresh/library/PullToRefreshListView.java index 17c1d7771..0aa9a27d6 100644 --- a/library/src/com/handmark/pulltorefresh/library/PullToRefreshListView.java +++ b/library/src/com/handmark/pulltorefresh/library/PullToRefreshListView.java @@ -22,7 +22,6 @@ import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.util.AttributeSet; -import android.view.ContextMenu.ContextMenuInfo; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -58,18 +57,13 @@ public PullToRefreshListView(Context context, Mode mode, AnimationStyle style) { super(context, mode, style); } - @Override - public ContextMenuInfo getContextMenuInfo() { - return ((InternalListView) getRefreshableView()).getContextMenuInfo(); - } - @Override public final Orientation getPullToRefreshScrollDirection() { return Orientation.VERTICAL; } @Override - void onRefreshing(final boolean doScroll) { + protected void onRefreshing(final boolean doScroll) { /** * If we're not showing the Refreshing view, or the list is empty, the * the header/footer views won't show so we use the normal method. @@ -92,7 +86,7 @@ void onRefreshing(final boolean doScroll) { listViewLoadingView = mFooterLoadingView; oppositeListViewLoadingView = mHeaderLoadingView; selection = mRefreshableView.getCount() - 1; - scrollToY = getScrollY() - getFooterHeight(); + scrollToY = getScrollY() - getFooterSize(); break; case PULL_FROM_START: default: @@ -100,12 +94,13 @@ void onRefreshing(final boolean doScroll) { listViewLoadingView = mHeaderLoadingView; oppositeListViewLoadingView = mFooterLoadingView; selection = 0; - scrollToY = getScrollY() + getHeaderHeight(); + scrollToY = getScrollY() + getHeaderSize(); break; } // Hide our original Loading View - origLoadingView.setVisibility(View.INVISIBLE); + origLoadingView.reset(); + origLoadingView.hideAllViews(); // Make sure the opposite end is hidden too oppositeListViewLoadingView.setVisibility(View.GONE); @@ -132,7 +127,7 @@ void onRefreshing(final boolean doScroll) { } @Override - void onReset() { + protected void onReset() { /** * If the extras are not enabled, just call up to super and return. */ @@ -151,14 +146,14 @@ void onReset() { originalLoadingLayout = getFooterLayout(); listViewLoadingLayout = mFooterLoadingView; selection = mRefreshableView.getCount() - 1; - scrollToHeight = getFooterHeight(); + scrollToHeight = getFooterSize(); scrollLvToEdge = Math.abs(mRefreshableView.getLastVisiblePosition() - selection) <= 1; break; case PULL_FROM_START: default: originalLoadingLayout = getHeaderLayout(); listViewLoadingLayout = mHeaderLoadingView; - scrollToHeight = -getHeaderHeight(); + scrollToHeight = -getHeaderSize(); selection = 0; scrollLvToEdge = Math.abs(mRefreshableView.getFirstVisiblePosition() - selection) <= 1; break; @@ -169,7 +164,7 @@ void onReset() { if (listViewLoadingLayout.getVisibility() == View.VISIBLE) { // Set our Original View to Visible - originalLoadingLayout.setVisibility(View.VISIBLE); + originalLoadingLayout.showInvisibleViews(); // Hide the ListView Header/Footer listViewLoadingLayout.setVisibility(View.GONE); @@ -316,10 +311,6 @@ public boolean dispatchTouchEvent(MotionEvent ev) { } } - public ContextMenuInfo getContextMenuInfo() { - return super.getContextMenuInfo(); - } - @Override public void setAdapter(ListAdapter adapter) { // Add the Footer View at the last possible moment diff --git a/library/src/com/handmark/pulltorefresh/library/internal/LoadingLayout.java b/library/src/com/handmark/pulltorefresh/library/internal/LoadingLayout.java index 3c7d4541b..b9e715050 100644 --- a/library/src/com/handmark/pulltorefresh/library/internal/LoadingLayout.java +++ b/library/src/com/handmark/pulltorefresh/library/internal/LoadingLayout.java @@ -18,15 +18,16 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.res.ColorStateList; -import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Typeface; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.TypedValue; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; @@ -46,6 +47,8 @@ public abstract class LoadingLayout extends FrameLayout implements ILoadingLayou static final Interpolator ANIMATION_INTERPOLATOR = new LinearInterpolator(); + private FrameLayout mInnerLayout; + protected final ImageView mHeaderImage; protected final ProgressBar mHeaderProgress; @@ -66,8 +69,6 @@ public LoadingLayout(Context context, final Mode mode, final Orientation scrollD mMode = mode; mScrollDirection = scrollDirection; - resetPadding(); - switch (scrollDirection) { case HORIZONTAL: LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_horizontal, this); @@ -78,13 +79,18 @@ public LoadingLayout(Context context, final Mode mode, final Orientation scrollD break; } - mHeaderText = (TextView) findViewById(R.id.pull_to_refresh_text); - mHeaderProgress = (ProgressBar) findViewById(R.id.pull_to_refresh_progress); - mSubHeaderText = (TextView) findViewById(R.id.pull_to_refresh_sub_text); - mHeaderImage = (ImageView) findViewById(R.id.pull_to_refresh_image); + mInnerLayout = (FrameLayout) findViewById(R.id.fl_inner); + mHeaderText = (TextView) mInnerLayout.findViewById(R.id.pull_to_refresh_text); + mHeaderProgress = (ProgressBar) mInnerLayout.findViewById(R.id.pull_to_refresh_progress); + mSubHeaderText = (TextView) mInnerLayout.findViewById(R.id.pull_to_refresh_sub_text); + mHeaderImage = (ImageView) mInnerLayout.findViewById(R.id.pull_to_refresh_image); + + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mInnerLayout.getLayoutParams(); switch (mode) { case PULL_FROM_END: + lp.gravity = scrollDirection == Orientation.VERTICAL ? Gravity.TOP : Gravity.LEFT; + // Load in labels mPullLabel = context.getString(R.string.pull_to_refresh_from_bottom_pull_label); mRefreshingLabel = context.getString(R.string.pull_to_refresh_from_bottom_refreshing_label); @@ -93,6 +99,8 @@ public LoadingLayout(Context context, final Mode mode, final Orientation scrollD case PULL_FROM_START: default: + lp.gravity = scrollDirection == Orientation.VERTICAL ? Gravity.BOTTOM : Gravity.RIGHT; + // Load in labels mPullLabel = context.getString(R.string.pull_to_refresh_pull_label); mRefreshingLabel = context.getString(R.string.pull_to_refresh_refreshing_label); @@ -172,24 +180,41 @@ public LoadingLayout(Context context, final Mode mode, final Orientation scrollD reset(); } - public final void adjustHeightUsingBottomPadding(final int height) { - setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom() + height - - getMeasuredHeight()); + public final void setHeight(int height) { + ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams(); + lp.height = height; + requestLayout(); } - public final void adjustHeightUsingTopPadding(final int height) { - setPadding(getPaddingLeft(), getPaddingTop() + height - getMeasuredHeight(), getPaddingRight(), - getPaddingBottom()); + public final void setWidth(int width) { + ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams(); + lp.width = width; + requestLayout(); } - public final void adjustWidthUsingLeftPadding(final int width) { - setPadding(getPaddingLeft() + width - getMeasuredWidth(), getPaddingTop(), getPaddingRight(), - getPaddingBottom()); + public final int getContentSize() { + switch (mScrollDirection) { + case HORIZONTAL: + return mInnerLayout.getWidth(); + case VERTICAL: + default: + return mInnerLayout.getHeight(); + } } - public final void adjustWidthUsingRightPadding(final int width) { - setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight() + width - getMeasuredWidth(), - getPaddingBottom()); + public final void hideAllViews() { + if (View.VISIBLE == mHeaderText.getVisibility()) { + mHeaderText.setVisibility(View.INVISIBLE); + } + if (View.VISIBLE == mHeaderProgress.getVisibility()) { + mHeaderProgress.setVisibility(View.INVISIBLE); + } + if (View.VISIBLE == mHeaderImage.getVisibility()) { + mHeaderImage.setVisibility(View.INVISIBLE); + } + if (View.VISIBLE == mSubHeaderText.getVisibility()) { + mSubHeaderText.setVisibility(View.INVISIBLE); + } } public final void onPull(float scaleOfLayout) { @@ -255,10 +280,6 @@ public final void reset() { } } - public final void resetForMeasure() { - resetPadding(); - } - @Override public void setLastUpdatedLabel(CharSequence label) { setSubHeaderText(label); @@ -290,6 +311,21 @@ public void setTextTypeface(Typeface tf) { mHeaderText.setTypeface(tf); } + public final void showInvisibleViews() { + if (View.INVISIBLE == mHeaderText.getVisibility()) { + mHeaderText.setVisibility(View.VISIBLE); + } + if (View.INVISIBLE == mHeaderProgress.getVisibility()) { + mHeaderProgress.setVisibility(View.VISIBLE); + } + if (View.INVISIBLE == mHeaderImage.getVisibility()) { + mHeaderImage.setVisibility(View.VISIBLE); + } + if (View.INVISIBLE == mSubHeaderText.getVisibility()) { + mSubHeaderText.setVisibility(View.VISIBLE); + } + } + /** * Callbacks for derivative Layouts */ @@ -308,14 +344,6 @@ public void setTextTypeface(Typeface tf) { protected abstract void resetImpl(); - private void resetPadding() { - Resources res = getResources(); - final int tbPadding = res.getDimensionPixelSize(R.dimen.header_footer_top_bottom_padding); - final int lrPadding = res.getDimensionPixelSize(R.dimen.header_footer_left_right_padding); - setPadding(lrPadding, tbPadding, lrPadding, tbPadding); - - } - private void setSubHeaderText(CharSequence label) { if (null != mSubHeaderText) { if (TextUtils.isEmpty(label)) { diff --git a/pom.xml b/pom.xml index 9948458a1..516f13b16 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.github.chrisbanes.pulltorefresh parent pom - 2.1 + 2.1.1 Android-PullToRefresh Project Implementation of the Pull-to-Refresh UI Pattern for Android. https://github.com/chrisbanes/Android-PullToRefresh @@ -24,7 +24,7 @@ https://github.com/chrisbanes/Android-PullToRefresh scm:git:git://github.com/chrisbanes/Android-PullToRefresh.git scm:git:git@github.com:chrisbanes/Android-PullToRefresh.git - v2.1 + v2.1.1 diff --git a/sample/AndroidManifest.xml b/sample/AndroidManifest.xml index 714039c1f..af06dffa8 100755 --- a/sample/AndroidManifest.xml +++ b/sample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="2110" + android:versionName="2.1.1" > + + diff --git a/sample/pom.xml b/sample/pom.xml index 48f65b6b0..7f18729d6 100644 --- a/sample/pom.xml +++ b/sample/pom.xml @@ -10,7 +10,7 @@ com.github.chrisbanes.pulltorefresh parent - 2.1 + 2.1.1 diff --git a/sample/res/layout/activity_ptr_list_in_vp.xml b/sample/res/layout/activity_ptr_list_in_vp.xml new file mode 100755 index 000000000..a04737689 --- /dev/null +++ b/sample/res/layout/activity_ptr_list_in_vp.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/sample/res/layout/layout_listview_in_viewpager.xml b/sample/res/layout/layout_listview_in_viewpager.xml new file mode 100644 index 000000000..3bfc689d4 --- /dev/null +++ b/sample/res/layout/layout_listview_in_viewpager.xml @@ -0,0 +1,6 @@ + + diff --git a/sample/src/com/handmark/pulltorefresh/samples/LauncherActivity.java b/sample/src/com/handmark/pulltorefresh/samples/LauncherActivity.java index 5d9730ce2..8eb47bc91 100644 --- a/sample/src/com/handmark/pulltorefresh/samples/LauncherActivity.java +++ b/sample/src/com/handmark/pulltorefresh/samples/LauncherActivity.java @@ -25,7 +25,7 @@ public class LauncherActivity extends ListActivity { public static final String[] options = { "ListView", "ExpandableListView", "GridView", "WebView", "ScrollView", - "Horizontal ScrollView", "ViewPager", "ListView Fragment", "WebView Advanced" }; + "Horizontal ScrollView", "ViewPager", "ListView Fragment", "WebView Advanced", "ListView in ViewPager" }; @Override protected void onCreate(Bundle savedInstanceState) { @@ -66,6 +66,9 @@ protected void onListItemClick(ListView l, View v, int position, long id) { case 8: intent = new Intent(this, PullToRefreshWebView2Activity.class); break; + case 9: + intent = new Intent(this, PullToRefreshListInViewPagerActivity.class); + break; } startActivity(intent); diff --git a/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListActivity.java b/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListActivity.java index 700185069..13b572ea2 100755 --- a/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListActivity.java +++ b/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListActivity.java @@ -22,8 +22,12 @@ import android.os.AsyncTask; import android.os.Bundle; import android.text.format.DateUtils; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; import android.view.Menu; import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; @@ -81,6 +85,9 @@ public void onLastItemVisible() { ListView actualListView = mPullRefreshListView.getRefreshableView(); + // Need to use the Actual ListView when registering for Context Menu + registerForContextMenu(actualListView); + mListItems = new LinkedList(); mListItems.addAll(Arrays.asList(mStrings)); @@ -136,6 +143,19 @@ public boolean onCreateOptionsMenu(Menu menu) { return super.onCreateOptionsMenu(menu); } + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { + AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; + + menu.setHeaderTitle("Item: " + getListView().getItemAtPosition(info.position)); + menu.add("Item 1"); + menu.add("Item 2"); + menu.add("Item 3"); + menu.add("Item 4"); + + super.onCreateContextMenu(menu, v, menuInfo); + } + @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem disableItem = menu.findItem(MENU_DISABLE_SCROLL); diff --git a/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListInViewPagerActivity.java b/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListInViewPagerActivity.java new file mode 100644 index 000000000..45b9b1e32 --- /dev/null +++ b/sample/src/com/handmark/pulltorefresh/samples/PullToRefreshListInViewPagerActivity.java @@ -0,0 +1,110 @@ +package com.handmark.pulltorefresh.samples; + +import java.util.Arrays; + +import android.app.Activity; +import android.content.Context; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; +import android.widget.ListView; + +import com.handmark.pulltorefresh.library.PullToRefreshBase; +import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; +import com.handmark.pulltorefresh.library.PullToRefreshListView; + +public class PullToRefreshListInViewPagerActivity extends Activity implements OnRefreshListener { + + private static final String[] STRINGS = { "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", + "Ackawi", "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre", + "Allgauer Emmentaler", "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi", + "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre", + "Allgauer Emmentaler" }; + + private ViewPager mViewPager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_ptr_list_in_vp); + + mViewPager = (ViewPager) findViewById(R.id.vp_list); + mViewPager.setAdapter(new ListViewPagerAdapter()); + } + + private class ListViewPagerAdapter extends PagerAdapter { + + @Override + public View instantiateItem(ViewGroup container, int position) { + Context context = container.getContext(); + + PullToRefreshListView plv = (PullToRefreshListView) LayoutInflater.from(context).inflate( + R.layout.layout_listview_in_viewpager, container, false); + + ListAdapter adapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1, + Arrays.asList(STRINGS)); + plv.setAdapter(adapter); + + plv.setOnRefreshListener(PullToRefreshListInViewPagerActivity.this); + + // Now just add ListView to ViewPager and return it + container.addView(plv, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + + return plv; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + container.removeView((View) object); + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return view == object; + } + + @Override + public int getCount() { + return 3; + } + + } + + @Override + public void onRefresh(PullToRefreshBase refreshView) { + new GetDataTask(refreshView).execute(); + } + + private static class GetDataTask extends AsyncTask { + + PullToRefreshBase mRefreshedView; + + public GetDataTask(PullToRefreshBase refreshedView) { + mRefreshedView = refreshedView; + } + + @Override + protected Void doInBackground(Void... params) { + // Simulates a background job. + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + mRefreshedView.onRefreshComplete(); + super.onPostExecute(result); + } + } + +}