Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java

Issue 2776183002: NTP: Prevent conflict of dismiss animations and scroll position handling. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.ntp; 5 package org.chromium.chrome.browser.ntp;
6 6
7 import android.annotation.SuppressLint; 7 import android.annotation.SuppressLint;
8 import android.content.Context; 8 import android.content.Context;
9 import android.content.res.Configuration; 9 import android.content.res.Configuration;
10 import android.graphics.Canvas; 10 import android.graphics.Canvas;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 import org.chromium.chrome.browser.widget.displaystyle.UiConfig; 51 import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
52 import org.chromium.ui.base.DeviceFormFactor; 52 import org.chromium.ui.base.DeviceFormFactor;
53 53
54 /** 54 /**
55 * The native new tab page, represented by some basic data such as title and url , and an Android 55 * The native new tab page, represented by some basic data such as title and url , and an Android
56 * View that displays the page. 56 * View that displays the page.
57 */ 57 */
58 public class NewTabPageView extends FrameLayout implements TileGroup.Observer { 58 public class NewTabPageView extends FrameLayout implements TileGroup.Observer {
59 private static final String TAG = "NewTabPageView"; 59 private static final String TAG = "NewTabPageView";
60 60
61 private static final long SNAP_SCROLL_DELAY_MS = 30; 61 private static final long SCROLL_RUNNABLE_DELAY_MS = 30;
62 62
63 /** 63 /**
64 * Experiment parameter for the maximum number of tile suggestion rows to sh ow. 64 * Experiment parameter for the maximum number of tile suggestion rows to sh ow.
65 */ 65 */
66 private static final String PARAM_NTP_MAX_TILE_ROWS = "ntp_max_tile_rows"; 66 private static final String PARAM_NTP_MAX_TILE_ROWS = "ntp_max_tile_rows";
67 67
68 /** 68 /**
69 * Experiment parameter for the number of tile title lines to show. 69 * Experiment parameter for the number of tile title lines to show.
70 */ 70 */
71 private static final String PARAM_NTP_TILE_TITLE_LINES = "ntp_tile_title_lin es"; 71 private static final String PARAM_NTP_TILE_TITLE_LINES = "ntp_tile_title_lin es";
(...skipping 22 matching lines...) Expand all
94 94
95 private OnSearchBoxScrollListener mSearchBoxScrollListener; 95 private OnSearchBoxScrollListener mSearchBoxScrollListener;
96 96
97 private ChromeActivity mActivity; 97 private ChromeActivity mActivity;
98 private NewTabPageManager mManager; 98 private NewTabPageManager mManager;
99 private LogoView.Delegate mLogoDelegate; 99 private LogoView.Delegate mLogoDelegate;
100 private TileGroup.Delegate mTileGroupDelegate; 100 private TileGroup.Delegate mTileGroupDelegate;
101 private TileGroup mTileGroup; 101 private TileGroup mTileGroup;
102 private UiConfig mUiConfig; 102 private UiConfig mUiConfig;
103 private Runnable mSnapScrollRunnable; 103 private Runnable mSnapScrollRunnable;
104 private Runnable mUpdateSearchBoxOnScrollRunnable;
104 private boolean mFirstShow = true; 105 private boolean mFirstShow = true;
105 private boolean mSearchProviderHasLogo = true; 106 private boolean mSearchProviderHasLogo = true;
106 private boolean mPendingSnapScroll; 107 private boolean mPendingSnapScroll;
107 private boolean mInitialized; 108 private boolean mInitialized;
108 private int mLastScrollY = -1; 109 private int mLastScrollY = -1;
109 110
110 /** 111 /**
111 * The number of asynchronous tasks that need to complete before the page is done loading. 112 * The number of asynchronous tasks that need to complete before the page is done loading.
112 * This starts at one to track when the view is finished attaching to the wi ndow. 113 * This starts at one to track when the view is finished attaching to the wi ndow.
113 */ 114 */
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 190
190 mRecyclerView = new NewTabPageRecyclerView(getContext()); 191 mRecyclerView = new NewTabPageRecyclerView(getContext());
191 mRecyclerView.setContainsLocationBar(manager.isLocationBarShownInNTP()); 192 mRecyclerView.setContainsLocationBar(manager.isLocationBarShownInNTP());
192 addView(mRecyclerView); 193 addView(mRecyclerView);
193 194
194 // Don't attach now, the recyclerView itself will determine when to do i t. 195 // Don't attach now, the recyclerView itself will determine when to do i t.
195 mNewTabPageLayout = mRecyclerView.getAboveTheFoldView(); 196 mNewTabPageLayout = mRecyclerView.getAboveTheFoldView();
196 197
197 mRecyclerView.setItemAnimator(new DefaultItemAnimator() { 198 mRecyclerView.setItemAnimator(new DefaultItemAnimator() {
198 @Override 199 @Override
200 public boolean animateMove(ViewHolder holder, int fromX, int fromY, int toX, int toY) {
201 // If |mNewTabPageLayout| is animated by the RecyclerView becaus e an item below it
Bernhard Bauer 2017/03/27 17:36:54 Stupid question, why doesn't it work to call updat
Michael van Ouwerkerk 2017/03/28 10:44:15 Because this method (animateMove) is called only o
202 // was dismissed, avoid also manipulating its vertical offset in our scroll handling
203 // at the same time. The onScrolled() method is called when an i tem is dismissed and
204 // the item at the top of the viewport is repositioned.
205 if (holder.itemView == mNewTabPageLayout) setUrlFocusAnimationsD isabled(true);
206
207 // Cancel any pending scroll update handling, a new one will be scheduled in
208 // onAnimationFinished().
209 mRecyclerView.removeCallbacks(mUpdateSearchBoxOnScrollRunnable);
210
211 return super.animateMove(holder, fromX, fromY, toX, toY);
212 }
213
214 @Override
199 public void onAnimationFinished(ViewHolder viewHolder) { 215 public void onAnimationFinished(ViewHolder viewHolder) {
200 super.onAnimationFinished(viewHolder); 216 super.onAnimationFinished(viewHolder);
201 // When removing sections, because the animations are all transl ations, the 217
202 // scroll events don't fire and we can get in the situation wher e the toolbar 218 // When an item is dismissed, the items at the top of the viewpo rt might not move,
203 // buttons disappear. 219 // and onScrolled() might not be called. We can get in the situa tion where the
204 updateSearchBoxOnScroll(); 220 // toolbar buttons disappear, so schedule an update for it. This can be cancelled
221 // from animateMove() in case |mNewTabPageLayout| will be moved. We don't know that
222 // from here, as the RecyclerView will animate multiple items wh en one is dismissed,
223 // and some will "finish" synchronously if they are already in t he correct place,
224 // before other moves have even been scheduled.
225 if (viewHolder.itemView == mNewTabPageLayout) setUrlFocusAnimati onsDisabled(false);
226 mRecyclerView.removeCallbacks(mUpdateSearchBoxOnScrollRunnable);
227 mRecyclerView.postDelayed(
228 mUpdateSearchBoxOnScrollRunnable, SCROLL_RUNNABLE_DELAY_ MS);
Bernhard Bauer 2017/03/27 17:36:54 Is there a reason to use that particular delay (wh
Michael van Ouwerkerk 2017/03/28 10:44:15 As it turns out, there's no need to use postDelaye
205 } 229 }
206 }); 230 });
207 231
208 mContextMenuManager = 232 mContextMenuManager =
209 new ContextMenuManager(mActivity, mManager.getNavigationDelegate (), mRecyclerView); 233 new ContextMenuManager(mActivity, mManager.getNavigationDelegate (), mRecyclerView);
210 mActivity.getWindowAndroid().addContextMenuCloseListener(mContextMenuMan ager); 234 mActivity.getWindowAndroid().addContextMenuCloseListener(mContextMenuMan ager);
211 manager.addDestructionObserver(new DestructionObserver() { 235 manager.addDestructionObserver(new DestructionObserver() {
212 @Override 236 @Override
213 public void onDestroy() { 237 public void onDestroy() {
214 mActivity.getWindowAndroid().removeContextMenuCloseListener(mCon textMenuManager); 238 mActivity.getWindowAndroid().removeContextMenuCloseListener(mCon textMenuManager);
215 } 239 }
216 }); 240 });
217 241
218 OfflinePageBridge offlinePageBridge = 242 OfflinePageBridge offlinePageBridge =
219 OfflinePageBridge.getForProfile(Profile.getLastUsedProfile()); 243 OfflinePageBridge.getForProfile(Profile.getLastUsedProfile());
220 244
221 mTileGridLayout = (TileGridLayout) mNewTabPageLayout.findViewById(R.id.t ile_grid_layout); 245 mTileGridLayout = (TileGridLayout) mNewTabPageLayout.findViewById(R.id.t ile_grid_layout);
222 mTileGridLayout.setMaxRows(getMaxTileRows(searchProviderHasLogo)); 246 mTileGridLayout.setMaxRows(getMaxTileRows(searchProviderHasLogo));
223 mTileGridLayout.setMaxColumns(getMaxTileColumns()); 247 mTileGridLayout.setMaxColumns(getMaxTileColumns());
224 mTileGroup = new TileGroup(mActivity, mManager, mContextMenuManager, mTi leGroupDelegate, 248 mTileGroup = new TileGroup(mActivity, mManager, mContextMenuManager, mTi leGroupDelegate,
225 /* observer = */ this, offlinePageBridge, getTileTitleLines()); 249 /* observer = */ this, offlinePageBridge, getTileTitleLines());
226 250
227 mSearchProviderLogoView = 251 mSearchProviderLogoView =
228 (LogoView) mNewTabPageLayout.findViewById(R.id.search_provider_l ogo); 252 (LogoView) mNewTabPageLayout.findViewById(R.id.search_provider_l ogo);
229 mLogoDelegate = new LogoDelegateImpl(tab, mSearchProviderLogoView); 253 mLogoDelegate = new LogoDelegateImpl(tab, mSearchProviderLogoView);
230 mSearchBoxView = mNewTabPageLayout.findViewById(R.id.search_box); 254 mSearchBoxView = mNewTabPageLayout.findViewById(R.id.search_box);
231 mNoSearchLogoSpacer = mNewTabPageLayout.findViewById(R.id.no_search_logo _spacer); 255 mNoSearchLogoSpacer = mNewTabPageLayout.findViewById(R.id.no_search_logo _spacer);
232 256
233 mSnapScrollRunnable = new SnapScrollRunnable(); 257 mSnapScrollRunnable = new SnapScrollRunnable();
258 mUpdateSearchBoxOnScrollRunnable = new UpdateSearchBoxOnScrollRunnable() ;
234 259
235 initializeSearchBoxTextView(); 260 initializeSearchBoxTextView();
236 initializeVoiceSearchButton(); 261 initializeVoiceSearchButton();
237 initializeLayoutChangeListeners(); 262 initializeLayoutChangeListeners();
238 setSearchProviderHasLogo(searchProviderHasLogo); 263 setSearchProviderHasLogo(searchProviderHasLogo);
239 264
240 tab.addObserver(new EmptyTabObserver() { 265 tab.addObserver(new EmptyTabObserver() {
241 @Override 266 @Override
242 public void onShown(Tab tab) { 267 public void onShown(Tab tab) {
243 mTileGroup.onSwitchToForeground(); 268 mTileGroup.onSwitchToForeground();
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 512
488 mRecyclerView.setOnTouchListener(new OnTouchListener() { 513 mRecyclerView.setOnTouchListener(new OnTouchListener() {
489 @Override 514 @Override
490 @SuppressLint("ClickableViewAccessibility") 515 @SuppressLint("ClickableViewAccessibility")
491 public boolean onTouch(View v, MotionEvent event) { 516 public boolean onTouch(View v, MotionEvent event) {
492 mRecyclerView.removeCallbacks(mSnapScrollRunnable); 517 mRecyclerView.removeCallbacks(mSnapScrollRunnable);
493 518
494 if (event.getActionMasked() == MotionEvent.ACTION_CANCEL 519 if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
495 || event.getActionMasked() == MotionEvent.ACTION_UP) { 520 || event.getActionMasked() == MotionEvent.ACTION_UP) {
496 mPendingSnapScroll = true; 521 mPendingSnapScroll = true;
497 mRecyclerView.postDelayed(mSnapScrollRunnable, SNAP_SCROLL_D ELAY_MS); 522 mRecyclerView.postDelayed(mSnapScrollRunnable, SCROLL_RUNNAB LE_DELAY_MS);
498 } else { 523 } else {
499 mPendingSnapScroll = false; 524 mPendingSnapScroll = false;
500 } 525 }
501 return false; 526 return false;
502 } 527 }
503 }); 528 });
504 TraceEvent.end(TAG + ".setupScrollHandling()"); 529 TraceEvent.end(TAG + ".setupScrollHandling()");
505 } 530 }
506 531
507 private void handleScroll() { 532 private void handleScroll() {
508 if (mPendingSnapScroll) { 533 if (mPendingSnapScroll) {
509 mRecyclerView.removeCallbacks(mSnapScrollRunnable); 534 mRecyclerView.removeCallbacks(mSnapScrollRunnable);
510 mRecyclerView.postDelayed(mSnapScrollRunnable, SNAP_SCROLL_DELAY_MS) ; 535 mRecyclerView.postDelayed(mSnapScrollRunnable, SCROLL_RUNNABLE_DELAY _MS);
511 } 536 }
512 updateSearchBoxOnScroll(); 537 updateSearchBoxOnScroll();
513 mRecyclerView.updatePeekingCardAndHeader(); 538 mRecyclerView.updatePeekingCardAndHeader();
514 } 539 }
515 540
516 /** 541 /**
517 * Decrements the count of pending load tasks and notifies the manager when the page load 542 * Decrements the count of pending load tasks and notifies the manager when the page load
518 * is complete. 543 * is complete.
519 */ 544 */
520 private void loadTaskCompleted() { 545 private void loadTaskCompleted() {
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 953
929 private class SnapScrollRunnable implements Runnable { 954 private class SnapScrollRunnable implements Runnable {
930 @Override 955 @Override
931 public void run() { 956 public void run() {
932 assert mPendingSnapScroll; 957 assert mPendingSnapScroll;
933 mPendingSnapScroll = false; 958 mPendingSnapScroll = false;
934 959
935 mRecyclerView.snapScroll(mSearchBoxView, getHeight()); 960 mRecyclerView.snapScroll(mSearchBoxView, getHeight());
936 } 961 }
937 } 962 }
963
964 private class UpdateSearchBoxOnScrollRunnable implements Runnable {
965 @Override
966 public void run() {
967 updateSearchBoxOnScroll();
968 }
969 }
938 } 970 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698