Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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.searchwidget; | 5 package org.chromium.chrome.browser.searchwidget; |
| 6 | 6 |
| 7 import android.animation.Animator; | |
| 8 import android.animation.AnimatorListenerAdapter; | |
| 9 import android.animation.ValueAnimator; | |
| 10 import android.content.Intent; | 7 import android.content.Intent; |
| 11 import android.graphics.Rect; | 8 import android.graphics.Rect; |
| 12 import android.graphics.drawable.Drawable; | 9 import android.graphics.drawable.Drawable; |
| 13 import android.net.Uri; | 10 import android.net.Uri; |
| 14 import android.os.Handler; | 11 import android.os.Handler; |
| 15 import android.support.customtabs.CustomTabsIntent; | 12 import android.support.customtabs.CustomTabsIntent; |
| 16 import android.support.v4.app.ActivityOptionsCompat; | 13 import android.support.v4.app.ActivityOptionsCompat; |
| 17 import android.text.TextUtils; | 14 import android.text.TextUtils; |
| 18 import android.view.Gravity; | 15 import android.view.LayoutInflater; |
| 19 import android.view.View; | 16 import android.view.View; |
| 20 import android.view.View.MeasureSpec; | |
| 21 import android.view.ViewGroup; | 17 import android.view.ViewGroup; |
| 22 import android.view.ViewGroup.LayoutParams; | |
| 23 import android.view.ViewStub; | |
| 24 import android.widget.FrameLayout; | |
| 25 | 18 |
| 26 import org.chromium.base.ApiCompatibilityUtils; | 19 import org.chromium.base.ApiCompatibilityUtils; |
| 27 import org.chromium.base.ContextUtils; | 20 import org.chromium.base.ContextUtils; |
| 28 import org.chromium.chrome.R; | 21 import org.chromium.chrome.R; |
| 29 import org.chromium.chrome.browser.IntentHandler; | 22 import org.chromium.chrome.browser.IntentHandler; |
| 30 import org.chromium.chrome.browser.WebContentsFactory; | 23 import org.chromium.chrome.browser.WebContentsFactory; |
| 31 import org.chromium.chrome.browser.WindowDelegate; | 24 import org.chromium.chrome.browser.WindowDelegate; |
| 32 import org.chromium.chrome.browser.customtabs.CustomTabsConnection; | 25 import org.chromium.chrome.browser.customtabs.CustomTabsConnection; |
| 33 import org.chromium.chrome.browser.document.ChromeLauncherActivity; | 26 import org.chromium.chrome.browser.document.ChromeLauncherActivity; |
| 34 import org.chromium.chrome.browser.init.AsyncInitializationActivity; | 27 import org.chromium.chrome.browser.init.AsyncInitializationActivity; |
| 35 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; | 28 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; |
| 36 import org.chromium.chrome.browser.omnibox.AutocompleteController; | 29 import org.chromium.chrome.browser.omnibox.AutocompleteController; |
| 37 import org.chromium.chrome.browser.omnibox.UrlBar; | 30 import org.chromium.chrome.browser.omnibox.UrlBar; |
| 38 import org.chromium.chrome.browser.profiles.Profile; | 31 import org.chromium.chrome.browser.profiles.Profile; |
| 39 import org.chromium.chrome.browser.snackbar.SnackbarManager; | 32 import org.chromium.chrome.browser.snackbar.SnackbarManager; |
| 40 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable; | 33 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable; |
| 41 import org.chromium.chrome.browser.tab.Tab; | 34 import org.chromium.chrome.browser.tab.Tab; |
| 42 import org.chromium.chrome.browser.tab.TabDelegateFactory; | 35 import org.chromium.chrome.browser.tab.TabDelegateFactory; |
| 43 import org.chromium.chrome.browser.tab.TabIdManager; | 36 import org.chromium.chrome.browser.tab.TabIdManager; |
| 44 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; | 37 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; |
| 45 import org.chromium.chrome.browser.util.IntentUtils; | 38 import org.chromium.chrome.browser.util.IntentUtils; |
| 46 import org.chromium.chrome.browser.widget.FadingBackgroundView; | |
| 47 import org.chromium.components.url_formatter.UrlFormatter; | 39 import org.chromium.components.url_formatter.UrlFormatter; |
| 48 import org.chromium.content_public.browser.LoadUrlParams; | 40 import org.chromium.content_public.browser.LoadUrlParams; |
| 49 import org.chromium.ui.UiUtils; | 41 import org.chromium.ui.UiUtils; |
| 50 import org.chromium.ui.base.ActivityWindowAndroid; | 42 import org.chromium.ui.base.ActivityWindowAndroid; |
| 51 | 43 |
| 52 /** Prototype that queries the user's default search engine and shows autocomple te suggestions. */ | 44 /** Prototype that queries the user's default search engine and shows autocomple te suggestions. */ |
| 53 public class SearchActivity extends AsyncInitializationActivity | 45 public class SearchActivity extends AsyncInitializationActivity |
| 54 implements SnackbarManageable, SearchLocationBarLayout.Delegate, | 46 implements SnackbarManageable, SearchActivityLocationBarLayout.Delegate, |
| 55 View.OnLayoutChangeListener { | 47 View.OnLayoutChangeListener { |
| 56 private static final String TAG = "searchwidget"; | 48 private static final String TAG = "searchwidget"; |
| 57 | 49 |
| 58 /** How long the animation should run for. */ | |
| 59 private static final int ANIMATION_DURATION_MS = 200; | |
| 60 | |
| 61 /** Padding gleaned from the background Drawable of the search box. */ | 50 /** Padding gleaned from the background Drawable of the search box. */ |
| 62 private final Rect mSearchBoxPadding = new Rect(); | 51 private final Rect mSearchBoxPadding = new Rect(); |
| 63 | 52 |
| 64 /** Location of the search box on the home screen. */ | |
| 65 private Rect mSearchBoxWidgetBounds; | |
| 66 | |
| 67 /** Small margin/padding used for the search box. */ | |
| 68 private int mSpacingSmall; | |
| 69 | |
| 70 /** Medium margin/padding used for the search box. */ | 53 /** Medium margin/padding used for the search box. */ |
| 71 private int mSpacingMedium; | 54 private int mSpacingMedium; |
| 72 | 55 |
| 73 /** Large margin/padding used for the search box. */ | 56 /** Large margin/padding used for the search box. */ |
| 74 private int mSpacingLarge; | 57 private int mSpacingLarge; |
| 75 | 58 |
| 76 /** | |
| 77 * View that the omnibox suggestion list anchors to. This is different from the main search box | |
| 78 * because the upstream LocationBarLayout code expects a full white box inst ead of a floating | |
| 79 * box with shadows. | |
| 80 */ | |
| 81 private View mAnchorView; | |
| 82 | |
| 83 /** See {@link BoxAnimatorScrim}. */ | |
| 84 private BoxAnimatorScrim mScrimView; | |
| 85 | |
| 86 /** Main content view. */ | 59 /** Main content view. */ |
| 87 private ViewGroup mContentView; | 60 private ViewGroup mContentView; |
| 88 | 61 |
| 89 /** Whether or not the library has begun loading. */ | |
| 90 private boolean mIsNativeLoading; | |
| 91 | |
| 92 /** Whether the native library has been loaded. */ | 62 /** Whether the native library has been loaded. */ |
| 93 private boolean mIsNativeReady; | 63 private boolean mIsNativeReady; |
| 94 | 64 |
| 95 /** Input submitted before before the native library was loaded. */ | 65 /** Input submitted before before the native library was loaded. */ |
| 96 private String mQueuedUrl; | 66 private String mQueuedUrl; |
| 97 | 67 |
| 98 /** Animates the SearchActivity's controls moving into place. */ | |
| 99 private ValueAnimator mAnimator; | |
| 100 | |
| 101 /** The View that represents the search box. */ | 68 /** The View that represents the search box. */ |
| 102 private SearchLocationBarLayout mSearchBox; | 69 private SearchActivityLocationBarLayout mSearchBox; |
| 103 | 70 |
| 104 private UrlBar mUrlBar; | 71 private UrlBar mUrlBar; |
| 105 | 72 |
| 106 private SearchBoxDataProvider mSearchBoxDataProvider; | 73 private SearchBoxDataProvider mSearchBoxDataProvider; |
| 107 | 74 |
| 108 private SnackbarManager mSnackbarManager; | 75 private SnackbarManager mSnackbarManager; |
| 109 private ActivityWindowAndroid mWindowAndroid; | 76 private ActivityWindowAndroid mWindowAndroid; |
| 110 private Tab mTab; | 77 private Tab mTab; |
| 111 | 78 |
| 112 @Override | 79 @Override |
| 113 public void backKeyPressed() { | 80 public void backKeyPressed() { |
| 114 finish(); | 81 finish(); |
| 115 } | 82 } |
| 116 | 83 |
| 117 @Override | 84 @Override |
| 118 public void onStop() { | 85 public void onStop() { |
| 119 finish(); | 86 finish(); |
| 120 super.onStop(); | 87 super.onStop(); |
| 121 } | 88 } |
| 122 | 89 |
| 123 @Override | 90 @Override |
| 124 public void finish() { | 91 public void finish() { |
| 125 if (SearchWidgetProvider.ANIMATE_TRANSITION) { | |
| 126 // Update the search widgets so that they all show up as opaque agai n. | |
| 127 SearchWidgetProvider.setLaunchingWidgetId(SearchWidgetProvider.INVAL ID_WIDGET_ID); | |
| 128 SearchWidgetProvider.updateAllWidgets(); | |
| 129 } | |
| 130 | |
| 131 super.finish(); | 92 super.finish(); |
| 132 overridePendingTransition(0, android.R.anim.fade_out); | 93 overridePendingTransition(0, android.R.anim.fade_out); |
| 133 } | 94 } |
| 134 | 95 |
| 135 @Override | 96 @Override |
| 136 protected boolean shouldDelayBrowserStartup() { | 97 protected boolean shouldDelayBrowserStartup() { |
| 137 return true; | 98 return true; |
| 138 } | 99 } |
| 139 | 100 |
| 140 @Override | 101 @Override |
| 141 public boolean onActivityResultWithNative(int requestCode, int resultCode, I ntent intent) { | 102 public boolean onActivityResultWithNative(int requestCode, int resultCode, I ntent intent) { |
| 142 if (super.onActivityResultWithNative(requestCode, resultCode, intent)) r eturn true; | 103 if (super.onActivityResultWithNative(requestCode, resultCode, intent)) r eturn true; |
| 143 boolean result = mWindowAndroid.onActivityResult(requestCode, resultCode , intent); | 104 boolean result = mWindowAndroid.onActivityResult(requestCode, resultCode , intent); |
| 144 | 105 |
| 145 // The voice query should have completed. If the voice recognition isn' t confident about | 106 // The voice query should have completed. If the voice recognition isn' t confident about |
| 146 // what it heard, it puts the query into the omnibox. We need to focus it at that point. | 107 // what it heard, it puts the query into the omnibox. We need to focus it at that point. |
| 147 if (mUrlBar != null) focusTextBox(false); | 108 if (mUrlBar != null) focusTextBox(false); |
| 148 | 109 |
| 149 return result; | 110 return result; |
| 150 } | 111 } |
| 151 | 112 |
| 152 @Override | 113 @Override |
| 153 protected void setContentView() { | 114 protected void setContentView() { |
| 154 initializeDimensions(); | 115 initializeDimensions(); |
| 155 | 116 |
| 156 mWindowAndroid = new ActivityWindowAndroid(this); | 117 mWindowAndroid = new ActivityWindowAndroid(this); |
| 157 mSnackbarManager = new SnackbarManager(this); | 118 mSnackbarManager = new SnackbarManager(this); |
| 119 mSearchBoxDataProvider = new SearchBoxDataProvider(); | |
| 158 | 120 |
| 159 // Build the Views that {@link SearchLocationBarLayout} expects to exist . | 121 mContentView = createContentView(mSearchBox); |
| 160 ViewStub resultsStub = new ViewStub(this); | 122 mContentView.setOnClickListener(new View.OnClickListener() { |
| 161 resultsStub.setId(R.id.omnibox_results_container_stub); | |
| 162 resultsStub.setLayoutResource(R.layout.omnibox_results_container); | |
| 163 | |
| 164 // The FadingBackgroundView isn't used here, but is still animated by th e LocationBarLayout. | |
| 165 // This interferes with the animation we need to show the widget moving to the right place. | |
| 166 FadingBackgroundView fadingView = new FadingBackgroundView(this, null) { | |
| 167 @Override | |
| 168 public void showFadingOverlay() {} | |
| 169 @Override | |
| 170 public void hideFadingOverlay(boolean fadeOut) {} | |
| 171 }; | |
| 172 | |
| 173 fadingView.setId(R.id.fading_focus_target); | |
| 174 FrameLayout.LayoutParams fadingBackgroundLayoutParams = new FrameLayout. LayoutParams(0, 0); | |
| 175 | |
| 176 // Add an empty view to prevent crashing. | |
| 177 ViewGroup bottomContainer = new FrameLayout(this); | |
| 178 bottomContainer.setId(R.id.bottom_container); | |
| 179 | |
| 180 // Build the search box, set it to invisible until the animation is done . | |
| 181 mSearchBox = new SearchLocationBarLayout(this, null); | |
| 182 mSearchBox.setDelegate(this); | |
| 183 mSearchBox.setVisibility(mSearchBoxWidgetBounds == null ? View.VISIBLE : View.INVISIBLE); | |
| 184 mSearchBox.setBackgroundResource(R.drawable.card_single); | |
| 185 mSearchBox.setPadding(mSpacingLarge, mSpacingMedium, mSpacingLarge, mSpa cingMedium); | |
| 186 mSearchBox.initializeControls(new WindowDelegate(getWindow()), mWindowAn droid); | |
| 187 mSearchBox.setUrlBarFocusable(true); | |
| 188 mSearchBoxDataProvider = new SearchBoxDataProvider(); | |
| 189 mSearchBox.setToolbarDataProvider(mSearchBoxDataProvider); | |
| 190 FrameLayout.LayoutParams searchParams = | |
| 191 new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutPa rams.WRAP_CONTENT); | |
| 192 ApiCompatibilityUtils.setMarginStart(searchParams, mSpacingSmall); | |
| 193 ApiCompatibilityUtils.setMarginEnd(searchParams, mSpacingSmall); | |
| 194 searchParams.topMargin = mSpacingSmall; | |
| 195 | |
| 196 // The scrim animates the search box moving into place. | |
| 197 mScrimView = new BoxAnimatorScrim(this, null); | |
| 198 mScrimView.setOnClickListener(new View.OnClickListener() { | |
| 199 @Override | 123 @Override |
| 200 public void onClick(View v) { | 124 public void onClick(View v) { |
| 201 // Don't allow clicking on the scrim until the animation complet es. | |
| 202 if (mScrimView.getInterpolatedValue() < 1.0f) return; | |
| 203 | |
| 204 // Finish the Activity if the user clicks on the scrim. | 125 // Finish the Activity if the user clicks on the scrim. |
| 205 finish(); | 126 finish(); |
| 206 } | 127 } |
| 207 }); | 128 }); |
| 208 if (!SearchWidgetProvider.ANIMATE_TRANSITION) mScrimView.setInterpolated Value(1.0f); | |
| 209 | 129 |
| 210 // The anchor view puts the omnibox suggestions in the correct place, vi sually. | 130 // Build the search box. |
| 211 mAnchorView = new View(this); | 131 mSearchBox = (SearchActivityLocationBarLayout) mContentView.findViewById ( |
| 212 mAnchorView.setId(R.id.toolbar); | 132 R.id.search_location_bar); |
| 213 mAnchorView.setClickable(true); | 133 mSearchBox.setDelegate(this); |
| 214 FrameLayout.LayoutParams anchorParams = | 134 mSearchBox.setPadding(mSpacingLarge, mSpacingMedium, mSpacingLarge, mSpa cingMedium); |
| 215 new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutPa rams.WRAP_CONTENT); | 135 mSearchBox.initializeControls(new WindowDelegate(getWindow()), mWindowAn droid); |
| 216 anchorParams.gravity = Gravity.CENTER_HORIZONTAL; | 136 mSearchBox.setUrlBarFocusable(true); |
| 137 mSearchBox.setToolbarDataProvider(mSearchBoxDataProvider); | |
| 217 | 138 |
| 218 // Initialize and build the View hierarchy. | |
| 219 mContentView = createContentView(mSearchBox); | |
| 220 mContentView.addView(fadingView, fadingBackgroundLayoutParams); | |
| 221 mContentView.addView(mScrimView); | |
| 222 mContentView.addView(resultsStub); | |
| 223 mContentView.addView(mAnchorView, anchorParams); | |
| 224 mContentView.addView(mSearchBox, searchParams); | |
| 225 mContentView.addView(bottomContainer); | |
| 226 setContentView(mContentView); | 139 setContentView(mContentView); |
| 227 mUrlBar = (UrlBar) mSearchBox.findViewById(R.id.url_bar); | 140 mUrlBar = (UrlBar) mSearchBox.findViewById(R.id.url_bar); |
| 228 | |
| 229 mSearchBox.setShowCachedZeroSuggestResults(true); | |
| 230 } | 141 } |
| 231 | 142 |
| 232 @Override | 143 @Override |
| 233 public void finishNativeInitialization() { | 144 public void finishNativeInitialization() { |
| 234 super.finishNativeInitialization(); | 145 super.finishNativeInitialization(); |
| 235 mIsNativeReady = true; | 146 mIsNativeReady = true; |
| 236 | 147 |
| 237 mTab = new Tab(TabIdManager.getInstance().generateValidId(Tab.INVALID_TA B_ID), | 148 mTab = new Tab(TabIdManager.getInstance().generateValidId(Tab.INVALID_TA B_ID), |
| 238 Tab.INVALID_TAB_ID, false, this, mWindowAndroid, TabLaunchType.F ROM_EXTERNAL_APP, | 149 Tab.INVALID_TAB_ID, false, this, mWindowAndroid, TabLaunchType.F ROM_EXTERNAL_APP, |
| 239 null, null); | 150 null, null); |
| 240 mTab.initialize(WebContentsFactory.createWebContents(false, false), null , | 151 mTab.initialize(WebContentsFactory.createWebContents(false, false), null , |
| 241 new TabDelegateFactory(), false, false); | 152 new TabDelegateFactory(), false, false); |
| 242 mTab.loadUrl(new LoadUrlParams("about:blank")); | 153 mTab.loadUrl(new LoadUrlParams("about:blank")); |
| 243 mSearchBoxDataProvider.onNativeLibraryReady(mTab); | 154 mSearchBoxDataProvider.onNativeLibraryReady(mTab); |
| 244 mSearchBox.onNativeLibraryReady(); | 155 mSearchBox.onNativeLibraryReady(); |
| 245 mSearchBox.setAutocompleteProfile(Profile.getLastUsedProfile().getOrigin alProfile()); | 156 mSearchBox.setAutocompleteProfile(Profile.getLastUsedProfile().getOrigin alProfile()); |
| 157 mSearchBox.setShowCachedZeroSuggestResults(true); | |
| 246 | 158 |
| 247 if (mQueuedUrl != null) loadUrl(mQueuedUrl); | 159 if (mQueuedUrl != null) loadUrl(mQueuedUrl); |
| 248 | 160 |
| 249 new Handler().post(new Runnable() { | 161 new Handler().post(new Runnable() { |
| 250 @Override | 162 @Override |
| 251 public void run() { | 163 public void run() { |
| 252 onDeferredStartup(); | 164 onDeferredStartup(); |
| 253 } | 165 } |
| 254 }); | 166 }); |
| 255 } | 167 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 focusTextBox(true); | 205 focusTextBox(true); |
| 294 } | 206 } |
| 295 } | 207 } |
| 296 | 208 |
| 297 @Override | 209 @Override |
| 298 protected void onDestroy() { | 210 protected void onDestroy() { |
| 299 if (mTab != null && mTab.isInitialized()) mTab.destroy(); | 211 if (mTab != null && mTab.isInitialized()) mTab.destroy(); |
| 300 super.onDestroy(); | 212 super.onDestroy(); |
| 301 } | 213 } |
| 302 | 214 |
| 303 private void focusTextBox(boolean clearQuery) { | 215 private void focusTextBox(boolean clearQuery) { |
|
Yusuf
2017/04/07 18:08:28
maybe this should be in the SearchLocationBar clas
gone
2017/04/07 18:15:26
Talked offline:
There's a lot more cleanup to be d
| |
| 304 if (mIsNativeReady) mSearchBox.onUrlFocusChange(true); | 216 if (mIsNativeReady) mSearchBox.onUrlFocusChange(true); |
| 217 | |
| 218 if (clearQuery) { | |
| 219 mUrlBar.setIgnoreTextChangesForAutocomplete(true); | |
| 220 mUrlBar.setUrl("", null); | |
| 221 mUrlBar.setIgnoreTextChangesForAutocomplete(false); | |
| 222 } | |
| 305 mUrlBar.setCursorVisible(true); | 223 mUrlBar.setCursorVisible(true); |
| 306 mUrlBar.setIgnoreTextChangesForAutocomplete(true); | |
| 307 if (clearQuery) mUrlBar.setUrl("", null); | |
| 308 mUrlBar.setIgnoreTextChangesForAutocomplete(false); | |
| 309 mUrlBar.setSelection(0, mUrlBar.getText().length()); | 224 mUrlBar.setSelection(0, mUrlBar.getText().length()); |
| 310 new Handler().post(new Runnable() { | 225 new Handler().post(new Runnable() { |
| 311 @Override | 226 @Override |
| 312 public void run() { | 227 public void run() { |
| 313 UiUtils.showKeyboard(mUrlBar); | 228 UiUtils.showKeyboard(mUrlBar); |
| 314 } | 229 } |
| 315 }); | 230 }); |
| 316 } | 231 } |
| 317 | 232 |
| 318 @Override | 233 @Override |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 347 startActivity(intent, | 262 startActivity(intent, |
| 348 ActivityOptionsCompat | 263 ActivityOptionsCompat |
| 349 .makeCustomAnimation(this, android.R.anim.fade_in, andro id.R.anim.fade_out) | 264 .makeCustomAnimation(this, android.R.anim.fade_in, andro id.R.anim.fade_out) |
| 350 .toBundle()); | 265 .toBundle()); |
| 351 finish(); | 266 finish(); |
| 352 } | 267 } |
| 353 | 268 |
| 354 private ViewGroup createContentView(final View searchBox) { | 269 private ViewGroup createContentView(final View searchBox) { |
| 355 assert mContentView == null; | 270 assert mContentView == null; |
| 356 | 271 |
| 357 ViewGroup contentView = new FrameLayout(this) { | 272 ViewGroup contentView = (ViewGroup) LayoutInflater.from(this).inflate( |
| 358 @Override | 273 R.layout.search_activity, null, false); |
| 359 public void onMeasure(int widthSpec, int heightSpec) { | |
| 360 super.onMeasure(widthSpec, heightSpec); | |
| 361 if (mAnchorView == null) return; | |
| 362 | |
| 363 // Calculate how big the box is without shadow-induced padding. | |
| 364 FrameLayout.LayoutParams anchorParams = | |
| 365 (FrameLayout.LayoutParams) mAnchorView.getLayoutParams() ; | |
| 366 int anchorViewWidth = searchBox.getMeasuredWidth() - mSearchBoxP adding.left | |
| 367 - mSearchBoxPadding.right; | |
| 368 int anchorViewHeight = | |
| 369 mSpacingSmall + mSearchBox.getMeasuredHeight() - mSearch BoxPadding.bottom; | |
| 370 if (anchorParams.width == anchorViewWidth | |
| 371 && anchorParams.height == anchorViewHeight) { | |
| 372 return; | |
| 373 } | |
| 374 | |
| 375 // Move the anchor view up a little bit as a dirty hack until we can add a | |
| 376 // dimension. This allows the suggestion list to move up past th e rounded corners of | |
| 377 // the search box. | |
| 378 anchorParams.topMargin = -(mSpacingSmall / 4); | |
| 379 anchorParams.width = anchorViewWidth; | |
| 380 anchorParams.height = anchorViewHeight; | |
| 381 | |
| 382 // Measure the anchor view to match the search box's height with out its side or | |
| 383 // bottom shadow padding. This isn't exactly what we need, but i t's hard to get the | |
| 384 // correct behavior because LocationBarLayout overrides how the suggestions are | |
| 385 // laid out. | |
| 386 int anchorWidthSpec = | |
| 387 MeasureSpec.makeMeasureSpec(anchorViewWidth, MeasureSpec .EXACTLY); | |
| 388 int anchorHeightSpec = | |
| 389 MeasureSpec.makeMeasureSpec(anchorViewHeight, MeasureSpe c.EXACTLY); | |
| 390 measureChild(mAnchorView, anchorWidthSpec, anchorHeightSpec); | |
| 391 } | |
| 392 }; | |
| 393 | |
| 394 contentView.addOnLayoutChangeListener(this); | 274 contentView.addOnLayoutChangeListener(this); |
| 395 contentView.setId(R.id.control_container); | |
| 396 return contentView; | 275 return contentView; |
| 397 } | 276 } |
| 398 | 277 |
| 399 @Override | 278 @Override |
| 400 public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, | 279 public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, |
| 401 int oldTop, int oldRight, int oldBottom) { | 280 int oldTop, int oldRight, int oldBottom) { |
| 402 if (mSearchBoxWidgetBounds != null) { | |
| 403 if (mAnimator == null) initializeAnimation(); | |
| 404 } else { | |
| 405 // If there's no animation, then we can load the library immediately without worrying | |
| 406 // about jank. | |
| 407 beginLoadingLibrary(); | |
| 408 } | |
| 409 mContentView.removeOnLayoutChangeListener(this); | 281 mContentView.removeOnLayoutChangeListener(this); |
| 282 beginLoadingLibrary(); | |
| 410 } | 283 } |
| 411 | 284 |
| 412 private void initializeDimensions() { | 285 private void initializeDimensions() { |
| 413 mSearchBoxWidgetBounds = getIntent().getSourceBounds(); | |
| 414 | |
| 415 // Cache the padding of the Drawable that is used as the background for the search box. | 286 // Cache the padding of the Drawable that is used as the background for the search box. |
| 416 Drawable searchBackground = | 287 Drawable searchBackground = |
| 417 ApiCompatibilityUtils.getDrawable(getResources(), R.drawable.car d_single); | 288 ApiCompatibilityUtils.getDrawable(getResources(), R.drawable.car d_single); |
| 418 searchBackground.getPadding(mSearchBoxPadding); | 289 searchBackground.getPadding(mSearchBoxPadding); |
| 419 | 290 |
| 420 // TODO(dfalcantara): Add values to the XML files instead of reusing ran dom ones. | 291 // TODO(dfalcantara): Add values to the XML files instead of reusing ran dom ones. |
| 421 mSpacingSmall = getResources().getDimensionPixelSize( | |
| 422 R.dimen.tablet_toolbar_start_padding_no_buttons); | |
| 423 mSpacingMedium = | 292 mSpacingMedium = |
| 424 getResources().getDimensionPixelSize(R.dimen.location_bar_incogn ito_badge_padding); | 293 getResources().getDimensionPixelSize(R.dimen.location_bar_incogn ito_badge_padding); |
| 425 mSpacingLarge = | 294 mSpacingLarge = |
| 426 getResources().getDimensionPixelSize(R.dimen.contextual_search_p eek_promo_padding); | 295 getResources().getDimensionPixelSize(R.dimen.contextual_search_p eek_promo_padding); |
| 427 } | 296 } |
| 428 | 297 |
| 429 private void initializeAnimation() { | |
| 430 assert SearchWidgetProvider.ANIMATE_TRANSITION; | |
| 431 | |
| 432 // The bounds of the home screen widget are given in window space coordi nates, so they need | |
| 433 // to be converted into conrdinates that are relative from the root View . The converted | |
| 434 // bounds are used to animate the box moving from its widget location to the location at the | |
| 435 // top of the screen. | |
| 436 int[] rootWindowLocation = new int[2]; | |
| 437 mContentView.getLocationInWindow(rootWindowLocation); | |
| 438 | |
| 439 final Rect sourceRect = new Rect(); | |
| 440 sourceRect.left = mSearchBoxWidgetBounds.left - rootWindowLocation[0]; | |
| 441 sourceRect.right = mSearchBoxWidgetBounds.right - rootWindowLocation[0]; | |
| 442 sourceRect.top = mSearchBoxWidgetBounds.top - rootWindowLocation[1]; | |
| 443 sourceRect.bottom = mSearchBoxWidgetBounds.bottom - rootWindowLocation[1 ]; | |
| 444 | |
| 445 int[] targetBoxLocation = new int[2]; | |
| 446 mSearchBox.getLocationInWindow(targetBoxLocation); | |
| 447 final Rect targetRect = new Rect(); | |
| 448 targetRect.left = targetBoxLocation[0] - rootWindowLocation[0]; | |
| 449 targetRect.right = targetRect.left + mSearchBox.getMeasuredWidth(); | |
| 450 targetRect.top = targetBoxLocation[1] - rootWindowLocation[1]; | |
| 451 targetRect.bottom = targetRect.top + mSearchBox.getMeasuredHeight(); | |
| 452 | |
| 453 mScrimView.setAnimationRects(sourceRect, targetRect); | |
| 454 | |
| 455 mAnimator = ValueAnimator.ofFloat(0, 1); | |
| 456 mAnimator.setDuration(ANIMATION_DURATION_MS); | |
| 457 mAnimator.addListener(new AnimatorListenerAdapter() { | |
| 458 @Override | |
| 459 public void onAnimationStart(Animator animation) { | |
| 460 // Make the widget on the homescreen hide itself. | |
| 461 SearchWidgetProvider.updateAllWidgets(); | |
| 462 } | |
| 463 | |
| 464 @Override | |
| 465 public void onAnimationEnd(Animator animation) { | |
| 466 // Defer loading the library until the box is in the right place to prevent jank. | |
| 467 beginLoadingLibrary(); | |
| 468 } | |
| 469 }); | |
| 470 mAnimator.addUpdateListener(mScrimView); | |
| 471 | |
| 472 new Handler().post(new Runnable() { | |
| 473 @Override | |
| 474 public void run() { | |
| 475 mAnimator.start(); | |
| 476 } | |
| 477 }); | |
| 478 } | |
| 479 | |
| 480 private void beginLoadingLibrary() { | 298 private void beginLoadingLibrary() { |
| 481 if (mIsNativeLoading) return; | |
| 482 mIsNativeLoading = true; | |
| 483 | |
| 484 // Show the real search box and let the user type in it. | |
| 485 mScrimView.setInterpolatedValue(1.0f); | |
| 486 mSearchBox.setVisibility(View.VISIBLE); | |
| 487 beginQuery(); | 299 beginQuery(); |
| 488 mHandler.post(new Runnable() { | 300 mHandler.post(new Runnable() { |
| 489 @Override | 301 @Override |
| 490 public void run() { | 302 public void run() { |
| 491 mSearchBox.showCachedZeroSuggestResultsIfAvailable(); | 303 mSearchBox.showCachedZeroSuggestResultsIfAvailable(); |
| 492 } | 304 } |
| 493 }); | 305 }); |
| 494 ChromeBrowserInitializer.getInstance(getApplicationContext()) | 306 ChromeBrowserInitializer.getInstance(getApplicationContext()) |
| 495 .handlePreNativeStartup(SearchActivity.this); | 307 .handlePreNativeStartup(SearchActivity.this); |
| 496 } | 308 } |
| 497 } | 309 } |
| OLD | NEW |