admin
2020-10-13 69edda8e18b747039488d8e68aec51ba6a966073
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*******************************************************************************
 * 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);
        }
    }
}