Merge branch 'develop' into feature/updated-server-settings
@ -1,8 +0,0 @@
|
||||
apply from: bootstrap.androidModule
|
||||
|
||||
android {
|
||||
lintOptions {
|
||||
baselineFile file("lint-baseline.xml")
|
||||
abortOnError true
|
||||
}
|
||||
}
|
@ -1,326 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<issues format="4" by="lint 2.3.3">
|
||||
|
||||
<issue
|
||||
id="LocaleFolder"
|
||||
message="The locale folder "`he`" should be called "`iw`" instead; see the `java.util.Locale` documentation">
|
||||
<location
|
||||
file="src/main/res/values-he"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="OldTargetApi"
|
||||
message="Not targeting the latest versions of Android; compatibility modes apply. Consider testing and updating this version. Consult the `android.os.Build.VERSION_CODES` javadoc for details."
|
||||
errorLine1=" <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="16" />"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/AndroidManifest.xml"
|
||||
line="7"
|
||||
column="41"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="GradleOverrides"
|
||||
message="This `minSdkVersion` value (`4`) is not used; it is always overridden by the value specified in the Gradle build script (`14`)"
|
||||
errorLine1=" <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="16" />"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/AndroidManifest.xml"
|
||||
line="7"
|
||||
column="15"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="GradleOverrides"
|
||||
message="This `targetSdkVersion` value (`16`) is not used; it is always overridden by the value specified in the Gradle build script (`22`)"
|
||||
errorLine1=" <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="16" />"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/AndroidManifest.xml"
|
||||
line="7"
|
||||
column="41"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="Deprecated"
|
||||
message="`android:singleLine` is deprecated: Use `maxLines="1"` instead"
|
||||
errorLine1=" android:singleLine="true""
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/pull_to_refresh_header_vertical.xml"
|
||||
line="45"
|
||||
column="17"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="Deprecated"
|
||||
message="`android:singleLine` is deprecated: Use `maxLines="1"` instead"
|
||||
errorLine1=" android:singleLine="true""
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/pull_to_refresh_header_vertical.xml"
|
||||
line="53"
|
||||
column="17"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="MissingTranslation"
|
||||
message=""`pull_to_refresh_from_bottom_pull_label`" is not translated in "es" (Spanish), "fr" (French), "pt" (Portuguese), "pt-BR" (Portuguese: Brazil)"
|
||||
errorLine1=" <string name="pull_to_refresh_from_bottom_pull_label">@string/pull_to_refresh_pull_label</string>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/values/pull_refresh_strings.xml"
|
||||
line="9"
|
||||
column="13"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="MissingTranslation"
|
||||
message=""`pull_to_refresh_from_bottom_release_label`" is not translated in "es" (Spanish), "fr" (French), "pt" (Portuguese), "pt-BR" (Portuguese: Brazil)"
|
||||
errorLine1=" <string name="pull_to_refresh_from_bottom_release_label">@string/pull_to_refresh_release_label</string>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/values/pull_refresh_strings.xml"
|
||||
line="10"
|
||||
column="13"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="MissingTranslation"
|
||||
message=""`pull_to_refresh_from_bottom_refreshing_label`" is not translated in "es" (Spanish), "fr" (French), "pt" (Portuguese), "pt-BR" (Portuguese: Brazil)"
|
||||
errorLine1=" <string name="pull_to_refresh_from_bottom_refreshing_label">@string/pull_to_refresh_refreshing_label</string>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/values/pull_refresh_strings.xml"
|
||||
line="11"
|
||||
column="13"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="AddJavascriptInterface"
|
||||
message="`WebView.addJavascriptInterface` should not be called with minSdkVersion < 17 for security reasons: JavaScript can use reflection to manipulate application"
|
||||
errorLine1=" webView.addJavascriptInterface(mJsCallback, JS_INTERFACE_PKG);"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/extras/PullToRefreshWebView2.java"
|
||||
line="90"
|
||||
column="11"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="JavascriptInterface"
|
||||
message="None of the methods in the added interface (JsValueCallback) have been annotated with `@android.webkit.JavascriptInterface`; they will not be visible in API 17"
|
||||
errorLine1=" webView.addJavascriptInterface(mJsCallback, JS_INTERFACE_PKG);"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/extras/PullToRefreshWebView2.java"
|
||||
line="90"
|
||||
column="11"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ObsoleteSdkInt"
|
||||
message="Unnecessary; SDK_INT is always >= 14"
|
||||
errorLine1=" return VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD && mOverScrollEnabled"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/PullToRefreshBase.java"
|
||||
line="211"
|
||||
column="10"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ObsoleteSdkInt"
|
||||
message="Unnecessary; SDK_INT is always >= 14"
|
||||
errorLine1=" if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/PullToRefreshExpandableListView.java"
|
||||
line="54"
|
||||
column="7"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ObsoleteSdkInt"
|
||||
message="Unnecessary; SDK_INT is always >= 14"
|
||||
errorLine1=" if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/PullToRefreshGridView.java"
|
||||
line="54"
|
||||
column="7"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ObsoleteSdkInt"
|
||||
message="Unnecessary; SDK_INT is always >= 14"
|
||||
errorLine1=" if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/PullToRefreshHorizontalScrollView.java"
|
||||
line="53"
|
||||
column="7"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ObsoleteSdkInt"
|
||||
message="Unnecessary; SDK_INT is always >= 14"
|
||||
errorLine1=" if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/PullToRefreshListView.java"
|
||||
line="207"
|
||||
column="7"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ObsoleteSdkInt"
|
||||
message="Unnecessary; SDK_INT is always >= 14"
|
||||
errorLine1=" if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/PullToRefreshScrollView.java"
|
||||
line="52"
|
||||
column="7"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ObsoleteSdkInt"
|
||||
message="Unnecessary; SDK_INT is always >= 14"
|
||||
errorLine1=" if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/PullToRefreshWebView.java"
|
||||
line="98"
|
||||
column="7"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ObsoleteSdkInt"
|
||||
message="Unnecessary; SDK_INT is always >= 14"
|
||||
errorLine1=" if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/internal/ViewCompat.java"
|
||||
line="44"
|
||||
column="7"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="FloatMath"
|
||||
message="Use `java.lang.Math#floor` instead of `android.util.FloatMath#floor()` since it is faster as of API 8"
|
||||
errorLine1=" float exactContentHeight = FloatMath.floor(mRefreshableView.getContentHeight() * mRefreshableView.getScale());"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/PullToRefreshWebView.java"
|
||||
line="115"
|
||||
column="30"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="FloatMath"
|
||||
message="Use `java.lang.Math#floor` instead of `android.util.FloatMath#floor()` since it is faster as of API 8"
|
||||
errorLine1=" return (int) Math.max(0, FloatMath.floor(mRefreshableView.getContentHeight() * mRefreshableView.getScale())"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/PullToRefreshWebView.java"
|
||||
line="161"
|
||||
column="29"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="IconMissingDensityFolder"
|
||||
message="Missing density variation folders in `src/main/res`: drawable-xxhdpi">
|
||||
<location
|
||||
file="src/main/res"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ViewConstructor"
|
||||
message="Custom view `RotateLoadingLayout` is missing constructor used by tools: `(Context)` or `(Context,AttributeSet)` or `(Context,AttributeSet,int)`"
|
||||
errorLine1="public class RotateLoadingLayout extends LoadingLayout {"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/internal/RotateLoadingLayout.java"
|
||||
line="30"
|
||||
column="14"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ContentDescription"
|
||||
message="[Accessibility] Missing `contentDescription` attribute on image"
|
||||
errorLine1=" <ImageView"
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="src/main/res/layout/pull_to_refresh_header_horizontal.xml"
|
||||
line="13"
|
||||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ContentDescription"
|
||||
message="[Accessibility] Missing `contentDescription` attribute on image"
|
||||
errorLine1=" <ImageView"
|
||||
errorLine2=" ^">
|
||||
<location
|
||||
file="src/main/res/layout/pull_to_refresh_header_vertical.xml"
|
||||
line="18"
|
||||
column="13"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="RtlHardcoded"
|
||||
message="Use "`Gravity.START`" instead of "`Gravity.LEFT`" to ensure correct behavior in right-to-left locales"
|
||||
errorLine1=" lp.gravity = scrollDirection == Orientation.VERTICAL ? Gravity.TOP : Gravity.LEFT;"
|
||||
errorLine2=" ~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/internal/LoadingLayout.java"
|
||||
line="92"
|
||||
column="82"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="RtlHardcoded"
|
||||
message="Use "`Gravity.END`" instead of "`Gravity.RIGHT`" to ensure correct behavior in right-to-left locales"
|
||||
errorLine1=" lp.gravity = scrollDirection == Orientation.VERTICAL ? Gravity.BOTTOM : Gravity.RIGHT;"
|
||||
errorLine2=" ~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/internal/LoadingLayout.java"
|
||||
line="102"
|
||||
column="85"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="RtlHardcoded"
|
||||
message="Use "`Gravity.END`" instead of "`Gravity.RIGHT`" to ensure correct behavior in right-to-left locales"
|
||||
errorLine1=" params.gravity = Gravity.TOP | Gravity.RIGHT;"
|
||||
errorLine2=" ~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java"
|
||||
line="344"
|
||||
column="43"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="RtlHardcoded"
|
||||
message="Use "`Gravity.END`" instead of "`Gravity.RIGHT`" to ensure correct behavior in right-to-left locales"
|
||||
errorLine1=" params.gravity = Gravity.BOTTOM | Gravity.RIGHT;"
|
||||
errorLine2=" ~~~~~">
|
||||
<location
|
||||
file="src/main/java/com/handmark/pulltorefresh/library/PullToRefreshAdapterViewBase.java"
|
||||
line="359"
|
||||
column="46"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="RtlHardcoded"
|
||||
message="Use "`start`" instead of "`left`" to ensure correct behavior in right-to-left locales"
|
||||
errorLine1=" android:layout_gravity="left|center_vertical" >"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/pull_to_refresh_header_vertical.xml"
|
||||
line="16"
|
||||
column="37"/>
|
||||
</issue>
|
||||
|
||||
</issues>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.handmark.pulltorefresh.library"
|
||||
android:versionCode="2110"
|
||||
android:versionName="2.1.1">
|
||||
</manifest>
|
@ -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
|
||||
* <code>setLoadingDrawable(drawable, Mode.BOTH)</code>
|
||||
*
|
||||
* @param drawable - Drawable to display
|
||||
*/
|
||||
public void setLoadingDrawable(Drawable drawable);
|
||||
|
||||
/**
|
||||
* Set Text to show when the Widget is being Pulled
|
||||
* <code>setPullLabel(releaseLabel, Mode.BOTH)</code>
|
||||
*
|
||||
* @param pullLabel - CharSequence to display
|
||||
*/
|
||||
public void setPullLabel(CharSequence pullLabel);
|
||||
|
||||
/**
|
||||
* Set Text to show when the Widget is refreshing
|
||||
* <code>setRefreshingLabel(releaseLabel, Mode.BOTH)</code>
|
||||
*
|
||||
* @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
|
||||
* <code>setReleaseLabel(releaseLabel, Mode.BOTH)</code>
|
||||
*
|
||||
* @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);
|
||||
|
||||
}
|
@ -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<T extends View> {
|
||||
|
||||
/**
|
||||
* 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 <code>Mode.BOTH</code>.
|
||||
*
|
||||
* @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).
|
||||
* <p />
|
||||
* 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.
|
||||
* <p />
|
||||
* 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
|
||||
* <code>Mode.BOTH</code>, you can use <code>getCurrentMode()</code> 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<T> listener);
|
||||
|
||||
/**
|
||||
* Set OnRefreshListener for the Widget
|
||||
*
|
||||
* @param listener - Listener to be used when the Widget is set to Refresh
|
||||
*/
|
||||
public void setOnRefreshListener(OnRefreshListener<T> listener);
|
||||
|
||||
/**
|
||||
* Set OnRefreshListener for the Widget
|
||||
*
|
||||
* @param listener - Listener to be used when the Widget is set to Refresh
|
||||
*/
|
||||
public void setOnRefreshListener(OnRefreshListener2<T> 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);
|
||||
|
||||
}
|
@ -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<LoadingLayout> mLoadingLayouts;
|
||||
|
||||
LoadingLayoutProxy() {
|
||||
mLoadingLayouts = new HashSet<LoadingLayout>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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.
|
||||
* <p/>
|
||||
* 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;
|
||||
}
|
||||
}
|
@ -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<T extends AbsListView> extends PullToRefreshBase<T> 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 <var>true</var> 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<ListAdapter>) mRefreshableView).setAdapter(adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Empty View to be used by the Adapter View.
|
||||
* <p/>
|
||||
* We need it handle it ourselves so that we can Pull-to-Refresh when the
|
||||
* Empty View is shown.
|
||||
* <p/>
|
||||
* Please note, you do <strong>not</strong> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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<ExpandableListView> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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<GridView> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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<HorizontalScrollView> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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<ListView> {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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<ScrollView> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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<WebView> {
|
||||
|
||||
private static final OnRefreshListener<WebView> defaultOnRefreshListener = new OnRefreshListener<WebView>() {
|
||||
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<WebView> 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()));
|
||||
}
|
||||
}
|
||||
}
|
@ -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:
|
||||
* <p/>
|
||||
* <ul>
|
||||
* <li>{@link PullToRefreshWebView} doesn't work correctly because you're using
|
||||
* <code>overflow:scroll</code> or something else which means
|
||||
* {@link WebView#getScrollY()} doesn't return correct values.</li>
|
||||
* <li>You control the web content being displayed, as you need to write some
|
||||
* Javascript callbacks.</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* <p/>
|
||||
* The way this call works is that when a PullToRefresh gesture is in action,
|
||||
* the following Javascript methods will be called:
|
||||
* <code>isReadyForPullDown()</code> and <code>isReadyForPullUp()</code>, 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:
|
||||
* <p/>
|
||||
*
|
||||
* <pre>
|
||||
* 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);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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<V extends View> implements PullToRefreshBase.OnPullEventListener<V> {
|
||||
|
||||
private final Context mContext;
|
||||
private final HashMap<State, Integer> mSoundMap;
|
||||
|
||||
private MediaPlayer mCurrentMediaPlayer;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param context - Context
|
||||
*/
|
||||
public SoundPullEventListener(Context context) {
|
||||
mContext = context;
|
||||
mSoundMap = new HashMap<State, Integer>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPullEvent(PullToRefreshBase<V> 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.
|
||||
* <p/>
|
||||
* 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.
|
||||
* <var>R.raw.pull_sound</var>)
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2009 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<translate xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@android:integer/config_longAnimTime"
|
||||
android:fromYDelta="100%p"
|
||||
android:toYDelta="0" />
|
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2009 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<translate xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@android:integer/config_longAnimTime"
|
||||
android:fromYDelta="-100%p"
|
||||
android:toYDelta="0" />
|
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2009 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<translate xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@android:integer/config_longAnimTime"
|
||||
android:fromYDelta="0"
|
||||
android:toYDelta="100%p" />
|
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2009 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<translate xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@android:integer/config_longAnimTime"
|
||||
android:fromYDelta="0"
|
||||
android:toYDelta="-100%p" />
|
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 390 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 445 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 429 B |
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle" >
|
||||
|
||||
<solid android:color="#40000000" />
|
||||
|
||||
<!--
|
||||
I know the android:radius is useless here but it's needed to fix an old bug:
|
||||
http://code.google.com/p/android/issues/detail?id=939
|
||||
-->
|
||||
<corners
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp"
|
||||
android:radius="1dp"
|
||||
android:topLeftRadius="@dimen/indicator_corner_radius"
|
||||
android:topRightRadius="@dimen/indicator_corner_radius" />
|
||||
|
||||
</shape>
|
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle" >
|
||||
|
||||
<solid android:color="#40000000" />
|
||||
|
||||
<!--
|
||||
I know the android:radius is useless here but it's needed to fix an old bug:
|
||||
http://code.google.com/p/android/issues/detail?id=939
|
||||
-->
|
||||
<corners
|
||||
android:bottomLeftRadius="@dimen/indicator_corner_radius"
|
||||
android:bottomRightRadius="@dimen/indicator_corner_radius"
|
||||
android:radius="1dp"
|
||||
android:topLeftRadius="0dp"
|
||||
android:topRightRadius="0dp" />
|
||||
|
||||
</shape>
|
@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/fl_inner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:paddingBottom="@dimen/header_footer_top_bottom_padding"
|
||||
android:paddingLeft="@dimen/header_footer_left_right_padding"
|
||||
android:paddingRight="@dimen/header_footer_left_right_padding"
|
||||
android:paddingTop="@dimen/header_footer_top_bottom_padding" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pull_to_refresh_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pull_to_refresh_progress"
|
||||
style="?android:attr/progressBarStyleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
|
||||
</merge>
|
@ -1,59 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/fl_inner"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/header_footer_top_bottom_padding"
|
||||
android:paddingLeft="@dimen/header_footer_left_right_padding"
|
||||
android:paddingRight="@dimen/header_footer_left_right_padding"
|
||||
android:paddingTop="@dimen/header_footer_top_bottom_padding" >
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left|center_vertical" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pull_to_refresh_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pull_to_refresh_progress"
|
||||
style="?android:attr/progressBarStyleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pull_to_refresh_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearance"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pull_to_refresh_sub_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
</merge>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">اسحب للتحديث…</string>
|
||||
<string name="pull_to_refresh_release_label">اترك للتحديث…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">تحميل…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">Tažením aktualizujete…</string>
|
||||
<string name="pull_to_refresh_release_label">Uvolněním aktualizujete…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">Načítání…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">Ziehen zum Aktualisieren…</string>
|
||||
<string name="pull_to_refresh_release_label">Loslassen zum Aktualisieren…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">Laden…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">Tirar para actualizar…</string>
|
||||
<string name="pull_to_refresh_release_label">Soltar para actualizar…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">Cargando…</string>
|
||||
</resources>
|
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="pull_to_refresh_pull_label">Päivitä vetämällä alas…</string>
|
||||
<string name="pull_to_refresh_release_label">Päivitä vapauttamalla…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">Päivitetään…</string>
|
||||
|
||||
<!-- Just use standard Pull Down String when pulling up. These can be set for languages which require it -->
|
||||
<string name="pull_to_refresh_from_bottom_pull_label">Päivitä vetämällä ylös…</string>
|
||||
<string name="pull_to_refresh_from_bottom_release_label">@string/pull_to_refresh_release_label</string>
|
||||
<string name="pull_to_refresh_from_bottom_refreshing_label">@string/pull_to_refresh_refreshing_label</string>
|
||||
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">Tirez pour rafraîchir…</string>
|
||||
<string name="pull_to_refresh_release_label">Relâcher pour rafraîchir…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">Chargement…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">משוך לרענון…</string>
|
||||
<string name="pull_to_refresh_release_label">שחרר לרענון…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">טוען…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">Tira per aggiornare…</string>
|
||||
<string name="pull_to_refresh_release_label">Rilascia per aggionare…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">Caricamento…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">משוך לרענון…</string>
|
||||
<string name="pull_to_refresh_release_label">שחרר לרענון…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">טוען…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">画面を引っ張って…</string>
|
||||
<string name="pull_to_refresh_release_label">指を離して更新…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">読み込み中…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">당겨서 새로 고침…</string>
|
||||
<string name="pull_to_refresh_release_label">놓아서 새로 고침…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">로드 중…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">Sleep om te vernieuwen…</string>
|
||||
<string name="pull_to_refresh_release_label">Loslaten om te vernieuwen…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">Laden…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">Pociągnij, aby odświeżyć…</string>
|
||||
<string name="pull_to_refresh_release_label">Puść, aby odświeżyć…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">Wczytywanie…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">Puxe para atualizar…</string>
|
||||
<string name="pull_to_refresh_release_label">Libere para atualizar…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">Carregando…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">Puxe para atualizar…</string>
|
||||
<string name="pull_to_refresh_release_label">Liberação para atualizar…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">A carregar…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">Trage pentru a reîmprospăta…</string>
|
||||
<string name="pull_to_refresh_release_label">Eliberează pentru a reîmprospăta…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">Încărcare…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">Потяните для обновления…</string>
|
||||
<string name="pull_to_refresh_release_label">Отпустите для обновления…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">Загрузка…</string>
|
||||
</resources>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="pull_to_refresh_pull_label">下拉刷新…</string>
|
||||
<string name="pull_to_refresh_release_label">放开以刷新…</string>
|
||||
<string name="pull_to_refresh_refreshing_label">正在载入…</string>
|
||||
</resources>
|
@ -1,80 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<declare-styleable name="PullToRefresh">
|
||||
|
||||
<!-- A drawable to use as the background of the Refreshable View -->
|
||||
<attr name="ptrRefreshableViewBackground" format="reference|color" />
|
||||
|
||||
<!-- A drawable to use as the background of the Header and Footer Loading Views -->
|
||||
<attr name="ptrHeaderBackground" format="reference|color" />
|
||||
|
||||
<!-- Text Color of the Header and Footer Loading Views -->
|
||||
<attr name="ptrHeaderTextColor" format="reference|color" />
|
||||
|
||||
<!-- Text Color of the Header and Footer Loading Views Sub Header -->
|
||||
<attr name="ptrHeaderSubTextColor" format="reference|color" />
|
||||
|
||||
<!-- Mode of Pull-to-Refresh that should be used -->
|
||||
<attr name="ptrMode">
|
||||
<flag name="disabled" value="0x0" />
|
||||
<flag name="pullFromStart" value="0x1" />
|
||||
<flag name="pullFromEnd" value="0x2" />
|
||||
<flag name="both" value="0x3" />
|
||||
<flag name="manualOnly" value="0x4" />
|
||||
|
||||
<!-- These last two are depreacted -->
|
||||
<flag name="pullDownFromTop" value="0x1" />
|
||||
<flag name="pullUpFromBottom" value="0x2" />
|
||||
</attr>
|
||||
|
||||
<!-- Whether the Indicator overlay(s) should be used -->
|
||||
<attr name="ptrShowIndicator" format="reference|boolean" />
|
||||
|
||||
<!-- Drawable to use as Loading Indicator. Changes both Header and Footer. -->
|
||||
<attr name="ptrDrawable" format="reference" />
|
||||
|
||||
<!-- Drawable to use as Loading Indicator in the Header View. Overrides value set in ptrDrawable. -->
|
||||
<attr name="ptrDrawableStart" format="reference" />
|
||||
|
||||
<!-- Drawable to use as Loading Indicator in the Footer View. Overrides value set in ptrDrawable. -->
|
||||
<attr name="ptrDrawableEnd" format="reference" />
|
||||
|
||||
<!-- Whether Android's built-in Over Scroll should be utilised for Pull-to-Refresh. -->
|
||||
<attr name="ptrOverScroll" format="reference|boolean" />
|
||||
|
||||
<!-- Base text color, typeface, size, and style for Header and Footer Loading Views -->
|
||||
<attr name="ptrHeaderTextAppearance" format="reference" />
|
||||
|
||||
<!-- Base text color, typeface, size, and style for Header and Footer Loading Views Sub Header -->
|
||||
<attr name="ptrSubHeaderTextAppearance" format="reference" />
|
||||
|
||||
<!-- Style of Animation should be used displayed when pulling. -->
|
||||
<attr name="ptrAnimationStyle">
|
||||
<flag name="rotate" value="0x0" />
|
||||
<flag name="flip" value="0x1" />
|
||||
</attr>
|
||||
|
||||
<!-- Whether the user can scroll while the View is Refreshing -->
|
||||
<attr name="ptrScrollingWhileRefreshingEnabled" format="reference|boolean" />
|
||||
|
||||
<!--
|
||||
Whether PullToRefreshListView has it's extras enabled. This allows the user to be
|
||||
able to scroll while refreshing, and behaves better. It acheives this by adding
|
||||
Header and/or Footer Views to the ListView.
|
||||
-->
|
||||
<attr name="ptrListViewExtrasEnabled" format="reference|boolean" />
|
||||
|
||||
<!--
|
||||
Whether the Drawable should be continually rotated as you pull. This only
|
||||
takes effect when using the 'Rotate' Animation Style.
|
||||
-->
|
||||
<attr name="ptrRotateDrawableWhilePulling" format="reference|boolean" />
|
||||
|
||||
<!-- BELOW HERE ARE DEPRECEATED. DO NOT USE. -->
|
||||
<attr name="ptrAdapterViewBackground" format="reference|color" />
|
||||
<attr name="ptrDrawableTop" format="reference" />
|
||||
<attr name="ptrDrawableBottom" format="reference" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<dimen name="indicator_right_padding">10dp</dimen>
|
||||
<dimen name="indicator_corner_radius">12dp</dimen>
|
||||
<dimen name="indicator_internal_padding">4dp</dimen>
|
||||
<dimen name="header_footer_left_right_padding">24dp</dimen>
|
||||
<dimen name="header_footer_top_bottom_padding">12dp</dimen>
|
||||
|
||||
</resources>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<item type="id" name="gridview" />
|
||||
<item type="id" name="webview" />
|
||||
<item type="id" name="scrollview" />
|
||||
|
||||
</resources>
|
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<string name="pull_to_refresh_pull_label" tools:ignore="MissingTranslation">Pull to refresh…</string>
|
||||
<string name="pull_to_refresh_release_label" tools:ignore="MissingTranslation">Release to refresh…</string>
|
||||
<string name="pull_to_refresh_refreshing_label" tools:ignore="MissingTranslation">Loading…</string>
|
||||
|
||||
<!-- Just use standard Pull Down String when pulling up. These can be set for languages which require it -->
|
||||
<string name="pull_to_refresh_from_bottom_pull_label" tools:ignore="MissingTranslation">@string/pull_to_refresh_pull_label</string>
|
||||
<string name="pull_to_refresh_from_bottom_release_label" tools:ignore="MissingTranslation">@string/pull_to_refresh_release_label</string>
|
||||
<string name="pull_to_refresh_from_bottom_refreshing_label" tools:ignore="MissingTranslation">@string/pull_to_refresh_refreshing_label</string>
|
||||
|
||||
</resources>
|
@ -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'
|
||||
|
@ -57,7 +57,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')
|
||||
|
@ -33,7 +33,7 @@
|
||||
<li>Écoute et téléchargement illimités vers autant de iPhones et d'appareils Android que souhaité.</li>
|
||||
<li>Lecture de vidéos.</li>
|
||||
<li>Une adresse web personnalisée pour votre serveur Subsonic (<em>votrenom</em>.subsonic.org).</li>
|
||||
<li>Aucunes publicitées; dans l'interface web de Subsonic.</li>
|
||||
<li>Aucunes publicités dans l'interface web de Subsonic.</li>
|
||||
<li>Accès gratuit aux nouvelles fonctionnalités avancées.</li>
|
||||
</ul>
|
||||
|
||||
|
@ -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.data.ActiveServerProvider;
|
||||
import org.moire.ultrasonic.domain.MusicDirectory;
|
||||
@ -50,7 +49,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;
|
||||
@ -71,13 +70,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<ListView>()
|
||||
refreshAlbumListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView)
|
||||
public void onRefresh()
|
||||
{
|
||||
new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
@ -473,7 +472,6 @@ public class BookmarkActivity extends SubsonicTabActivity
|
||||
@Override
|
||||
protected void onPostExecute(String[] result)
|
||||
{
|
||||
refreshAlbumListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
|
@ -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.data.ActiveServerProvider;
|
||||
import org.moire.ultrasonic.domain.ChatMessage;
|
||||
@ -43,7 +44,6 @@ import static org.koin.java.KoinJavaComponent.inject;
|
||||
*/
|
||||
public final class ChatActivity extends SubsonicTabActivity
|
||||
{
|
||||
private PullToRefreshListView refreshChatListView;
|
||||
private ListView chatListView;
|
||||
private EditText messageEditText;
|
||||
private ImageButton sendButton;
|
||||
@ -58,9 +58,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);
|
||||
|
||||
@ -74,7 +71,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);
|
||||
|
||||
@ -121,15 +118,6 @@ public final class ChatActivity extends SubsonicTabActivity
|
||||
}
|
||||
});
|
||||
|
||||
refreshChatListView.setOnRefreshListener(new OnRefreshListener<ListView>()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView)
|
||||
{
|
||||
new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
});
|
||||
|
||||
View chatMenuItem = findViewById(R.id.menu_chat);
|
||||
menuDrawer.setActiveView(chatMenuItem);
|
||||
|
||||
@ -144,6 +132,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()
|
||||
{
|
||||
@ -283,7 +298,6 @@ public final class ChatActivity extends SubsonicTabActivity
|
||||
protected void onPostExecute(String[] result)
|
||||
{
|
||||
load();
|
||||
refreshChatListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
|
@ -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.data.ActiveServerProvider;
|
||||
@ -61,13 +59,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;
|
||||
@ -92,50 +88,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<ListView>()
|
||||
refreshAlbumListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> 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<albumListView.getChildCount();i++) {
|
||||
Object child = albumListView.getChildAt(i);
|
||||
if (child instanceof AlbumView) {
|
||||
AlbumView albumView = (AlbumView) child;
|
||||
if (albumView.isMaximized()) {
|
||||
albumView.maximizeOrMinimize();
|
||||
}
|
||||
}
|
||||
if (child instanceof SongView) {
|
||||
SongView songView = (SongView) child;
|
||||
if (songView.isMaximized()) {
|
||||
songView.maximizeOrMinimize();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||
}
|
||||
});
|
||||
|
||||
header = LayoutInflater.from(this).inflate(R.layout.select_album_header, albumListView, false);
|
||||
|
||||
albumListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
||||
@ -1320,7 +1289,6 @@ public class SelectAlbumActivity extends SubsonicTabActivity
|
||||
@Override
|
||||
protected void onPostExecute(String[] result)
|
||||
{
|
||||
refreshAlbumListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
|
@ -32,9 +32,8 @@ import android.widget.AdapterView;
|
||||
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.data.ActiveServerProvider;
|
||||
import org.moire.ultrasonic.data.ServerSetting;
|
||||
@ -64,7 +63,7 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
|
||||
|
||||
private static final int MENU_GROUP_MUSIC_FOLDER = 10;
|
||||
|
||||
private PullToRefreshListView refreshArtistListView;
|
||||
private SwipeRefreshLayout refreshArtistListView;
|
||||
private ListView artistListView;
|
||||
private View folderButton;
|
||||
private TextView folderName;
|
||||
@ -79,13 +78,13 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.select_artist);
|
||||
|
||||
refreshArtistListView = (PullToRefreshListView) findViewById(R.id.select_artist_list);
|
||||
artistListView = refreshArtistListView.getRefreshableView();
|
||||
refreshArtistListView = findViewById(R.id.select_artist_refresh);
|
||||
artistListView = findViewById(R.id.select_artist_list);
|
||||
|
||||
refreshArtistListView.setOnRefreshListener(new OnRefreshListener<ListView>()
|
||||
refreshArtistListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView)
|
||||
public void onRefresh()
|
||||
{
|
||||
new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
@ -362,7 +361,6 @@ public class SelectArtistActivity extends SubsonicTabActivity implements Adapter
|
||||
@Override
|
||||
protected void onPostExecute(String[] result)
|
||||
{
|
||||
refreshArtistListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
|
@ -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<ListView>()
|
||||
refreshGenreListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> 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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -64,7 +62,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;
|
||||
@ -75,13 +73,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<ListView>()
|
||||
refreshPlaylistsListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> refreshView)
|
||||
public void onRefresh()
|
||||
{
|
||||
new GetDataTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
@ -380,7 +378,6 @@ public class SelectPlaylistActivity extends SubsonicTabActivity implements Adapt
|
||||
@Override
|
||||
protected void onPostExecute(String[] result)
|
||||
{
|
||||
refreshPlaylistsListView.onRefreshComplete();
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
|
@ -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<ListView>()
|
||||
refreshSharesListView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()
|
||||
{
|
||||
@Override
|
||||
public void onRefresh(PullToRefreshBase<ListView> 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);
|
||||
}
|
||||
|
||||
|
BIN
ultrasonic/src/main/res/drawable-hdpi/ic_menu_refresh_dark.png
Normal file
After Width: | Height: | Size: 498 B |
BIN
ultrasonic/src/main/res/drawable-hdpi/ic_menu_refresh_light.png
Normal file
After Width: | Height: | Size: 492 B |
BIN
ultrasonic/src/main/res/drawable-mdpi/ic_menu_refresh_dark.png
Normal file
After Width: | Height: | Size: 412 B |
BIN
ultrasonic/src/main/res/drawable-mdpi/ic_menu_refresh_light.png
Normal file
After Width: | Height: | Size: 391 B |
BIN
ultrasonic/src/main/res/drawable-xhdpi/ic_menu_refresh_dark.png
Normal file
After Width: | Height: | Size: 712 B |
BIN
ultrasonic/src/main/res/drawable-xhdpi/ic_menu_refresh_light.png
Normal file
After Width: | Height: | Size: 698 B |
BIN
ultrasonic/src/main/res/drawable-xxhdpi/ic_menu_refresh_dark.png
Normal file
After Width: | Height: | Size: 1017 B |
After Width: | Height: | Size: 1002 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
@ -6,12 +6,12 @@
|
||||
|
||||
<include layout="@layout/tab_progress" />
|
||||
|
||||
<com.handmark.pulltorefresh.library.PullToRefreshListView
|
||||
a:id="@+id/chat_entries"
|
||||
<ListView
|
||||
a:id="@+id/chat_entries_list"
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="0dip"
|
||||
a:layout_weight="1.0"
|
||||
a:textFilterEnabled="true" />
|
||||
a:layout_weight="1.0" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
a:layout_height="4dip"
|
||||
|
@ -19,13 +19,19 @@
|
||||
a:text="@string/select_album.empty"
|
||||
a:visibility="gone" />
|
||||
|
||||
<com.handmark.pulltorefresh.library.PullToRefreshListView
|
||||
a:id="@+id/select_album_entries"
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="0dip"
|
||||
a:layout_weight="1.0"
|
||||
a:fastScrollEnabled="true"
|
||||
a:textFilterEnabled="true" />
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/select_album_entries_refresh"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/select_album_entries_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<include layout="@layout/album_buttons" />
|
||||
|
||||
|
@ -6,13 +6,19 @@
|
||||
|
||||
<include layout="@layout/tab_progress" />
|
||||
|
||||
<com.handmark.pulltorefresh.library.PullToRefreshListView
|
||||
a:id="@+id/select_artist_list"
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="0dip"
|
||||
a:layout_weight="1.0"
|
||||
a:fastScrollEnabled="true"
|
||||
a:textFilterEnabled="true" />
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/select_artist_refresh"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/select_artist_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<include layout="@layout/now_playing" />
|
||||
|
||||
|
@ -14,13 +14,19 @@
|
||||
a:text="@string/select_genre.empty"
|
||||
a:visibility="gone" />
|
||||
|
||||
<com.handmark.pulltorefresh.library.PullToRefreshListView
|
||||
a:id="@+id/select_genre_list"
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="0dip"
|
||||
a:layout_weight="1.0"
|
||||
a:fastScrollEnabled="true"
|
||||
a:textFilterEnabled="true" />
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/select_genre_refresh"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/select_genre_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<include layout="@layout/now_playing" />
|
||||
|
||||
|
@ -14,13 +14,19 @@
|
||||
a:text="@string/select_playlist.empty"
|
||||
a:visibility="gone" />
|
||||
|
||||
<com.handmark.pulltorefresh.library.PullToRefreshListView
|
||||
a:id="@+id/select_playlist_list"
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="0dip"
|
||||
a:layout_weight="1.0"
|
||||
a:fastScrollEnabled="true"
|
||||
a:textFilterEnabled="true" />
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/select_playlist_refresh"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/select_playlist_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<include layout="@layout/now_playing" />
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="fill_parent"
|
||||
a:orientation="vertical" >
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="fill_parent"
|
||||
a:orientation="vertical">
|
||||
|
||||
<include layout="@layout/tab_progress" />
|
||||
|
||||
@ -14,13 +14,20 @@
|
||||
a:text="@string/select_share.empty"
|
||||
a:visibility="gone" />
|
||||
|
||||
<com.handmark.pulltorefresh.library.PullToRefreshListView
|
||||
a:id="@+id/select_share_list"
|
||||
a:layout_width="fill_parent"
|
||||
a:layout_height="0dip"
|
||||
a:layout_weight="1.0"
|
||||
a:fastScrollEnabled="true"
|
||||
a:textFilterEnabled="true" />
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/select_share_refresh"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1.0">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/select_share_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<include layout="@layout/now_playing" />
|
||||
|
||||
|
9
ultrasonic/src/main/res/menu/chat.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item
|
||||
android:id="@+id/menu_refresh"
|
||||
android:title="@string/menu_refresh"
|
||||
android:icon="?attr/refresh"
|
||||
app:showAsAction="ifRoom|withText" />
|
||||
</menu>
|
@ -480,5 +480,6 @@
|
||||
anstatt einfach Elemente zu markieren / zu entfernen.
|
||||
</string>
|
||||
<string name="feature_flags_category_title">Funktionseinstellungem</string>
|
||||
<string name="menu_refresh">Aktualisierung</string>
|
||||
|
||||
</resources>
|
||||
|
@ -483,5 +483,6 @@
|
||||
en lugar de simplemente destacar / desestimar elementos.
|
||||
</string>
|
||||
<string name="feature_flags_category_title">Banderas de características</string>
|
||||
<string name="menu_refresh">Actualizar</string>
|
||||
|
||||
</resources>
|
||||
|
@ -484,5 +484,6 @@
|
||||
au lieu de simplement mettre en vedette / désactiver les éléments.
|
||||
</string>
|
||||
<string name="feature_flags_category_title">Drapeaux des fonctionnalités</string>
|
||||
<string name="menu_refresh">Rafraichir</string>
|
||||
|
||||
</resources>
|
||||
|
@ -483,5 +483,6 @@
|
||||
csillaggal jelölés helyett.
|
||||
</string>
|
||||
<string name="feature_flags_category_title">Jellemzők Zászlók</string>
|
||||
<string name="menu_refresh">Refresh</string>
|
||||
|
||||
</resources>
|
||||
|
@ -483,5 +483,6 @@
|
||||
in plaats van items simpelweg in de hoofdrol te zetten / niet te verwijderen.
|
||||
</string>
|
||||
<string name="feature_flags_category_title">Experimentele functies</string>
|
||||
<string name="menu_refresh">Refresh</string>
|
||||
|
||||
</resources>
|
||||
|
@ -496,5 +496,6 @@ Obecnie nie zapisuje obrazów w pamięci urządzenia, tylko wykorzystuje tylko p
|
||||
zamiast po prostu grać gwiazdkami / bez gwiazd.
|
||||
</string>
|
||||
<string name="feature_flags_category_title">Flagi funkcji</string>
|
||||
<string name="menu_refresh">Refresh</string>
|
||||
|
||||
</resources>
|
||||
|
@ -483,5 +483,6 @@
|
||||
em vez de simplesmente estrelar / não estrelar itens.
|
||||
</string>
|
||||
<string name="feature_flags_category_title">Bandeiras de recursos</string>
|
||||
<string name="menu_refresh">Refresh</string>
|
||||
|
||||
</resources>
|
||||
|
@ -483,5 +483,6 @@
|
||||
em vez de simplesmente estrelar / não estrelar itens.
|
||||
</string>
|
||||
<string name="feature_flags_category_title">Bandeiras de recursos</string>
|
||||
<string name="menu_refresh">Refresh</string>
|
||||
|
||||
</resources>
|
||||
|
@ -487,5 +487,6 @@
|
||||
instead of simply starring/unstarring items.
|
||||
</string>
|
||||
<string name="feature_flags_category_title">Feature Flags</string>
|
||||
<string name="menu_refresh">Refresh</string>
|
||||
|
||||
</resources>
|
||||
|
@ -80,6 +80,7 @@
|
||||
<attr name="media_shuffle" format="reference"/>
|
||||
<attr name="media_play" format="reference"/>
|
||||
<attr name="podcasts" format="reference"/>
|
||||
<attr name="refresh" format="reference"/>
|
||||
<attr name="media_play_next" format="reference"/>
|
||||
<attr name="media_play_small" format="reference"/>
|
||||
<attr name="media_stop" format="reference"/>
|
||||
|