refreshView) {
34 | refreshView.getRefreshableView().reload();
35 | }
36 |
37 | };
38 |
39 | private final WebChromeClient defaultWebChromeClient = new WebChromeClient() {
40 |
41 | @Override
42 | public void onProgressChanged(WebView view, int newProgress) {
43 | if (newProgress == 100) {
44 | onRefreshComplete();
45 | }
46 | }
47 |
48 | };
49 |
50 | public PullToRefreshWebView(Context context) {
51 | super(context);
52 |
53 | /**
54 | * Added so that by default, Pull-to-Refresh refreshes the page
55 | */
56 | setOnRefreshListener(defaultOnRefreshListener);
57 | mRefreshableView.setWebChromeClient(defaultWebChromeClient);
58 | }
59 |
60 | public PullToRefreshWebView(Context context, AttributeSet attrs) {
61 | super(context, attrs);
62 |
63 | /**
64 | * Added so that by default, Pull-to-Refresh refreshes the page
65 | */
66 | setOnRefreshListener(defaultOnRefreshListener);
67 | mRefreshableView.setWebChromeClient(defaultWebChromeClient);
68 | }
69 |
70 | public PullToRefreshWebView(Context context, Mode mode) {
71 | super(context, mode);
72 |
73 | /**
74 | * Added so that by default, Pull-to-Refresh refreshes the page
75 | */
76 | setOnRefreshListener(defaultOnRefreshListener);
77 | mRefreshableView.setWebChromeClient(defaultWebChromeClient);
78 | }
79 |
80 | public PullToRefreshWebView(Context context, Mode mode, AnimationStyle style) {
81 | super(context, mode, style);
82 |
83 | /**
84 | * Added so that by default, Pull-to-Refresh refreshes the page
85 | */
86 | setOnRefreshListener(defaultOnRefreshListener);
87 | mRefreshableView.setWebChromeClient(defaultWebChromeClient);
88 | }
89 |
90 | @Override
91 | public final Orientation getPullToRefreshScrollDirection() {
92 | return Orientation.VERTICAL;
93 | }
94 |
95 | @Override
96 | protected WebView createRefreshableView(Context context, AttributeSet attrs) {
97 | WebView webView;
98 | if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {
99 | webView = new InternalWebViewSDK9(context, attrs);
100 | } else {
101 | webView = new WebView(context, attrs);
102 | }
103 |
104 | webView.setId(R.id.webview);
105 | return webView;
106 | }
107 |
108 | @Override
109 | protected boolean isReadyForPullStart() {
110 | return mRefreshableView.getScrollY() == 0;
111 | }
112 |
113 | @Override
114 | protected boolean isReadyForPullEnd() {
115 | float exactContentHeight = (float) Math.floor(mRefreshableView.getContentHeight() * mRefreshableView.getScale());
116 | return mRefreshableView.getScrollY() >= (exactContentHeight - mRefreshableView.getHeight());
117 | }
118 |
119 | @Override
120 | protected void onPtrRestoreInstanceState(Bundle savedInstanceState) {
121 | super.onPtrRestoreInstanceState(savedInstanceState);
122 | mRefreshableView.restoreState(savedInstanceState);
123 | }
124 |
125 | @Override
126 | protected void onPtrSaveInstanceState(Bundle saveState) {
127 | super.onPtrSaveInstanceState(saveState);
128 | mRefreshableView.saveState(saveState);
129 | }
130 |
131 | @TargetApi(9)
132 | final class InternalWebViewSDK9 extends WebView {
133 |
134 | // WebView doesn't always scroll back to it's edge so we add some
135 | // fuzziness
136 | static final int OVERSCROLL_FUZZY_THRESHOLD = 2;
137 |
138 | // WebView seems quite reluctant to overscroll so we use the scale
139 | // factor to scale it's value
140 | static final float OVERSCROLL_SCALE_FACTOR = 1.5f;
141 |
142 | public InternalWebViewSDK9(Context context, AttributeSet attrs) {
143 | super(context, attrs);
144 | }
145 |
146 | @Override
147 | protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,
148 | int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
149 |
150 | final boolean returnValue = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
151 | scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
152 |
153 | // Does all of the hard work...
154 | OverscrollHelper.overScrollBy(PullToRefreshWebView.this, deltaX, scrollX, deltaY, scrollY,
155 | getScrollRange(), OVERSCROLL_FUZZY_THRESHOLD, OVERSCROLL_SCALE_FACTOR, isTouchEvent);
156 |
157 | return returnValue;
158 | }
159 |
160 | private int getScrollRange() {
161 | return (int) Math.max(0, Math.floor(mRefreshableView.getContentHeight() * mRefreshableView.getScale())
162 | - (getHeight() - getPaddingBottom() - getPaddingTop()));
163 | }
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/java/com/itheima/pulltorefreshlib/extras/PullToRefreshWebView2.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package com.itheima.pulltorefreshlib.extras;
17 |
18 | import android.content.Context;
19 | import android.util.AttributeSet;
20 | import android.webkit.WebView;
21 |
22 | import com.itheima.pulltorefreshlib.PullToRefreshWebView;
23 |
24 | import java.util.concurrent.atomic.AtomicBoolean;
25 |
26 |
27 | /**
28 | * An advanced version of {@link PullToRefreshWebView} which delegates the
29 | * triggering of the PullToRefresh gesture to the Javascript running within the
30 | * WebView. This means that you should only use this class if:
31 | *
32 | *
33 | * - {@link PullToRefreshWebView} doesn't work correctly because you're using
34 | *
overflow:scroll
or something else which means
35 | * {@link WebView#getScrollY()} doesn't return correct values.
36 | * - You control the web content being displayed, as you need to write some
37 | * Javascript callbacks.
38 | *
39 | *
40 | *
41 | * The way this call works is that when a PullToRefresh gesture is in action,
42 | * the following Javascript methods will be called:
43 | * isReadyForPullDown()
and isReadyForPullUp()
, it is
44 | * your job to calculate whether the view is in a state where a PullToRefresh
45 | * can happen, and return the result via the callback mechanism. An example can
46 | * be seen below:
47 | *
48 | *
49 | *
50 | * function isReadyForPullDown() {
51 | * var result = ... // Probably using the .scrollTop DOM attribute
52 | * ptr.isReadyForPullDownResponse(result);
53 | * }
54 | *
55 | * function isReadyForPullUp() {
56 | * var result = ... // Probably using the .scrollBottom DOM attribute
57 | * ptr.isReadyForPullUpResponse(result);
58 | * }
59 | *
60 | *
61 | * @author Chris Banes
62 | */
63 | public class PullToRefreshWebView2 extends PullToRefreshWebView {
64 |
65 | static final String JS_INTERFACE_PKG = "ptr";
66 | static final String DEF_JS_READY_PULL_DOWN_CALL = "javascript:isReadyForPullDown();";
67 | static final String DEF_JS_READY_PULL_UP_CALL = "javascript:isReadyForPullUp();";
68 |
69 | public PullToRefreshWebView2(Context context) {
70 | super(context);
71 | }
72 |
73 | public PullToRefreshWebView2(Context context, AttributeSet attrs) {
74 | super(context, attrs);
75 | }
76 |
77 | public PullToRefreshWebView2(Context context, Mode mode) {
78 | super(context, mode);
79 | }
80 |
81 | private JsValueCallback mJsCallback;
82 | private final AtomicBoolean mIsReadyForPullDown = new AtomicBoolean(false);
83 | private final AtomicBoolean mIsReadyForPullUp = new AtomicBoolean(false);
84 |
85 | @Override
86 | protected WebView createRefreshableView(Context context, AttributeSet attrs) {
87 | WebView webView = super.createRefreshableView(context, attrs);
88 |
89 | // Need to add JS Interface so we can get the response back
90 | mJsCallback = new JsValueCallback();
91 | webView.addJavascriptInterface(mJsCallback, JS_INTERFACE_PKG);
92 |
93 | return webView;
94 | }
95 |
96 | @Override
97 | protected boolean isReadyForPullStart() {
98 | // Call Javascript...
99 | getRefreshableView().loadUrl(DEF_JS_READY_PULL_DOWN_CALL);
100 |
101 | // Response will be given to JsValueCallback, which will update
102 | // mIsReadyForPullDown
103 |
104 | return mIsReadyForPullDown.get();
105 | }
106 |
107 | @Override
108 | protected boolean isReadyForPullEnd() {
109 | // Call Javascript...
110 | getRefreshableView().loadUrl(DEF_JS_READY_PULL_UP_CALL);
111 |
112 | // Response will be given to JsValueCallback, which will update
113 | // mIsReadyForPullUp
114 |
115 | return mIsReadyForPullUp.get();
116 | }
117 |
118 | /**
119 | * Used for response from Javascript
120 | *
121 | * @author Chris Banes
122 | */
123 | final class JsValueCallback {
124 |
125 | public void isReadyForPullUpResponse(boolean response) {
126 | mIsReadyForPullUp.set(response);
127 | }
128 |
129 | public void isReadyForPullDownResponse(boolean response) {
130 | mIsReadyForPullDown.set(response);
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/java/com/itheima/pulltorefreshlib/extras/SoundPullEventListener.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package com.itheima.pulltorefreshlib.extras;
17 |
18 | import android.content.Context;
19 | import android.media.MediaPlayer;
20 | import android.view.View;
21 |
22 | import com.itheima.pulltorefreshlib.PullToRefreshBase.Mode;
23 | import com.itheima.pulltorefreshlib.PullToRefreshBase.State;
24 | import com.itheima.pulltorefreshlib.PullToRefreshBase;
25 |
26 | import java.util.HashMap;
27 |
28 |
29 | public class SoundPullEventListener implements PullToRefreshBase.OnPullEventListener {
30 |
31 | private final Context mContext;
32 | private final HashMap mSoundMap;
33 |
34 | private MediaPlayer mCurrentMediaPlayer;
35 |
36 | /**
37 | * Constructor
38 | *
39 | * @param context - Context
40 | */
41 | public SoundPullEventListener(Context context) {
42 | mContext = context;
43 | mSoundMap = new HashMap();
44 | }
45 |
46 | @Override
47 | public final void onPullEvent(PullToRefreshBase refreshView, State event, Mode direction) {
48 | Integer soundResIdObj = mSoundMap.get(event);
49 | if (null != soundResIdObj) {
50 | playSound(soundResIdObj.intValue());
51 | }
52 | }
53 |
54 | /**
55 | * Set the Sounds to be played when a Pull Event happens. You specify which
56 | * sound plays for which events by calling this method multiple times for
57 | * each event.
58 | *
59 | * If you've already set a sound for a certain event, and add another sound
60 | * for that event, only the new sound will be played.
61 | *
62 | * @param event - The event for which the sound will be played.
63 | * @param resId - Resource Id of the sound file to be played (e.g.
64 | * R.raw.pull_sound)
65 | */
66 | public void addSoundEvent(State event, int resId) {
67 | mSoundMap.put(event, resId);
68 | }
69 |
70 | /**
71 | * Clears all of the previously set sounds and events.
72 | */
73 | public void clearSounds() {
74 | mSoundMap.clear();
75 | }
76 |
77 | /**
78 | * Gets the current (or last) MediaPlayer instance.
79 | */
80 | public MediaPlayer getCurrentMediaPlayer() {
81 | return mCurrentMediaPlayer;
82 | }
83 |
84 | private void playSound(int resId) {
85 | // Stop current player, if there's one playing
86 | if (null != mCurrentMediaPlayer) {
87 | mCurrentMediaPlayer.stop();
88 | mCurrentMediaPlayer.release();
89 | }
90 |
91 | mCurrentMediaPlayer = MediaPlayer.create(mContext, resId);
92 | if (null != mCurrentMediaPlayer) {
93 | mCurrentMediaPlayer.start();
94 | }
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/java/com/itheima/pulltorefreshlib/internal/EmptyViewMethodAccessor.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package com.itheima.pulltorefreshlib.internal;
17 |
18 | import android.view.View;
19 |
20 | /**
21 | * Interface that allows PullToRefreshBase to hijack the call to
22 | * AdapterView.setEmptyView()
23 | *
24 | * @author chris
25 | */
26 | public interface EmptyViewMethodAccessor {
27 |
28 | /**
29 | * Calls upto AdapterView.setEmptyView()
30 | *
31 | * @param emptyView - to set as Empty View
32 | */
33 | public void setEmptyViewInternal(View emptyView);
34 |
35 | /**
36 | * Should call PullToRefreshBase.setEmptyView() which will then
37 | * automatically call through to setEmptyViewInternal()
38 | *
39 | * @param emptyView - to set as Empty View
40 | */
41 | public void setEmptyView(View emptyView);
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/java/com/itheima/pulltorefreshlib/internal/FlipLoadingLayout.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package com.itheima.pulltorefreshlib.internal;
17 |
18 | import android.annotation.SuppressLint;
19 | import android.content.Context;
20 | import android.content.res.TypedArray;
21 | import android.graphics.Matrix;
22 | import android.graphics.drawable.Drawable;
23 | import android.view.View;
24 | import android.view.ViewGroup;
25 | import android.view.animation.Animation;
26 | import android.view.animation.RotateAnimation;
27 | import android.widget.ImageView.ScaleType;
28 |
29 | import com.itheima.pulltorefreshlib.PullToRefreshBase;
30 | import com.itheima.pulltorefreshlib.R;
31 |
32 |
33 | @SuppressLint("ViewConstructor")
34 | public class FlipLoadingLayout extends LoadingLayout {
35 |
36 | static final int FLIP_ANIMATION_DURATION = 150;
37 |
38 | private final Animation mRotateAnimation, mResetRotateAnimation;
39 |
40 | public FlipLoadingLayout(Context context, final PullToRefreshBase.Mode mode, final PullToRefreshBase.Orientation scrollDirection, TypedArray attrs) {
41 | super(context, mode, scrollDirection, attrs);
42 |
43 | final int rotateAngle = mode == PullToRefreshBase.Mode.PULL_FROM_START ? -180 : 180;
44 |
45 | mRotateAnimation = new RotateAnimation(0, rotateAngle, Animation.RELATIVE_TO_SELF, 0.5f,
46 | Animation.RELATIVE_TO_SELF, 0.5f);
47 | mRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR);
48 | mRotateAnimation.setDuration(FLIP_ANIMATION_DURATION);
49 | mRotateAnimation.setFillAfter(true);
50 |
51 | mResetRotateAnimation = new RotateAnimation(rotateAngle, 0, Animation.RELATIVE_TO_SELF, 0.5f,
52 | Animation.RELATIVE_TO_SELF, 0.5f);
53 | mResetRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR);
54 | mResetRotateAnimation.setDuration(FLIP_ANIMATION_DURATION);
55 | mResetRotateAnimation.setFillAfter(true);
56 | }
57 |
58 | @Override
59 | protected void onLoadingDrawableSet(Drawable imageDrawable) {
60 | if (null != imageDrawable) {
61 | final int dHeight = imageDrawable.getIntrinsicHeight();
62 | final int dWidth = imageDrawable.getIntrinsicWidth();
63 |
64 | /**
65 | * We need to set the width/height of the ImageView so that it is
66 | * square with each side the size of the largest drawable dimension.
67 | * This is so that it doesn't clip when rotated.
68 | */
69 | ViewGroup.LayoutParams lp = mHeaderImage.getLayoutParams();
70 | lp.width = lp.height = Math.max(dHeight, dWidth);
71 | mHeaderImage.requestLayout();
72 |
73 | /**
74 | * We now rotate the Drawable so that is at the correct rotation,
75 | * and is centered.
76 | */
77 | mHeaderImage.setScaleType(ScaleType.MATRIX);
78 | Matrix matrix = new Matrix();
79 | matrix.postTranslate((lp.width - dWidth) / 2f, (lp.height - dHeight) / 2f);
80 | matrix.postRotate(getDrawableRotationAngle(), lp.width / 2f, lp.height / 2f);
81 | mHeaderImage.setImageMatrix(matrix);
82 | }
83 | }
84 |
85 | @Override
86 | protected void onPullImpl(float scaleOfLayout) {
87 | // NO-OP
88 | }
89 |
90 | @Override
91 | protected void pullToRefreshImpl() {
92 | // Only start reset Animation, we've previously show the rotate anim
93 | if (mRotateAnimation == mHeaderImage.getAnimation()) {
94 | mHeaderImage.startAnimation(mResetRotateAnimation);
95 | }
96 | }
97 |
98 | @Override
99 | protected void refreshingImpl() {
100 | mHeaderImage.clearAnimation();
101 | mHeaderImage.setVisibility(View.INVISIBLE);
102 | mHeaderProgress.setVisibility(View.VISIBLE);
103 | }
104 |
105 | @Override
106 | protected void releaseToRefreshImpl() {
107 | mHeaderImage.startAnimation(mRotateAnimation);
108 | }
109 |
110 | @Override
111 | protected void resetImpl() {
112 | mHeaderImage.clearAnimation();
113 | mHeaderProgress.setVisibility(View.GONE);
114 | mHeaderImage.setVisibility(View.VISIBLE);
115 | }
116 |
117 | @Override
118 | protected int getDefaultDrawableResId() {
119 | return R.drawable.default_ptr_flip;
120 | }
121 |
122 | private float getDrawableRotationAngle() {
123 | float angle = 0f;
124 | switch (mMode) {
125 | case PULL_FROM_END:
126 | if (mScrollDirection == PullToRefreshBase.Orientation.HORIZONTAL) {
127 | angle = 90f;
128 | } else {
129 | angle = 180f;
130 | }
131 | break;
132 |
133 | case PULL_FROM_START:
134 | if (mScrollDirection == PullToRefreshBase.Orientation.HORIZONTAL) {
135 | angle = 270f;
136 | }
137 | break;
138 |
139 | default:
140 | break;
141 | }
142 |
143 | return angle;
144 | }
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/java/com/itheima/pulltorefreshlib/internal/IndicatorLayout.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package com.itheima.pulltorefreshlib.internal;
17 |
18 | import android.annotation.SuppressLint;
19 | import android.content.Context;
20 | import android.graphics.Matrix;
21 | import android.graphics.drawable.Drawable;
22 | import android.view.View;
23 | import android.view.animation.Animation;
24 | import android.view.animation.Animation.AnimationListener;
25 | import android.view.animation.AnimationUtils;
26 | import android.view.animation.Interpolator;
27 | import android.view.animation.LinearInterpolator;
28 | import android.view.animation.RotateAnimation;
29 | import android.widget.FrameLayout;
30 | import android.widget.ImageView;
31 | import android.widget.ImageView.ScaleType;
32 |
33 | import com.itheima.pulltorefreshlib.PullToRefreshBase;
34 | import com.itheima.pulltorefreshlib.R;
35 |
36 |
37 | @SuppressLint("ViewConstructor")
38 | public class IndicatorLayout extends FrameLayout implements AnimationListener {
39 |
40 | static final int DEFAULT_ROTATION_ANIMATION_DURATION = 150;
41 |
42 | private Animation mInAnim, mOutAnim;
43 | private ImageView mArrowImageView;
44 |
45 | private final Animation mRotateAnimation, mResetRotateAnimation;
46 |
47 | public IndicatorLayout(Context context, PullToRefreshBase.Mode mode) {
48 | super(context);
49 | mArrowImageView = new ImageView(context);
50 |
51 | Drawable arrowD = getResources().getDrawable(R.drawable.indicator_arrow);
52 | mArrowImageView.setImageDrawable(arrowD);
53 |
54 | final int padding = getResources().getDimensionPixelSize(R.dimen.indicator_internal_padding);
55 | mArrowImageView.setPadding(padding, padding, padding, padding);
56 | addView(mArrowImageView);
57 |
58 | int inAnimResId, outAnimResId;
59 | switch (mode) {
60 | case PULL_FROM_END:
61 | inAnimResId = R.anim.slide_in_from_bottom;
62 | outAnimResId = R.anim.slide_out_to_bottom;
63 | setBackgroundResource(R.drawable.indicator_bg_bottom);
64 |
65 | // Rotate Arrow so it's pointing the correct way
66 | mArrowImageView.setScaleType(ScaleType.MATRIX);
67 | Matrix matrix = new Matrix();
68 | matrix.setRotate(180f, arrowD.getIntrinsicWidth() / 2f, arrowD.getIntrinsicHeight() / 2f);
69 | mArrowImageView.setImageMatrix(matrix);
70 | break;
71 | default:
72 | case PULL_FROM_START:
73 | inAnimResId = R.anim.slide_in_from_top;
74 | outAnimResId = R.anim.slide_out_to_top;
75 | setBackgroundResource(R.drawable.indicator_bg_top);
76 | break;
77 | }
78 |
79 | mInAnim = AnimationUtils.loadAnimation(context, inAnimResId);
80 | mInAnim.setAnimationListener(this);
81 |
82 | mOutAnim = AnimationUtils.loadAnimation(context, outAnimResId);
83 | mOutAnim.setAnimationListener(this);
84 |
85 | final Interpolator interpolator = new LinearInterpolator();
86 | mRotateAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
87 | 0.5f);
88 | mRotateAnimation.setInterpolator(interpolator);
89 | mRotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION);
90 | mRotateAnimation.setFillAfter(true);
91 |
92 | mResetRotateAnimation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 0.5f,
93 | Animation.RELATIVE_TO_SELF, 0.5f);
94 | mResetRotateAnimation.setInterpolator(interpolator);
95 | mResetRotateAnimation.setDuration(DEFAULT_ROTATION_ANIMATION_DURATION);
96 | mResetRotateAnimation.setFillAfter(true);
97 |
98 | }
99 |
100 | public final boolean isVisible() {
101 | Animation currentAnim = getAnimation();
102 | if (null != currentAnim) {
103 | return mInAnim == currentAnim;
104 | }
105 |
106 | return getVisibility() == View.VISIBLE;
107 | }
108 |
109 | public void hide() {
110 | startAnimation(mOutAnim);
111 | }
112 |
113 | public void show() {
114 | mArrowImageView.clearAnimation();
115 | startAnimation(mInAnim);
116 | }
117 |
118 | @Override
119 | public void onAnimationEnd(Animation animation) {
120 | if (animation == mOutAnim) {
121 | mArrowImageView.clearAnimation();
122 | setVisibility(View.GONE);
123 | } else if (animation == mInAnim) {
124 | setVisibility(View.VISIBLE);
125 | }
126 |
127 | clearAnimation();
128 | }
129 |
130 | @Override
131 | public void onAnimationRepeat(Animation animation) {
132 | // NO-OP
133 | }
134 |
135 | @Override
136 | public void onAnimationStart(Animation animation) {
137 | setVisibility(View.VISIBLE);
138 | }
139 |
140 | public void releaseToRefresh() {
141 | mArrowImageView.startAnimation(mRotateAnimation);
142 | }
143 |
144 | public void pullToRefresh() {
145 | mArrowImageView.startAnimation(mResetRotateAnimation);
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/java/com/itheima/pulltorefreshlib/internal/LoadingLayout.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package com.itheima.pulltorefreshlib.internal;
17 |
18 | import android.annotation.SuppressLint;
19 | import android.content.Context;
20 | import android.content.res.ColorStateList;
21 | import android.content.res.TypedArray;
22 | import android.graphics.Typeface;
23 | import android.graphics.drawable.AnimationDrawable;
24 | import android.graphics.drawable.Drawable;
25 | import android.text.TextUtils;
26 | import android.util.TypedValue;
27 | import android.view.Gravity;
28 | import android.view.LayoutInflater;
29 | import android.view.View;
30 | import android.view.ViewGroup;
31 | import android.view.animation.Interpolator;
32 | import android.view.animation.LinearInterpolator;
33 | import android.widget.FrameLayout;
34 | import android.widget.ImageView;
35 | import android.widget.ProgressBar;
36 | import android.widget.TextView;
37 |
38 | import com.itheima.pulltorefreshlib.ILoadingLayout;
39 | import com.itheima.pulltorefreshlib.PullToRefreshBase;
40 | import com.itheima.pulltorefreshlib.R;
41 |
42 |
43 | @SuppressLint("ViewConstructor")
44 | public abstract class LoadingLayout extends FrameLayout implements ILoadingLayout {
45 |
46 | static final String LOG_TAG = "PullToRefresh-LoadingLayout";
47 |
48 | static final Interpolator ANIMATION_INTERPOLATOR = new LinearInterpolator();
49 |
50 | private FrameLayout mInnerLayout;
51 |
52 | protected final ImageView mHeaderImage;
53 | protected final ProgressBar mHeaderProgress;
54 |
55 | private boolean mUseIntrinsicAnimation;
56 |
57 | private final TextView mHeaderText;
58 | private final TextView mSubHeaderText;
59 |
60 | protected final PullToRefreshBase.Mode mMode;
61 | protected final PullToRefreshBase.Orientation mScrollDirection;
62 |
63 | private CharSequence mPullLabel;
64 | private CharSequence mRefreshingLabel;
65 | private CharSequence mReleaseLabel;
66 |
67 | public LoadingLayout(Context context, final PullToRefreshBase.Mode mode, final PullToRefreshBase.Orientation scrollDirection, TypedArray attrs) {
68 | super(context);
69 | mMode = mode;
70 | mScrollDirection = scrollDirection;
71 |
72 | switch (scrollDirection) {
73 | case HORIZONTAL:
74 | LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_horizontal, this);
75 | break;
76 | case VERTICAL:
77 | default:
78 | LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_vertical, this);
79 | break;
80 | }
81 |
82 | mInnerLayout = (FrameLayout) findViewById(R.id.fl_inner);
83 | mHeaderText = (TextView) mInnerLayout.findViewById(R.id.pull_to_refresh_text);
84 | mHeaderProgress = (ProgressBar) mInnerLayout.findViewById(R.id.pull_to_refresh_progress);
85 | mSubHeaderText = (TextView) mInnerLayout.findViewById(R.id.pull_to_refresh_sub_text);
86 | mHeaderImage = (ImageView) mInnerLayout.findViewById(R.id.pull_to_refresh_image);
87 |
88 | LayoutParams lp = (LayoutParams) mInnerLayout.getLayoutParams();
89 |
90 | switch (mode) {
91 | case PULL_FROM_END:
92 | lp.gravity = scrollDirection == PullToRefreshBase.Orientation.VERTICAL ? Gravity.TOP : Gravity.LEFT;
93 |
94 | // Load in labels
95 | mPullLabel = context.getString(R.string.pull_to_refresh_from_bottom_pull_label);
96 | mRefreshingLabel = context.getString(R.string.pull_to_refresh_from_bottom_refreshing_label);
97 | mReleaseLabel = context.getString(R.string.pull_to_refresh_from_bottom_release_label);
98 | break;
99 |
100 | case PULL_FROM_START:
101 | default:
102 | lp.gravity = scrollDirection == PullToRefreshBase.Orientation.VERTICAL ? Gravity.BOTTOM : Gravity.RIGHT;
103 |
104 | // Load in labels
105 | mPullLabel = context.getString(R.string.pull_to_refresh_pull_label);
106 | mRefreshingLabel = context.getString(R.string.pull_to_refresh_refreshing_label);
107 | mReleaseLabel = context.getString(R.string.pull_to_refresh_release_label);
108 | break;
109 | }
110 |
111 | if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderBackground)) {
112 | Drawable background = attrs.getDrawable(R.styleable.PullToRefresh_ptrHeaderBackground);
113 | if (null != background) {
114 | ViewCompat.setBackground(this, background);
115 | }
116 | }
117 |
118 | if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderTextAppearance)) {
119 | TypedValue styleID = new TypedValue();
120 | attrs.getValue(R.styleable.PullToRefresh_ptrHeaderTextAppearance, styleID);
121 | setTextAppearance(styleID.data);
122 | }
123 | if (attrs.hasValue(R.styleable.PullToRefresh_ptrSubHeaderTextAppearance)) {
124 | TypedValue styleID = new TypedValue();
125 | attrs.getValue(R.styleable.PullToRefresh_ptrSubHeaderTextAppearance, styleID);
126 | setSubTextAppearance(styleID.data);
127 | }
128 |
129 | // Text Color attrs need to be set after TextAppearance attrs
130 | if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderTextColor)) {
131 | ColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderTextColor);
132 | if (null != colors) {
133 | setTextColor(colors);
134 | }
135 | }
136 | if (attrs.hasValue(R.styleable.PullToRefresh_ptrHeaderSubTextColor)) {
137 | ColorStateList colors = attrs.getColorStateList(R.styleable.PullToRefresh_ptrHeaderSubTextColor);
138 | if (null != colors) {
139 | setSubTextColor(colors);
140 | }
141 | }
142 |
143 | // Try and get defined drawable from Attrs
144 | Drawable imageDrawable = null;
145 | if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawable)) {
146 | imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawable);
147 | }
148 |
149 | // Check Specific Drawable from Attrs, these overrite the generic
150 | // drawable attr above
151 | switch (mode) {
152 | case PULL_FROM_START:
153 | default:
154 | if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableStart)) {
155 | imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableStart);
156 | } else if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableTop)) {
157 | Utils.warnDeprecation("ptrDrawableTop", "ptrDrawableStart");
158 | imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableTop);
159 | }
160 | break;
161 |
162 | case PULL_FROM_END:
163 | if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableEnd)) {
164 | imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableEnd);
165 | } else if (attrs.hasValue(R.styleable.PullToRefresh_ptrDrawableBottom)) {
166 | Utils.warnDeprecation("ptrDrawableBottom", "ptrDrawableEnd");
167 | imageDrawable = attrs.getDrawable(R.styleable.PullToRefresh_ptrDrawableBottom);
168 | }
169 | break;
170 | }
171 |
172 | // If we don't have a user defined drawable, load the default
173 | if (null == imageDrawable) {
174 | imageDrawable = context.getResources().getDrawable(getDefaultDrawableResId());
175 | }
176 |
177 | // Set Drawable, and save width/height
178 | setLoadingDrawable(imageDrawable);
179 |
180 | reset();
181 | }
182 |
183 | public final void setHeight(int height) {
184 | ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams();
185 | lp.height = height;
186 | requestLayout();
187 | }
188 |
189 | public final void setWidth(int width) {
190 | ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams();
191 | lp.width = width;
192 | requestLayout();
193 | }
194 |
195 | public final int getContentSize() {
196 | switch (mScrollDirection) {
197 | case HORIZONTAL:
198 | return mInnerLayout.getWidth();
199 | case VERTICAL:
200 | default:
201 | return mInnerLayout.getHeight();
202 | }
203 | }
204 |
205 | public final void hideAllViews() {
206 | if (View.VISIBLE == mHeaderText.getVisibility()) {
207 | mHeaderText.setVisibility(View.INVISIBLE);
208 | }
209 | if (View.VISIBLE == mHeaderProgress.getVisibility()) {
210 | mHeaderProgress.setVisibility(View.INVISIBLE);
211 | }
212 | if (View.VISIBLE == mHeaderImage.getVisibility()) {
213 | mHeaderImage.setVisibility(View.INVISIBLE);
214 | }
215 | if (View.VISIBLE == mSubHeaderText.getVisibility()) {
216 | mSubHeaderText.setVisibility(View.INVISIBLE);
217 | }
218 | }
219 |
220 | public final void onPull(float scaleOfLayout) {
221 | if (!mUseIntrinsicAnimation) {
222 | onPullImpl(scaleOfLayout);
223 | }
224 | }
225 |
226 | public final void pullToRefresh() {
227 | if (null != mHeaderText) {
228 | mHeaderText.setText(mPullLabel);
229 | }
230 |
231 | // Now call the callback
232 | pullToRefreshImpl();
233 | }
234 |
235 | public final void refreshing() {
236 | if (null != mHeaderText) {
237 | mHeaderText.setText(mRefreshingLabel);
238 | }
239 |
240 | if (mUseIntrinsicAnimation) {
241 | ((AnimationDrawable) mHeaderImage.getDrawable()).start();
242 | } else {
243 | // Now call the callback
244 | refreshingImpl();
245 | }
246 |
247 | if (null != mSubHeaderText) {
248 | mSubHeaderText.setVisibility(View.GONE);
249 | }
250 | }
251 |
252 | public final void releaseToRefresh() {
253 | if (null != mHeaderText) {
254 | mHeaderText.setText(mReleaseLabel);
255 | }
256 |
257 | // Now call the callback
258 | releaseToRefreshImpl();
259 | }
260 |
261 | public final void reset() {
262 | if (null != mHeaderText) {
263 | mHeaderText.setText(mPullLabel);
264 | }
265 | mHeaderImage.setVisibility(View.VISIBLE);
266 |
267 | if (mUseIntrinsicAnimation) {
268 | ((AnimationDrawable) mHeaderImage.getDrawable()).stop();
269 | } else {
270 | // Now call the callback
271 | resetImpl();
272 | }
273 |
274 | if (null != mSubHeaderText) {
275 | if (TextUtils.isEmpty(mSubHeaderText.getText())) {
276 | mSubHeaderText.setVisibility(View.GONE);
277 | } else {
278 | mSubHeaderText.setVisibility(View.VISIBLE);
279 | }
280 | }
281 | }
282 |
283 | @Override
284 | public void setLastUpdatedLabel(CharSequence label) {
285 | setSubHeaderText(label);
286 | }
287 |
288 | public final void setLoadingDrawable(Drawable imageDrawable) {
289 | // Set Drawable
290 | mHeaderImage.setImageDrawable(imageDrawable);
291 | mUseIntrinsicAnimation = (imageDrawable instanceof AnimationDrawable);
292 |
293 | // Now call the callback
294 | onLoadingDrawableSet(imageDrawable);
295 | }
296 |
297 | public void setPullLabel(CharSequence pullLabel) {
298 | mPullLabel = pullLabel;
299 | }
300 |
301 | public void setRefreshingLabel(CharSequence refreshingLabel) {
302 | mRefreshingLabel = refreshingLabel;
303 | }
304 |
305 | public void setReleaseLabel(CharSequence releaseLabel) {
306 | mReleaseLabel = releaseLabel;
307 | }
308 |
309 | @Override
310 | public void setTextTypeface(Typeface tf) {
311 | mHeaderText.setTypeface(tf);
312 | }
313 |
314 | public final void showInvisibleViews() {
315 | if (View.INVISIBLE == mHeaderText.getVisibility()) {
316 | mHeaderText.setVisibility(View.VISIBLE);
317 | }
318 | if (View.INVISIBLE == mHeaderProgress.getVisibility()) {
319 | mHeaderProgress.setVisibility(View.VISIBLE);
320 | }
321 | if (View.INVISIBLE == mHeaderImage.getVisibility()) {
322 | mHeaderImage.setVisibility(View.VISIBLE);
323 | }
324 | if (View.INVISIBLE == mSubHeaderText.getVisibility()) {
325 | mSubHeaderText.setVisibility(View.VISIBLE);
326 | }
327 | }
328 |
329 | /**
330 | * Callbacks for derivative Layouts
331 | */
332 |
333 | protected abstract int getDefaultDrawableResId();
334 |
335 | protected abstract void onLoadingDrawableSet(Drawable imageDrawable);
336 |
337 | protected abstract void onPullImpl(float scaleOfLayout);
338 |
339 | protected abstract void pullToRefreshImpl();
340 |
341 | protected abstract void refreshingImpl();
342 |
343 | protected abstract void releaseToRefreshImpl();
344 |
345 | protected abstract void resetImpl();
346 |
347 | private void setSubHeaderText(CharSequence label) {
348 | if (null != mSubHeaderText) {
349 | if (TextUtils.isEmpty(label)) {
350 | mSubHeaderText.setVisibility(View.GONE);
351 | } else {
352 | mSubHeaderText.setText(label);
353 |
354 | // Only set it to Visible if we're GONE, otherwise VISIBLE will
355 | // be set soon
356 | if (View.GONE == mSubHeaderText.getVisibility()) {
357 | mSubHeaderText.setVisibility(View.VISIBLE);
358 | }
359 | }
360 | }
361 | }
362 |
363 | private void setSubTextAppearance(int value) {
364 | if (null != mSubHeaderText) {
365 | mSubHeaderText.setTextAppearance(getContext(), value);
366 | }
367 | }
368 |
369 | private void setSubTextColor(ColorStateList color) {
370 | if (null != mSubHeaderText) {
371 | mSubHeaderText.setTextColor(color);
372 | }
373 | }
374 |
375 | private void setTextAppearance(int value) {
376 | if (null != mHeaderText) {
377 | mHeaderText.setTextAppearance(getContext(), value);
378 | }
379 | if (null != mSubHeaderText) {
380 | mSubHeaderText.setTextAppearance(getContext(), value);
381 | }
382 | }
383 |
384 | private void setTextColor(ColorStateList color) {
385 | if (null != mHeaderText) {
386 | mHeaderText.setTextColor(color);
387 | }
388 | if (null != mSubHeaderText) {
389 | mSubHeaderText.setTextColor(color);
390 | }
391 | }
392 |
393 | }
394 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/java/com/itheima/pulltorefreshlib/internal/RotateLoadingLayout.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package com.itheima.pulltorefreshlib.internal;
17 |
18 | import android.content.Context;
19 | import android.content.res.TypedArray;
20 | import android.graphics.Matrix;
21 | import android.graphics.drawable.Drawable;
22 | import android.view.animation.Animation;
23 | import android.view.animation.RotateAnimation;
24 | import android.widget.ImageView.ScaleType;
25 |
26 | import com.itheima.pulltorefreshlib.PullToRefreshBase;
27 | import com.itheima.pulltorefreshlib.R;
28 |
29 |
30 | public class RotateLoadingLayout extends LoadingLayout {
31 |
32 | static final int ROTATION_ANIMATION_DURATION = 1200;
33 |
34 | private final Animation mRotateAnimation;
35 | private final Matrix mHeaderImageMatrix;
36 |
37 | private float mRotationPivotX, mRotationPivotY;
38 |
39 | private final boolean mRotateDrawableWhilePulling;
40 |
41 | public RotateLoadingLayout(Context context, PullToRefreshBase.Mode mode, PullToRefreshBase.Orientation scrollDirection, TypedArray attrs) {
42 | super(context, mode, scrollDirection, attrs);
43 |
44 | mRotateDrawableWhilePulling = attrs.getBoolean(R.styleable.PullToRefresh_ptrRotateDrawableWhilePulling, true);
45 |
46 | mHeaderImage.setScaleType(ScaleType.MATRIX);
47 | mHeaderImageMatrix = new Matrix();
48 | mHeaderImage.setImageMatrix(mHeaderImageMatrix);
49 |
50 | mRotateAnimation = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
51 | 0.5f);
52 | mRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR);
53 | mRotateAnimation.setDuration(ROTATION_ANIMATION_DURATION);
54 | mRotateAnimation.setRepeatCount(Animation.INFINITE);
55 | mRotateAnimation.setRepeatMode(Animation.RESTART);
56 | }
57 |
58 | public void onLoadingDrawableSet(Drawable imageDrawable) {
59 | if (null != imageDrawable) {
60 | mRotationPivotX = Math.round(imageDrawable.getIntrinsicWidth() / 2f);
61 | mRotationPivotY = Math.round(imageDrawable.getIntrinsicHeight() / 2f);
62 | }
63 | }
64 |
65 | protected void onPullImpl(float scaleOfLayout) {
66 | float angle;
67 | if (mRotateDrawableWhilePulling) {
68 | angle = scaleOfLayout * 90f;
69 | } else {
70 | angle = Math.max(0f, Math.min(180f, scaleOfLayout * 360f - 180f));
71 | }
72 |
73 | mHeaderImageMatrix.setRotate(angle, mRotationPivotX, mRotationPivotY);
74 | mHeaderImage.setImageMatrix(mHeaderImageMatrix);
75 | }
76 |
77 | @Override
78 | protected void refreshingImpl() {
79 | mHeaderImage.startAnimation(mRotateAnimation);
80 | }
81 |
82 | @Override
83 | protected void resetImpl() {
84 | mHeaderImage.clearAnimation();
85 | resetImageRotation();
86 | }
87 |
88 | private void resetImageRotation() {
89 | if (null != mHeaderImageMatrix) {
90 | mHeaderImageMatrix.reset();
91 | mHeaderImage.setImageMatrix(mHeaderImageMatrix);
92 | }
93 | }
94 |
95 | @Override
96 | protected void pullToRefreshImpl() {
97 | // NO-OP
98 | }
99 |
100 | @Override
101 | protected void releaseToRefreshImpl() {
102 | // NO-OP
103 | }
104 |
105 | @Override
106 | protected int getDefaultDrawableResId() {
107 | return R.drawable.default_ptr_rotate;
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/java/com/itheima/pulltorefreshlib/internal/Utils.java:
--------------------------------------------------------------------------------
1 | package com.itheima.pulltorefreshlib.internal;
2 |
3 | import android.util.Log;
4 |
5 | public class Utils {
6 |
7 | static final String LOG_TAG = "PullToRefresh";
8 |
9 | public static void warnDeprecation(String depreacted, String replacement) {
10 | Log.w(LOG_TAG, "You're using the deprecated " + depreacted + " attr, please switch over to " + replacement);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/java/com/itheima/pulltorefreshlib/internal/ViewCompat.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package com.itheima.pulltorefreshlib.internal;
17 |
18 | import android.annotation.TargetApi;
19 | import android.graphics.drawable.Drawable;
20 | import android.os.Build.VERSION;
21 | import android.os.Build.VERSION_CODES;
22 | import android.view.View;
23 |
24 | @SuppressWarnings("deprecation")
25 | public class ViewCompat {
26 |
27 | public static void postOnAnimation(View view, Runnable runnable) {
28 | if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
29 | SDK16.postOnAnimation(view, runnable);
30 | } else {
31 | view.postDelayed(runnable, 16);
32 | }
33 | }
34 |
35 | public static void setBackground(View view, Drawable background) {
36 | if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
37 | SDK16.setBackground(view, background);
38 | } else {
39 | view.setBackgroundDrawable(background);
40 | }
41 | }
42 |
43 | public static void setLayerType(View view, int layerType) {
44 | if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
45 | SDK11.setLayerType(view, layerType);
46 | }
47 | }
48 |
49 | @TargetApi(11)
50 | static class SDK11 {
51 |
52 | public static void setLayerType(View view, int layerType) {
53 | view.setLayerType(layerType, null);
54 | }
55 | }
56 |
57 | @TargetApi(16)
58 | static class SDK16 {
59 |
60 | public static void postOnAnimation(View view, Runnable runnable) {
61 | view.postOnAnimation(runnable);
62 | }
63 |
64 | public static void setBackground(View view, Drawable background) {
65 | view.setBackground(background);
66 | }
67 |
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/anim/slide_in_from_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
22 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/anim/slide_in_from_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
22 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/anim/slide_out_to_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
22 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/anim/slide_out_to_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
22 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/drawable-hdpi/default_ptr_flip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/PullToRefresh/ffbcc1572ea38f63d63ed20ecf8efc60c87aa567/pulltorefreshlib/src/main/res/drawable-hdpi/default_ptr_flip.png
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/drawable-hdpi/default_ptr_rotate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/PullToRefresh/ffbcc1572ea38f63d63ed20ecf8efc60c87aa567/pulltorefreshlib/src/main/res/drawable-hdpi/default_ptr_rotate.png
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/drawable-hdpi/indicator_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/PullToRefresh/ffbcc1572ea38f63d63ed20ecf8efc60c87aa567/pulltorefreshlib/src/main/res/drawable-hdpi/indicator_arrow.png
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/drawable-mdpi/default_ptr_flip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/PullToRefresh/ffbcc1572ea38f63d63ed20ecf8efc60c87aa567/pulltorefreshlib/src/main/res/drawable-mdpi/default_ptr_flip.png
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/drawable-mdpi/default_ptr_rotate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/PullToRefresh/ffbcc1572ea38f63d63ed20ecf8efc60c87aa567/pulltorefreshlib/src/main/res/drawable-mdpi/default_ptr_rotate.png
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/drawable-mdpi/indicator_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/PullToRefresh/ffbcc1572ea38f63d63ed20ecf8efc60c87aa567/pulltorefreshlib/src/main/res/drawable-mdpi/indicator_arrow.png
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/drawable-xhdpi/default_ptr_flip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/PullToRefresh/ffbcc1572ea38f63d63ed20ecf8efc60c87aa567/pulltorefreshlib/src/main/res/drawable-xhdpi/default_ptr_flip.png
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/drawable-xhdpi/default_ptr_rotate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/PullToRefresh/ffbcc1572ea38f63d63ed20ecf8efc60c87aa567/pulltorefreshlib/src/main/res/drawable-xhdpi/default_ptr_rotate.png
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/drawable-xhdpi/indicator_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/PullToRefresh/ffbcc1572ea38f63d63ed20ecf8efc60c87aa567/pulltorefreshlib/src/main/res/drawable-xhdpi/indicator_arrow.png
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/drawable/indicator_bg_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
11 |
17 |
18 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/drawable/indicator_bg_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
11 |
17 |
18 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/layout/pull_to_refresh_header_horizontal.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
18 |
19 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/layout/pull_to_refresh_header_vertical.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
17 |
18 |
23 |
24 |
32 |
33 |
34 |
40 |
41 |
48 |
49 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-ar/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | اسحب للتحديث…
4 | اترك للتحديث…
5 | تحميل…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-cs/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Tažením aktualizujete…
4 | Uvolněním aktualizujete…
5 | Načítání…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-de/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Ziehen zum Aktualisieren…
4 | Loslassen zum Aktualisieren…
5 | Laden…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-es/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Tirar para actualizar…
4 | Soltar para actualizar…
5 | Cargando…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-fi/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Päivitä vetämällä alas…
5 | Päivitä vapauttamalla…
6 | Päivitetään…
7 |
8 |
9 | Päivitä vetämällä ylös…
10 | @string/pull_to_refresh_release_label
11 | @string/pull_to_refresh_refreshing_label
12 |
13 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-fr/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Tirez pour rafraîchir…
4 | Relâcher pour rafraîchir…
5 | Chargement…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-he/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | משוך לרענון…
4 | שחרר לרענון…
5 | טוען…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-it/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Tira per aggiornare…
4 | Rilascia per aggionare…
5 | Caricamento…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-iw/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | משוך לרענון…
4 | שחרר לרענון…
5 | טוען…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-ja/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 画面を引っ張って…
4 | 指を離して更新…
5 | 読み込み中…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-ko/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 당겨서 새로 고침…
4 | 놓아서 새로 고침…
5 | 로드 중…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-nl/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sleep om te vernieuwen…
4 | Loslaten om te vernieuwen…
5 | Laden…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-pl/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Pociągnij, aby odświeżyć…
4 | Puść, aby odświeżyć…
5 | Wczytywanie…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-pt-rBR/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Puxe para atualizar…
4 | Libere para atualizar…
5 | Carregando…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-pt/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Puxe para atualizar…
4 | Liberação para atualizar…
5 | A carregar…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-ro/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Trage pentru a reîmprospăta…
4 | Eliberează pentru a reîmprospăta…
5 | Încărcare…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-ru/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Потяните для обновления…
4 | Отпустите для обновления…
5 | Загрузка…
6 |
7 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values-zh/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 下拉刷新…
4 | 放开以刷新…
5 | 正在载入…
6 |
7 | 上拉加载更多…
8 | 放开以加载…
9 | 正在加载…
10 |
11 |
12 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
66 |
67 |
68 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 10dp
5 | 12dp
6 | 4dp
7 | 24dp
8 | 12dp
9 |
10 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values/pull_refresh_strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Pull to refresh…
5 | Release to refresh…
6 | Loading…
7 |
8 |
9 | @string/pull_to_refresh_pull_label
10 | @string/pull_to_refresh_release_label
11 | @string/pull_to_refresh_refreshing_label
12 |
13 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | PullToRefreshLib
3 |
4 |
--------------------------------------------------------------------------------
/pulltorefreshlib/src/test/java/com/itheima/pulltorefreshlib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.itheima.pulltorefreshlib;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':pulltorefreshlib'
2 |
--------------------------------------------------------------------------------