From 251e575421dd808083605d391deddf83987c27a0 Mon Sep 17 00:00:00 2001 From: Max Pop Date: Mon, 21 Sep 2020 12:17:55 +0200 Subject: [PATCH] Resign all with gpg key --- core/pulltorefresh/build.gradle | 8 - core/pulltorefresh/lint-baseline.xml | 326 ---- .../src/main/AndroidManifest.xml | 6 - .../pulltorefresh/library/ILoadingLayout.java | 57 - .../pulltorefresh/library/IPullToRefresh.java | 246 --- .../library/LoadingLayoutProxy.java | 73 - .../library/OverscrollHelper.java | 178 -- .../library/PullToRefreshAdapterViewBase.java | 475 ----- .../library/PullToRefreshBase.java | 1653 ----------------- .../PullToRefreshExpandableListView.java | 103 - .../library/PullToRefreshGridView.java | 102 - .../PullToRefreshHorizontalScrollView.java | 110 -- .../library/PullToRefreshListView.java | 337 ---- .../library/PullToRefreshScrollView.java | 109 -- .../library/PullToRefreshWebView.java | 164 -- .../library/extras/PullToRefreshWebView2.java | 132 -- .../extras/SoundPullEventListener.java | 96 - .../internal/EmptyViewMethodAccessor.java | 43 - .../library/internal/FlipLoadingLayout.java | 146 -- .../library/internal/IndicatorLayout.java | 147 -- .../library/internal/LoadingLayout.java | 393 ---- .../library/internal/RotateLoadingLayout.java | 110 -- .../pulltorefresh/library/internal/Utils.java | 13 - .../library/internal/ViewCompat.java | 70 - .../main/res/anim/slide_in_from_bottom.xml | 21 - .../src/main/res/anim/slide_in_from_top.xml | 21 - .../src/main/res/anim/slide_out_to_bottom.xml | 21 - .../src/main/res/anim/slide_out_to_top.xml | 21 - .../res/drawable-hdpi/default_ptr_flip.png | Bin 1835 -> 0 bytes .../res/drawable-hdpi/default_ptr_rotate.png | Bin 48963 -> 0 bytes .../res/drawable-hdpi/indicator_arrow.png | Bin 390 -> 0 bytes .../res/drawable-mdpi/default_ptr_flip.png | Bin 1612 -> 0 bytes .../res/drawable-mdpi/default_ptr_rotate.png | Bin 49665 -> 0 bytes .../res/drawable-mdpi/indicator_arrow.png | Bin 445 -> 0 bytes .../res/drawable-xhdpi/default_ptr_flip.png | Bin 1983 -> 0 bytes .../res/drawable-xhdpi/default_ptr_rotate.png | Bin 50019 -> 0 bytes .../res/drawable-xhdpi/indicator_arrow.png | Bin 429 -> 0 bytes .../main/res/drawable/indicator_bg_bottom.xml | 18 - .../main/res/drawable/indicator_bg_top.xml | 18 - .../pull_to_refresh_header_horizontal.xml | 29 - .../pull_to_refresh_header_vertical.xml | 59 - .../res/values-ar/pull_refresh_strings.xml | 6 - .../res/values-cs/pull_refresh_strings.xml | 6 - .../res/values-de/pull_refresh_strings.xml | 6 - .../res/values-es/pull_refresh_strings.xml | 6 - .../res/values-fi/pull_refresh_strings.xml | 13 - .../res/values-fr/pull_refresh_strings.xml | 6 - .../res/values-he/pull_refresh_strings.xml | 6 - .../res/values-it/pull_refresh_strings.xml | 6 - .../res/values-iw/pull_refresh_strings.xml | 6 - .../res/values-ja/pull_refresh_strings.xml | 6 - .../res/values-ko/pull_refresh_strings.xml | 6 - .../res/values-nl/pull_refresh_strings.xml | 6 - .../res/values-pl/pull_refresh_strings.xml | 6 - .../values-pt-rBR/pull_refresh_strings.xml | 6 - .../res/values-pt/pull_refresh_strings.xml | 6 - .../res/values-ro/pull_refresh_strings.xml | 6 - .../res/values-ru/pull_refresh_strings.xml | 6 - .../res/values-zh/pull_refresh_strings.xml | 6 - .../src/main/res/values/attrs.xml | 80 - .../src/main/res/values/dimens.xml | 10 - .../pulltorefresh/src/main/res/values/ids.xml | 8 - .../main/res/values/pull_refresh_strings.xml | 13 - settings.gradle | 1 - ultrasonic/build.gradle | 1 - ultrasonic/src/main/assets/html/fr/index.html | 2 +- .../ultrasonic/activity/BookmarkActivity.java | 16 +- .../ultrasonic/activity/ChatActivity.java | 54 +- .../activity/SelectAlbumActivity.java | 46 +- .../activity/SelectArtistActivity.java | 18 +- .../activity/SelectGenreActivity.java | 18 +- .../activity/SelectPlaylistActivity.java | 15 +- .../ultrasonic/activity/ShareActivity.java | 17 +- .../drawable-hdpi/ic_menu_refresh_dark.png | Bin 0 -> 498 bytes .../drawable-hdpi/ic_menu_refresh_light.png | Bin 0 -> 492 bytes .../drawable-mdpi/ic_menu_refresh_dark.png | Bin 0 -> 412 bytes .../drawable-mdpi/ic_menu_refresh_light.png | Bin 0 -> 391 bytes .../drawable-xhdpi/ic_menu_refresh_dark.png | Bin 0 -> 712 bytes .../drawable-xhdpi/ic_menu_refresh_light.png | Bin 0 -> 698 bytes .../drawable-xxhdpi/ic_menu_refresh_dark.png | Bin 0 -> 1017 bytes .../drawable-xxhdpi/ic_menu_refresh_light.png | Bin 0 -> 1002 bytes .../drawable-xxxhdpi/ic_menu_refresh_dark.png | Bin 0 -> 1277 bytes .../ic_menu_refresh_light.png | Bin 0 -> 1277 bytes ultrasonic/src/main/res/layout/chat.xml | 24 +- .../src/main/res/layout/select_album.xml | 22 +- .../src/main/res/layout/select_artist.xml | 22 +- .../src/main/res/layout/select_genre.xml | 22 +- .../src/main/res/layout/select_playlist.xml | 22 +- .../src/main/res/layout/select_share.xml | 29 +- ultrasonic/src/main/res/menu/chat.xml | 9 + ultrasonic/src/main/res/values-de/strings.xml | 1 + ultrasonic/src/main/res/values-es/strings.xml | 1 + ultrasonic/src/main/res/values-fr/strings.xml | 1 + ultrasonic/src/main/res/values-hu/strings.xml | 1 + ultrasonic/src/main/res/values-nl/strings.xml | 1 + ultrasonic/src/main/res/values-pl/strings.xml | 1 + .../src/main/res/values-pt-rBR/strings.xml | 1 + ultrasonic/src/main/res/values-pt/strings.xml | 1 + ultrasonic/src/main/res/values/strings.xml | 1 + ultrasonic/src/main/res/values/styles.xml | 1 + ultrasonic/src/main/res/values/themes.xml | 2 + 101 files changed, 185 insertions(+), 5696 deletions(-) delete mode 100644 core/pulltorefresh/build.gradle delete mode 100644 core/pulltorefresh/lint-baseline.xml delete mode 100644 core/pulltorefresh/src/main/AndroidManifest.xml delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/ILoadingLayout.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/IPullToRefresh.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/OverscrollHelper.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshBase.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshGridView.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshHorizontalScrollView.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshListView.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshScrollView.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshWebView.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/extras/PullToRefreshWebView2.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/extras/SoundPullEventListener.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/EmptyViewMethodAccessor.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/FlipLoadingLayout.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/IndicatorLayout.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/LoadingLayout.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/RotateLoadingLayout.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/Utils.java delete mode 100644 core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/ViewCompat.java delete mode 100644 core/pulltorefresh/src/main/res/anim/slide_in_from_bottom.xml delete mode 100644 core/pulltorefresh/src/main/res/anim/slide_in_from_top.xml delete mode 100644 core/pulltorefresh/src/main/res/anim/slide_out_to_bottom.xml delete mode 100644 core/pulltorefresh/src/main/res/anim/slide_out_to_top.xml delete mode 100644 core/pulltorefresh/src/main/res/drawable-hdpi/default_ptr_flip.png delete mode 100644 core/pulltorefresh/src/main/res/drawable-hdpi/default_ptr_rotate.png delete mode 100644 core/pulltorefresh/src/main/res/drawable-hdpi/indicator_arrow.png delete mode 100644 core/pulltorefresh/src/main/res/drawable-mdpi/default_ptr_flip.png delete mode 100644 core/pulltorefresh/src/main/res/drawable-mdpi/default_ptr_rotate.png delete mode 100644 core/pulltorefresh/src/main/res/drawable-mdpi/indicator_arrow.png delete mode 100644 core/pulltorefresh/src/main/res/drawable-xhdpi/default_ptr_flip.png delete mode 100644 core/pulltorefresh/src/main/res/drawable-xhdpi/default_ptr_rotate.png delete mode 100644 core/pulltorefresh/src/main/res/drawable-xhdpi/indicator_arrow.png delete mode 100644 core/pulltorefresh/src/main/res/drawable/indicator_bg_bottom.xml delete mode 100644 core/pulltorefresh/src/main/res/drawable/indicator_bg_top.xml delete mode 100644 core/pulltorefresh/src/main/res/layout/pull_to_refresh_header_horizontal.xml delete mode 100644 core/pulltorefresh/src/main/res/layout/pull_to_refresh_header_vertical.xml delete mode 100644 core/pulltorefresh/src/main/res/values-ar/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-cs/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-de/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-es/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-fi/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-fr/pull_refresh_strings.xml delete mode 100644 core/pulltorefresh/src/main/res/values-he/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-it/pull_refresh_strings.xml delete mode 100644 core/pulltorefresh/src/main/res/values-iw/pull_refresh_strings.xml delete mode 100644 core/pulltorefresh/src/main/res/values-ja/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-ko/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-nl/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-pl/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-pt-rBR/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-pt/pull_refresh_strings.xml delete mode 100644 core/pulltorefresh/src/main/res/values-ro/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-ru/pull_refresh_strings.xml delete mode 100755 core/pulltorefresh/src/main/res/values-zh/pull_refresh_strings.xml delete mode 100644 core/pulltorefresh/src/main/res/values/attrs.xml delete mode 100644 core/pulltorefresh/src/main/res/values/dimens.xml delete mode 100644 core/pulltorefresh/src/main/res/values/ids.xml delete mode 100755 core/pulltorefresh/src/main/res/values/pull_refresh_strings.xml create mode 100644 ultrasonic/src/main/res/drawable-hdpi/ic_menu_refresh_dark.png create mode 100644 ultrasonic/src/main/res/drawable-hdpi/ic_menu_refresh_light.png create mode 100644 ultrasonic/src/main/res/drawable-mdpi/ic_menu_refresh_dark.png create mode 100644 ultrasonic/src/main/res/drawable-mdpi/ic_menu_refresh_light.png create mode 100644 ultrasonic/src/main/res/drawable-xhdpi/ic_menu_refresh_dark.png create mode 100644 ultrasonic/src/main/res/drawable-xhdpi/ic_menu_refresh_light.png create mode 100644 ultrasonic/src/main/res/drawable-xxhdpi/ic_menu_refresh_dark.png create mode 100644 ultrasonic/src/main/res/drawable-xxhdpi/ic_menu_refresh_light.png create mode 100644 ultrasonic/src/main/res/drawable-xxxhdpi/ic_menu_refresh_dark.png create mode 100644 ultrasonic/src/main/res/drawable-xxxhdpi/ic_menu_refresh_light.png create mode 100644 ultrasonic/src/main/res/menu/chat.xml diff --git a/core/pulltorefresh/build.gradle b/core/pulltorefresh/build.gradle deleted file mode 100644 index 102c5711..00000000 --- a/core/pulltorefresh/build.gradle +++ /dev/null @@ -1,8 +0,0 @@ -apply from: bootstrap.androidModule - -android { - lintOptions { - baselineFile file("lint-baseline.xml") - abortOnError true - } -} diff --git a/core/pulltorefresh/lint-baseline.xml b/core/pulltorefresh/lint-baseline.xml deleted file mode 100644 index 771b65e4..00000000 --- a/core/pulltorefresh/lint-baseline.xml +++ /dev/null @@ -1,326 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/core/pulltorefresh/src/main/AndroidManifest.xml b/core/pulltorefresh/src/main/AndroidManifest.xml deleted file mode 100644 index 2dc1eb5f..00000000 --- a/core/pulltorefresh/src/main/AndroidManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/ILoadingLayout.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/ILoadingLayout.java deleted file mode 100644 index ff2a9572..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/ILoadingLayout.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.handmark.pulltorefresh.library; - -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; - -public interface ILoadingLayout { - - /** - * Set the Last Updated Text. This displayed under the main label when - * Pulling - * - * @param label - Label to set - */ - public void setLastUpdatedLabel(CharSequence label); - - /** - * Set the drawable used in the loading layout. This is the same as calling - * setLoadingDrawable(drawable, Mode.BOTH) - * - * @param drawable - Drawable to display - */ - public void setLoadingDrawable(Drawable drawable); - - /** - * Set Text to show when the Widget is being Pulled - * setPullLabel(releaseLabel, Mode.BOTH) - * - * @param pullLabel - CharSequence to display - */ - public void setPullLabel(CharSequence pullLabel); - - /** - * Set Text to show when the Widget is refreshing - * setRefreshingLabel(releaseLabel, Mode.BOTH) - * - * @param refreshingLabel - CharSequence to display - */ - public void setRefreshingLabel(CharSequence refreshingLabel); - - /** - * Set Text to show when the Widget is being pulled, and will refresh when - * released. This is the same as calling - * setReleaseLabel(releaseLabel, Mode.BOTH) - * - * @param releaseLabel - CharSequence to display - */ - public void setReleaseLabel(CharSequence releaseLabel); - - /** - * Set's the Sets the typeface and style in which the text should be - * displayed. Please see - * {@link android.widget.TextView#setTypeface(Typeface) - * TextView#setTypeface(Typeface)}. - */ - public void setTextTypeface(Typeface tf); - -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/IPullToRefresh.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/IPullToRefresh.java deleted file mode 100644 index a06cdd7c..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/IPullToRefresh.java +++ /dev/null @@ -1,246 +0,0 @@ -/******************************************************************************* - * 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.library; - -import android.view.View; -import android.view.animation.Interpolator; - -import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; -import com.handmark.pulltorefresh.library.PullToRefreshBase.OnPullEventListener; -import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; -import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener2; -import com.handmark.pulltorefresh.library.PullToRefreshBase.State; - -public interface IPullToRefresh { - - /** - * Demos the Pull-to-Refresh functionality to the user so that they are - * aware it is there. This could be useful when the user first opens your - * app, etc. The animation will only happen if the Refresh View (ListView, - * ScrollView, etc) is in a state where a Pull-to-Refresh could occur by a - * user's touch gesture (i.e. scrolled to the top/bottom). - * - * @return true - if the Demo has been started, false if not. - */ - public boolean demo(); - - /** - * Get the mode that this view is currently in. This is only really useful - * when using Mode.BOTH. - * - * @return Mode that the view is currently in - */ - public Mode getCurrentMode(); - - /** - * Returns whether the Touch Events are filtered or not. If true is - * returned, then the View will only use touch events where the difference - * in the Y-axis is greater than the difference in the X-axis. This means - * that the View will not interfere when it is used in a horizontal - * scrolling View (such as a ViewPager). - * - * @return boolean - true if the View is filtering Touch Events - */ - public boolean getFilterTouchEvents(); - - /** - * Returns a proxy object which allows you to call methods on all of the - * LoadingLayouts (the Views which show when Pulling/Refreshing). - *

- * You should not keep the result of this method any longer than you need - * it. - * - * @return Object which will proxy any calls you make on it, to all of the - * LoadingLayouts. - */ - public ILoadingLayout getLoadingLayoutProxy(); - - /** - * Returns a proxy object which allows you to call methods on the - * LoadingLayouts (the Views which show when Pulling/Refreshing). The actual - * LoadingLayout(s) which will be affected, are chosen by the parameters you - * give. - *

- * You should not keep the result of this method any longer than you need - * it. - * - * @param includeStart - Whether to include the Start/Header Views - * @param includeEnd - Whether to include the End/Footer Views - * @return Object which will proxy any calls you make on it, to the - * LoadingLayouts included. - */ - public ILoadingLayout getLoadingLayoutProxy(boolean includeStart, boolean includeEnd); - - /** - * Get the mode that this view has been set to. If this returns - * Mode.BOTH, you can use getCurrentMode() to - * check which mode the view is currently in - * - * @return Mode that the view has been set to - */ - public Mode getMode(); - - /** - * Get the Wrapped Refreshable View. Anything returned here has already been - * added to the content view. - * - * @return The View which is currently wrapped - */ - public T getRefreshableView(); - - /** - * Get whether the 'Refreshing' View should be automatically shown when - * refreshing. Returns true by default. - * - * @return - true if the Refreshing View will be show - */ - public boolean getShowViewWhileRefreshing(); - - /** - * @return - The state that the View is currently in. - */ - public State getState(); - - /** - * Whether Pull-to-Refresh is enabled - * - * @return enabled - */ - public boolean isPullToRefreshEnabled(); - - /** - * Gets whether Overscroll support is enabled. This is different to - * Android's standard Overscroll support (the edge-glow) which is available - * from GINGERBREAD onwards - * - * @return true - if both PullToRefresh-OverScroll and Android's inbuilt - * OverScroll are enabled - */ - public boolean isPullToRefreshOverScrollEnabled(); - - /** - * Returns whether the Widget is currently in the Refreshing mState - * - * @return true if the Widget is currently refreshing - */ - public boolean isRefreshing(); - - /** - * Returns whether the widget has enabled scrolling on the Refreshable View - * while refreshing. - * - * @return true if the widget has enabled scrolling while refreshing - */ - public boolean isScrollingWhileRefreshingEnabled(); - - /** - * Mark the current Refresh as complete. Will Reset the UI and hide the - * Refreshing View - */ - public void onRefreshComplete(); - - /** - * Set the Touch Events to be filtered or not. If set to true, then the View - * will only use touch events where the difference in the Y-axis is greater - * than the difference in the X-axis. This means that the View will not - * interfere when it is used in a horizontal scrolling View (such as a - * ViewPager), but will restrict which types of finger scrolls will trigger - * the View. - * - * @param filterEvents - true if you want to filter Touch Events. Default is - * true. - */ - public void setFilterTouchEvents(boolean filterEvents); - - /** - * Set the mode of Pull-to-Refresh that this view will use. - * - * @param mode - Mode to set the View to - */ - public void setMode(Mode mode); - - /** - * Set OnPullEventListener for the Widget - * - * @param listener - Listener to be used when the Widget has a pull event to - * propogate. - */ - public void setOnPullEventListener(OnPullEventListener listener); - - /** - * Set OnRefreshListener for the Widget - * - * @param listener - Listener to be used when the Widget is set to Refresh - */ - public void setOnRefreshListener(OnRefreshListener listener); - - /** - * Set OnRefreshListener for the Widget - * - * @param listener - Listener to be used when the Widget is set to Refresh - */ - public void setOnRefreshListener(OnRefreshListener2 listener); - - /** - * Sets whether Overscroll support is enabled. This is different to - * Android's standard Overscroll support (the edge-glow). This setting only - * takes effect when running on device with Android v2.3 or greater. - * - * @param enabled - true if you want Overscroll enabled - */ - public void setPullToRefreshOverScrollEnabled(boolean enabled); - - /** - * Sets the Widget to be in the refresh state. The UI will be updated to - * show the 'Refreshing' view, and be scrolled to show such. - */ - public void setRefreshing(); - - /** - * Sets the Widget to be in the refresh state. The UI will be updated to - * show the 'Refreshing' view. - * - * @param doScroll - true if you want to force a scroll to the Refreshing - * view. - */ - public void setRefreshing(boolean doScroll); - - /** - * Sets the Animation Interpolator that is used for animated scrolling. - * Defaults to a DecelerateInterpolator - * - * @param interpolator - Interpolator to use - */ - public void setScrollAnimationInterpolator(Interpolator interpolator); - - /** - * By default the Widget disables scrolling on the Refreshable View while - * refreshing. This method can change this behaviour. - * - * @param scrollingWhileRefreshingEnabled - true if you want to enable - * scrolling while refreshing - */ - public void setScrollingWhileRefreshingEnabled(boolean scrollingWhileRefreshingEnabled); - - /** - * A mutator to enable/disable whether the 'Refreshing' View should be - * automatically shown when refreshing. - * - * @param showView - */ - public void setShowViewWhileRefreshing(boolean showView); - -} \ No newline at end of file diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java deleted file mode 100644 index 5f76645d..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/LoadingLayoutProxy.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.handmark.pulltorefresh.library; - -import java.util.HashSet; - -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; - -import com.handmark.pulltorefresh.library.internal.LoadingLayout; - -public class LoadingLayoutProxy implements ILoadingLayout { - - private final HashSet mLoadingLayouts; - - LoadingLayoutProxy() { - mLoadingLayouts = new HashSet(); - } - - /** - * 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); - } - } - - @Override - public void setLastUpdatedLabel(CharSequence label) { - for (LoadingLayout layout : mLoadingLayouts) { - layout.setLastUpdatedLabel(label); - } - } - - @Override - public void setLoadingDrawable(Drawable drawable) { - for (LoadingLayout layout : mLoadingLayouts) { - layout.setLoadingDrawable(drawable); - } - } - - @Override - public void setRefreshingLabel(CharSequence refreshingLabel) { - for (LoadingLayout layout : mLoadingLayouts) { - layout.setRefreshingLabel(refreshingLabel); - } - } - - @Override - public void setPullLabel(CharSequence label) { - for (LoadingLayout layout : mLoadingLayouts) { - layout.setPullLabel(label); - } - } - - @Override - public void setReleaseLabel(CharSequence label) { - for (LoadingLayout layout : mLoadingLayouts) { - layout.setReleaseLabel(label); - } - } - - public void setTextTypeface(Typeface tf) { - for (LoadingLayout layout : mLoadingLayouts) { - layout.setTextTypeface(tf); - } - } -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/OverscrollHelper.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/OverscrollHelper.java deleted file mode 100644 index 52a20de2..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/OverscrollHelper.java +++ /dev/null @@ -1,178 +0,0 @@ -/******************************************************************************* - * 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.library; - -import android.annotation.TargetApi; -import android.util.Log; -import android.view.View; - -import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; -import com.handmark.pulltorefresh.library.PullToRefreshBase.State; - -@TargetApi(9) -public final class OverscrollHelper { - - static final String LOG_TAG = "OverscrollHelper"; - static final float DEFAULT_OVERSCROLL_SCALE = 1f; - - /** - * Helper method for Overscrolling that encapsulates all of the necessary - * function. - *

- * This should only be used on AdapterView's such as ListView as it just - * calls through to overScrollBy() with the scrollRange = 0. AdapterView's - * do not have a scroll range (i.e. getScrollY() doesn't work). - * - * @param view - PullToRefreshView that is calling this. - * @param deltaX - Change in X in pixels, passed through from from - * overScrollBy call - * @param scrollX - Current X scroll value in pixels before applying deltaY, - * passed through from from overScrollBy call - * @param deltaY - Change in Y in pixels, passed through from from - * overScrollBy call - * @param scrollY - Current Y scroll value in pixels before applying deltaY, - * passed through from from overScrollBy call - * @param isTouchEvent - true if this scroll operation is the result of a - * touch event, passed through from from overScrollBy call - */ - public static void overScrollBy(final PullToRefreshBase view, final int deltaX, final int scrollX, - final int deltaY, final int scrollY, final boolean isTouchEvent) { - overScrollBy(view, deltaX, scrollX, deltaY, scrollY, 0, isTouchEvent); - } - - /** - * Helper method for Overscrolling that encapsulates all of the necessary - * function. This version of the call is used for Views that need to specify - * a Scroll Range but scroll back to it's edge correctly. - * - * @param view - PullToRefreshView that is calling this. - * @param deltaX - Change in X in pixels, passed through from from - * overScrollBy call - * @param scrollX - Current X scroll value in pixels before applying deltaY, - * passed through from from overScrollBy call - * @param deltaY - Change in Y in pixels, passed through from from - * overScrollBy call - * @param scrollY - Current Y scroll value in pixels before applying deltaY, - * passed through from from overScrollBy call - * @param scrollRange - Scroll Range of the View, specifically needed for - * ScrollView - * @param isTouchEvent - true if this scroll operation is the result of a - * touch event, passed through from from overScrollBy call - */ - public static void overScrollBy(final PullToRefreshBase view, final int deltaX, final int scrollX, - final int deltaY, final int scrollY, final int scrollRange, final boolean isTouchEvent) { - overScrollBy(view, deltaX, scrollX, deltaY, scrollY, scrollRange, 0, DEFAULT_OVERSCROLL_SCALE, isTouchEvent); - } - - /** - * Helper method for Overscrolling that encapsulates all of the necessary - * function. This is the advanced version of the call. - * - * @param view - PullToRefreshView that is calling this. - * @param deltaX - Change in X in pixels, passed through from from - * overScrollBy call - * @param scrollX - Current X scroll value in pixels before applying deltaY, - * passed through from from overScrollBy call - * @param deltaY - Change in Y in pixels, passed through from from - * overScrollBy call - * @param scrollY - Current Y scroll value in pixels before applying deltaY, - * passed through from from overScrollBy call - * @param scrollRange - Scroll Range of the View, specifically needed for - * ScrollView - * @param fuzzyThreshold - Threshold for which the values how fuzzy we - * should treat the other values. Needed for WebView as it - * doesn't always scroll back to it's edge. 0 = no fuzziness. - * @param scaleFactor - Scale Factor for overscroll amount - * @param isTouchEvent - true if this scroll operation is the result of a - * touch event, passed through from from overScrollBy call - */ - public static void overScrollBy(final PullToRefreshBase view, final int deltaX, final int scrollX, - final int deltaY, final int scrollY, final int scrollRange, final int fuzzyThreshold, - final float scaleFactor, final boolean isTouchEvent) { - - final int deltaValue, currentScrollValue, scrollValue; - switch (view.getPullToRefreshScrollDirection()) { - case HORIZONTAL: - deltaValue = deltaX; - scrollValue = scrollX; - currentScrollValue = view.getScrollX(); - break; - case VERTICAL: - default: - deltaValue = deltaY; - scrollValue = scrollY; - currentScrollValue = view.getScrollY(); - break; - } - - // Check that OverScroll is enabled and that we're not currently - // refreshing. - if (view.isPullToRefreshOverScrollEnabled() && !view.isRefreshing()) { - final Mode mode = view.getMode(); - - // Check that Pull-to-Refresh is enabled, and the event isn't from - // touch - if (mode.permitsPullToRefresh() && !isTouchEvent && deltaValue != 0) { - final int newScrollValue = (deltaValue + scrollValue); - - if (PullToRefreshBase.DEBUG) { - Log.d(LOG_TAG, "OverScroll. DeltaX: " + deltaX + ", ScrollX: " + scrollX + ", DeltaY: " + deltaY - + ", ScrollY: " + scrollY + ", NewY: " + newScrollValue + ", ScrollRange: " + scrollRange - + ", CurrentScroll: " + currentScrollValue); - } - - if (newScrollValue < (0 - fuzzyThreshold)) { - // Check the mode supports the overscroll direction, and - // then move scroll - if (mode.showHeaderLoadingLayout()) { - // If we're currently at zero, we're about to start - // overscrolling, so change the state - if (currentScrollValue == 0) { - view.setState(State.OVERSCROLLING); - } - - view.setHeaderScroll((int) (scaleFactor * (currentScrollValue + newScrollValue))); - } - } else if (newScrollValue > (scrollRange + fuzzyThreshold)) { - // Check the mode supports the overscroll direction, and - // then move scroll - if (mode.showFooterLoadingLayout()) { - // If we're currently at zero, we're about to start - // overscrolling, so change the state - if (currentScrollValue == 0) { - view.setState(State.OVERSCROLLING); - } - - view.setHeaderScroll((int) (scaleFactor * (currentScrollValue + newScrollValue - scrollRange))); - } - } else if (Math.abs(newScrollValue) <= fuzzyThreshold - || Math.abs(newScrollValue - scrollRange) <= fuzzyThreshold) { - // Means we've stopped overscrolling, so scroll back to 0 - view.setState(State.RESET); - } - } else if (isTouchEvent && State.OVERSCROLLING == view.getState()) { - // This condition means that we were overscrolling from a fling, - // but the user has touched the View and is now overscrolling - // from touch instead. We need to just reset. - view.setState(State.RESET); - } - } - } - - static boolean isAndroidOverScrollEnabled(View view) { - return view.getOverScrollMode() != View.OVER_SCROLL_NEVER; - } -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java deleted file mode 100644 index cfff8371..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java +++ /dev/null @@ -1,475 +0,0 @@ -/******************************************************************************* - * 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.library; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.util.Log; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.widget.AbsListView; -import android.widget.AbsListView.OnScrollListener; -import android.widget.Adapter; -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; -import com.handmark.pulltorefresh.library.internal.IndicatorLayout; - -public abstract class PullToRefreshAdapterViewBase extends PullToRefreshBase implements - OnScrollListener { - - 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; - - private IndicatorLayout mIndicatorIvTop; - private IndicatorLayout mIndicatorIvBottom; - - private boolean mShowIndicator; - private boolean mScrollEmptyView = true; - - public PullToRefreshAdapterViewBase(Context context) { - super(context); - mRefreshableView.setOnScrollListener(this); - } - - public PullToRefreshAdapterViewBase(Context context, AttributeSet attrs) { - super(context, attrs); - mRefreshableView.setOnScrollListener(this); - } - - public PullToRefreshAdapterViewBase(Context context, Mode mode) { - super(context, mode); - mRefreshableView.setOnScrollListener(this); - } - - public PullToRefreshAdapterViewBase(Context context, Mode mode, AnimationStyle animStyle) { - super(context, mode, animStyle); - mRefreshableView.setOnScrollListener(this); - } - - /** - * 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 - * when the Adapter View is scrolled to the top and the mode is set to - * {@link Mode#PULL_FROM_START}. The default value is true if - * {@link PullToRefreshBase#isPullToRefreshOverScrollEnabled() - * isPullToRefreshOverScrollEnabled()} returns false. - * - * @return true if the indicators will be shown - */ - public boolean getShowIndicator() { - return mShowIndicator; - } - - public final void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount, - final int totalItemCount) { - - if (DEBUG) { - Log.d(LOG_TAG, "First Visible: " + firstVisibleItem + ". Visible Count: " + visibleItemCount - + ". Total Items:" + totalItemCount); - } - - /** - * Set whether the Last Item is Visible. lastVisibleItemIndex is a - * zero-based index, so we minus one totalItemCount to check - */ - if (null != mOnLastItemVisibleListener) { - mLastItemVisible = (totalItemCount > 0) && (firstVisibleItem + visibleItemCount >= totalItemCount - 1); - } - - // If we're showing the indicator, check positions... - if (getShowIndicatorInternal()) { - updateIndicatorViewsVisibility(); - } - - // Finally call OnScrollListener if we have one - if (null != mOnScrollListener) { - mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); - } - } - - 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, state); - } - } - - /** - * Pass-through method for {@link PullToRefreshBase#getRefreshableView() - * getRefreshableView()}. - * {@link AdapterView#setAdapter(android.widget.Adapter)} - * setAdapter(adapter)}. This is just for convenience! - * - * @param adapter - Adapter to set - */ - public void setAdapter(ListAdapter adapter) { - ((AdapterView) mRefreshableView).setAdapter(adapter); - } - - /** - * Sets the Empty View to be used by the Adapter View. - *

- * We need it handle it ourselves so that we can Pull-to-Refresh when the - * Empty View is shown. - *

- * Please note, you do not usually need to call this method - * yourself. Calling setEmptyView on the AdapterView will automatically call - * this method and set everything up. This includes when the Android - * Framework automatically sets the Empty View based on it's ID. - * - * @param newEmptyView - Empty View to be used - */ - public final void setEmptyView(View newEmptyView) { - FrameLayout refreshableViewWrapper = getRefreshableViewWrapper(); - - if (null != newEmptyView) { - // New view needs to be clickable so that Android recognizes it as a - // target for Touch Events - newEmptyView.setClickable(true); - - ViewParent newEmptyViewParent = newEmptyView.getParent(); - if (null != newEmptyViewParent && newEmptyViewParent instanceof ViewGroup) { - ((ViewGroup) newEmptyViewParent).removeView(newEmptyView); - } - - // 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) { - ((EmptyViewMethodAccessor) mRefreshableView).setEmptyViewInternal(newEmptyView); - } else { - mRefreshableView.setEmptyView(newEmptyView); - } - mEmptyView = newEmptyView; - } - - /** - * Pass-through method for {@link PullToRefreshBase#getRefreshableView() - * getRefreshableView()}. - * {@link AdapterView#setOnItemClickListener(OnItemClickListener) - * setOnItemClickListener(listener)}. This is just for convenience! - * - * @param listener - OnItemClickListener to use - */ - public void setOnItemClickListener(OnItemClickListener listener) { - mRefreshableView.setOnItemClickListener(listener); - } - - public final void setOnLastItemVisibleListener(OnLastItemVisibleListener listener) { - mOnLastItemVisibleListener = listener; - } - - public final void setOnScrollListener(OnScrollListener listener) { - mOnScrollListener = listener; - } - - public final void setScrollEmptyView(boolean doScroll) { - mScrollEmptyView = doScroll; - } - - /** - * Sets 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 - * when the Adapter View is scrolled to the top and the mode is set to - * {@link Mode#PULL_FROM_START} - * - * @param showIndicator - true if the indicators should be shown. - */ - public void setShowIndicator(boolean showIndicator) { - mShowIndicator = showIndicator; - - if (getShowIndicatorInternal()) { - // If we're set to Show Indicator, add/update them - addIndicatorViews(); - } else { - // If not, then remove then - removeIndicatorViews(); - } - } - - ; - - @Override - protected void onPullToRefresh() { - super.onPullToRefresh(); - - if (getShowIndicatorInternal()) { - switch (getCurrentMode()) { - case PULL_FROM_END: - mIndicatorIvBottom.pullToRefresh(); - break; - case PULL_FROM_START: - mIndicatorIvTop.pullToRefresh(); - break; - default: - // NO-OP - break; - } - } - } - - protected void onRefreshing(boolean doScroll) { - super.onRefreshing(doScroll); - - if (getShowIndicatorInternal()) { - updateIndicatorViewsVisibility(); - } - } - - @Override - protected void onReleaseToRefresh() { - super.onReleaseToRefresh(); - - if (getShowIndicatorInternal()) { - switch (getCurrentMode()) { - case PULL_FROM_END: - mIndicatorIvBottom.releaseToRefresh(); - break; - case PULL_FROM_START: - mIndicatorIvTop.releaseToRefresh(); - break; - default: - // NO-OP - break; - } - } - } - - @Override - protected void onReset() { - super.onReset(); - - if (getShowIndicatorInternal()) { - updateIndicatorViewsVisibility(); - } - } - - @Override - protected void handleStyledAttributes(TypedArray a) { - // Set Show Indicator to the XML value, or default value - mShowIndicator = a.getBoolean(R.styleable.PullToRefresh_ptrShowIndicator, !isPullToRefreshOverScrollEnabled()); - } - - protected boolean isReadyForPullStart() { - return isFirstItemVisible(); - } - - protected boolean isReadyForPullEnd() { - return isLastItemVisible(); - } - - @Override - protected void onScrollChanged(int l, int t, int oldl, int oldt) { - super.onScrollChanged(l, t, oldl, oldt); - if (null != mEmptyView && !mScrollEmptyView) { - mEmptyView.scrollTo(-l, -t); - } - } - - @Override - protected void updateUIForMode() { - super.updateUIForMode(); - - // Check Indicator Views consistent with new Mode - if (getShowIndicatorInternal()) { - addIndicatorViews(); - } else { - removeIndicatorViews(); - } - } - - private void addIndicatorViews() { - Mode mode = getMode(); - FrameLayout refreshableViewWrapper = getRefreshableViewWrapper(); - - if (mode.showHeaderLoadingLayout() && null == mIndicatorIvTop) { - // If the mode can pull down, and we don't have one set already - mIndicatorIvTop = new IndicatorLayout(getContext(), Mode.PULL_FROM_START); - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - params.rightMargin = getResources().getDimensionPixelSize(R.dimen.indicator_right_padding); - params.gravity = Gravity.TOP | Gravity.RIGHT; - refreshableViewWrapper.addView(mIndicatorIvTop, params); - - } else if (!mode.showHeaderLoadingLayout() && null != mIndicatorIvTop) { - // If we can't pull down, but have a View then remove it - refreshableViewWrapper.removeView(mIndicatorIvTop); - mIndicatorIvTop = null; - } - - if (mode.showFooterLoadingLayout() && null == mIndicatorIvBottom) { - // If the mode can pull down, and we don't have one set already - mIndicatorIvBottom = new IndicatorLayout(getContext(), Mode.PULL_FROM_END); - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - params.rightMargin = getResources().getDimensionPixelSize(R.dimen.indicator_right_padding); - params.gravity = Gravity.BOTTOM | Gravity.RIGHT; - refreshableViewWrapper.addView(mIndicatorIvBottom, params); - - } else if (!mode.showFooterLoadingLayout() && null != mIndicatorIvBottom) { - // If we can't pull down, but have a View then remove it - refreshableViewWrapper.removeView(mIndicatorIvBottom); - mIndicatorIvBottom = null; - } - } - - private boolean getShowIndicatorInternal() { - return mShowIndicator && isPullToRefreshEnabled(); - } - - private boolean isFirstItemVisible() { - final Adapter adapter = mRefreshableView.getAdapter(); - - if (null == adapter || adapter.isEmpty()) { - if (DEBUG) { - Log.d(LOG_TAG, "isFirstItemVisible. Empty View."); - } - return true; - - } else { - - /** - * This check should really just be: - * mRefreshableView.getFirstVisiblePosition() == 0, but PtRListView - * internally use a HeaderView which messes the positions up. For - * now we'll just add one to account for it and rely on the inner - * condition which checks getTop(). - */ - if (mRefreshableView.getFirstVisiblePosition() <= 1) { - final View firstVisibleChild = mRefreshableView.getChildAt(0); - if (firstVisibleChild != null) { - return firstVisibleChild.getTop() >= mRefreshableView.getTop(); - } - } - } - - return false; - } - - private boolean isLastItemVisible() { - final Adapter adapter = mRefreshableView.getAdapter(); - - if (null == adapter || adapter.isEmpty()) { - if (DEBUG) { - Log.d(LOG_TAG, "isLastItemVisible. Empty View."); - } - return true; - } else { - final int lastItemPosition = mRefreshableView.getCount() - 1; - final int lastVisiblePosition = mRefreshableView.getLastVisiblePosition(); - - if (DEBUG) { - Log.d(LOG_TAG, "isLastItemVisible. Last Item Position: " + lastItemPosition + " Last Visible Pos: " - + lastVisiblePosition); - } - - /** - * This check should really just be: lastVisiblePosition == - * lastItemPosition, but PtRListView internally uses a FooterView - * which messes the positions up. For me we'll just subtract one to - * account for it and rely on the inner condition which checks - * getBottom(). - */ - if (lastVisiblePosition >= lastItemPosition - 1) { - final int childIndex = lastVisiblePosition - mRefreshableView.getFirstVisiblePosition(); - final View lastVisibleChild = mRefreshableView.getChildAt(childIndex); - if (lastVisibleChild != null) { - return lastVisibleChild.getBottom() <= mRefreshableView.getBottom(); - } - } - } - - return false; - } - - private void removeIndicatorViews() { - if (null != mIndicatorIvTop) { - getRefreshableViewWrapper().removeView(mIndicatorIvTop); - mIndicatorIvTop = null; - } - - if (null != mIndicatorIvBottom) { - getRefreshableViewWrapper().removeView(mIndicatorIvBottom); - mIndicatorIvBottom = null; - } - } - - private void updateIndicatorViewsVisibility() { - if (null != mIndicatorIvTop) { - if (!isRefreshing() && isReadyForPullStart()) { - if (!mIndicatorIvTop.isVisible()) { - mIndicatorIvTop.show(); - } - } else { - if (mIndicatorIvTop.isVisible()) { - mIndicatorIvTop.hide(); - } - } - } - - if (null != mIndicatorIvBottom) { - if (!isRefreshing() && isReadyForPullEnd()) { - if (!mIndicatorIvBottom.isVisible()) { - mIndicatorIvBottom.show(); - } - } else { - if (mIndicatorIvBottom.isVisible()) { - mIndicatorIvBottom.hide(); - } - } - } - } -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshBase.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshBase.java deleted file mode 100644 index e76b234f..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshBase.java +++ /dev/null @@ -1,1653 +0,0 @@ -/******************************************************************************* - * 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.library; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.os.Bundle; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.util.Log; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; -import android.widget.FrameLayout; -import android.widget.LinearLayout; - -import com.handmark.pulltorefresh.library.internal.FlipLoadingLayout; -import com.handmark.pulltorefresh.library.internal.LoadingLayout; -import com.handmark.pulltorefresh.library.internal.RotateLoadingLayout; -import com.handmark.pulltorefresh.library.internal.Utils; -import com.handmark.pulltorefresh.library.internal.ViewCompat; - -public abstract class PullToRefreshBase extends LinearLayout implements IPullToRefresh { - - // =========================================================== - // Constants - // =========================================================== - - static final boolean DEBUG = true; - - static final boolean USE_HW_LAYERS = false; - - static final String LOG_TAG = "PullToRefresh"; - - static final float FRICTION = 2.0f; - - public static final int SMOOTH_SCROLL_DURATION_MS = 200; - public static final int SMOOTH_SCROLL_LONG_DURATION_MS = 325; - static final int DEMO_SCROLL_INTERVAL = 225; - - static final String STATE_STATE = "ptr_state"; - static final String STATE_MODE = "ptr_mode"; - static final String STATE_CURRENT_MODE = "ptr_current_mode"; - static final String STATE_SCROLLING_REFRESHING_ENABLED = "ptr_disable_scrolling"; - static final String STATE_SHOW_REFRESHING_VIEW = "ptr_show_refreshing_view"; - static final String STATE_SUPER = "ptr_super"; - - // =========================================================== - // Fields - // =========================================================== - - private int mTouchSlop; - private float mLastMotionX, mLastMotionY; - private float mInitialMotionX, mInitialMotionY; - - private boolean mIsBeingDragged = false; - private State mState = State.RESET; - private Mode mMode = Mode.getDefault(); - - private Mode mCurrentMode; - T mRefreshableView; - private FrameLayout mRefreshableViewWrapper; - - private boolean mShowViewWhileRefreshing = true; - private boolean mScrollingWhileRefreshingEnabled = false; - private boolean mFilterTouchEvents = true; - private boolean mOverScrollEnabled = true; - private boolean mLayoutVisibilityChangesEnabled = true; - - private Interpolator mScrollAnimationInterpolator; - private AnimationStyle mLoadingAnimationStyle = AnimationStyle.getDefault(); - - private LoadingLayout mHeaderLayout; - private LoadingLayout mFooterLayout; - - private OnRefreshListener mOnRefreshListener; - private OnRefreshListener2 mOnRefreshListener2; - private OnPullEventListener mOnPullEventListener; - - private SmoothScrollRunnable mCurrentSmoothScrollRunnable; - - // =========================================================== - // Constructors - // =========================================================== - - public PullToRefreshBase(Context context) { - super(context); - init(context, null); - } - - public PullToRefreshBase(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs); - } - - public PullToRefreshBase(Context context, Mode mode) { - super(context); - mMode = mode; - init(context, null); - } - - public PullToRefreshBase(Context context, Mode mode, AnimationStyle animStyle) { - super(context); - mMode = mode; - mLoadingAnimationStyle = animStyle; - init(context, null); - } - - @Override - public void addView(View child, int index, ViewGroup.LayoutParams params) { - if (DEBUG) { - Log.d(LOG_TAG, "addView: " + child.getClass().getSimpleName()); - } - - final T refreshableView = getRefreshableView(); - - if (refreshableView instanceof ViewGroup) { - ((ViewGroup) refreshableView).addView(child, index, params); - } else { - throw new UnsupportedOperationException("Refreshable View is not a ViewGroup so can't addView"); - } - } - - @Override - public final boolean demo() { - if (mMode.showHeaderLoadingLayout() && isReadyForPullStart()) { - smoothScrollToAndBack(-getHeaderSize() * 2); - return true; - } else if (mMode.showFooterLoadingLayout() && isReadyForPullEnd()) { - smoothScrollToAndBack(getFooterSize() * 2); - return true; - } - - return false; - } - - @Override - public final Mode getCurrentMode() { - return mCurrentMode; - } - - @Override - public final boolean getFilterTouchEvents() { - return mFilterTouchEvents; - } - - @Override - public final ILoadingLayout getLoadingLayoutProxy() { - return getLoadingLayoutProxy(true, true); - } - - @Override - public final ILoadingLayout getLoadingLayoutProxy(boolean includeStart, boolean includeEnd) { - return createLoadingLayoutProxy(includeStart, includeEnd); - } - - @Override - public final Mode getMode() { - return mMode; - } - - @Override - public final T getRefreshableView() { - return mRefreshableView; - } - - @Override - public final boolean getShowViewWhileRefreshing() { - return mShowViewWhileRefreshing; - } - - @Override - public final State getState() { - return mState; - } - - /** - * @deprecated See {@link #isScrollingWhileRefreshingEnabled()}. - */ - public final boolean isDisableScrollingWhileRefreshing() { - return !isScrollingWhileRefreshingEnabled(); - } - - @Override - public final boolean isPullToRefreshEnabled() { - return mMode.permitsPullToRefresh(); - } - - @Override - public final boolean isPullToRefreshOverScrollEnabled() { - return VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD && mOverScrollEnabled - && OverscrollHelper.isAndroidOverScrollEnabled(mRefreshableView); - } - - @Override - public final boolean isRefreshing() { - return mState == State.REFRESHING || mState == State.MANUAL_REFRESHING; - } - - @Override - public final boolean isScrollingWhileRefreshingEnabled() { - return mScrollingWhileRefreshingEnabled; - } - - @Override - public final boolean onInterceptTouchEvent(MotionEvent event) { - - if (!isPullToRefreshEnabled()) { - return false; - } - - final int action = event.getAction(); - - if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { - mIsBeingDragged = false; - return false; - } - - if (action != MotionEvent.ACTION_DOWN && mIsBeingDragged) { - return true; - } - - switch (action) { - case MotionEvent.ACTION_MOVE: { - // If we're refreshing, and the flag is set. Eat all MOVE events - if (!mScrollingWhileRefreshingEnabled && isRefreshing()) { - return true; - } - - if (isReadyForPull()) { - final float y = event.getY(), x = event.getX(); - final float diff, oppositeDiff, absDiff; - - // We need to use the correct values, based on scroll - // direction - switch (getPullToRefreshScrollDirection()) { - case HORIZONTAL: - diff = x - mLastMotionX; - oppositeDiff = y - mLastMotionY; - break; - case VERTICAL: - default: - diff = y - mLastMotionY; - oppositeDiff = x - mLastMotionX; - break; - } - absDiff = Math.abs(diff); - - if (absDiff > mTouchSlop && (!mFilterTouchEvents || absDiff > Math.abs(oppositeDiff))) { - if (mMode.showHeaderLoadingLayout() && diff >= 1f && isReadyForPullStart()) { - mLastMotionY = y; - mLastMotionX = x; - mIsBeingDragged = true; - if (mMode == Mode.BOTH) { - mCurrentMode = Mode.PULL_FROM_START; - } - } else if (mMode.showFooterLoadingLayout() && diff <= -1f && isReadyForPullEnd()) { - mLastMotionY = y; - mLastMotionX = x; - mIsBeingDragged = true; - if (mMode == Mode.BOTH) { - mCurrentMode = Mode.PULL_FROM_END; - } - } - } - } - break; - } - case MotionEvent.ACTION_DOWN: { - if (isReadyForPull()) { - mLastMotionY = mInitialMotionY = event.getY(); - mLastMotionX = mInitialMotionX = event.getX(); - mIsBeingDragged = false; - } - break; - } - } - - return mIsBeingDragged; - } - - @Override - public final void onRefreshComplete() { - if (isRefreshing()) { - setState(State.RESET); - } - } - - @Override - public final boolean onTouchEvent(MotionEvent event) { - - if (!isPullToRefreshEnabled()) { - return false; - } - - // If we're refreshing, and the flag is set. Eat the event - if (!mScrollingWhileRefreshingEnabled && isRefreshing()) { - return true; - } - - if (event.getAction() == MotionEvent.ACTION_DOWN && event.getEdgeFlags() != 0) { - return false; - } - - switch (event.getAction()) { - case MotionEvent.ACTION_MOVE: { - if (mIsBeingDragged) { - mLastMotionY = event.getY(); - mLastMotionX = event.getX(); - pullEvent(); - return true; - } - break; - } - - case MotionEvent.ACTION_DOWN: { - if (isReadyForPull()) { - mLastMotionY = mInitialMotionY = event.getY(); - mLastMotionX = mInitialMotionX = event.getX(); - return true; - } - break; - } - - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: { - if (mIsBeingDragged) { - mIsBeingDragged = false; - - if (mState == State.RELEASE_TO_REFRESH - && (null != mOnRefreshListener || null != mOnRefreshListener2)) { - setState(State.REFRESHING, true); - return true; - } - - // If we're already refreshing, just scroll back to the top - if (isRefreshing()) { - smoothScrollTo(0); - return true; - } - - // If we haven't returned by here, then we're not in a state - // to pull, so just reset - setState(State.RESET); - - return true; - } - break; - } - } - - return false; - } - - public final void setScrollingWhileRefreshingEnabled(boolean allowScrollingWhileRefreshing) { - mScrollingWhileRefreshingEnabled = allowScrollingWhileRefreshing; - } - - /** - * @deprecated See {@link #setScrollingWhileRefreshingEnabled(boolean)} - */ - public void setDisableScrollingWhileRefreshing(boolean disableScrollingWhileRefreshing) { - setScrollingWhileRefreshingEnabled(!disableScrollingWhileRefreshing); - } - - @Override - public final void setFilterTouchEvents(boolean filterEvents) { - mFilterTouchEvents = filterEvents; - } - - /** - * @deprecated You should now call this method on the result of - * {@link #getLoadingLayoutProxy()}. - */ - public void setLastUpdatedLabel(CharSequence label) { - getLoadingLayoutProxy().setLastUpdatedLabel(label); - } - - /** - * @deprecated You should now call this method on the result of - * {@link #getLoadingLayoutProxy()}. - */ - public void setLoadingDrawable(Drawable drawable) { - getLoadingLayoutProxy().setLoadingDrawable(drawable); - } - - /** - * @deprecated You should now call this method on the result of - * {@link #getLoadingLayoutProxy(boolean, boolean)}. - */ - public void setLoadingDrawable(Drawable drawable, Mode mode) { - getLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setLoadingDrawable( - drawable); - } - - @Override - public void setLongClickable(boolean longClickable) { - getRefreshableView().setLongClickable(longClickable); - } - - @Override - public final void setMode(Mode mode) { - if (mode != mMode) { - if (DEBUG) { - Log.d(LOG_TAG, "Setting mode to: " + mode); - } - mMode = mode; - updateUIForMode(); - } - } - - public void setOnPullEventListener(OnPullEventListener listener) { - mOnPullEventListener = listener; - } - - @Override - public final void setOnRefreshListener(OnRefreshListener listener) { - mOnRefreshListener = listener; - mOnRefreshListener2 = null; - } - - @Override - public final void setOnRefreshListener(OnRefreshListener2 listener) { - mOnRefreshListener2 = listener; - mOnRefreshListener = null; - } - - /** - * @deprecated You should now call this method on the result of - * {@link #getLoadingLayoutProxy()}. - */ - public void setPullLabel(CharSequence pullLabel) { - getLoadingLayoutProxy().setPullLabel(pullLabel); - } - - /** - * @deprecated You should now call this method on the result of - * {@link #getLoadingLayoutProxy(boolean, boolean)}. - */ - public void setPullLabel(CharSequence pullLabel, Mode mode) { - getLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setPullLabel(pullLabel); - } - - /** - * @param enable Whether Pull-To-Refresh should be used - * @deprecated This simple calls setMode with an appropriate mode based on - * the passed value. - */ - public final void setPullToRefreshEnabled(boolean enable) { - setMode(enable ? Mode.getDefault() : Mode.DISABLED); - } - - @Override - public final void setPullToRefreshOverScrollEnabled(boolean enabled) { - mOverScrollEnabled = enabled; - } - - @Override - public final void setRefreshing() { - setRefreshing(true); - } - - @Override - public final void setRefreshing(boolean doScroll) { - if (!isRefreshing()) { - setState(State.MANUAL_REFRESHING, doScroll); - } - } - - /** - * @deprecated You should now call this method on the result of - * {@link #getLoadingLayoutProxy()}. - */ - public void setRefreshingLabel(CharSequence refreshingLabel) { - getLoadingLayoutProxy().setRefreshingLabel(refreshingLabel); - } - - /** - * @deprecated You should now call this method on the result of - * {@link #getLoadingLayoutProxy(boolean, boolean)}. - */ - public void setRefreshingLabel(CharSequence refreshingLabel, Mode mode) { - getLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setRefreshingLabel( - refreshingLabel); - } - - /** - * @deprecated You should now call this method on the result of - * {@link #getLoadingLayoutProxy()}. - */ - public void setReleaseLabel(CharSequence releaseLabel) { - setReleaseLabel(releaseLabel, Mode.BOTH); - } - - /** - * @deprecated You should now call this method on the result of - * {@link #getLoadingLayoutProxy(boolean, boolean)}. - */ - public void setReleaseLabel(CharSequence releaseLabel, Mode mode) { - getLoadingLayoutProxy(mode.showHeaderLoadingLayout(), mode.showFooterLoadingLayout()).setReleaseLabel( - releaseLabel); - } - - public void setScrollAnimationInterpolator(Interpolator interpolator) { - mScrollAnimationInterpolator = interpolator; - } - - @Override - public final void setShowViewWhileRefreshing(boolean showView) { - mShowViewWhileRefreshing = showView; - } - - /** - * @return Either {@link Orientation#VERTICAL} or - * {@link Orientation#HORIZONTAL} depending on the scroll direction. - */ - public abstract Orientation getPullToRefreshScrollDirection(); - - final void setState(State state, final boolean... params) { - mState = state; - if (DEBUG) { - Log.d(LOG_TAG, "State: " + mState.name()); - } - - switch (mState) { - case RESET: - onReset(); - break; - case PULL_TO_REFRESH: - onPullToRefresh(); - break; - case RELEASE_TO_REFRESH: - onReleaseToRefresh(); - break; - case REFRESHING: - case MANUAL_REFRESHING: - onRefreshing(params[0]); - break; - case OVERSCROLLING: - // NO-OP - break; - } - - // Call OnPullEventListener - if (null != mOnPullEventListener) { - mOnPullEventListener.onPullEvent(this, mState, mCurrentMode); - } - } - - /** - * Used internally for adding view. Need because we override addView to - * pass-through to the Refreshable View - */ - protected final void addViewInternal(View child, int index, ViewGroup.LayoutParams params) { - super.addView(child, index, params); - } - - /** - * Used internally for adding view. Need because we override addView to - * pass-through to the Refreshable View - */ - protected final void addViewInternal(View child, ViewGroup.LayoutParams params) { - super.addView(child, -1, params); - } - - protected LoadingLayout createLoadingLayout(Context context, Mode mode, TypedArray attrs) { - LoadingLayout layout = mLoadingAnimationStyle.createLoadingLayout(context, mode, - getPullToRefreshScrollDirection(), attrs); - layout.setVisibility(View.INVISIBLE); - return layout; - } - - /** - * Used internally for {@link #getLoadingLayoutProxy(boolean, boolean)}. - * Allows derivative classes to include any extra LoadingLayouts. - */ - protected LoadingLayoutProxy createLoadingLayoutProxy(final boolean includeStart, final boolean includeEnd) { - LoadingLayoutProxy proxy = new LoadingLayoutProxy(); - - if (includeStart && mMode.showHeaderLoadingLayout()) { - proxy.addLayout(mHeaderLayout); - } - if (includeEnd && mMode.showFooterLoadingLayout()) { - proxy.addLayout(mFooterLayout); - } - - return proxy; - } - - /** - * This is implemented by derived classes to return the created View. If you - * need to use a custom View (such as a custom ListView), override this - * method and return an instance of your custom class. - *

- * Be sure to set the ID of the view in this method, especially if you're - * using a ListActivity or ListFragment. - * - * @param context Context to create view with - * @param attrs AttributeSet from wrapped class. Means that anything you - * include in the XML layout declaration will be routed to the - * created View - * @return New instance of the Refreshable View - */ - protected abstract T createRefreshableView(Context context, AttributeSet attrs); - - protected final void disableLoadingLayoutVisibilityChanges() { - mLayoutVisibilityChangesEnabled = false; - } - - protected final LoadingLayout getFooterLayout() { - return mFooterLayout; - } - - 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; - } - - protected int getPullToRefreshScrollDurationLonger() { - return SMOOTH_SCROLL_LONG_DURATION_MS; - } - - protected FrameLayout getRefreshableViewWrapper() { - return mRefreshableViewWrapper; - } - - /** - * Allows Derivative classes to handle the XML Attrs without creating a - * TypedArray themsevles - * - * @param a - TypedArray of PullToRefresh Attributes - */ - 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 end. - * - * @return true if the View is currently in the correct state (for example, - * bottom of a ListView) - */ - 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 start. - * - * @return true if the View is currently the correct state (for example, top - * of a ListView) - */ - protected abstract boolean isReadyForPullStart(); - - /** - * Called by {@link #onRestoreInstanceState(Parcelable)} so that derivative - * classes can handle their saved instance state. - * - * @param savedInstanceState - Bundle which contains saved instance state. - */ - protected void onPtrRestoreInstanceState(Bundle savedInstanceState) { - } - - /** - * Called by {@link #onSaveInstanceState()} so that derivative classes can - * save their instance state. - * - * @param saveState - Bundle to be updated with saved state. - */ - 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) { - - // Call Refresh Listener when the Scroll has finished - OnSmoothScrollFinishedListener listener = new OnSmoothScrollFinishedListener() { - @Override - public void onSmoothScrollFinished() { - callRefreshListener(); - } - }; - - switch (mCurrentMode) { - case MANUAL_REFRESH_ONLY: - case PULL_FROM_END: - smoothScrollTo(getFooterSize(), listener); - break; - default: - case PULL_FROM_START: - smoothScrollTo(-getHeaderSize(), listener); - break; - } - } else { - smoothScrollTo(0); - } - } else { - // We're not scrolling, so just call Refresh Listener now - callRefreshListener(); - } - } - - /** - * 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) { - Bundle bundle = (Bundle) state; - - setMode(Mode.mapIntToValue(bundle.getInt(STATE_MODE, 0))); - mCurrentMode = Mode.mapIntToValue(bundle.getInt(STATE_CURRENT_MODE, 0)); - - mScrollingWhileRefreshingEnabled = bundle.getBoolean(STATE_SCROLLING_REFRESHING_ENABLED, false); - mShowViewWhileRefreshing = bundle.getBoolean(STATE_SHOW_REFRESHING_VIEW, true); - - // Let super Restore Itself - super.onRestoreInstanceState(bundle.getParcelable(STATE_SUPER)); - - State viewState = State.mapIntToValue(bundle.getInt(STATE_STATE, 0)); - if (viewState == State.REFRESHING || viewState == State.MANUAL_REFRESHING) { - setState(viewState, true); - } - - // Now let derivative classes restore their state - onPtrRestoreInstanceState(bundle); - return; - } - - super.onRestoreInstanceState(state); - } - - @Override - protected final Parcelable onSaveInstanceState() { - Bundle bundle = new Bundle(); - - // Let derivative classes get a chance to save state first, that way we - // can make sure they don't overrite any of our values - onPtrSaveInstanceState(bundle); - - bundle.putInt(STATE_STATE, mState.getIntValue()); - bundle.putInt(STATE_MODE, mMode.getIntValue()); - bundle.putInt(STATE_CURRENT_MODE, mCurrentMode.getIntValue()); - bundle.putBoolean(STATE_SCROLLING_REFRESHING_ENABLED, mScrollingWhileRefreshingEnabled); - bundle.putBoolean(STATE_SHOW_REFRESHING_VIEW, mShowViewWhileRefreshing); - bundle.putParcelable(STATE_SUPER, super.onSaveInstanceState()); - - return bundle; - } - - @Override - 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; - } - } - - /** - * Helper method which just calls scrollTo() in the correct scrolling - * direction. - * - * @param value - New Scroll value - */ - protected final void setHeaderScroll(int value) { - if (DEBUG) { - Log.d(LOG_TAG, "setHeaderScroll: " + value); - } - - // Clamp value to with pull scroll range - final int maximumPullScroll = getMaximumPullScroll(); - value = Math.min(maximumPullScroll, Math.max(-maximumPullScroll, value)); - - if (mLayoutVisibilityChangesEnabled) { - if (value < 0) { - mHeaderLayout.setVisibility(View.VISIBLE); - } else if (value > 0) { - mFooterLayout.setVisibility(View.VISIBLE); - } else { - mHeaderLayout.setVisibility(View.INVISIBLE); - mFooterLayout.setVisibility(View.INVISIBLE); - } - } - - if (USE_HW_LAYERS) { - /** - * Use a Hardware Layer on the Refreshable View if we've scrolled at - * all. We don't use them on the Header/Footer Views as they change - * often, which would negate any HW layer performance boost. - */ - ViewCompat.setLayerType(mRefreshableViewWrapper, value != 0 ? View.LAYER_TYPE_HARDWARE - : View.LAYER_TYPE_NONE); - } - - switch (getPullToRefreshScrollDirection()) { - case VERTICAL: - scrollTo(0, value); - break; - case HORIZONTAL: - scrollTo(value, 0); - break; - } - } - - /** - * Smooth Scroll to position using the default duration of - * {@value #SMOOTH_SCROLL_DURATION_MS} ms. - * - * @param scrollValue - Position to scroll to - */ - protected final void smoothScrollTo(int scrollValue) { - smoothScrollTo(scrollValue, getPullToRefreshScrollDuration()); - } - - /** - * Smooth Scroll to position using the default duration of - * {@value #SMOOTH_SCROLL_DURATION_MS} ms. - * - * @param scrollValue - Position to scroll to - * @param listener - Listener for scroll - */ - protected final void smoothScrollTo(int scrollValue, OnSmoothScrollFinishedListener listener) { - smoothScrollTo(scrollValue, getPullToRefreshScrollDuration(), 0, listener); - } - - /** - * Smooth Scroll to position using the longer default duration of - * {@value #SMOOTH_SCROLL_LONG_DURATION_MS} ms. - * - * @param scrollValue - Position to scroll to - */ - protected final void smoothScrollToLonger(int scrollValue) { - smoothScrollTo(scrollValue, getPullToRefreshScrollDurationLonger()); - } - - /** - * Updates the View State when the mode has been set. This does not do any - * checking that the mode is different to current state so always updates. - */ - protected void updateUIForMode() { - // We need to use the correct LayoutParam values, based on scroll - // direction - final LinearLayout.LayoutParams lp = getLoadingLayoutLayoutParams(); - - // Remove Header, and then add Header Loading View again if needed - if (this == mHeaderLayout.getParent()) { - removeView(mHeaderLayout); - } - if (mMode.showHeaderLoadingLayout()) { - addViewInternal(mHeaderLayout, 0, lp); - } - - // Remove Footer, and then add Footer Loading View again if needed - if (this == mFooterLayout.getParent()) { - removeView(mFooterLayout); - } - if (mMode.showFooterLoadingLayout()) { - addViewInternal(mFooterLayout, lp); - } - - // Hide Loading Views - refreshLoadingViewsSize(); - - // If we're not using Mode.BOTH, set mCurrentMode to mMode, otherwise - // set it to pull down - mCurrentMode = (mMode != Mode.BOTH) ? mMode : Mode.PULL_FROM_START; - } - - private void addRefreshableView(Context context, T refreshableView) { - mRefreshableViewWrapper = new FrameLayout(context); - mRefreshableViewWrapper.addView(refreshableView, ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT); - - addViewInternal(mRefreshableViewWrapper, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.MATCH_PARENT)); - } - - private void callRefreshListener() { - if (null != mOnRefreshListener) { - mOnRefreshListener.onRefresh(this); - } else if (null != mOnRefreshListener2) { - if (mCurrentMode == Mode.PULL_FROM_START) { - mOnRefreshListener2.onPullDownToRefresh(this); - } else if (mCurrentMode == Mode.PULL_FROM_END) { - mOnRefreshListener2.onPullUpToRefresh(this); - } - } - } - - @SuppressWarnings("deprecation") - private void init(Context context, AttributeSet attrs) { - switch (getPullToRefreshScrollDirection()) { - case HORIZONTAL: - setOrientation(LinearLayout.HORIZONTAL); - break; - case VERTICAL: - default: - setOrientation(LinearLayout.VERTICAL); - break; - } - - setGravity(Gravity.CENTER); - - ViewConfiguration config = ViewConfiguration.get(context); - mTouchSlop = config.getScaledTouchSlop(); - - // Styleables from XML - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PullToRefresh); - - if (a.hasValue(R.styleable.PullToRefresh_ptrMode)) { - mMode = Mode.mapIntToValue(a.getInteger(R.styleable.PullToRefresh_ptrMode, 0)); - } - - if (a.hasValue(R.styleable.PullToRefresh_ptrAnimationStyle)) { - mLoadingAnimationStyle = AnimationStyle.mapIntToValue(a.getInteger( - R.styleable.PullToRefresh_ptrAnimationStyle, 0)); - } - - // Refreshable View - // By passing the attrs, we can add ListView/GridView params via XML - mRefreshableView = createRefreshableView(context, attrs); - addRefreshableView(context, mRefreshableView); - - // We need to create now layouts now - mHeaderLayout = createLoadingLayout(context, Mode.PULL_FROM_START, a); - mFooterLayout = createLoadingLayout(context, Mode.PULL_FROM_END, a); - - /** - * Styleables from XML - */ - if (a.hasValue(R.styleable.PullToRefresh_ptrRefreshableViewBackground)) { - Drawable background = a.getDrawable(R.styleable.PullToRefresh_ptrRefreshableViewBackground); - if (null != background) { - mRefreshableView.setBackgroundDrawable(background); - } - } else if (a.hasValue(R.styleable.PullToRefresh_ptrAdapterViewBackground)) { - Utils.warnDeprecation("ptrAdapterViewBackground", "ptrRefreshableViewBackground"); - Drawable background = a.getDrawable(R.styleable.PullToRefresh_ptrAdapterViewBackground); - if (null != background) { - mRefreshableView.setBackgroundDrawable(background); - } - } - - if (a.hasValue(R.styleable.PullToRefresh_ptrOverScroll)) { - mOverScrollEnabled = a.getBoolean(R.styleable.PullToRefresh_ptrOverScroll, true); - } - - if (a.hasValue(R.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled)) { - mScrollingWhileRefreshingEnabled = a.getBoolean( - R.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled, false); - } - - // Let the derivative classes have a go at handling attributes, then - // recycle them... - handleStyledAttributes(a); - a.recycle(); - - // Finally update the UI for the modes - updateUIForMode(); - } - - private boolean isReadyForPull() { - switch (mMode) { - case PULL_FROM_START: - return isReadyForPullStart(); - case PULL_FROM_END: - return isReadyForPullEnd(); - case BOTH: - return isReadyForPullEnd() || isReadyForPullStart(); - default: - return false; - } - } - - /** - * Actions a Pull Event - * - * @return true if the Event has been handled, false if there has been no - * change - */ - private void pullEvent() { - final int newScrollValue; - final int itemDimension; - final float initialMotionValue, lastMotionValue; - - switch (getPullToRefreshScrollDirection()) { - case HORIZONTAL: - initialMotionValue = mInitialMotionX; - lastMotionValue = mLastMotionX; - break; - case VERTICAL: - default: - initialMotionValue = mInitialMotionY; - lastMotionValue = mLastMotionY; - break; - } - - switch (mCurrentMode) { - case PULL_FROM_END: - newScrollValue = Math.round(Math.max(initialMotionValue - lastMotionValue, 0) / FRICTION); - itemDimension = getFooterSize(); - break; - case PULL_FROM_START: - default: - newScrollValue = Math.round(Math.min(initialMotionValue - lastMotionValue, 0) / FRICTION); - itemDimension = getHeaderSize(); - break; - } - - setHeaderScroll(newScrollValue); - - if (newScrollValue != 0 && !isRefreshing()) { - float scale = Math.abs(newScrollValue) / (float) itemDimension; - switch (mCurrentMode) { - case PULL_FROM_END: - mFooterLayout.onPull(scale); - break; - case PULL_FROM_START: - default: - mHeaderLayout.onPull(scale); - break; - } - - if (mState != State.PULL_TO_REFRESH && itemDimension >= Math.abs(newScrollValue)) { - setState(State.PULL_TO_REFRESH); - } else if (mState == State.PULL_TO_REFRESH && itemDimension < Math.abs(newScrollValue)) { - setState(State.RELEASE_TO_REFRESH); - } - } - } - - private LinearLayout.LayoutParams getLoadingLayoutLayoutParams() { - switch (getPullToRefreshScrollDirection()) { - case HORIZONTAL: - return new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.MATCH_PARENT); - case VERTICAL: - default: - return new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT); - } - } - - private int getMaximumPullScroll() { - switch (getPullToRefreshScrollDirection()) { - case HORIZONTAL: - return Math.round(getWidth() / FRICTION); - case VERTICAL: - default: - return Math.round(getHeight() / FRICTION); - } - } - - /** - * Smooth Scroll to position using the specific duration - * - * @param scrollValue - Position to scroll to - * @param duration - Duration of animation in milliseconds - */ - private final void smoothScrollTo(int scrollValue, long duration) { - smoothScrollTo(scrollValue, duration, 0, null); - } - - private final void smoothScrollTo(int newScrollValue, long duration, long delayMillis, - OnSmoothScrollFinishedListener listener) { - if (null != mCurrentSmoothScrollRunnable) { - mCurrentSmoothScrollRunnable.stop(); - } - - final int oldScrollValue; - switch (getPullToRefreshScrollDirection()) { - case HORIZONTAL: - oldScrollValue = getScrollX(); - break; - case VERTICAL: - default: - oldScrollValue = getScrollY(); - break; - } - - if (oldScrollValue != newScrollValue) { - if (null == mScrollAnimationInterpolator) { - // Default interpolator is a Decelerate Interpolator - mScrollAnimationInterpolator = new DecelerateInterpolator(); - } - mCurrentSmoothScrollRunnable = new SmoothScrollRunnable(oldScrollValue, newScrollValue, duration, listener); - - if (delayMillis > 0) { - postDelayed(mCurrentSmoothScrollRunnable, delayMillis); - } else { - post(mCurrentSmoothScrollRunnable); - } - } - } - - private final void smoothScrollToAndBack(int y) { - smoothScrollTo(y, SMOOTH_SCROLL_DURATION_MS, 0, new OnSmoothScrollFinishedListener() { - - @Override - public void onSmoothScrollFinished() { - smoothScrollTo(0, SMOOTH_SCROLL_DURATION_MS, DEMO_SCROLL_INTERVAL, null); - } - }); - } - - public static enum AnimationStyle { - /** - * This is the default for Android-PullToRefresh. Allows you to use any - * drawable, which is automatically rotated and used as a Progress Bar. - */ - ROTATE, - - /** - * This is the old default, and what is commonly used on iOS. Uses an - * arrow image which flips depending on where the user has scrolled. - */ - FLIP; - - static AnimationStyle getDefault() { - return ROTATE; - } - - /** - * Maps an int to a specific mode. This is needed when saving state, or - * inflating the view from XML where the mode is given through a attr - * int. - * - * @param modeInt - int to map a Mode to - * @return Mode that modeInt maps to, or ROTATE by default. - */ - static AnimationStyle mapIntToValue(int modeInt) { - switch (modeInt) { - case 0x0: - default: - return ROTATE; - case 0x1: - return FLIP; - } - } - - LoadingLayout createLoadingLayout(Context context, Mode mode, Orientation scrollDirection, TypedArray attrs) { - switch (this) { - case ROTATE: - default: - return new RotateLoadingLayout(context, mode, scrollDirection, attrs); - case FLIP: - return new FlipLoadingLayout(context, mode, scrollDirection, attrs); - } - } - } - - public static enum Mode { - - /** - * Disable all Pull-to-Refresh gesture and Refreshing handling - */ - DISABLED(0x0), - - /** - * Only allow the user to Pull from the start of the Refreshable View to - * refresh. The start is either the Top or Left, depending on the - * scrolling direction. - */ - PULL_FROM_START(0x1), - - /** - * Only allow the user to Pull from the end of the Refreshable View to - * refresh. The start is either the Bottom or Right, depending on the - * scrolling direction. - */ - PULL_FROM_END(0x2), - - /** - * Allow the user to both Pull from the start, from the end to refresh. - */ - BOTH(0x3), - - /** - * Disables Pull-to-Refresh gesture handling, but allows manually - * setting the Refresh state via - * {@link PullToRefreshBase#setRefreshing() setRefreshing()}. - */ - MANUAL_REFRESH_ONLY(0x4); - - /** - * @deprecated Use {@link #PULL_FROM_START} from now on. - */ - public static Mode PULL_DOWN_TO_REFRESH = Mode.PULL_FROM_START; - - /** - * @deprecated Use {@link #PULL_FROM_END} from now on. - */ - public static Mode PULL_UP_TO_REFRESH = Mode.PULL_FROM_END; - - /** - * Maps an int to a specific mode. This is needed when saving state, or - * inflating the view from XML where the mode is given through a attr - * int. - * - * @param modeInt - int to map a Mode to - * @return Mode that modeInt maps to, or PULL_FROM_START by default. - */ - static Mode mapIntToValue(final int modeInt) { - for (Mode value : Mode.values()) { - if (modeInt == value.getIntValue()) { - return value; - } - } - - // If not, return default - return getDefault(); - } - - static Mode getDefault() { - return PULL_FROM_START; - } - - private int mIntValue; - - // The modeInt values need to match those from attrs.xml - Mode(int modeInt) { - mIntValue = modeInt; - } - - /** - * @return true if the mode permits Pull-to-Refresh - */ - boolean permitsPullToRefresh() { - return !(this == DISABLED || this == MANUAL_REFRESH_ONLY); - } - - /** - * @return true if this mode wants the Loading Layout Header to be shown - */ - public boolean showHeaderLoadingLayout() { - return this == PULL_FROM_START || this == BOTH; - } - - /** - * @return true if this mode wants the Loading Layout Footer to be shown - */ - public boolean showFooterLoadingLayout() { - return this == PULL_FROM_END || this == BOTH || this == MANUAL_REFRESH_ONLY; - } - - int getIntValue() { - return mIntValue; - } - - } - - // =========================================================== - // 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 ( - * {@link PullToRefreshAdapterViewBase#setOnLastItemVisibleListener}. - * - * @author Chris Banes - */ - public static interface OnLastItemVisibleListener { - - /** - * Called when the user has scrolled to the end of the list - */ - public void onLastItemVisible(); - - } - - /** - * 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 - * (such as sounds). See ( - * {@link PullToRefreshAdapterViewBase#setOnPullEventListener}. - * - * @author Chris Banes - */ - public static interface OnPullEventListener { - - /** - * Called when the internal state has been changed, usually by the user - * pulling. - * - * @param refreshView - View which has had it's state change. - * @param state - The new state of View. - * @param direction - One of {@link Mode#PULL_FROM_START} or - * {@link Mode#PULL_FROM_END} depending on which direction - * the user is pulling. Only useful when state is - * {@link State#PULL_TO_REFRESH} or - * {@link State#RELEASE_TO_REFRESH}. - */ - public void onPullEvent(final PullToRefreshBase refreshView, State state, Mode direction); - - } - - /** - * Simple Listener to listen for any callbacks to Refresh. - * - * @author Chris Banes - */ - public static interface OnRefreshListener { - - /** - * onRefresh will be called for both a Pull from start, and Pull from - * end - */ - public void onRefresh(final PullToRefreshBase refreshView); - - } - - /** - * An advanced version of the Listener to listen for callbacks to Refresh. - * This listener is different as it allows you to differentiate between Pull - * Ups, and Pull Downs. - * - * @author Chris Banes - */ - public static interface OnRefreshListener2 { - // TODO These methods need renaming to START/END rather than DOWN/UP - - /** - * onPullDownToRefresh will be called only when the user has Pulled from - * the start, and released. - */ - public void onPullDownToRefresh(final PullToRefreshBase refreshView); - - /** - * onPullUpToRefresh will be called only when the user has Pulled from - * the end, and released. - */ - public void onPullUpToRefresh(final PullToRefreshBase refreshView); - - } - - public static enum Orientation { - VERTICAL, HORIZONTAL; - } - - public static enum State { - - /** - * When the UI is in a state which means that user is not interacting - * with the Pull-to-Refresh function. - */ - RESET(0x0), - - /** - * When the UI is being pulled by the user, but has not been pulled far - * enough so that it refreshes when released. - */ - PULL_TO_REFRESH(0x1), - - /** - * When the UI is being pulled by the user, and has - * been pulled far enough so that it will refresh when released. - */ - RELEASE_TO_REFRESH(0x2), - - /** - * When the UI is currently refreshing, caused by a pull gesture. - */ - REFRESHING(0x8), - - /** - * When the UI is currently refreshing, caused by a call to - * {@link PullToRefreshBase#setRefreshing() setRefreshing()}. - */ - MANUAL_REFRESHING(0x9), - - /** - * When the UI is currently overscrolling, caused by a fling on the - * Refreshable View. - */ - OVERSCROLLING(0x10); - - /** - * Maps an int to a specific state. This is needed when saving state. - * - * @param stateInt - int to map a State to - * @return State that stateInt maps to - */ - static State mapIntToValue(final int stateInt) { - for (State value : State.values()) { - if (stateInt == value.getIntValue()) { - return value; - } - } - - // If not, return default - return RESET; - } - - private int mIntValue; - - State(int intValue) { - mIntValue = intValue; - } - - int getIntValue() { - return mIntValue; - } - } - - final class SmoothScrollRunnable implements Runnable { - private final Interpolator mInterpolator; - private final int mScrollToY; - private final int mScrollFromY; - private final long mDuration; - private OnSmoothScrollFinishedListener mListener; - - private boolean mContinueRunning = true; - private long mStartTime = -1; - private int mCurrentY = -1; - - public SmoothScrollRunnable(int fromY, int toY, long duration, OnSmoothScrollFinishedListener listener) { - mScrollFromY = fromY; - mScrollToY = toY; - mInterpolator = mScrollAnimationInterpolator; - mDuration = duration; - mListener = listener; - } - - @Override - public void run() { - - /** - * Only set mStartTime if this is the first time we're starting, - * else actually calculate the Y delta - */ - if (mStartTime == -1) { - mStartTime = System.currentTimeMillis(); - } else { - - /** - * We do do all calculations in long to reduce software float - * calculations. We use 1000 as it gives us good accuracy and - * small rounding errors - */ - long normalizedTime = (1000 * (System.currentTimeMillis() - mStartTime)) / mDuration; - normalizedTime = Math.max(Math.min(normalizedTime, 1000), 0); - - final int deltaY = Math.round((mScrollFromY - mScrollToY) - * mInterpolator.getInterpolation(normalizedTime / 1000f)); - mCurrentY = mScrollFromY - deltaY; - setHeaderScroll(mCurrentY); - } - - // If we're not at the target Y, keep going... - if (mContinueRunning && mScrollToY != mCurrentY) { - ViewCompat.postOnAnimation(PullToRefreshBase.this, this); - } else { - if (null != mListener) { - mListener.onSmoothScrollFinished(); - } - } - } - - public void stop() { - mContinueRunning = false; - removeCallbacks(this); - } - } - - static interface OnSmoothScrollFinishedListener { - void onSmoothScrollFinished(); - } - -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java deleted file mode 100644 index 649020c6..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * 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.library; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.util.AttributeSet; -import android.view.View; -import android.widget.ExpandableListView; - -import com.handmark.pulltorefresh.library.internal.EmptyViewMethodAccessor; - -public class PullToRefreshExpandableListView extends PullToRefreshAdapterViewBase { - - public PullToRefreshExpandableListView(Context context) { - super(context); - } - - public PullToRefreshExpandableListView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public PullToRefreshExpandableListView(Context context, Mode mode) { - super(context, mode); - } - - public PullToRefreshExpandableListView(Context context, Mode mode, AnimationStyle style) { - super(context, mode, style); - } - - @Override - public final Orientation getPullToRefreshScrollDirection() { - return Orientation.VERTICAL; - } - - @Override - protected ExpandableListView createRefreshableView(Context context, AttributeSet attrs) { - final ExpandableListView lv; - if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { - lv = new InternalExpandableListViewSDK9(context, attrs); - } else { - lv = new InternalExpandableListView(context, attrs); - } - - // Set it to this so it can be used in ListActivity/ListFragment - lv.setId(android.R.id.list); - return lv; - } - - class InternalExpandableListView extends ExpandableListView implements EmptyViewMethodAccessor { - - public InternalExpandableListView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public void setEmptyView(View emptyView) { - PullToRefreshExpandableListView.this.setEmptyView(emptyView); - } - - @Override - public void setEmptyViewInternal(View emptyView) { - super.setEmptyView(emptyView); - } - } - - @TargetApi(9) - final class InternalExpandableListViewSDK9 extends InternalExpandableListView { - - public InternalExpandableListViewSDK9(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, - int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { - - final boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, - scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); - - // Does all of the hard work... - OverscrollHelper.overScrollBy(PullToRefreshExpandableListView.this, deltaX, scrollX, deltaY, scrollY, - isTouchEvent); - - return returnValue; - } - } -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshGridView.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshGridView.java deleted file mode 100644 index f9506889..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshGridView.java +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************* - * 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.library; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.util.AttributeSet; -import android.view.View; -import android.widget.GridView; - -import com.handmark.pulltorefresh.library.internal.EmptyViewMethodAccessor; - -public class PullToRefreshGridView extends PullToRefreshAdapterViewBase { - - public PullToRefreshGridView(Context context) { - super(context); - } - - public PullToRefreshGridView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public PullToRefreshGridView(Context context, Mode mode) { - super(context, mode); - } - - public PullToRefreshGridView(Context context, Mode mode, AnimationStyle style) { - super(context, mode, style); - } - - @Override - public final Orientation getPullToRefreshScrollDirection() { - return Orientation.VERTICAL; - } - - @Override - protected final GridView createRefreshableView(Context context, AttributeSet attrs) { - final GridView gv; - if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { - gv = new InternalGridViewSDK9(context, attrs); - } else { - gv = new InternalGridView(context, attrs); - } - - // Use Generated ID (from res/values/ids.xml) - gv.setId(R.id.gridview); - return gv; - } - - class InternalGridView extends GridView implements EmptyViewMethodAccessor { - - public InternalGridView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public void setEmptyView(View emptyView) { - PullToRefreshGridView.this.setEmptyView(emptyView); - } - - @Override - public void setEmptyViewInternal(View emptyView) { - super.setEmptyView(emptyView); - } - } - - @TargetApi(9) - final class InternalGridViewSDK9 extends InternalGridView { - - public InternalGridViewSDK9(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, - int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { - - final boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, - scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); - - // Does all of the hard work... - OverscrollHelper.overScrollBy(PullToRefreshGridView.this, deltaX, scrollX, deltaY, scrollY, isTouchEvent); - - return returnValue; - } - } -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshHorizontalScrollView.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshHorizontalScrollView.java deleted file mode 100644 index a70f7ad2..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshHorizontalScrollView.java +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************************* - * 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.library; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.util.AttributeSet; -import android.view.View; -import android.widget.HorizontalScrollView; - -public class PullToRefreshHorizontalScrollView extends PullToRefreshBase { - - public PullToRefreshHorizontalScrollView(Context context) { - super(context); - } - - public PullToRefreshHorizontalScrollView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public PullToRefreshHorizontalScrollView(Context context, Mode mode) { - super(context, mode); - } - - public PullToRefreshHorizontalScrollView(Context context, Mode mode, AnimationStyle style) { - super(context, mode, style); - } - - @Override - public final Orientation getPullToRefreshScrollDirection() { - return Orientation.HORIZONTAL; - } - - @Override - protected HorizontalScrollView createRefreshableView(Context context, AttributeSet attrs) { - HorizontalScrollView scrollView; - - if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { - scrollView = new InternalHorizontalScrollViewSDK9(context, attrs); - } else { - scrollView = new HorizontalScrollView(context, attrs); - } - - scrollView.setId(R.id.scrollview); - return scrollView; - } - - @Override - protected boolean isReadyForPullStart() { - return mRefreshableView.getScrollX() == 0; - } - - @Override - protected boolean isReadyForPullEnd() { - View scrollViewChild = mRefreshableView.getChildAt(0); - if (null != scrollViewChild) { - return mRefreshableView.getScrollX() >= (scrollViewChild.getWidth() - getWidth()); - } - return false; - } - - @TargetApi(9) - final class InternalHorizontalScrollViewSDK9 extends HorizontalScrollView { - - public InternalHorizontalScrollViewSDK9(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, - int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { - - final boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, - scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); - - // Does all of the hard work... - OverscrollHelper.overScrollBy(PullToRefreshHorizontalScrollView.this, deltaX, scrollX, deltaY, scrollY, - getScrollRange(), isTouchEvent); - - return returnValue; - } - - /** - * Taken from the AOSP ScrollView source - */ - private int getScrollRange() { - int scrollRange = 0; - if (getChildCount() > 0) { - View child = getChildAt(0); - scrollRange = Math.max(0, child.getWidth() - (getWidth() - getPaddingLeft() - getPaddingRight())); - } - return scrollRange; - } - } -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshListView.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshListView.java deleted file mode 100644 index 0aa9a27d..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshListView.java +++ /dev/null @@ -1,337 +0,0 @@ -/******************************************************************************* - * 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.library; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.ListAdapter; -import android.widget.ListView; - -import com.handmark.pulltorefresh.library.internal.EmptyViewMethodAccessor; -import com.handmark.pulltorefresh.library.internal.LoadingLayout; - -public class PullToRefreshListView extends PullToRefreshAdapterViewBase { - - private LoadingLayout mHeaderLoadingView; - private LoadingLayout mFooterLoadingView; - - private FrameLayout mLvFooterLoadingFrame; - - private boolean mListViewExtrasEnabled; - - public PullToRefreshListView(Context context) { - super(context); - } - - public PullToRefreshListView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public PullToRefreshListView(Context context, Mode mode) { - super(context, mode); - } - - public PullToRefreshListView(Context context, Mode mode, AnimationStyle style) { - super(context, mode, style); - } - - @Override - public final Orientation getPullToRefreshScrollDirection() { - return Orientation.VERTICAL; - } - - @Override - 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. - */ - ListAdapter adapter = mRefreshableView.getAdapter(); - if (!mListViewExtrasEnabled || !getShowViewWhileRefreshing() || null == adapter || adapter.isEmpty()) { - super.onRefreshing(doScroll); - return; - } - - super.onRefreshing(false); - - final LoadingLayout origLoadingView, listViewLoadingView, oppositeListViewLoadingView; - final int selection, scrollToY; - - switch (getCurrentMode()) { - case MANUAL_REFRESH_ONLY: - case PULL_FROM_END: - origLoadingView = getFooterLayout(); - listViewLoadingView = mFooterLoadingView; - oppositeListViewLoadingView = mHeaderLoadingView; - selection = mRefreshableView.getCount() - 1; - scrollToY = getScrollY() - getFooterSize(); - break; - case PULL_FROM_START: - default: - origLoadingView = getHeaderLayout(); - listViewLoadingView = mHeaderLoadingView; - oppositeListViewLoadingView = mFooterLoadingView; - selection = 0; - scrollToY = getScrollY() + getHeaderSize(); - break; - } - - // Hide our original Loading View - origLoadingView.reset(); - origLoadingView.hideAllViews(); - - // Make sure the opposite end is hidden too - oppositeListViewLoadingView.setVisibility(View.GONE); - - // Show the ListView Loading View and set it to refresh. - listViewLoadingView.setVisibility(View.VISIBLE); - listViewLoadingView.refreshing(); - - if (doScroll) { - // We need to disable the automatic visibility changes for now - disableLoadingLayoutVisibilityChanges(); - - // We scroll slightly so that the ListView's header/footer is at the - // same Y position as our normal header/footer - setHeaderScroll(scrollToY); - - // Make sure the ListView is scrolled to show the loading - // header/footer - mRefreshableView.setSelection(selection); - - // Smooth scroll as normal - smoothScrollTo(0); - } - } - - @Override - protected void onReset() { - /** - * If the extras are not enabled, just call up to super and return. - */ - if (!mListViewExtrasEnabled) { - super.onReset(); - return; - } - - final LoadingLayout originalLoadingLayout, listViewLoadingLayout; - final int scrollToHeight, selection; - final boolean scrollLvToEdge; - - switch (getCurrentMode()) { - case MANUAL_REFRESH_ONLY: - case PULL_FROM_END: - originalLoadingLayout = getFooterLayout(); - listViewLoadingLayout = mFooterLoadingView; - selection = mRefreshableView.getCount() - 1; - scrollToHeight = getFooterSize(); - scrollLvToEdge = Math.abs(mRefreshableView.getLastVisiblePosition() - selection) <= 1; - break; - case PULL_FROM_START: - default: - originalLoadingLayout = getHeaderLayout(); - listViewLoadingLayout = mHeaderLoadingView; - scrollToHeight = -getHeaderSize(); - selection = 0; - scrollLvToEdge = Math.abs(mRefreshableView.getFirstVisiblePosition() - selection) <= 1; - break; - } - - // If the ListView header loading layout is showing, then we need to - // flip so that the original one is showing instead - if (listViewLoadingLayout.getVisibility() == View.VISIBLE) { - - // Set our Original View to Visible - originalLoadingLayout.showInvisibleViews(); - - // Hide the ListView Header/Footer - listViewLoadingLayout.setVisibility(View.GONE); - - /** - * Scroll so the View is at the same Y as the ListView - * header/footer, but only scroll if: we've pulled to refresh, it's - * positioned correctly - */ - if (scrollLvToEdge && getState() != State.MANUAL_REFRESHING) { - mRefreshableView.setSelection(selection); - setHeaderScroll(scrollToHeight); - } - } - - // Finally, call up to super - super.onReset(); - } - - @Override - protected LoadingLayoutProxy createLoadingLayoutProxy(final boolean includeStart, final boolean includeEnd) { - LoadingLayoutProxy proxy = super.createLoadingLayoutProxy(includeStart, includeEnd); - - if (mListViewExtrasEnabled) { - final Mode mode = getMode(); - - if (includeStart && mode.showHeaderLoadingLayout()) { - proxy.addLayout(mHeaderLoadingView); - } - if (includeEnd && mode.showFooterLoadingLayout()) { - proxy.addLayout(mFooterLoadingView); - } - } - - return proxy; - } - - protected ListView createListView(Context context, AttributeSet attrs) { - final ListView lv; - if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { - lv = new InternalListViewSDK9(context, attrs); - } else { - lv = new InternalListView(context, attrs); - } - return lv; - } - - @Override - protected ListView createRefreshableView(Context context, AttributeSet attrs) { - ListView lv = createListView(context, attrs); - - // Set it to this so it can be used in ListActivity/ListFragment - lv.setId(android.R.id.list); - return lv; - } - - @Override - protected void handleStyledAttributes(TypedArray a) { - super.handleStyledAttributes(a); - - mListViewExtrasEnabled = a.getBoolean(R.styleable.PullToRefresh_ptrListViewExtrasEnabled, true); - - if (mListViewExtrasEnabled) { - final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, - FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL); - - // Create Loading Views ready for use later - FrameLayout frame = new FrameLayout(getContext()); - mHeaderLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_START, a); - mHeaderLoadingView.setVisibility(View.GONE); - frame.addView(mHeaderLoadingView, lp); - mRefreshableView.addHeaderView(frame, null, false); - - mLvFooterLoadingFrame = new FrameLayout(getContext()); - mFooterLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_END, a); - mFooterLoadingView.setVisibility(View.GONE); - mLvFooterLoadingFrame.addView(mFooterLoadingView, lp); - - /** - * If the value for Scrolling While Refreshing hasn't been - * explicitly set via XML, enable Scrolling While Refreshing. - */ - if (!a.hasValue(R.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled)) { - setScrollingWhileRefreshingEnabled(true); - } - } - } - - @TargetApi(9) - final class InternalListViewSDK9 extends InternalListView { - - public InternalListViewSDK9(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, - int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { - - final boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, - scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); - - // Does all of the hard work... - OverscrollHelper.overScrollBy(PullToRefreshListView.this, deltaX, scrollX, deltaY, scrollY, isTouchEvent); - - return returnValue; - } - } - - protected class InternalListView extends ListView implements EmptyViewMethodAccessor { - - private boolean mAddedLvFooter = false; - - public InternalListView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - /** - * This is a bit hacky, but Samsung's ListView has got a bug in it - * when using Header/Footer Views and the list is empty. This masks - * the issue so that it doesn't cause an FC. See Issue #66. - */ - try { - super.dispatchDraw(canvas); - } catch (IndexOutOfBoundsException e) { - e.printStackTrace(); - } - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - /** - * This is a bit hacky, but Samsung's ListView has got a bug in it - * when using Header/Footer Views and the list is empty. This masks - * the issue so that it doesn't cause an FC. See Issue #66. - */ - try { - return super.dispatchTouchEvent(ev); - } catch (IndexOutOfBoundsException e) { - e.printStackTrace(); - return false; - } - } - - @Override - public void setAdapter(ListAdapter adapter) { - // Add the Footer View at the last possible moment - if (null != mLvFooterLoadingFrame && !mAddedLvFooter) { - addFooterView(mLvFooterLoadingFrame, null, false); - mAddedLvFooter = true; - } - - super.setAdapter(adapter); - } - - @Override - public void setEmptyView(View emptyView) { - PullToRefreshListView.this.setEmptyView(emptyView); - } - - @Override - public void setEmptyViewInternal(View emptyView) { - super.setEmptyView(emptyView); - } - - } - -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshScrollView.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshScrollView.java deleted file mode 100644 index 3ae3627f..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshScrollView.java +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * 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.library; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.util.AttributeSet; -import android.view.View; -import android.widget.ScrollView; - -public class PullToRefreshScrollView extends PullToRefreshBase { - - public PullToRefreshScrollView(Context context) { - super(context); - } - - public PullToRefreshScrollView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public PullToRefreshScrollView(Context context, Mode mode) { - super(context, mode); - } - - public PullToRefreshScrollView(Context context, Mode mode, AnimationStyle style) { - super(context, mode, style); - } - - @Override - public final Orientation getPullToRefreshScrollDirection() { - return Orientation.VERTICAL; - } - - @Override - protected ScrollView createRefreshableView(Context context, AttributeSet attrs) { - ScrollView scrollView; - if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { - scrollView = new InternalScrollViewSDK9(context, attrs); - } else { - scrollView = new ScrollView(context, attrs); - } - - scrollView.setId(R.id.scrollview); - return scrollView; - } - - @Override - protected boolean isReadyForPullStart() { - return mRefreshableView.getScrollY() == 0; - } - - @Override - protected boolean isReadyForPullEnd() { - View scrollViewChild = mRefreshableView.getChildAt(0); - if (null != scrollViewChild) { - return mRefreshableView.getScrollY() >= (scrollViewChild.getHeight() - getHeight()); - } - return false; - } - - @TargetApi(9) - final class InternalScrollViewSDK9 extends ScrollView { - - public InternalScrollViewSDK9(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, - int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { - - final boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, - scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); - - // Does all of the hard work... - OverscrollHelper.overScrollBy(PullToRefreshScrollView.this, deltaX, scrollX, deltaY, scrollY, - getScrollRange(), isTouchEvent); - - return returnValue; - } - - /** - * Taken from the AOSP ScrollView source - */ - private int getScrollRange() { - int scrollRange = 0; - if (getChildCount() > 0) { - View child = getChildAt(0); - scrollRange = Math.max(0, child.getHeight() - (getHeight() - getPaddingBottom() - getPaddingTop())); - } - return scrollRange; - } - } -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshWebView.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshWebView.java deleted file mode 100644 index a008e424..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/PullToRefreshWebView.java +++ /dev/null @@ -1,164 +0,0 @@ -/******************************************************************************* - * 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.library; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.os.Bundle; -import android.util.AttributeSet; -import android.webkit.WebChromeClient; -import android.webkit.WebView; - -public class PullToRefreshWebView extends PullToRefreshBase { - - private static final OnRefreshListener defaultOnRefreshListener = new OnRefreshListener() { - - @Override - public void onRefresh(PullToRefreshBase refreshView) { - refreshView.getRefreshableView().reload(); - } - - }; - - private final WebChromeClient defaultWebChromeClient = new WebChromeClient() { - - @Override - public void onProgressChanged(WebView view, int newProgress) { - if (newProgress == 100) { - onRefreshComplete(); - } - } - - }; - - public PullToRefreshWebView(Context context) { - super(context); - - /** - * Added so that by default, Pull-to-Refresh refreshes the page - */ - setOnRefreshListener(defaultOnRefreshListener); - mRefreshableView.setWebChromeClient(defaultWebChromeClient); - } - - public PullToRefreshWebView(Context context, AttributeSet attrs) { - super(context, attrs); - - /** - * Added so that by default, Pull-to-Refresh refreshes the page - */ - setOnRefreshListener(defaultOnRefreshListener); - mRefreshableView.setWebChromeClient(defaultWebChromeClient); - } - - public PullToRefreshWebView(Context context, Mode mode) { - super(context, mode); - - /** - * Added so that by default, Pull-to-Refresh refreshes the page - */ - setOnRefreshListener(defaultOnRefreshListener); - mRefreshableView.setWebChromeClient(defaultWebChromeClient); - } - - public PullToRefreshWebView(Context context, Mode mode, AnimationStyle style) { - super(context, mode, style); - - /** - * Added so that by default, Pull-to-Refresh refreshes the page - */ - setOnRefreshListener(defaultOnRefreshListener); - mRefreshableView.setWebChromeClient(defaultWebChromeClient); - } - - @Override - public final Orientation getPullToRefreshScrollDirection() { - return Orientation.VERTICAL; - } - - @Override - protected WebView createRefreshableView(Context context, AttributeSet attrs) { - WebView webView; - if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { - webView = new InternalWebViewSDK9(context, attrs); - } else { - webView = new WebView(context, attrs); - } - - webView.setId(R.id.webview); - return webView; - } - - @Override - protected boolean isReadyForPullStart() { - return mRefreshableView.getScrollY() == 0; - } - - @Override - protected boolean isReadyForPullEnd() { - float exactContentHeight = (float) Math.floor(mRefreshableView.getContentHeight() * mRefreshableView.getScale()); - return mRefreshableView.getScrollY() >= (exactContentHeight - mRefreshableView.getHeight()); - } - - @Override - protected void onPtrRestoreInstanceState(Bundle savedInstanceState) { - super.onPtrRestoreInstanceState(savedInstanceState); - mRefreshableView.restoreState(savedInstanceState); - } - - @Override - protected void onPtrSaveInstanceState(Bundle saveState) { - super.onPtrSaveInstanceState(saveState); - mRefreshableView.saveState(saveState); - } - - @TargetApi(9) - final class InternalWebViewSDK9 extends WebView { - - // WebView doesn't always scroll back to it's edge so we add some - // fuzziness - static final int OVERSCROLL_FUZZY_THRESHOLD = 2; - - // WebView seems quite reluctant to overscroll so we use the scale - // factor to scale it's value - static final float OVERSCROLL_SCALE_FACTOR = 1.5f; - - public InternalWebViewSDK9(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, - int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { - - final boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, - scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); - - // Does all of the hard work... - OverscrollHelper.overScrollBy(PullToRefreshWebView.this, deltaX, scrollX, deltaY, scrollY, - getScrollRange(), OVERSCROLL_FUZZY_THRESHOLD, OVERSCROLL_SCALE_FACTOR, isTouchEvent); - - return returnValue; - } - - private int getScrollRange() { - return (int) Math.max(0, Math.floor(mRefreshableView.getContentHeight() * mRefreshableView.getScale()) - - (getHeight() - getPaddingBottom() - getPaddingTop())); - } - } -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/extras/PullToRefreshWebView2.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/extras/PullToRefreshWebView2.java deleted file mode 100644 index 78192037..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/extras/PullToRefreshWebView2.java +++ /dev/null @@ -1,132 +0,0 @@ -/******************************************************************************* - * 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.library.extras; - -import java.util.concurrent.atomic.AtomicBoolean; - -import android.content.Context; -import android.util.AttributeSet; -import android.webkit.WebView; - -import com.handmark.pulltorefresh.library.PullToRefreshWebView; - -/** - * An advanced version of {@link PullToRefreshWebView} which delegates the - * triggering of the PullToRefresh gesture to the Javascript running within the - * WebView. This means that you should only use this class if: - *

- *

- *

- *

- * The way this call works is that when a PullToRefresh gesture is in action, - * the following Javascript methods will be called: - * isReadyForPullDown() and isReadyForPullUp(), it is - * your job to calculate whether the view is in a state where a PullToRefresh - * can happen, and return the result via the callback mechanism. An example can - * be seen below: - *

- * - *

- * function isReadyForPullDown() {
- *   var result = ...  // Probably using the .scrollTop DOM attribute
- *   ptr.isReadyForPullDownResponse(result);
- * }
- * 
- * function isReadyForPullUp() {
- *   var result = ...  // Probably using the .scrollBottom DOM attribute
- *   ptr.isReadyForPullUpResponse(result);
- * }
- * 
- * - * @author Chris Banes - */ -public class PullToRefreshWebView2 extends PullToRefreshWebView { - - static final String JS_INTERFACE_PKG = "ptr"; - static final String DEF_JS_READY_PULL_DOWN_CALL = "javascript:isReadyForPullDown();"; - static final String DEF_JS_READY_PULL_UP_CALL = "javascript:isReadyForPullUp();"; - - public PullToRefreshWebView2(Context context) { - super(context); - } - - public PullToRefreshWebView2(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public PullToRefreshWebView2(Context context, Mode mode) { - super(context, mode); - } - - private JsValueCallback mJsCallback; - private final AtomicBoolean mIsReadyForPullDown = new AtomicBoolean(false); - private final AtomicBoolean mIsReadyForPullUp = new AtomicBoolean(false); - - @Override - protected WebView createRefreshableView(Context context, AttributeSet attrs) { - WebView webView = super.createRefreshableView(context, attrs); - - // Need to add JS Interface so we can get the response back - mJsCallback = new JsValueCallback(); - webView.addJavascriptInterface(mJsCallback, JS_INTERFACE_PKG); - - return webView; - } - - @Override - protected boolean isReadyForPullStart() { - // Call Javascript... - getRefreshableView().loadUrl(DEF_JS_READY_PULL_DOWN_CALL); - - // Response will be given to JsValueCallback, which will update - // mIsReadyForPullDown - - return mIsReadyForPullDown.get(); - } - - @Override - protected boolean isReadyForPullEnd() { - // Call Javascript... - getRefreshableView().loadUrl(DEF_JS_READY_PULL_UP_CALL); - - // Response will be given to JsValueCallback, which will update - // mIsReadyForPullUp - - return mIsReadyForPullUp.get(); - } - - /** - * Used for response from Javascript - * - * @author Chris Banes - */ - final class JsValueCallback { - - public void isReadyForPullUpResponse(boolean response) { - mIsReadyForPullUp.set(response); - } - - public void isReadyForPullDownResponse(boolean response) { - mIsReadyForPullDown.set(response); - } - } -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/extras/SoundPullEventListener.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/extras/SoundPullEventListener.java deleted file mode 100644 index a7aac306..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/extras/SoundPullEventListener.java +++ /dev/null @@ -1,96 +0,0 @@ -/******************************************************************************* - * 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.library.extras; - -import java.util.HashMap; - -import android.content.Context; -import android.media.MediaPlayer; -import android.view.View; - -import com.handmark.pulltorefresh.library.PullToRefreshBase; -import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; -import com.handmark.pulltorefresh.library.PullToRefreshBase.State; - -public class SoundPullEventListener implements PullToRefreshBase.OnPullEventListener { - - private final Context mContext; - private final HashMap mSoundMap; - - private MediaPlayer mCurrentMediaPlayer; - - /** - * Constructor - * - * @param context - Context - */ - public SoundPullEventListener(Context context) { - mContext = context; - mSoundMap = new HashMap(); - } - - @Override - public final void onPullEvent(PullToRefreshBase refreshView, State event, Mode direction) { - Integer soundResIdObj = mSoundMap.get(event); - if (null != soundResIdObj) { - playSound(soundResIdObj.intValue()); - } - } - - /** - * Set the Sounds to be played when a Pull Event happens. You specify which - * sound plays for which events by calling this method multiple times for - * each event. - *

- * If you've already set a sound for a certain event, and add another sound - * for that event, only the new sound will be played. - * - * @param event - The event for which the sound will be played. - * @param resId - Resource Id of the sound file to be played (e.g. - * R.raw.pull_sound) - */ - public void addSoundEvent(State event, int resId) { - mSoundMap.put(event, resId); - } - - /** - * Clears all of the previously set sounds and events. - */ - public void clearSounds() { - mSoundMap.clear(); - } - - /** - * Gets the current (or last) MediaPlayer instance. - */ - public MediaPlayer getCurrentMediaPlayer() { - return mCurrentMediaPlayer; - } - - private void playSound(int resId) { - // Stop current player, if there's one playing - if (null != mCurrentMediaPlayer) { - mCurrentMediaPlayer.stop(); - mCurrentMediaPlayer.release(); - } - - mCurrentMediaPlayer = MediaPlayer.create(mContext, resId); - if (null != mCurrentMediaPlayer) { - mCurrentMediaPlayer.start(); - } - } - -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/EmptyViewMethodAccessor.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/EmptyViewMethodAccessor.java deleted file mode 100644 index 369f21e8..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/EmptyViewMethodAccessor.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * 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.library.internal; - -import android.view.View; - -/** - * Interface that allows PullToRefreshBase to hijack the call to - * AdapterView.setEmptyView() - * - * @author chris - */ -public interface EmptyViewMethodAccessor { - - /** - * Calls upto AdapterView.setEmptyView() - * - * @param emptyView - to set as Empty View - */ - public void setEmptyViewInternal(View emptyView); - - /** - * Should call PullToRefreshBase.setEmptyView() which will then - * automatically call through to setEmptyViewInternal() - * - * @param emptyView - to set as Empty View - */ - public void setEmptyView(View emptyView); - -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/FlipLoadingLayout.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/FlipLoadingLayout.java deleted file mode 100644 index fef31605..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/FlipLoadingLayout.java +++ /dev/null @@ -1,146 +0,0 @@ -/******************************************************************************* - * 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.library.internal; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Matrix; -import android.graphics.drawable.Drawable; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.Animation; -import android.view.animation.RotateAnimation; -import android.widget.ImageView.ScaleType; - -import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; -import com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation; -import com.handmark.pulltorefresh.library.R; - -@SuppressLint("ViewConstructor") -public class FlipLoadingLayout extends LoadingLayout { - - static final int FLIP_ANIMATION_DURATION = 150; - - private final Animation mRotateAnimation, mResetRotateAnimation; - - public FlipLoadingLayout(Context context, final Mode mode, final Orientation scrollDirection, TypedArray attrs) { - super(context, mode, scrollDirection, attrs); - - final int rotateAngle = mode == Mode.PULL_FROM_START ? -180 : 180; - - mRotateAnimation = new RotateAnimation(0, rotateAngle, Animation.RELATIVE_TO_SELF, 0.5f, - Animation.RELATIVE_TO_SELF, 0.5f); - mRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR); - mRotateAnimation.setDuration(FLIP_ANIMATION_DURATION); - mRotateAnimation.setFillAfter(true); - - mResetRotateAnimation = new RotateAnimation(rotateAngle, 0, Animation.RELATIVE_TO_SELF, 0.5f, - Animation.RELATIVE_TO_SELF, 0.5f); - mResetRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR); - mResetRotateAnimation.setDuration(FLIP_ANIMATION_DURATION); - mResetRotateAnimation.setFillAfter(true); - } - - @Override - protected void onLoadingDrawableSet(Drawable imageDrawable) { - if (null != imageDrawable) { - final int dHeight = imageDrawable.getIntrinsicHeight(); - final int dWidth = imageDrawable.getIntrinsicWidth(); - - /** - * We need to set the width/height of the ImageView so that it is - * square with each side the size of the largest drawable dimension. - * This is so that it doesn't clip when rotated. - */ - ViewGroup.LayoutParams lp = mHeaderImage.getLayoutParams(); - lp.width = lp.height = Math.max(dHeight, dWidth); - mHeaderImage.requestLayout(); - - /** - * We now rotate the Drawable so that is at the correct rotation, - * and is centered. - */ - mHeaderImage.setScaleType(ScaleType.MATRIX); - Matrix matrix = new Matrix(); - matrix.postTranslate((lp.width - dWidth) / 2f, (lp.height - dHeight) / 2f); - matrix.postRotate(getDrawableRotationAngle(), lp.width / 2f, lp.height / 2f); - mHeaderImage.setImageMatrix(matrix); - } - } - - @Override - protected void onPullImpl(float scaleOfLayout) { - // NO-OP - } - - @Override - protected void pullToRefreshImpl() { - // Only start reset Animation, we've previously show the rotate anim - if (mRotateAnimation == mHeaderImage.getAnimation()) { - mHeaderImage.startAnimation(mResetRotateAnimation); - } - } - - @Override - protected void refreshingImpl() { - mHeaderImage.clearAnimation(); - mHeaderImage.setVisibility(View.INVISIBLE); - mHeaderProgress.setVisibility(View.VISIBLE); - } - - @Override - protected void releaseToRefreshImpl() { - mHeaderImage.startAnimation(mRotateAnimation); - } - - @Override - protected void resetImpl() { - mHeaderImage.clearAnimation(); - mHeaderProgress.setVisibility(View.GONE); - mHeaderImage.setVisibility(View.VISIBLE); - } - - @Override - protected int getDefaultDrawableResId() { - return R.drawable.default_ptr_flip; - } - - private float getDrawableRotationAngle() { - float angle = 0f; - switch (mMode) { - case PULL_FROM_END: - if (mScrollDirection == Orientation.HORIZONTAL) { - angle = 90f; - } else { - angle = 180f; - } - break; - - case PULL_FROM_START: - if (mScrollDirection == Orientation.HORIZONTAL) { - angle = 270f; - } - break; - - default: - break; - } - - return angle; - } - -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/IndicatorLayout.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/IndicatorLayout.java deleted file mode 100644 index a9069f2a..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/IndicatorLayout.java +++ /dev/null @@ -1,147 +0,0 @@ -/******************************************************************************* - * 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.library.internal; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.Matrix; -import android.graphics.drawable.Drawable; -import android.view.View; -import android.view.animation.Animation; -import android.view.animation.Animation.AnimationListener; -import android.view.animation.AnimationUtils; -import android.view.animation.Interpolator; -import android.view.animation.LinearInterpolator; -import android.view.animation.RotateAnimation; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.ImageView.ScaleType; - -import com.handmark.pulltorefresh.library.PullToRefreshBase; -import com.handmark.pulltorefresh.library.R; - -@SuppressLint("ViewConstructor") -public class IndicatorLayout extends FrameLayout implements AnimationListener { - - static final int DEFAULT_ROTATION_ANIMATION_DURATION = 150; - - private Animation mInAnim, mOutAnim; - private ImageView mArrowImageView; - - private final Animation mRotateAnimation, mResetRotateAnimation; - - public IndicatorLayout(Context context, PullToRefreshBase.Mode mode) { - super(context); - mArrowImageView = new ImageView(context); - - Drawable arrowD = getResources().getDrawable(R.drawable.indicator_arrow); - mArrowImageView.setImageDrawable(arrowD); - - final int padding = getResources().getDimensionPixelSize(R.dimen.indicator_internal_padding); - mArrowImageView.setPadding(padding, padding, padding, padding); - addView(mArrowImageView); - - int inAnimResId, outAnimResId; - switch (mode) { - case PULL_FROM_END: - inAnimResId = R.anim.slide_in_from_bottom; - outAnimResId = R.anim.slide_out_to_bottom; - setBackgroundResource(R.drawable.indicator_bg_bottom); - - // Rotate Arrow so it's pointing the correct way - mArrowImageView.setScaleType(ScaleType.MATRIX); - Matrix matrix = new Matrix(); - matrix.setRotate(180f, arrowD.getIntrinsicWidth() / 2f, arrowD.getIntrinsicHeight() / 2f); - mArrowImageView.setImageMatrix(matrix); - break; - default: - case PULL_FROM_START: - inAnimResId = R.anim.slide_in_from_top; - outAnimResId = R.anim.slide_out_to_top; - setBackgroundResource(R.drawable.indicator_bg_top); - break; - } - - mInAnim = AnimationUtils.loadAnimation(context, inAnimResId); - mInAnim.setAnimationListener(this); - - mOutAnim = AnimationUtils.loadAnimation(context, outAnimResId); - mOutAnim.setAnimationListener(this); - - final Interpolator interpolator = new LinearInterpolator(); - mRotateAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, - 0.5f); - mRotateAnimation.setInterpolator(interpolator); - mRotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION); - mRotateAnimation.setFillAfter(true); - - mResetRotateAnimation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 0.5f, - Animation.RELATIVE_TO_SELF, 0.5f); - mResetRotateAnimation.setInterpolator(interpolator); - mResetRotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION); - mResetRotateAnimation.setFillAfter(true); - - } - - public final boolean isVisible() { - Animation currentAnim = getAnimation(); - if (null != currentAnim) { - return mInAnim == currentAnim; - } - - return getVisibility() == View.VISIBLE; - } - - public void hide() { - startAnimation(mOutAnim); - } - - public void show() { - mArrowImageView.clearAnimation(); - startAnimation(mInAnim); - } - - @Override - public void onAnimationEnd(Animation animation) { - if (animation == mOutAnim) { - mArrowImageView.clearAnimation(); - setVisibility(View.GONE); - } else if (animation == mInAnim) { - setVisibility(View.VISIBLE); - } - - clearAnimation(); - } - - @Override - public void onAnimationRepeat(Animation animation) { - // NO-OP - } - - @Override - public void onAnimationStart(Animation animation) { - setVisibility(View.VISIBLE); - } - - public void releaseToRefresh() { - mArrowImageView.startAnimation(mRotateAnimation); - } - - public void pullToRefresh() { - mArrowImageView.startAnimation(mResetRotateAnimation); - } - -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/LoadingLayout.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/LoadingLayout.java deleted file mode 100644 index 9c12586d..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/LoadingLayout.java +++ /dev/null @@ -1,393 +0,0 @@ -/******************************************************************************* - * 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.library.internal; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.res.ColorStateList; -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; -import android.widget.ImageView; -import android.widget.ProgressBar; -import android.widget.TextView; - -import com.handmark.pulltorefresh.library.ILoadingLayout; -import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; -import com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation; -import com.handmark.pulltorefresh.library.R; - -@SuppressLint("ViewConstructor") -public abstract class LoadingLayout extends FrameLayout implements ILoadingLayout { - - static final String LOG_TAG = "PullToRefresh-LoadingLayout"; - - static final Interpolator ANIMATION_INTERPOLATOR = new LinearInterpolator(); - - private FrameLayout mInnerLayout; - - protected final ImageView mHeaderImage; - protected final ProgressBar mHeaderProgress; - - private boolean mUseIntrinsicAnimation; - - private final TextView mHeaderText; - private final TextView mSubHeaderText; - - protected final Mode mMode; - protected final Orientation mScrollDirection; - - private CharSequence mPullLabel; - private CharSequence mRefreshingLabel; - private CharSequence mReleaseLabel; - - public LoadingLayout(Context context, final Mode mode, final Orientation scrollDirection, TypedArray attrs) { - super(context); - mMode = mode; - mScrollDirection = scrollDirection; - - switch (scrollDirection) { - case HORIZONTAL: - LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_horizontal, this); - break; - case VERTICAL: - default: - LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_vertical, this); - break; - } - - 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); - mReleaseLabel = context.getString(R.string.pull_to_refresh_from_bottom_release_label); - break; - - 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); - mReleaseLabel = context.getString(R.string.pull_to_refresh_release_label); - break; - } - - if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderBackground)) { - Drawable background = attrs.getDrawable(R.styleable.PullToRefresh_ptrHeaderBackground); - if (null != background) { - ViewCompat.setBackground(this, background); - } - } - - if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderTextAppearance)) { - TypedValue styleID = new TypedValue(); - attrs.getValue(R.styleable.PullToRefresh_ptrHeaderTextAppearance, styleID); - setTextAppearance(styleID.data); - } - if (attrs.hasValue(R.styleable.PullToRefresh_ptrSubHeaderTextAppearance)) { - TypedValue styleID = new TypedValue(); - attrs.getValue(R.styleable.PullToRefresh_ptrSubHeaderTextAppearance, styleID); - setSubTextAppearance(styleID.data); - } - - // Text Color attrs need to be set after TextAppearance attrs - if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderTextColor)) { - ColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderTextColor); - if (null != colors) { - setTextColor(colors); - } - } - if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderSubTextColor)) { - ColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderSubTextColor); - if (null != colors) { - setSubTextColor(colors); - } - } - - // Try and get defined drawable from Attrs - Drawable imageDrawable = null; - if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawable)) { - imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawable); - } - - // Check Specific Drawable from Attrs, these overrite the generic - // drawable attr above - switch (mode) { - case PULL_FROM_START: - default: - if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableStart)) { - imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableStart); - } else if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableTop)) { - Utils.warnDeprecation("ptrDrawableTop", "ptrDrawableStart"); - imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableTop); - } - break; - - case PULL_FROM_END: - if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableEnd)) { - imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableEnd); - } else if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableBottom)) { - Utils.warnDeprecation("ptrDrawableBottom", "ptrDrawableEnd"); - imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableBottom); - } - break; - } - - // If we don't have a user defined drawable, load the default - if (null == imageDrawable) { - imageDrawable = context.getResources().getDrawable(getDefaultDrawableResId()); - } - - // Set Drawable, and save width/height - setLoadingDrawable(imageDrawable); - - reset(); - } - - public final void setHeight(int height) { - ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams(); - lp.height = height; - requestLayout(); - } - - public final void setWidth(int width) { - ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams(); - lp.width = width; - requestLayout(); - } - - public final int getContentSize() { - switch (mScrollDirection) { - case HORIZONTAL: - return mInnerLayout.getWidth(); - case VERTICAL: - default: - return mInnerLayout.getHeight(); - } - } - - 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) { - if (!mUseIntrinsicAnimation) { - onPullImpl(scaleOfLayout); - } - } - - public final void pullToRefresh() { - if (null != mHeaderText) { - mHeaderText.setText(mPullLabel); - } - - // Now call the callback - pullToRefreshImpl(); - } - - public final void refreshing() { - if (null != mHeaderText) { - mHeaderText.setText(mRefreshingLabel); - } - - if (mUseIntrinsicAnimation) { - ((AnimationDrawable) mHeaderImage.getDrawable()).start(); - } else { - // Now call the callback - refreshingImpl(); - } - - if (null != mSubHeaderText) { - mSubHeaderText.setVisibility(View.GONE); - } - } - - public final void releaseToRefresh() { - if (null != mHeaderText) { - mHeaderText.setText(mReleaseLabel); - } - - // Now call the callback - releaseToRefreshImpl(); - } - - public final void reset() { - if (null != mHeaderText) { - mHeaderText.setText(mPullLabel); - } - mHeaderImage.setVisibility(View.VISIBLE); - - if (mUseIntrinsicAnimation) { - ((AnimationDrawable) mHeaderImage.getDrawable()).stop(); - } else { - // Now call the callback - resetImpl(); - } - - if (null != mSubHeaderText) { - if (TextUtils.isEmpty(mSubHeaderText.getText())) { - mSubHeaderText.setVisibility(View.GONE); - } else { - mSubHeaderText.setVisibility(View.VISIBLE); - } - } - } - - @Override - public void setLastUpdatedLabel(CharSequence label) { - setSubHeaderText(label); - } - - public final void setLoadingDrawable(Drawable imageDrawable) { - // Set Drawable - mHeaderImage.setImageDrawable(imageDrawable); - mUseIntrinsicAnimation = (imageDrawable instanceof AnimationDrawable); - - // Now call the callback - onLoadingDrawableSet(imageDrawable); - } - - public void setPullLabel(CharSequence pullLabel) { - mPullLabel = pullLabel; - } - - public void setRefreshingLabel(CharSequence refreshingLabel) { - mRefreshingLabel = refreshingLabel; - } - - public void setReleaseLabel(CharSequence releaseLabel) { - mReleaseLabel = releaseLabel; - } - - @Override - 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 - */ - - protected abstract int getDefaultDrawableResId(); - - protected abstract void onLoadingDrawableSet(Drawable imageDrawable); - - protected abstract void onPullImpl(float scaleOfLayout); - - protected abstract void pullToRefreshImpl(); - - protected abstract void refreshingImpl(); - - protected abstract void releaseToRefreshImpl(); - - protected abstract void resetImpl(); - - private void setSubHeaderText(CharSequence label) { - if (null != mSubHeaderText) { - if (TextUtils.isEmpty(label)) { - mSubHeaderText.setVisibility(View.GONE); - } else { - mSubHeaderText.setText(label); - - // Only set it to Visible if we're GONE, otherwise VISIBLE will - // be set soon - if (View.GONE == mSubHeaderText.getVisibility()) { - mSubHeaderText.setVisibility(View.VISIBLE); - } - } - } - } - - private void setSubTextAppearance(int value) { - if (null != mSubHeaderText) { - mSubHeaderText.setTextAppearance(getContext(), value); - } - } - - private void setSubTextColor(ColorStateList color) { - if (null != mSubHeaderText) { - mSubHeaderText.setTextColor(color); - } - } - - private void setTextAppearance(int value) { - if (null != mHeaderText) { - mHeaderText.setTextAppearance(getContext(), value); - } - if (null != mSubHeaderText) { - mSubHeaderText.setTextAppearance(getContext(), value); - } - } - - private void setTextColor(ColorStateList color) { - if (null != mHeaderText) { - mHeaderText.setTextColor(color); - } - if (null != mSubHeaderText) { - mSubHeaderText.setTextColor(color); - } - } - -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/RotateLoadingLayout.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/RotateLoadingLayout.java deleted file mode 100644 index bda7b2fc..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/RotateLoadingLayout.java +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************************* - * 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.library.internal; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Matrix; -import android.graphics.drawable.Drawable; -import android.view.animation.Animation; -import android.view.animation.RotateAnimation; -import android.widget.ImageView.ScaleType; - -import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; -import com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation; -import com.handmark.pulltorefresh.library.R; - -public class RotateLoadingLayout extends LoadingLayout { - - static final int ROTATION_ANIMATION_DURATION = 1200; - - private final Animation mRotateAnimation; - private final Matrix mHeaderImageMatrix; - - private float mRotationPivotX, mRotationPivotY; - - private final boolean mRotateDrawableWhilePulling; - - public RotateLoadingLayout(Context context, Mode mode, Orientation scrollDirection, TypedArray attrs) { - super(context, mode, scrollDirection, attrs); - - mRotateDrawableWhilePulling = attrs.getBoolean(R.styleable.PullToRefresh_ptrRotateDrawableWhilePulling, true); - - mHeaderImage.setScaleType(ScaleType.MATRIX); - mHeaderImageMatrix = new Matrix(); - mHeaderImage.setImageMatrix(mHeaderImageMatrix); - - mRotateAnimation = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, - 0.5f); - mRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR); - mRotateAnimation.setDuration(ROTATION_ANIMATION_DURATION); - mRotateAnimation.setRepeatCount(Animation.INFINITE); - mRotateAnimation.setRepeatMode(Animation.RESTART); - } - - public void onLoadingDrawableSet(Drawable imageDrawable) { - if (null != imageDrawable) { - mRotationPivotX = Math.round(imageDrawable.getIntrinsicWidth() / 2f); - mRotationPivotY = Math.round(imageDrawable.getIntrinsicHeight() / 2f); - } - } - - protected void onPullImpl(float scaleOfLayout) { - float angle; - if (mRotateDrawableWhilePulling) { - angle = scaleOfLayout * 90f; - } else { - angle = Math.max(0f, Math.min(180f, scaleOfLayout * 360f - 180f)); - } - - mHeaderImageMatrix.setRotate(angle, mRotationPivotX, mRotationPivotY); - mHeaderImage.setImageMatrix(mHeaderImageMatrix); - } - - @Override - protected void refreshingImpl() { - mHeaderImage.startAnimation(mRotateAnimation); - } - - @Override - protected void resetImpl() { - mHeaderImage.clearAnimation(); - resetImageRotation(); - } - - private void resetImageRotation() { - if (null != mHeaderImageMatrix) { - mHeaderImageMatrix.reset(); - mHeaderImage.setImageMatrix(mHeaderImageMatrix); - } - } - - @Override - protected void pullToRefreshImpl() { - // NO-OP - } - - @Override - protected void releaseToRefreshImpl() { - // NO-OP - } - - @Override - protected int getDefaultDrawableResId() { - return R.drawable.default_ptr_rotate; - } - -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/Utils.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/Utils.java deleted file mode 100644 index 73432189..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/Utils.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.handmark.pulltorefresh.library.internal; - -import android.util.Log; - -public class Utils { - - static final String LOG_TAG = "PullToRefresh"; - - public static void warnDeprecation(String depreacted, String replacement) { - Log.w(LOG_TAG, "You're using the deprecated " + depreacted + " attr, please switch over to " + replacement); - } - -} diff --git a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/ViewCompat.java b/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/ViewCompat.java deleted file mode 100644 index 618bace0..00000000 --- a/core/pulltorefresh/src/main/java/com/handmark/pulltorefresh/library/internal/ViewCompat.java +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* - * 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.library.internal; - -import android.annotation.TargetApi; -import android.graphics.drawable.Drawable; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.view.View; - -@SuppressWarnings("deprecation") -public class ViewCompat { - - public static void postOnAnimation(View view, Runnable runnable) { - if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { - SDK16.postOnAnimation(view, runnable); - } else { - view.postDelayed(runnable, 16); - } - } - - public static void setBackground(View view, Drawable background) { - if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { - SDK16.setBackground(view, background); - } else { - view.setBackgroundDrawable(background); - } - } - - public static void setLayerType(View view, int layerType) { - if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) { - SDK11.setLayerType(view, layerType); - } - } - - @TargetApi(11) - static class SDK11 { - - public static void setLayerType(View view, int layerType) { - view.setLayerType(layerType, null); - } - } - - @TargetApi(16) - static class SDK16 { - - public static void postOnAnimation(View view, Runnable runnable) { - view.postOnAnimation(runnable); - } - - public static void setBackground(View view, Drawable background) { - view.setBackground(background); - } - - } - -} diff --git a/core/pulltorefresh/src/main/res/anim/slide_in_from_bottom.xml b/core/pulltorefresh/src/main/res/anim/slide_in_from_bottom.xml deleted file mode 100644 index bb430ce9..00000000 --- a/core/pulltorefresh/src/main/res/anim/slide_in_from_bottom.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - diff --git a/core/pulltorefresh/src/main/res/anim/slide_in_from_top.xml b/core/pulltorefresh/src/main/res/anim/slide_in_from_top.xml deleted file mode 100644 index 52d91afc..00000000 --- a/core/pulltorefresh/src/main/res/anim/slide_in_from_top.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - diff --git a/core/pulltorefresh/src/main/res/anim/slide_out_to_bottom.xml b/core/pulltorefresh/src/main/res/anim/slide_out_to_bottom.xml deleted file mode 100644 index 83eca5ad..00000000 --- a/core/pulltorefresh/src/main/res/anim/slide_out_to_bottom.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - diff --git a/core/pulltorefresh/src/main/res/anim/slide_out_to_top.xml b/core/pulltorefresh/src/main/res/anim/slide_out_to_top.xml deleted file mode 100644 index 5105ae1f..00000000 --- a/core/pulltorefresh/src/main/res/anim/slide_out_to_top.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - diff --git a/core/pulltorefresh/src/main/res/drawable-hdpi/default_ptr_flip.png b/core/pulltorefresh/src/main/res/drawable-hdpi/default_ptr_flip.png deleted file mode 100644 index 0a2c0bd9bb4907fc43e8ba68e3b9b6fefd6d84ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1835 zcmZXU2{fDO8pnesN{d@dgm5jfs~U8u1Ytxa$RdlSt;RB=RYhsIG)=2BsuJy3+o=|v zS{lo-v|4Iks$}d*89`$kEe1ntZ3Xwc*S*d?=RW7W|L^zw-~V&Yci#7$mrWwL%E_wB zfZ=j^Oaii!vhx%>kNbn4h`+C;<{RoQ_Z zK`wxzwS8RgaNbtXC}(To>SY}eTt?xN8?)V7X#_6&wryDK+KZ*PUvK;Exvth}>6Bv~r?3oBbOmfvY;PtZZj{5)W? zpi*|Y0b*y!O`YZ@!=mGp{QT)<86R?1hwb;(#Q&$Z%o7Gr$Yl};~H9*2yBnfxo< zBlzu0(H2Y%*mM56{=!2Z;?!{T1;wfY)%azvt(U@}xwIl4C1f&Svek`Ml0|Gd%| z)LnHZt49)%@_jS6cP3ss9{sYcp$Ob7K-yU4K|i~DhlZCIJB^k<^7TBjW0{3IpTaW^ ztH0ltsnsoC7xPrD8|v1k z<#`sOIxDU;|MuJmO&O68YXw#nvF1qY}Foq?oL zkd+hLn)B|{B1R2AHhz=VZ-_x@*{JW8+o+@Hx_eOm536WjP-N_7xTzBGY{*=}`d$Tr zjwt?XNeDzY#2}D_JjsLVvbVQ~!{P9FJdH;4{CD{hd;unt$pivnABaRE(2_``gUmiq zC=_4IA z<9C?T?jCpo(UVN2dHebY1&4%1T#1T}zm<^0zWeZTZe9Vmq`dM)bzNgi+uPrI`uRh` z_oB&}xrLS0&HlJPCUE{{IE)h&rdHNE@8u)`0}mkH^kz=wrRtW)VG9b#o|)8>^E>nc zjHcG`nHxel2zo4<&C z6qe=Vbihi=3CaXd7+KHx81@!R*57{Gh2t!6D{yktB+HV&CJ9mpwTpdn-r}IxFF{?- zCfOtj@~2Ers@nzXkKbQSlPkTdl?o?MXDg<@JR;E6H#e3sX1Ro5vqHNZyT(aSayj1C zwb>T7 a+Ju$p-kaba>tx`1KsXlyru;kqAO8vU6*3Y4 diff --git a/core/pulltorefresh/src/main/res/drawable-hdpi/default_ptr_rotate.png b/core/pulltorefresh/src/main/res/drawable-hdpi/default_ptr_rotate.png deleted file mode 100644 index dc641b72459953994dd5800438f559dc4659f228..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48963 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

    Ys7l zAukqY^p64u8u$6luCcnyh~(9;R@n~S8EcdVgy@fQN+h)n31;XM$4|D6Nt4XJ++$9S z);5*ajBeYsuYdqEK7Yfm2UeIF#w*l}5_2+UfkUp)`T$|-#<(>WZq_Cx-$1Be1oMBPSq&E}3U z_pk1zP3%6kaZ6J5L_N|vRCT`Pm5JVT;JpoXj%X^}fYEv4p?80uVOkt6EX6kFE1HL2 zy2t7P@4z%~bM2jx*2#(IFhxP_l)H@u7Qv_T^;%(`OV diff --git a/core/pulltorefresh/src/main/res/drawable-hdpi/indicator_arrow.png b/core/pulltorefresh/src/main/res/drawable-hdpi/indicator_arrow.png deleted file mode 100644 index 8ae79770973e4fd85f994c0f6edff5eb5ebae6c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 390 zcmeAS@N?(olHy`uVBq!ia0vp^LO`s}!VDxogtJxwDdu7)&kzm{j@u9Y9{{O>_%)r16w3}Oq z@zUM8KR`j564!{5;QX|b^2DN42FH~Aq*MjB%%art{G#k)1?OPX!mW?Zfa=zIx;TbN zOifNmNDu*n1O`SmRaI416EP+Z#-kz!brO@4lbsE`j~qRERPc<`jHZOnwzf95MH>aG z1RZpNfU|dL91yfD<4c_F=I-t;EXDoMuI065`nfrljJ-#7nVA94ek1j`Rw2C;>ZYolBP$$cBi;Bqs#Pm zN_H)lBW3aKDhEO(ckt`#k8Gj}8yV^wZ;TTVbrl(}FBuK1`; zbs$4tSCBGH4>PDm98In)xfOW2YuF|!qS{WTVf`R-e$wyqf#vkvnnTYt5(c*}(&`hi zZ=cK?&fv=#Wi`0K3yPAYCDA##XgGPk@D`gn_}PuYDA67S4=S>Rr}EYIEuVnGzKuMlRhgp`JMAT@5+52%E)YQ0x?;QQNX$-|+iG!b%JG^p&Q0lhs!2?_>Ov1Y1JuZa1aEJ2uot zJ<{udd9(`0H(w|@8gp!8pIEUjQ>X8*hXbNXCRq2Z7|TW5d;%Nx`}I(Qo@O_?jk&m( z5MWk8uM0geIiyVc)MnlvNCz`}LEM$UI|A(xM3L6XfwQ}kKD5PMf2_l^$|C1t+R9Ef zJg+!_rS`6q!h`NS2b0QpKAOKlQT22v8fy89ZLu)NB}URLKTAck}2QTt3(lS;ISk>kO2ugugZ!ryy$_fh&PvU9)u zbFtfGGaoD1{X$eT++DPqwOSZfz$nn^8N!^1)5GMMvMt$LS1j1(Y?~EN4%539v100X zyFS@kaaY|m@1dEPRmKQ}3~>C8zYcl0!<s_M; z)`x!eb-5~Q!c2G__bq_1r!*HD^!wsx2lo- zwJde0+QWLMD@e2!KMNtd#&lBofyYz(%D~ zf7X8()&P8gE`Za10x+!MR|Tm2C;!N6&R_jB8s%5R8vnm5@^R%mUt7i#RgJMV_Cm74*E! ziJwKx+J;$JL%-amv~4fVxftw^hkQuCb~%F3!k1J??k#3i*_9Xsllcu$IOMunBXc@8 zF`}!bC0b`BFeYK%cExS{(4`6m+F4Ci;@)9z3$F5&{l+Lkj=jK^g|W|0sfW8`Y^6JG z4~Km7wl_w}`W{q5tQ(H#A+q6m6?dhdv^-!JeAU{sUdQk_J2k_Rc5ZppQMhZqZHjDe Rga~W{!nqP$O7{j_`WN%b-~Ipq diff --git a/core/pulltorefresh/src/main/res/drawable-mdpi/default_ptr_rotate.png b/core/pulltorefresh/src/main/res/drawable-mdpi/default_ptr_rotate.png deleted file mode 100644 index 95b22bd71c4f2ed6c91652ac255b62bb8461e38a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49665 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%0A-uWX&~N5)pN#W zu`0cP$zA7Q6u$OcB#vfjO7D5R6x^@|BGahayXS#+Q+{D;nW}m&wKv9Ml=~IMli@TnQGfJc_l^?N zT9_!qDlNBjA}6yhYEG9Ka9A9ZvXirFZ;6Fm5(SeT`59wxsiLa+U+>5|sFBNu!?Fq$ zBhQBj{k?|A3;~)fTqDvWE2=Kd#1QWz!HZXhu@AzB#0*{Tv1a!aAW3p$R)ZU7%AOi( z13E%PxUN>_S&y5^R6HCUe$X=iV2hND$)WInIXtk<^sL5!<~D6X9er%*uPK_>$y2o7 zP&ZPggj!0xKY!xA2>Vdy#4LS4>ABHwOzinh#tyoLH@8^`UE)y{d|4Xsdp#nimP*uBLQMZ_1I`B=HIrB2OdF6yOu z&W4FfHN}Ukj)nVAr$$-gzW$j4tP);)Y`9Tg?wbc?HxFEpC}3r!YoU3JSb1J%bad;q zQX$nQ_*-$~5CPV&qwG-SJhAAiyH}qoaJ5~DrbRINz(&}4Rd@dta%)+4s{88oHd?xRHSko9ni_i-HBC%7ldxD=M5R zYet6QVQvgX?)M&;W-fasUdMO*#=TFUaj_QMs!<4Md)01p-Z$0qGI}A)#xsqwV}!pn zd{w>+FKPr~ok?dRmw`!h+9_+4L-UM@^|YD>9$rtnKt{t9Rzn#DACnT6Iam>anBgzeoCfK%(6~ zRIhBa66|2|@&Lk_=w7T{zR@ekWLu>z9@60!n%?l=GwBHk=-VOUrl|6n+@M`5S`pnI ztkjENJf|H1ZPk0}x}q;4sca4`E$bR}T-`|Dg&J9eXBhAl%5#7T3Kd>khA(11o@l84 zTmZSHlgAB3Y+1m!viqx@*iDLzr9N9?M8wZG_3r{HHN|cCTfdyOj}UR^Fcr~8-U2C2 z%$>ftw3mH_a=B3pFW|iN!)8v@QKRQYf@9t4OB7VS&!fNLPye{1LdNTpAbB&t6VGM<&SduFBmXOw-R+Cfuf)IN ztFQmJuOi#aGazM3TEY&Q71Hls!h9)0Urpa{&?Jl5V7xT6F_)Bm8pKXSFKK?573)T) zb1obexpf?2fbVv4UJL)0`o#wD0)%UClkPYh4WmvqFPus9d5B43!)UI{ID(|z#^!*v z9CtTa6U^tXHas2X6Wx7HpQuC^2D1`=FtquXQ9+>?{!h%@v%A$=(c^fz8P^u%9Af4< z|DB6cFrl?=GbCd`Gmbs{59W?hx?X*3@rzAyzDG%E!3rVX(GJy?UU^D0==BR7!G0qi zoF4(2nDo5^8qffcpnE=GV5qWO*y+kb8qdBysb1l} zYRwN@j-2P~NP0?=pYJmD4<1~eMRc^?h|BY>cr5gyZgno{8me|4D|PCAG`<J z)pF3K$~2v{k?()CccxKEt!o^&EHy37tgKTR;>j`M!6y6fDvKb*DhhrJgcUiSJu z&-?D*{CcmrpzwOP)X+)0V z+tfTzIlWae<{y>rkml@0!Fc~DDOhJ^Bk#e(vn*Zs+7I2x_MDlLsqwvc#`|2iog=J> zPI}cx`)H?(n>@p)Uw;MvKx0lrk3(2dS@(EyOHnY+#nNJtN{-uc^Wg?JRH;r&vT&9? zudvN+OWfU}79s2S%g4QmHr_HvoV@jC7BD}HYPJ&|^9JRp{-VM(FH!U9^vS#zq6!TT zPTOK7hO6FJJLd@Jk;KwZk`GUtq}_&j%6eocKgs6SSdR0xO}S&piD>QgrSpb0qaIgf z0x!hHRMT_)w#o+;m=y7>aCNt|!qLn7hg3?kGfk`mI>u7j`YAaxx@HWSj3B%D!$C=Dah_1}yazB6y*488RN4JhpKw}A z;6U;10(B|%+I#ywZM00wX+@)TXJGl&Jh?Nki?KE#rR$CEJKoo|TU;jJD|yTOU>x!r zp}0|*+kGuiB_^~(L$1pZI-~#Mj6xixC_p1~-Z|lAy<+LuJaMk^YU6>}#yW3RyVI+q zuQp^Y75SO-2}UyIZky%bdYCF0l##suC11T}e(ED*nZAnyV~s6IdK}dyHz-`Om0=vX zdBd?OC#OSc4(ATBs-+sVcAv;JnKoqSBz3s>&9|-4NK>co)jqaArMfLmrEgiK?MhPL zy~-}9T_<&9s}@zx)Q*}J=5U5R9U`vdI&-l1mpJ4Edmej|Pbf&aR>+sl(Znh8mLzN? z8yQSHu6h1T*~ad)^t+^sxZ6U!R ztnJrz7sroWxzo6#VD24-ZtgaDe@lw%YqzyKnECc*F)DXOqD_hy--mD~{1MtUg~6z* zO^5Ps@SBEWm-pg6atQ_%HRs#jzv$fV6O(SCp&r&HCYshV@Bv3IKN62vBMF{DwZTl| zV3YT}qVx@Y597O|1kS@Dad8$qd=;PvPm{4txN8d7`o4`(l?G?V6E!ao~#(52ONgWPiEGA(6tK9SzqS@laBIIml2qV@(f`yAZ7kH{nm?x-9 z5hzGEtYxHaHjAh#PTx5|f@<9yzbU-IaBp&Y*Y|pLKI zdA3v=gIUqSm%Ez(mSur3F{z_OJK9?6)gRC3H3+P;evZ_39;2wg+?s3O$1D zk{9X%+rPIX%>FdH()rP_ip+VqUHe>@bahp4B=&;B)i-zO^X2t}SYhI6IkiSl_9u(A z&yz)}U2V4Pylby^P98e_u5mZF{PjT#kF`!WbNeoymgOc3#h+f<1}=RDTijcAe1B6r zYlE2g?mzvoJ;hnu>vwRiuS^Mll z`J&y2v+CXjx6G_5{rC_u(s1?J>;t(vfk+%NpzSqN?^6CQy&&}ef4JtjShn-*dM-;V zS0p8+{}b8CmFa4?2Th;_!0zX!P>dOyjwkpNnGkOxiA=>pCrT@z5V8*z z>SAc8XGgar9wFNt3nDrm+v`L)=1(y3fts1hW7ud(g8(8E4`ByTs0=h43;og;Eg644 z4TnO$AWVNO)co^=5LdhX5KCGR5n>2K>Js!22nY%VLl_vMPzW7}z8*p!t|xh*bP)z< zLlj!y2=eWKn#xN?m>?ftv;)rS+jNp=Sm+TZla7YNSu7Teg@n<9NN|LSiOJ_S`ue&O zLYEOjW#ZYoREEaaCcpQ=5gCLaGM!1LQ6ZoE;=O6XOe_@od7|&fx9bX^f1ilT_~uSx z5zfZb;Ru)>{Cj6fAx7c^Z5c$wGigCiG#bV9>y=xPgNQ6zkUs-r>4<`Cv%?d}R3?pa zL<rNFfFgsZ55%AL2j#`4G^) zw4eYy)07;5ClTRvDhUJsaq=(M_jT2hh)B{2{~piZm;U{>{w;$a-v5^NUz>uH0Fn#p z0(Aj000;)t1?mE101ynO3)BV303aAl7pM!60YEUAE>IUB1At&KU7#*N1^~fex=>l~DG5`n$(*^1RWB?EhrVG>s$N(T1Oc$sNkO4q2m@ZHkAOnD4 zFkPT7Kn4K8V7fqEfD8bF!E}MT02u%TgXscw0Wtsx2Ga%V0%QOX45kaz1;_v(_%G8X z|6{`kkt*5c!IEs}Xenx0D*4a(fZaHAC!2)ZP5a{0iK}a;1ZAFx3(!~9X80V)uAi;Q z+6pnK-o2HJm7hK3?2k`Gy@XCF$(`BYVNAM$nqRa`9!l4U9QRemoA*JjJA7O_>~Wj2 zN_4wKBkiLX5Trp_C5#Xw49$Ly6)-MlnmG8vp7XI~p8F!0xwh-n)Tl*nx9wV@w%%FU zKfUxfoZMiXXuZ98TUTQIOHFm8OYgd3qYM~6 z%zkwH-6fGr#>a$yP`&SE@5;H zdt>Ho{>d&lDwH#`eioUR(}ESFa6so6c1c12SbD;C0V?&q}Gvi_YW zDHRPe8C**Z4UP7@t2z}+9$wd}siySQTU0~~UyS3blMXH(^($qZFC8C-k}jp!%NQjn zFk}S$EiI1Ri2e`aSkmBrU)WjAx8$+B!PMyyGY_e0eXm5^pKGl(Zr*K>1i7@NJOa1lUuix04t}M0h zc_YK#C_CwZJMXXAWEd+uxyAIc)tEzZYn*?e%anBalLyLytx|@)snfU+eV7)f;n_%~ uXY8(rk=n|E5x1ep>{~mL2j)u$yq=Df*_i1hul~FXY4@(ZxO|JlQU3-y!Tj0) diff --git a/core/pulltorefresh/src/main/res/drawable-mdpi/indicator_arrow.png b/core/pulltorefresh/src/main/res/drawable-mdpi/indicator_arrow.png deleted file mode 100644 index 20fe2c126ae700d57be9c7f19a0cf7296ece8055..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 445 zcmV;u0Yd(XP)=Zx2#&4L) zK8=5n)@r~%(8dq25D}Ygf)-ju1T8`$8bu5W7I)FRVfVa&E$+=eW_IVcMlM984Kygm zR8>c_kGe@VfEFcTg=Zi!?7K`@0hSD#0CzFr3z!C2w8AiJtFq7m+J=pQ%b4&1yaiaa z!aeY0Sm8`o*aDUfdjw8n!Yj}WuxN!bW>COOnXn108a4p>F`*AU7*?2z6%t@Rz@owq zux{8ba1|3mzjxt%SfL3l1lVuXMC1fmq*}b!fi7@VQP@ws_haYWC$LR=L$P(Js^B*8$cdn=e$g2QZf_cR)JTmRW-=mmWIbponY$$NatP39zTCH?uv3DSGdR&bcwL no3+wa)w6%ELPS(VG?e=R;L=SFhh?BF00000NkvXXu0mjf7aXr< diff --git a/core/pulltorefresh/src/main/res/drawable-xhdpi/default_ptr_flip.png b/core/pulltorefresh/src/main/res/drawable-xhdpi/default_ptr_flip.png deleted file mode 100644 index 3e6ddba5c554ba6983077079125c30387e70fed8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1983 zcmZXUcT`hp8ixaz&_M|aU8FN0B1Mn{h%R9u1d@;j48~A~8j5H{5Tayg23#4Mqo{C1 zkR}j}h++^y+7OT;B1M`5Dhi6ULF(S!oRhO>_dVx(zUO}L@4bKAd(Y(%a4zyP>M|e@ zNFL*gCIY)Yun1BT0Dq1&Vu3*W^uwH-2pA`)Lxi)@!C?_WAkgsxsg$Ycak8=_Cz@CS zM;-EZNzZ7nrI37|YN%ItKrp$bi*E4J`4JQSS%fX8LPK(V{&6Kffo%)f7CSL2q3CL_ zBM%8k7+rty2t!IYsl>P@d}>qFFC?~8EraJ3dSndphOiPtRr5HrY(cNmkrvqBufEJ^Wk?AYv%l`**7ce%X1*KX z=;B{Q!L(Rv8*-jKLyX5*7b;q^_zTw zRZH<9_WY4x^9Fyqglbpr3?)jVQ8zf7SDoX3wr|EfE2hC>Pw~jD^Q#NAWbduprB4H& zC~_uE*U8U0sJHd2noC$Nz4j@_|1x+ZYjZGBJWktlwIYYboc!oQr&lXaLMFip182%) zJ+{KnTO??z)(xx~e7Vu3cl_=75G7uTO42v##-owIPub;Nq_AoK=@vIuRtY4eUdS{a)lTeSU`Q_l=L4>VUF?<>8#fYk@I5}2R;NvN~V|f#KI;-oa z$Y=SjdD;Sn#@M@R0=Qepz`Wt*>fnnZ2gXLg&k9w>elMCBTwp>}<3~_@g!u=E<~VJL z81VSs3ztu5v>py_7VxIR4Ov1cw9IR3`q{?bz_KeP^`*eyLKi=%6fqHRm-Sa?%GHM| zO=iWOrO3|OGtGb2d80_9V%ypQyoIA0A&)VR`!m%lL}ttI==jo4r}PX$4%Y>8c*S-@@8=5qd}x8hYM#(6NlcKrJZPcSD|S zyjpzDU@*61R{lAW8QE#Wjp}&Zx-n8)XSN+l6i519%(#BHdnvY6I!;f^;gr~G1Nkq} z(?0!U#Id@2rJsMW`}GW4P+g8agHLDrD|d@`E27HjDk#OA!vnq3W+x+c^_8MH} zr}TrlWwT973)1Voaywd0s!SPPxJP}0+4p^_)`|v@JCL^>(Fou`5-4FnNb-LQXaNN%&=sDDC~S!coC}jeiY`SW zN&>eMxhO1(0U~l?SH%CG`hOP<{!e~!xnvl4yx~kDjs%hbLnNi7W#!}*6!$AZm0@sI zHFXV5t%KT!baeIf4UbqJvqRcDo^Wz;bI0L{6z`C*h^XioWIqeGP>a`mMcZ%*7 z-!HGMs;T2WYG~v)HNR}{=o0h}3=R#CzMFbK_v!QE_m%Y@jjTPH07`d z{&cy(_>k1}IZA5!v9q|Vex=L0&N*qXuIN1I0cW>#pHfzPP=^hWGesIb^#1FQ_T$&R zU&zGd*+ij$~L<=kFW)=SOjrs6QSX z2mZK_k~KF4bEL-Ne#PW?9XL4L<6x0YX)>?$u9qxMqa+xId-HAuz!}9lhOR^LY=ItI z5Xcrl*#Z(3ci@6x`nMrE|k{P7~Ku^`CdOEKQ)2drbmN7oSniUQQO z&2)d~-S4au5@l=JtYPW8DftCxaN`QE%*vy@l}+|Q?Jw| gCi2}MRGSUa$q>U(&CSpX;1d90oN?%yfB60OFCnXS-T(jq diff --git a/core/pulltorefresh/src/main/res/drawable-xhdpi/default_ptr_rotate.png b/core/pulltorefresh/src/main/res/drawable-xhdpi/default_ptr_rotate.png deleted file mode 100644 index 00225c9a2c5800ee8cc3ad4a123811f33b7f975e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50019 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%0D731?v8faG#q))U_N1H8!D-i( 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%0DB)*GP*zwyj4yv)M9;>dco3RUK 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 diff --git a/core/pulltorefresh/src/main/res/drawable/indicator_bg_bottom.xml b/core/pulltorefresh/src/main/res/drawable/indicator_bg_bottom.xml deleted file mode 100644 index 81a91aa6..00000000 --- a/core/pulltorefresh/src/main/res/drawable/indicator_bg_bottom.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/core/pulltorefresh/src/main/res/drawable/indicator_bg_top.xml b/core/pulltorefresh/src/main/res/drawable/indicator_bg_top.xml deleted file mode 100644 index 59fa9cfe..00000000 --- a/core/pulltorefresh/src/main/res/drawable/indicator_bg_top.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/core/pulltorefresh/src/main/res/layout/pull_to_refresh_header_horizontal.xml b/core/pulltorefresh/src/main/res/layout/pull_to_refresh_header_horizontal.xml deleted file mode 100644 index f05bb033..00000000 --- a/core/pulltorefresh/src/main/res/layout/pull_to_refresh_header_horizontal.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/core/pulltorefresh/src/main/res/layout/pull_to_refresh_header_vertical.xml b/core/pulltorefresh/src/main/res/layout/pull_to_refresh_header_vertical.xml deleted file mode 100644 index 2185e2d6..00000000 --- a/core/pulltorefresh/src/main/res/layout/pull_to_refresh_header_vertical.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/core/pulltorefresh/src/main/res/values-ar/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-ar/pull_refresh_strings.xml deleted file mode 100644 index 25d5392d..00000000 --- a/core/pulltorefresh/src/main/res/values-ar/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - اسحب للتحديث… - اترك للتحديث… - تحميل… - diff --git a/core/pulltorefresh/src/main/res/values-cs/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-cs/pull_refresh_strings.xml deleted file mode 100755 index c878da0c..00000000 --- a/core/pulltorefresh/src/main/res/values-cs/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Tažením aktualizujete… - Uvolněním aktualizujete… - Načítání… - diff --git a/core/pulltorefresh/src/main/res/values-de/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-de/pull_refresh_strings.xml deleted file mode 100755 index 901291bf..00000000 --- a/core/pulltorefresh/src/main/res/values-de/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Ziehen zum Aktualisieren… - Loslassen zum Aktualisieren… - Laden… - diff --git a/core/pulltorefresh/src/main/res/values-es/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-es/pull_refresh_strings.xml deleted file mode 100755 index 5e9d2803..00000000 --- a/core/pulltorefresh/src/main/res/values-es/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Tirar para actualizar… - Soltar para actualizar… - Cargando… - diff --git a/core/pulltorefresh/src/main/res/values-fi/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-fi/pull_refresh_strings.xml deleted file mode 100755 index 0381287b..00000000 --- a/core/pulltorefresh/src/main/res/values-fi/pull_refresh_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - Päivitä vetämällä alas… - Päivitä vapauttamalla… - Päivitetään… - - - Päivitä vetämällä ylös… - @string/pull_to_refresh_release_label - @string/pull_to_refresh_refreshing_label - - \ No newline at end of file diff --git a/core/pulltorefresh/src/main/res/values-fr/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-fr/pull_refresh_strings.xml deleted file mode 100755 index fb53ef8c..00000000 --- a/core/pulltorefresh/src/main/res/values-fr/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Tirez pour rafraîchir… - Relâcher pour rafraîchir… - Chargement… - diff --git a/core/pulltorefresh/src/main/res/values-he/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-he/pull_refresh_strings.xml deleted file mode 100644 index beedc1f6..00000000 --- a/core/pulltorefresh/src/main/res/values-he/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - משוך לרענון… - שחרר לרענון… - טוען… - diff --git a/core/pulltorefresh/src/main/res/values-it/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-it/pull_refresh_strings.xml deleted file mode 100755 index 415fb9ed..00000000 --- a/core/pulltorefresh/src/main/res/values-it/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Tira per aggiornare… - Rilascia per aggionare… - Caricamento… - diff --git a/core/pulltorefresh/src/main/res/values-iw/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-iw/pull_refresh_strings.xml deleted file mode 100644 index beedc1f6..00000000 --- a/core/pulltorefresh/src/main/res/values-iw/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - משוך לרענון… - שחרר לרענון… - טוען… - diff --git a/core/pulltorefresh/src/main/res/values-ja/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-ja/pull_refresh_strings.xml deleted file mode 100644 index d24842c9..00000000 --- a/core/pulltorefresh/src/main/res/values-ja/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 画面を引っ張って… - 指を離して更新… - 読み込み中… - diff --git a/core/pulltorefresh/src/main/res/values-ko/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-ko/pull_refresh_strings.xml deleted file mode 100755 index 53edd592..00000000 --- a/core/pulltorefresh/src/main/res/values-ko/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 당겨서 새로 고침… - 놓아서 새로 고침… - 로드 중… - diff --git a/core/pulltorefresh/src/main/res/values-nl/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-nl/pull_refresh_strings.xml deleted file mode 100755 index 4c063ed9..00000000 --- a/core/pulltorefresh/src/main/res/values-nl/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Sleep om te vernieuwen… - Loslaten om te vernieuwen… - Laden… - diff --git a/core/pulltorefresh/src/main/res/values-pl/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-pl/pull_refresh_strings.xml deleted file mode 100755 index 007255a2..00000000 --- a/core/pulltorefresh/src/main/res/values-pl/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Pociągnij, aby odświeżyć… - Puść, aby odświeżyć… - Wczytywanie… - diff --git a/core/pulltorefresh/src/main/res/values-pt-rBR/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-pt-rBR/pull_refresh_strings.xml deleted file mode 100755 index 0ec1ef7f..00000000 --- a/core/pulltorefresh/src/main/res/values-pt-rBR/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Puxe para atualizar… - Libere para atualizar… - Carregando… - diff --git a/core/pulltorefresh/src/main/res/values-pt/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-pt/pull_refresh_strings.xml deleted file mode 100755 index d08bc63b..00000000 --- a/core/pulltorefresh/src/main/res/values-pt/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Puxe para atualizar… - Liberação para atualizar… - A carregar… - diff --git a/core/pulltorefresh/src/main/res/values-ro/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-ro/pull_refresh_strings.xml deleted file mode 100644 index 87ddc941..00000000 --- a/core/pulltorefresh/src/main/res/values-ro/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Trage pentru a reîmprospăta… - Eliberează pentru a reîmprospăta… - Încărcare… - diff --git a/core/pulltorefresh/src/main/res/values-ru/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-ru/pull_refresh_strings.xml deleted file mode 100755 index 71ddcda7..00000000 --- a/core/pulltorefresh/src/main/res/values-ru/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Потяните для обновления… - Отпустите для обновления… - Загрузка… - diff --git a/core/pulltorefresh/src/main/res/values-zh/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values-zh/pull_refresh_strings.xml deleted file mode 100755 index 08766e0b..00000000 --- a/core/pulltorefresh/src/main/res/values-zh/pull_refresh_strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - 下拉刷新… - 放开以刷新… - 正在载入… - diff --git a/core/pulltorefresh/src/main/res/values/attrs.xml b/core/pulltorefresh/src/main/res/values/attrs.xml deleted file mode 100644 index a3408ae7..00000000 --- a/core/pulltorefresh/src/main/res/values/attrs.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/core/pulltorefresh/src/main/res/values/dimens.xml b/core/pulltorefresh/src/main/res/values/dimens.xml deleted file mode 100644 index 24339b5b..00000000 --- a/core/pulltorefresh/src/main/res/values/dimens.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - 10dp - 12dp - 4dp - 24dp - 12dp - - \ No newline at end of file diff --git a/core/pulltorefresh/src/main/res/values/ids.xml b/core/pulltorefresh/src/main/res/values/ids.xml deleted file mode 100644 index 26c9ae76..00000000 --- a/core/pulltorefresh/src/main/res/values/ids.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/core/pulltorefresh/src/main/res/values/pull_refresh_strings.xml b/core/pulltorefresh/src/main/res/values/pull_refresh_strings.xml deleted file mode 100755 index 20cd2fa4..00000000 --- a/core/pulltorefresh/src/main/res/values/pull_refresh_strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - Pull to refresh… - Release to refresh… - Loading… - - - @string/pull_to_refresh_pull_label - @string/pull_to_refresh_release_label - @string/pull_to_refresh_refreshing_label - - \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index b5554310..df54c39f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,5 +4,4 @@ include ':core:subsonic-api' include ':core:subsonic-api-image-loader' include ':core:cache' include ':core:menudrawer' -include ':core:pulltorefresh' include ':ultrasonic' diff --git a/ultrasonic/build.gradle b/ultrasonic/build.gradle index f70422f9..b0e8b248 100644 --- a/ultrasonic/build.gradle +++ b/ultrasonic/build.gradle @@ -56,7 +56,6 @@ tasks.withType(Test) { dependencies { implementation project(':core:menudrawer') - implementation project(':core:pulltorefresh') implementation project(':core:library') implementation project(':core:domain') implementation project(':core:subsonic-api') diff --git a/ultrasonic/src/main/assets/html/fr/index.html b/ultrasonic/src/main/assets/html/fr/index.html index 0fc3ee9c..81334bf9 100644 --- a/ultrasonic/src/main/assets/html/fr/index.html +++ b/ultrasonic/src/main/assets/html/fr/index.html @@ -33,7 +33,7 @@
  • Écoute et téléchargement illimités vers autant de iPhones et d'appareils Android que souhaité.
  • Lecture de vidéos.
  • Une adresse web personnalisée pour votre serveur Subsonic (votrenom.subsonic.org).
  • -
  • Aucunes publicitées; dans l'interface web de Subsonic.
  • +
  • Aucunes publicités dans l'interface web de Subsonic.
  • Accès gratuit aux nouvelles fonctionnalités avancées.
diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/BookmarkActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/BookmarkActivity.java index cae4632d..d9a69532 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/BookmarkActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/BookmarkActivity.java @@ -27,9 +27,8 @@ import android.widget.AdapterView; import android.widget.ImageView; import android.widget.ListView; -import com.handmark.pulltorefresh.library.PullToRefreshBase; -import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; -import com.handmark.pulltorefresh.library.PullToRefreshListView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + import org.moire.ultrasonic.R; import org.moire.ultrasonic.domain.MusicDirectory; import org.moire.ultrasonic.domain.MusicDirectory.Entry; @@ -49,7 +48,7 @@ import java.util.List; public class BookmarkActivity extends SubsonicTabActivity { - private PullToRefreshListView refreshAlbumListView; + private SwipeRefreshLayout refreshAlbumListView; private ListView albumListView; private View albumButtons; private View emptyView; @@ -70,13 +69,13 @@ public class BookmarkActivity extends SubsonicTabActivity albumButtons = findViewById(R.id.menu_album); - refreshAlbumListView = (PullToRefreshListView) findViewById(R.id.select_album_entries); - albumListView = refreshAlbumListView.getRefreshableView(); + refreshAlbumListView = findViewById(R.id.select_album_entries_refresh); + albumListView = findViewById(R.id.select_album_entries_list); - refreshAlbumListView.setOnRefreshListener(new OnRefreshListener() + refreshAlbumListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override - public void onRefresh(PullToRefreshBase refreshView) + public void onRefresh() { new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -472,7 +471,6 @@ public class BookmarkActivity extends SubsonicTabActivity @Override protected void onPostExecute(String[] result) { - refreshAlbumListView.onRefreshComplete(); super.onPostExecute(result); } diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/ChatActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/ChatActivity.java index 2e4bf1c8..e91fc007 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/ChatActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/ChatActivity.java @@ -5,6 +5,9 @@ import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.EditText; @@ -13,10 +16,8 @@ import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; -import com.handmark.pulltorefresh.library.PullToRefreshBase; -import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; -import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; -import com.handmark.pulltorefresh.library.PullToRefreshListView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + import org.moire.ultrasonic.R; import org.moire.ultrasonic.domain.ChatMessage; import org.moire.ultrasonic.service.MusicService; @@ -37,7 +38,6 @@ import java.util.TimerTask; */ public final class ChatActivity extends SubsonicTabActivity { - private PullToRefreshListView refreshChatListView; private ListView chatListView; private EditText messageEditText; private ImageButton sendButton; @@ -51,9 +51,6 @@ public final class ChatActivity extends SubsonicTabActivity super.onCreate(bundle); setContentView(R.layout.chat); - refreshChatListView = (PullToRefreshListView) findViewById(R.id.chat_entries); - refreshChatListView.setMode(Mode.PULL_FROM_END); - messageEditText = (EditText) findViewById(R.id.chat_edittext); sendButton = (ImageButton) findViewById(R.id.chat_send); @@ -67,7 +64,7 @@ public final class ChatActivity extends SubsonicTabActivity } }); - chatListView = refreshChatListView.getRefreshableView(); + chatListView = findViewById(R.id.chat_entries_list); chatListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL); chatListView.setStackFromBottom(true); @@ -114,15 +111,6 @@ public final class ChatActivity extends SubsonicTabActivity } }); - refreshChatListView.setOnRefreshListener(new OnRefreshListener() - { - @Override - public void onRefresh(PullToRefreshBase refreshView) - { - new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - }); - View chatMenuItem = findViewById(R.id.menu_chat); menuDrawer.setActiveView(chatMenuItem); @@ -137,6 +125,33 @@ public final class ChatActivity extends SubsonicTabActivity timerMethod(); } + @Override + public boolean onCreateOptionsMenu(Menu menu) + { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.chat, menu); + super.onCreateOptionsMenu(menu); + + return true; + } + + /* + * Listen for option item selections so that we receive a notification + * when the user requests a refresh by selecting the refresh action bar item. + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + // Check if user triggered a refresh: + case R.id.menu_refresh: + // Start the refresh background task. + new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + return true; + } + // User didn't trigger a refresh, let the superclass handle this action + return super.onOptionsItemSelected(item); + } + @Override protected void onResume() { @@ -276,7 +291,6 @@ public final class ChatActivity extends SubsonicTabActivity protected void onPostExecute(String[] result) { load(); - refreshChatListView.onRefreshComplete(); super.onPostExecute(result); } @@ -286,4 +300,4 @@ public final class ChatActivity extends SubsonicTabActivity return null; } } -} \ No newline at end of file +} diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectAlbumActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectAlbumActivity.java index a96159a2..769e7e0c 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectAlbumActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectAlbumActivity.java @@ -27,14 +27,12 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; -import com.handmark.pulltorefresh.library.PullToRefreshBase; -import com.handmark.pulltorefresh.library.PullToRefreshListView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import org.moire.ultrasonic.R; import org.moire.ultrasonic.domain.MusicDirectory; @@ -60,13 +58,11 @@ import java.util.LinkedList; import java.util.List; import java.util.Random; -import static com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; - public class SelectAlbumActivity extends SubsonicTabActivity { public static final String allSongsId = "-1"; - private PullToRefreshListView refreshAlbumListView; + private SwipeRefreshLayout refreshAlbumListView; private ListView albumListView; private View header; private View albumButtons; @@ -91,50 +87,23 @@ public class SelectAlbumActivity extends SubsonicTabActivity * Called when the activity is first created. */ @Override - public void onCreate(Bundle savedInstanceState) - { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.select_album); albumButtons = findViewById(R.id.menu_album); - refreshAlbumListView = (PullToRefreshListView) findViewById(R.id.select_album_entries); - albumListView = refreshAlbumListView.getRefreshableView(); + refreshAlbumListView = findViewById(R.id.select_album_entries_refresh); + albumListView = findViewById(R.id.select_album_entries_list); - refreshAlbumListView.setOnRefreshListener(new OnRefreshListener() + refreshAlbumListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override - public void onRefresh(PullToRefreshBase refreshView) - { + public void onRefresh() { new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } }); - refreshAlbumListView.setOnScrollListener(new AbsListView.OnScrollListener() { - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - for (int i=0;i() + refreshArtistListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override - public void onRefresh(PullToRefreshBase refreshView) + public void onRefresh() { new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -347,7 +346,6 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter @Override protected void onPostExecute(String[] result) { - refreshArtistListView.onRefreshComplete(); super.onPostExecute(result); } @@ -358,4 +356,4 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter return null; } } -} \ No newline at end of file +} diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectGenreActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectGenreActivity.java index aa038463..996edd6d 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectGenreActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectGenreActivity.java @@ -29,9 +29,8 @@ import android.view.View; import android.widget.AdapterView; import android.widget.ListView; -import com.handmark.pulltorefresh.library.PullToRefreshBase; -import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; -import com.handmark.pulltorefresh.library.PullToRefreshListView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + import org.moire.ultrasonic.R; import org.moire.ultrasonic.domain.Genre; import org.moire.ultrasonic.service.MusicService; @@ -50,7 +49,7 @@ public class SelectGenreActivity extends SubsonicTabActivity implements AdapterV private static final String TAG = SelectGenreActivity.class.getSimpleName(); - private PullToRefreshListView refreshGenreListView; + private SwipeRefreshLayout refreshGenreListView; private ListView genreListView; private View emptyView; @@ -63,13 +62,13 @@ public class SelectGenreActivity extends SubsonicTabActivity implements AdapterV super.onCreate(savedInstanceState); setContentView(R.layout.select_genre); - refreshGenreListView = (PullToRefreshListView) findViewById(R.id.select_genre_list); - genreListView = refreshGenreListView.getRefreshableView(); + refreshGenreListView = findViewById(R.id.select_genre_refresh); + genreListView = findViewById(R.id.select_genre_list); - refreshGenreListView.setOnRefreshListener(new OnRefreshListener() + refreshGenreListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override - public void onRefresh(PullToRefreshBase refreshView) + public void onRefresh() { new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -181,7 +180,6 @@ public class SelectGenreActivity extends SubsonicTabActivity implements AdapterV @Override protected void onPostExecute(String[] result) { - refreshGenreListView.onRefreshComplete(); super.onPostExecute(result); } @@ -192,4 +190,4 @@ public class SelectGenreActivity extends SubsonicTabActivity implements AdapterV return null; } } -} \ No newline at end of file +} diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectPlaylistActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectPlaylistActivity.java index 0ba31f04..eeeccd2d 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectPlaylistActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectPlaylistActivity.java @@ -40,9 +40,7 @@ import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; -import com.handmark.pulltorefresh.library.PullToRefreshBase; -import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; -import com.handmark.pulltorefresh.library.PullToRefreshListView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import org.moire.ultrasonic.R; import org.moire.ultrasonic.api.subsonic.ApiNotSupportedException; @@ -63,7 +61,7 @@ import java.util.List; public class SelectPlaylistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener { - private PullToRefreshListView refreshPlaylistsListView; + private SwipeRefreshLayout refreshPlaylistsListView; private ListView playlistsListView; private View emptyTextView; private PlaylistAdapter playlistAdapter; @@ -74,13 +72,13 @@ public class SelectPlaylistActivity extends SubsonicTabActivity implements Adapt super.onCreate(savedInstanceState); setContentView(R.layout.select_playlist); - refreshPlaylistsListView = (PullToRefreshListView) findViewById(R.id.select_playlist_list); - playlistsListView = refreshPlaylistsListView.getRefreshableView(); + refreshPlaylistsListView = findViewById(R.id.select_playlist_refresh); + playlistsListView = findViewById(R.id.select_playlist_list); - refreshPlaylistsListView.setOnRefreshListener(new OnRefreshListener() + refreshPlaylistsListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override - public void onRefresh(PullToRefreshBase refreshView) + public void onRefresh() { new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -379,7 +377,6 @@ public class SelectPlaylistActivity extends SubsonicTabActivity implements Adapt @Override protected void onPostExecute(String[] result) { - refreshPlaylistsListView.onRefreshComplete(); super.onPostExecute(result); } diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/ShareActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/ShareActivity.java index d7a2d237..9e012dd6 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/ShareActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/ShareActivity.java @@ -41,9 +41,7 @@ import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; -import com.handmark.pulltorefresh.library.PullToRefreshBase; -import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener; -import com.handmark.pulltorefresh.library.PullToRefreshListView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import org.moire.ultrasonic.R; import org.moire.ultrasonic.api.subsonic.ApiNotSupportedException; @@ -65,7 +63,7 @@ import java.util.List; public class ShareActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener { - private PullToRefreshListView refreshSharesListView; + private SwipeRefreshLayout refreshSharesListView; private ListView sharesListView; private View emptyTextView; private ShareAdapter shareAdapter; @@ -76,13 +74,13 @@ public class ShareActivity extends SubsonicTabActivity implements AdapterView.On super.onCreate(savedInstanceState); setContentView(R.layout.select_share); - refreshSharesListView = (PullToRefreshListView) findViewById(R.id.select_share_list); - sharesListView = refreshSharesListView.getRefreshableView(); + refreshSharesListView = findViewById(R.id.select_share_refresh); + sharesListView = findViewById(R.id.select_share_list); - refreshSharesListView.setOnRefreshListener(new OnRefreshListener() + refreshSharesListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override - public void onRefresh(PullToRefreshBase refreshView) + public void onRefresh() { new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -374,7 +372,6 @@ public class ShareActivity extends SubsonicTabActivity implements AdapterView.On @Override protected void onPostExecute(String[] result) { - refreshSharesListView.onRefreshComplete(); super.onPostExecute(result); } @@ -385,4 +382,4 @@ public class ShareActivity extends SubsonicTabActivity implements AdapterView.On return null; } } -} \ No newline at end of file +} diff --git a/ultrasonic/src/main/res/drawable-hdpi/ic_menu_refresh_dark.png b/ultrasonic/src/main/res/drawable-hdpi/ic_menu_refresh_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6cae3ecac303d7aef2320669041a7e40ab9df576 GIT binary patch literal 498 zcmV540fwO{iUEeAfMIwTilTrb2!>$@iUNkA7=j`wf+7fl zA_%?#IEhH&E^D|C0P+7xF5bIP6h%=Kso(_H=-~lF4Dp0JT;T(%umW6$+;D&!jIC~j z2KBP>kaKv2Z~0q0`dqyUg@X@HM1{8Uyn>s5U%XKh67%D&&ARCgwe^bFgu`btka`||^MeP6kA-I-!OpU>y>mC!^F158%N=%ayK80=CVnO8syGuR!ah!JcV z-XgOMo-v0#&>Xe(!y}_Ye8DRDKtT=<=oeuMD`AE%%DBeG$`vZ;;s;hjf*4j%EnG8v ziW&^I6(E+2tfyBFgEc>YfPK3_;&Oo(SfK@jL(3y|u|SB0IJl2vYq|Oby5i6Y^4Sj$ zg>v$O!-JdQq0qfJaO`e)DAW-LHrx#lh2*WX-+-p*(bzF^(_`C z;-q>N3&c37s$zj5vM7g{#w}Zxmk)BdgLaSNGp10hCk`LMK&yiM_R)k|mspAq=s+VQ zzaY#JK(#ikP|xT;!4uRAkiZHZm;>)3Mu000045gQkXppo0&%!cRpjjID{P&{y;eA7cv)v9v){feu!Z zDO#~3bg}RcQ3b}52Q;GuWHyMhaH^;mB_Q)3Q5L>RCQ$-1TSQryO1{L7kl8_$g-6M| zcx%?gF|a0%0Tz;WyfxfQ`mrZul5v!Uk>ob^gqdU*W#L?sqZ<|BLh>8Ur~(to3@1?% znwU$jqbi&sm)zkbc7z6|k|(rcAGlOBLpQcS4-bky#UbEYQI1>m(T*2rV}S4emc=3A z61no07{qJ9876j<;|860Z8*mW_gF}t@B>#kjasdCg#G|@Di7Faoa%T000009s>#PLA98imXrO}rq5avU** zKg>ZW-6IZApdD_!F({XVf0YCdeYDIiCisAVtvQrYxB-;$iF@QV%DHHvS~x;xjRyW( z2m5G)yfbf6M@TN_h1yU?KjIjK_Y9d;p><(2SvMs%n#}))Cw{Qt`J%sUyzxha9yO3c?}#@^B&l5 zG*GHBl#!r=y!zNe84rlk49ZBc#K3zJni%2@@;F3oj1&rVzz`>?ixq@CDHdqq`7T)(nc*4Pk_w;})l002ovPDHLkV1kb&m^}ah literal 0 HcmV?d00001 diff --git a/ultrasonic/src/main/res/drawable-xhdpi/ic_menu_refresh_dark.png b/ultrasonic/src/main/res/drawable-xhdpi/ic_menu_refresh_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..415da26a96bce8e9652d1a2e128735e2b8f069cc GIT binary patch literal 712 zcmV;(0yq7MP)%#ZU}o2#O*oieVUvpeTj_0EQtLhG8gzp%{vyC<+*YA_$7& zA$a%(P~2&%8S4Kz+?_ z@Fpx6zGoQ-%eWR-<9*^ED0!fPW(PUOfi_plGjXTsbktoX8v|I;Y$GIwU2)UU7MzJ2h6ECB z#l+!AT#faR2(~rb4Q;_1YH`OQ5uAw|V=1%=Up4C`h;yXbr&L#5Dsfet3rD;|EpCcV zNC5-QCRj~>-Nt_Edxux|MA}^Nn^S3a98$vuD$OeN7IgG9(`P%bE;erubgW<4#P`^ReVM5`P^WDY-4vhu5==JOjQ%D_YDu)N4iVJXUDv+t5&9=6uzVZ_`^Q zZH}0vFNM9vGLJt@wu*Y8eD8s&|D@xNZLv-dj2xIRwzdD0N$zNV&6s-0kSC?rFzd!v zt7Q}3{&;_&u$U+B<6PGlNZ1 z6+HDa6))tEEMn|ECeW>%VbUHU<8b@u=C#b3+#Rl*Qoh&fk6vIC=(aMcYKpj{JY}Au zn7PMZ?T(`&iXw{VKJkbsa%!E}W!!O;>7JCM&aMyhzt2y)vlZy3)Ra)(Ne_7LS+z7q ze3=ls*z~(0`+8dkA(Mx@%~TGW?g@9|+1L@-y52A0n#^;KnO7QBW-Jyta6eaXLS*F` z8RgK4Vd@=e}#hrS~1Qfm$-Z2$$wyAcPtqx>0?oeNEaUgE0JG-HZ zs$t&7>r+24F#lBZE(ti$|56~gMiL2qA>_h!aQR^Qv$WHg%ga-&olbioJTB3 zxx)_byuMp>(3(9K*$2ZW2HxHsIK#9X=6by`>3J%8De#sSdhbD@o09BIKu&Y=wKZyzq~%+6ZY`~BeNS}tsqt&!LW;o zm%GCuHf9`f4sh?~p79;B4Tg_1#5zZNPVed3oYgVbZ+J4j8*IGNGJT5(hIbg6&OJJB zu*KNJb7O;{g-g@9#{2X}u!cXI8tlk)PSC2z9`U?U!LXsc3HB{@xfR6*El zL@;!ecbs!9sKcN!RL&Jz)sB^auwCWcVJY`ml@5jljFhvPf2`^U>ni6mgIHMvJ6CLi zc2iU?gv+O$|u*Uj>Fzz2)I;i zD^){4U$JfqwK|$QOw|z3Q*6-C{pV&?@BPxG%`?^&8)KoW7mq$G*2^f^SH&(IApm#2;nOy~41r$;Q|hv}T9 zTwoa^(;1-sM$7ofbRO_7(o8Bo_U+GKLH@#=HQ;zW2%Zza}k5hiM(Z}S4u{Pq` zkN-Bo6?#~n@z>PFB|yX~{-ur0Zh%8{v4u9?|6_Pq#U^&}9YcVKH3h6=q<%(u$0}Z$ z2I}JiOR34Qh%?nT#_uWo4coX?J-1j(;os0g7Z2Xv9d;F8Qy8#-eLQ)6Lv+zf(+PNo z9J literal 0 HcmV?d00001 diff --git a/ultrasonic/src/main/res/drawable-xxhdpi/ic_menu_refresh_light.png b/ultrasonic/src/main/res/drawable-xxhdpi/ic_menu_refresh_light.png new file mode 100644 index 0000000000000000000000000000000000000000..0c7fa34050afaa487f4f7713a9b1267c1087d2e7 GIT binary patch literal 1002 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 - - - + + + @@ -32,20 +32,20 @@ a:layout_weight="1" a:autoLink="all" a:hint="@string/chat.send_a_message" - a:inputType="textEmailAddress|textMultiLine" + a:inputType="textEmailAddress|textMultiLine" a:linksClickable="true" a:paddingBottom="10dip" a:paddingTop="10dip" /> - + - + - \ No newline at end of file + diff --git a/ultrasonic/src/main/res/layout/select_album.xml b/ultrasonic/src/main/res/layout/select_album.xml index 1a527ee9..5a037202 100644 --- a/ultrasonic/src/main/res/layout/select_album.xml +++ b/ultrasonic/src/main/res/layout/select_album.xml @@ -19,16 +19,22 @@ a:text="@string/select_album.empty" a:visibility="gone" /> - + + + + + - \ No newline at end of file + diff --git a/ultrasonic/src/main/res/layout/select_artist.xml b/ultrasonic/src/main/res/layout/select_artist.xml index 50fb304f..43a1a8ae 100644 --- a/ultrasonic/src/main/res/layout/select_artist.xml +++ b/ultrasonic/src/main/res/layout/select_artist.xml @@ -6,14 +6,20 @@ - + + + + + - \ No newline at end of file + diff --git a/ultrasonic/src/main/res/layout/select_genre.xml b/ultrasonic/src/main/res/layout/select_genre.xml index 57ff820d..ccfb8797 100644 --- a/ultrasonic/src/main/res/layout/select_genre.xml +++ b/ultrasonic/src/main/res/layout/select_genre.xml @@ -14,14 +14,20 @@ a:text="@string/select_genre.empty" a:visibility="gone" /> - + + + + + - \ No newline at end of file + diff --git a/ultrasonic/src/main/res/layout/select_playlist.xml b/ultrasonic/src/main/res/layout/select_playlist.xml index aefcc934..e7176513 100644 --- a/ultrasonic/src/main/res/layout/select_playlist.xml +++ b/ultrasonic/src/main/res/layout/select_playlist.xml @@ -14,14 +14,20 @@ a:text="@string/select_playlist.empty" a:visibility="gone" /> - + + + + + - \ No newline at end of file + diff --git a/ultrasonic/src/main/res/layout/select_share.xml b/ultrasonic/src/main/res/layout/select_share.xml index 7b0641c9..66a07823 100644 --- a/ultrasonic/src/main/res/layout/select_share.xml +++ b/ultrasonic/src/main/res/layout/select_share.xml @@ -1,8 +1,8 @@ + a:layout_width="fill_parent" + a:layout_height="fill_parent" + a:orientation="vertical"> @@ -14,14 +14,21 @@ a:text="@string/select_share.empty" a:visibility="gone" /> - + + + + + + - \ No newline at end of file + diff --git a/ultrasonic/src/main/res/menu/chat.xml b/ultrasonic/src/main/res/menu/chat.xml new file mode 100644 index 00000000..288df21f --- /dev/null +++ b/ultrasonic/src/main/res/menu/chat.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/ultrasonic/src/main/res/values-de/strings.xml b/ultrasonic/src/main/res/values-de/strings.xml index 246fbae3..75c7ad43 100644 --- a/ultrasonic/src/main/res/values-de/strings.xml +++ b/ultrasonic/src/main/res/values-de/strings.xml @@ -467,5 +467,6 @@          anstatt einfach Elemente zu markieren / zu entfernen. Funktionseinstellungem + Aktualisierung diff --git a/ultrasonic/src/main/res/values-es/strings.xml b/ultrasonic/src/main/res/values-es/strings.xml index 469b8ef2..7d6b8ba8 100644 --- a/ultrasonic/src/main/res/values-es/strings.xml +++ b/ultrasonic/src/main/res/values-es/strings.xml @@ -470,5 +470,6 @@ en lugar de simplemente destacar / desestimar elementos. Banderas de características + Actualizar diff --git a/ultrasonic/src/main/res/values-fr/strings.xml b/ultrasonic/src/main/res/values-fr/strings.xml index b96db050..6754c260 100644 --- a/ultrasonic/src/main/res/values-fr/strings.xml +++ b/ultrasonic/src/main/res/values-fr/strings.xml @@ -471,5 +471,6 @@ au lieu de simplement mettre en vedette / désactiver les éléments. Drapeaux des fonctionnalités + Rafraichir diff --git a/ultrasonic/src/main/res/values-hu/strings.xml b/ultrasonic/src/main/res/values-hu/strings.xml index 2059fdab..e5ab13a9 100644 --- a/ultrasonic/src/main/res/values-hu/strings.xml +++ b/ultrasonic/src/main/res/values-hu/strings.xml @@ -470,5 +470,6 @@ csillaggal jelölés helyett. Jellemzők Zászlók + Refresh diff --git a/ultrasonic/src/main/res/values-nl/strings.xml b/ultrasonic/src/main/res/values-nl/strings.xml index bc3f5a1d..70fbbe5f 100644 --- a/ultrasonic/src/main/res/values-nl/strings.xml +++ b/ultrasonic/src/main/res/values-nl/strings.xml @@ -470,5 +470,6 @@ in plaats van items simpelweg in de hoofdrol te zetten / niet te verwijderen. Experimentele functies + Refresh diff --git a/ultrasonic/src/main/res/values-pl/strings.xml b/ultrasonic/src/main/res/values-pl/strings.xml index 66f46d2d..06595852 100644 --- a/ultrasonic/src/main/res/values-pl/strings.xml +++ b/ultrasonic/src/main/res/values-pl/strings.xml @@ -483,5 +483,6 @@ Obecnie nie zapisuje obrazów w pamięci urządzenia, tylko wykorzystuje tylko p zamiast po prostu grać gwiazdkami / bez gwiazd. Flagi funkcji + Refresh diff --git a/ultrasonic/src/main/res/values-pt-rBR/strings.xml b/ultrasonic/src/main/res/values-pt-rBR/strings.xml index 2ab07c9f..1f331143 100644 --- a/ultrasonic/src/main/res/values-pt-rBR/strings.xml +++ b/ultrasonic/src/main/res/values-pt-rBR/strings.xml @@ -470,5 +470,6 @@ em vez de simplesmente estrelar / não estrelar itens. Bandeiras de recursos + Refresh diff --git a/ultrasonic/src/main/res/values-pt/strings.xml b/ultrasonic/src/main/res/values-pt/strings.xml index 8e53355d..68199729 100644 --- a/ultrasonic/src/main/res/values-pt/strings.xml +++ b/ultrasonic/src/main/res/values-pt/strings.xml @@ -470,5 +470,6 @@ em vez de simplesmente estrelar / não estrelar itens. Bandeiras de recursos + Refresh diff --git a/ultrasonic/src/main/res/values/strings.xml b/ultrasonic/src/main/res/values/strings.xml index 71c884b6..b5bfb427 100644 --- a/ultrasonic/src/main/res/values/strings.xml +++ b/ultrasonic/src/main/res/values/strings.xml @@ -474,5 +474,6 @@ instead of simply starring/unstarring items. Feature Flags + Refresh diff --git a/ultrasonic/src/main/res/values/styles.xml b/ultrasonic/src/main/res/values/styles.xml index aeae6325..ed9fae4c 100644 --- a/ultrasonic/src/main/res/values/styles.xml +++ b/ultrasonic/src/main/res/values/styles.xml @@ -81,6 +81,7 @@ + diff --git a/ultrasonic/src/main/res/values/themes.xml b/ultrasonic/src/main/res/values/themes.xml index e78d0318..0280d683 100644 --- a/ultrasonic/src/main/res/values/themes.xml +++ b/ultrasonic/src/main/res/values/themes.xml @@ -35,6 +35,7 @@ @drawable/media_shuffle_normal_dark @drawable/media_start_normal_dark @drawable/ic_menu_podcasts_dark + @drawable/ic_menu_refresh_dark @drawable/media_play_next @drawable/ic_stat_play_dark @drawable/media_stop_normal_dark @@ -84,6 +85,7 @@ @drawable/media_shuffle_normal_light @drawable/media_start_normal_light @drawable/ic_menu_podcasts_light + @drawable/ic_menu_refresh_light @drawable/media_play_next @drawable/ic_stat_play_light @drawable/media_stop_normal_light