Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser; | 5 package org.chromium.chrome.browser; |
| 6 | 6 |
| 7 import android.content.Context; | 7 import android.content.Context; |
| 8 import android.view.ViewGroup; | |
| 8 import android.view.ViewGroup.LayoutParams; | 9 import android.view.ViewGroup.LayoutParams; |
| 9 | 10 |
| 10 import org.chromium.base.TraceEvent; | 11 import org.chromium.base.TraceEvent; |
| 12 import org.chromium.base.annotations.CalledByNative; | |
| 11 import org.chromium.base.metrics.RecordUserAction; | 13 import org.chromium.base.metrics.RecordUserAction; |
| 12 import org.chromium.chrome.R; | 14 import org.chromium.chrome.R; |
| 13 import org.chromium.chrome.browser.tab.Tab; | 15 import org.chromium.chrome.browser.tab.Tab; |
| 14 import org.chromium.content.browser.ContentViewCore; | |
| 15 import org.chromium.content.browser.OverscrollRefreshHandler; | 16 import org.chromium.content.browser.OverscrollRefreshHandler; |
| 17 import org.chromium.content_public.browser.WebContents; | |
| 16 import org.chromium.third_party.android.swiperefresh.SwipeRefreshLayout; | 18 import org.chromium.third_party.android.swiperefresh.SwipeRefreshLayout; |
| 17 | 19 |
| 18 /** | 20 /** |
| 19 * An overscroll handler implemented in terms a modified version of the Android | 21 * An overscroll handler implemented in terms a modified version of the Android |
| 20 * compat library's SwipeRefreshLayout effect. | 22 * compat library's SwipeRefreshLayout effect. |
| 21 */ | 23 */ |
| 22 public class SwipeRefreshHandler implements OverscrollRefreshHandler { | 24 public class SwipeRefreshHandler implements OverscrollRefreshHandler { |
| 23 // Synthetic delay between the {@link #didStopRefreshing()} signal and the | 25 // Synthetic delay between the {@link #didStopRefreshing()} signal and the |
| 24 // call to stop the refresh animation. | 26 // call to stop the refresh animation. |
| 25 private static final int STOP_REFRESH_ANIMATION_DELAY_MS = 500; | 27 private static final int STOP_REFRESH_ANIMATION_DELAY_MS = 500; |
| 26 | 28 |
| 27 // Max allowed duration of the refresh animation after a refresh signal, | 29 // Max allowed duration of the refresh animation after a refresh signal, |
| 28 // guarding against cases where the page reload fails or takes too long. | 30 // guarding against cases where the page reload fails or takes too long. |
| 29 private static final int MAX_REFRESH_ANIMATION_DURATION_MS = 7500; | 31 private static final int MAX_REFRESH_ANIMATION_DURATION_MS = 7500; |
| 30 | 32 |
| 31 // The modified AppCompat version of the refresh effect, handling all core | 33 // The modified AppCompat version of the refresh effect, handling all core |
| 32 // logic, rendering and animation. | 34 // logic, rendering and animation. |
| 33 private final SwipeRefreshLayout mSwipeRefreshLayout; | 35 private final SwipeRefreshLayout mSwipeRefreshLayout; |
| 34 | 36 |
| 35 // The Tab where the swipe occurs. | 37 // The Tab where the swipe occurs. |
| 36 private Tab mTab; | 38 private Tab mTab; |
| 37 | 39 |
| 38 // The ContentViewCore with which the handler is associated. The handler | 40 // The container view the SwipeRefreshHandler instance is currently |
| 39 // will set/unset itself as the default OverscrollRefreshHandler as the | 41 // associated with. |
| 40 // association changes. | 42 private ViewGroup mContainerView; |
| 41 private ContentViewCore mContentViewCore; | |
| 42 | 43 |
| 43 // Async runnable for ending the refresh animation after the page first | 44 // Async runnable for ending the refresh animation after the page first |
| 44 // loads a frame. This is used to provide a reasonable minimum animation tim e. | 45 // loads a frame. This is used to provide a reasonable minimum animation tim e. |
| 45 private Runnable mStopRefreshingRunnable; | 46 private Runnable mStopRefreshingRunnable; |
| 46 | 47 |
| 47 // Handles removing the layout from the view hierarchy. This is posted to e nsure it does not | 48 // Handles removing the layout from the view hierarchy. This is posted to e nsure it does not |
| 48 // conflict with pending Android draws. | 49 // conflict with pending Android draws. |
| 49 private Runnable mDetachLayoutRunnable; | 50 private Runnable mDetachLayoutRunnable; |
| 50 | 51 |
| 51 // Accessibility utterance used to indicate refresh activation. | 52 // Accessibility utterance used to indicate refresh activation. |
| 52 private String mAccessibilityRefreshString; | 53 private String mAccessibilityRefreshString; |
| 53 | 54 |
| 54 /** | 55 /** |
| 55 * Simple constructor to use when creating an OverscrollRefresh instance fro m code. | 56 * Simple constructor to use when creating an OverscrollRefresh instance fro m code. |
| 56 * | 57 * |
| 57 * @param context The associated context. | 58 * @param context The associated context. |
| 58 * @param tab The Tab where the swipe occurs. | 59 * @param tab The Tab where the swipe occurs. |
| 59 */ | 60 */ |
| 60 public SwipeRefreshHandler(Context context, Tab tab) { | 61 public SwipeRefreshHandler(final Context context, Tab tab, WebContents webCo ntents) { |
|
Ted C
2016/12/01 00:53:56
no need to pass in WebContents, mTab.getWebContent
| |
| 61 mTab = tab; | 62 mTab = tab; |
| 62 mContentViewCore = mTab.getContentViewCore(); | 63 mContainerView = mTab.getContentViewCore().getContainerView(); |
| 63 | 64 |
| 64 mSwipeRefreshLayout = new SwipeRefreshLayout(context); | 65 mSwipeRefreshLayout = new SwipeRefreshLayout(context); |
| 65 mSwipeRefreshLayout.setLayoutParams( | 66 mSwipeRefreshLayout.setLayoutParams( |
| 66 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_P ARENT)); | 67 new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_P ARENT)); |
| 67 mSwipeRefreshLayout.setColorSchemeResources(R.color.light_active_color); | 68 mSwipeRefreshLayout.setColorSchemeResources(R.color.light_active_color); |
| 68 // SwipeRefreshLayout.LARGE layouts appear broken on JellyBean. | 69 // SwipeRefreshLayout.LARGE layouts appear broken on JellyBean. |
| 69 mSwipeRefreshLayout.setSize(SwipeRefreshLayout.DEFAULT); | 70 mSwipeRefreshLayout.setSize(SwipeRefreshLayout.DEFAULT); |
| 70 mSwipeRefreshLayout.setEnabled(false); | 71 mSwipeRefreshLayout.setEnabled(false); |
| 71 | 72 |
| 72 setEnabled(true); | 73 setEnabled(true); |
| 73 mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefres hListener() { | 74 mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefres hListener() { |
| 74 @Override | 75 @Override |
| 75 public void onRefresh() { | 76 public void onRefresh() { |
| 76 cancelStopRefreshingRunnable(); | 77 cancelStopRefreshingRunnable(); |
| 77 mSwipeRefreshLayout.postDelayed( | 78 mSwipeRefreshLayout.postDelayed( |
| 78 getStopRefreshingRunnable(), MAX_REFRESH_ANIMATION_DURAT ION_MS); | 79 getStopRefreshingRunnable(), MAX_REFRESH_ANIMATION_DURAT ION_MS); |
| 79 if (mAccessibilityRefreshString == null) { | 80 if (mAccessibilityRefreshString == null) { |
| 80 int resId = R.string.accessibility_swipe_refresh; | 81 int resId = R.string.accessibility_swipe_refresh; |
| 81 mAccessibilityRefreshString = | 82 mAccessibilityRefreshString = context.getResources().getStri ng(resId); |
| 82 mContentViewCore.getContext().getResources().getStri ng(resId); | |
| 83 } | 83 } |
| 84 mSwipeRefreshLayout.announceForAccessibility(mAccessibilityRefre shString); | 84 mSwipeRefreshLayout.announceForAccessibility(mAccessibilityRefre shString); |
| 85 mTab.reload(); | 85 mTab.reload(); |
| 86 RecordUserAction.record("MobilePullGestureReload"); | 86 RecordUserAction.record("MobilePullGestureReload"); |
| 87 } | 87 } |
| 88 }); | 88 }); |
| 89 mSwipeRefreshLayout.setOnResetListener(new SwipeRefreshLayout.OnResetLis tener() { | 89 mSwipeRefreshLayout.setOnResetListener(new SwipeRefreshLayout.OnResetLis tener() { |
| 90 @Override | 90 @Override |
| 91 public void onReset() { | 91 public void onReset() { |
| 92 if (mDetachLayoutRunnable != null) return; | 92 if (mDetachLayoutRunnable != null) return; |
| 93 mDetachLayoutRunnable = new Runnable() { | 93 mDetachLayoutRunnable = new Runnable() { |
| 94 @Override | 94 @Override |
| 95 public void run() { | 95 public void run() { |
| 96 mDetachLayoutRunnable = null; | 96 mDetachLayoutRunnable = null; |
| 97 detachSwipeRefreshLayoutIfNecessary(); | 97 detachSwipeRefreshLayoutIfNecessary(); |
| 98 } | 98 } |
| 99 }; | 99 }; |
| 100 mSwipeRefreshLayout.post(mDetachLayoutRunnable); | 100 mSwipeRefreshLayout.post(mDetachLayoutRunnable); |
| 101 } | 101 } |
| 102 }); | 102 }); |
| 103 | 103 webContents.setOverscrollRefreshHandler(this); |
| 104 mContentViewCore.setOverscrollRefreshHandler(this); | |
| 105 } | 104 } |
| 106 | 105 |
| 107 /** | 106 /** |
| 108 * Destroys and cleans up itself. | 107 * Destroys and cleans up itself. |
| 109 */ | 108 */ |
| 110 public void destroy() { | 109 public void destroy() { |
| 111 setEnabled(false); | 110 setEnabled(false); |
| 112 cancelStopRefreshingRunnable(); | 111 cancelStopRefreshingRunnable(); |
| 113 mSwipeRefreshLayout.setOnRefreshListener(null); | 112 mSwipeRefreshLayout.setOnRefreshListener(null); |
| 114 mContentViewCore.setOverscrollRefreshHandler(null); | |
| 115 } | 113 } |
| 116 | 114 |
| 117 /** | 115 /** |
| 118 * Notify the SwipeRefreshLayout that a refresh action has completed. | 116 * Notify the SwipeRefreshLayout that a refresh action has completed. |
| 119 * Defer the notification by a reasonable minimum to ensure sufficient | 117 * Defer the notification by a reasonable minimum to ensure sufficient |
| 120 * visiblity of the animation. | 118 * visiblity of the animation. |
| 121 */ | 119 */ |
| 122 public void didStopRefreshing() { | 120 public void didStopRefreshing() { |
| 123 if (!mSwipeRefreshLayout.isRefreshing()) return; | 121 if (!mSwipeRefreshLayout.isRefreshing()) return; |
| 124 cancelStopRefreshingRunnable(); | 122 cancelStopRefreshingRunnable(); |
| 125 mSwipeRefreshLayout.postDelayed( | 123 mSwipeRefreshLayout.postDelayed( |
| 126 getStopRefreshingRunnable(), STOP_REFRESH_ANIMATION_DELAY_MS); | 124 getStopRefreshingRunnable(), STOP_REFRESH_ANIMATION_DELAY_MS); |
| 127 } | 125 } |
| 128 | 126 |
| 129 @Override | 127 @Override |
| 128 @CalledByNative | |
|
Ted C
2016/12/01 00:53:56
The @CalledByNative should be on the OverscrollRef
| |
| 130 public boolean start() { | 129 public boolean start() { |
| 131 attachSwipeRefreshLayoutIfNecessary(); | 130 attachSwipeRefreshLayoutIfNecessary(); |
| 132 return mSwipeRefreshLayout.start(); | 131 return mSwipeRefreshLayout.start(); |
| 133 } | 132 } |
| 134 | 133 |
| 135 @Override | 134 @Override |
| 135 @CalledByNative | |
| 136 public void pull(float delta) { | 136 public void pull(float delta) { |
| 137 TraceEvent.begin("SwipeRefreshHandler.pull"); | 137 TraceEvent.begin("SwipeRefreshHandler.pull"); |
| 138 mSwipeRefreshLayout.pull(delta); | 138 mSwipeRefreshLayout.pull(delta); |
| 139 TraceEvent.end("SwipeRefreshHandler.pull"); | 139 TraceEvent.end("SwipeRefreshHandler.pull"); |
| 140 } | 140 } |
| 141 | 141 |
| 142 @Override | 142 @Override |
| 143 @CalledByNative | |
| 143 public void release(boolean allowRefresh) { | 144 public void release(boolean allowRefresh) { |
| 144 TraceEvent.begin("SwipeRefreshHandler.release"); | 145 TraceEvent.begin("SwipeRefreshHandler.release"); |
| 145 mSwipeRefreshLayout.release(allowRefresh); | 146 mSwipeRefreshLayout.release(allowRefresh); |
| 146 TraceEvent.end("SwipeRefreshHandler.release"); | 147 TraceEvent.end("SwipeRefreshHandler.release"); |
| 147 } | 148 } |
| 148 | 149 |
| 149 @Override | 150 @Override |
| 151 @CalledByNative | |
| 150 public void reset() { | 152 public void reset() { |
| 151 cancelStopRefreshingRunnable(); | 153 cancelStopRefreshingRunnable(); |
| 152 mSwipeRefreshLayout.reset(); | 154 mSwipeRefreshLayout.reset(); |
| 153 } | 155 } |
| 154 | 156 |
| 155 @Override | 157 @Override |
| 156 public void setEnabled(boolean enabled) { | 158 public void setEnabled(boolean enabled) { |
| 157 mSwipeRefreshLayout.setEnabled(enabled); | 159 mSwipeRefreshLayout.setEnabled(enabled); |
| 158 if (!enabled) reset(); | 160 if (!enabled) reset(); |
| 159 } | 161 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 181 }; | 183 }; |
| 182 } | 184 } |
| 183 return mStopRefreshingRunnable; | 185 return mStopRefreshingRunnable; |
| 184 } | 186 } |
| 185 | 187 |
| 186 // The animation view is attached/detached on-demand to minimize overlap | 188 // The animation view is attached/detached on-demand to minimize overlap |
| 187 // with composited SurfaceView content. | 189 // with composited SurfaceView content. |
| 188 private void attachSwipeRefreshLayoutIfNecessary() { | 190 private void attachSwipeRefreshLayoutIfNecessary() { |
| 189 cancelDetachLayoutRunnable(); | 191 cancelDetachLayoutRunnable(); |
| 190 if (mSwipeRefreshLayout.getParent() == null) { | 192 if (mSwipeRefreshLayout.getParent() == null) { |
| 191 mContentViewCore.getContainerView().addView(mSwipeRefreshLayout); | 193 mContainerView.addView(mSwipeRefreshLayout); |
| 192 } | 194 } |
| 193 } | 195 } |
| 194 | 196 |
| 195 private void detachSwipeRefreshLayoutIfNecessary() { | 197 private void detachSwipeRefreshLayoutIfNecessary() { |
| 196 cancelDetachLayoutRunnable(); | 198 cancelDetachLayoutRunnable(); |
| 197 if (mSwipeRefreshLayout.getParent() != null) { | 199 if (mSwipeRefreshLayout.getParent() != null) { |
| 198 mContentViewCore.getContainerView().removeView(mSwipeRefreshLayout); | 200 mContainerView.removeView(mSwipeRefreshLayout); |
| 199 } | 201 } |
| 200 } | 202 } |
| 201 } | 203 } |
| OLD | NEW |