• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
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 
17 package com.android.browser;
18 
19 import android.animation.Animator;
20 import android.animation.AnimatorListenerAdapter;
21 import android.animation.AnimatorSet;
22 import android.animation.ObjectAnimator;
23 import android.app.Activity;
24 import android.content.Context;
25 import android.graphics.Bitmap;
26 import android.graphics.Canvas;
27 import android.graphics.Matrix;
28 import android.os.Message;
29 import android.util.Log;
30 import android.util.TypedValue;
31 import android.view.ActionMode;
32 import android.view.Gravity;
33 import android.view.KeyEvent;
34 import android.view.LayoutInflater;
35 import android.view.Menu;
36 import android.view.MenuItem;
37 import android.view.View;
38 import android.view.ViewGroup;
39 import android.view.accessibility.AccessibilityEvent;
40 import android.webkit.WebView;
41 import android.widget.FrameLayout;
42 import android.widget.ImageView;
43 
44 import com.android.browser.UrlInputView.StateListener;
45 
46 /**
47  * Ui for regular phone screen sizes
48  */
49 public class PhoneUi extends BaseUi {
50 
51     private static final String LOGTAG = "PhoneUi";
52     private static final int MSG_INIT_NAVSCREEN = 100;
53 
54     private PieControlPhone mPieControl;
55     private NavScreen mNavScreen;
56     private AnimScreen mAnimScreen;
57     private NavigationBarPhone mNavigationBar;
58     private int mActionBarHeight;
59 
60     boolean mExtendedMenuOpen;
61     boolean mOptionsMenuOpen;
62     boolean mAnimating;
63 
64     /**
65      * @param browser
66      * @param controller
67      */
PhoneUi(Activity browser, UiController controller)68     public PhoneUi(Activity browser, UiController controller) {
69         super(browser, controller);
70         setUseQuickControls(BrowserSettings.getInstance().useQuickControls());
71         mNavigationBar = (NavigationBarPhone) mTitleBar.getNavigationBar();
72         TypedValue heightValue = new TypedValue();
73         browser.getTheme().resolveAttribute(
74                 com.android.internal.R.attr.actionBarSize, heightValue, true);
75         mActionBarHeight = TypedValue.complexToDimensionPixelSize(heightValue.data,
76                 browser.getResources().getDisplayMetrics());
77     }
78 
79     @Override
onDestroy()80     public void onDestroy() {
81         hideTitleBar();
82     }
83 
84     @Override
editUrl(boolean clearInput)85     public void editUrl(boolean clearInput) {
86         if (mUseQuickControls) {
87             mTitleBar.setShowProgressOnly(false);
88         }
89         super.editUrl(clearInput);
90     }
91 
92     @Override
onBackKey()93     public boolean onBackKey() {
94         if (showingNavScreen()) {
95             mNavScreen.close(mUiController.getTabControl().getCurrentPosition());
96             return true;
97         }
98         return super.onBackKey();
99     }
100 
showingNavScreen()101     private boolean showingNavScreen() {
102         return mNavScreen != null && mNavScreen.getVisibility() == View.VISIBLE;
103     }
104 
105     @Override
dispatchKey(int code, KeyEvent event)106     public boolean dispatchKey(int code, KeyEvent event) {
107         return false;
108     }
109 
110     @Override
onProgressChanged(Tab tab)111     public void onProgressChanged(Tab tab) {
112         if (tab.inForeground()) {
113             int progress = tab.getLoadProgress();
114             mTitleBar.setProgress(progress);
115             if (progress == 100) {
116                 if (!mOptionsMenuOpen || !mExtendedMenuOpen) {
117                     suggestHideTitleBar();
118                     if (mUseQuickControls) {
119                         mTitleBar.setShowProgressOnly(false);
120                     }
121                 }
122             } else {
123                 if (!mOptionsMenuOpen || mExtendedMenuOpen) {
124                     if (mUseQuickControls && !mTitleBar.isEditingUrl()) {
125                         mTitleBar.setShowProgressOnly(true);
126                         setTitleGravity(Gravity.TOP);
127                     }
128                     showTitleBar();
129                 }
130             }
131         }
132         if (mNavScreen == null && getTitleBar().getHeight() > 0) {
133             mHandler.sendEmptyMessage(MSG_INIT_NAVSCREEN);
134         }
135     }
136 
137     @Override
handleMessage(Message msg)138     protected void handleMessage(Message msg) {
139         super.handleMessage(msg);
140         if (msg.what == MSG_INIT_NAVSCREEN) {
141             if (mNavScreen == null) {
142                 mNavScreen = new NavScreen(mActivity, mUiController, this);
143                 mCustomViewContainer.addView(mNavScreen, COVER_SCREEN_PARAMS);
144                 mNavScreen.setVisibility(View.GONE);
145             }
146             if (mAnimScreen == null) {
147                 mAnimScreen = new AnimScreen(mActivity);
148                 // initialize bitmaps
149                 mAnimScreen.set(getTitleBar(), getWebView());
150             }
151         }
152     }
153 
154     @Override
setActiveTab(final Tab tab)155     public void setActiveTab(final Tab tab) {
156         mTitleBar.cancelTitleBarAnimation(true);
157         mTitleBar.setSkipTitleBarAnimations(true);
158         super.setActiveTab(tab);
159         BrowserWebView view = (BrowserWebView) tab.getWebView();
160         // TabControl.setCurrentTab has been called before this,
161         // so the tab is guaranteed to have a webview
162         if (view == null) {
163             Log.e(LOGTAG, "active tab with no webview detected");
164             return;
165         }
166         // Request focus on the top window.
167         if (mUseQuickControls) {
168             mPieControl.forceToTop(mContentView);
169         } else {
170             // check if title bar is already attached by animation
171             if (mTitleBar.getParent() == null) {
172                 view.setEmbeddedTitleBar(mTitleBar);
173             }
174         }
175         if (tab.isInVoiceSearchMode()) {
176             showVoiceTitleBar(tab.getVoiceDisplayTitle(), tab.getVoiceSearchResults());
177         } else {
178             revertVoiceTitleBar(tab);
179         }
180         // update nav bar state
181         mNavigationBar.onStateChanged(StateListener.STATE_NORMAL);
182         updateLockIconToLatest(tab);
183         tab.getTopWindow().requestFocus();
184         mTitleBar.setSkipTitleBarAnimations(false);
185     }
186 
187     // menu handling callbacks
188 
189     @Override
onPrepareOptionsMenu(Menu menu)190     public boolean onPrepareOptionsMenu(Menu menu) {
191         updateMenuState(mActiveTab, menu);
192         return true;
193     }
194 
195     @Override
updateMenuState(Tab tab, Menu menu)196     public void updateMenuState(Tab tab, Menu menu) {
197         MenuItem abm = menu.findItem(R.id.add_bookmark_menu_id);
198         if (abm != null) {
199             abm.setVisible((tab != null) && !tab.isSnapshot() && !showingNavScreen());
200         }
201         MenuItem info = menu.findItem(R.id.page_info_menu_id);
202         if (info != null) {
203             info.setVisible(false);
204         }
205         MenuItem newtab = menu.findItem(R.id.new_tab_menu_id);
206         if (newtab != null && !mUseQuickControls) {
207             newtab.setVisible(false);
208         }
209         MenuItem incognito = menu.findItem(R.id.incognito_menu_id);
210         if (incognito != null) {
211             incognito.setVisible(showingNavScreen() || mUseQuickControls);
212         }
213         if (showingNavScreen()) {
214             menu.setGroupVisible(R.id.LIVE_MENU, false);
215             menu.setGroupVisible(R.id.SNAPSHOT_MENU, false);
216             menu.setGroupVisible(R.id.NAV_MENU, false);
217             menu.setGroupVisible(R.id.COMBO_MENU, true);
218         }
219     }
220 
221     @Override
onOptionsItemSelected(MenuItem item)222     public boolean onOptionsItemSelected(MenuItem item) {
223         if (showingNavScreen()
224                 && (item.getItemId() != R.id.history_menu_id)
225                 && (item.getItemId() != R.id.snapshots_menu_id)) {
226             hideNavScreen(mUiController.getTabControl().getCurrentPosition(), false);
227         }
228         return false;
229     }
230 
231     @Override
onContextMenuCreated(Menu menu)232     public void onContextMenuCreated(Menu menu) {
233         hideTitleBar();
234     }
235 
236     @Override
onContextMenuClosed(Menu menu, boolean inLoad)237     public void onContextMenuClosed(Menu menu, boolean inLoad) {
238         if (inLoad) {
239             showTitleBar();
240         }
241     }
242 
243     // action mode callbacks
244 
245     @Override
onActionModeStarted(ActionMode mode)246     public void onActionModeStarted(ActionMode mode) {
247         if (!isEditingUrl()) {
248             hideTitleBar();
249         } else {
250             mTitleBar.animate().translationY(mActionBarHeight);
251         }
252     }
253 
254     @Override
onActionModeFinished(boolean inLoad)255     public void onActionModeFinished(boolean inLoad) {
256         mTitleBar.animate().translationY(0);
257         if (inLoad) {
258             if (mUseQuickControls) {
259                 mTitleBar.setShowProgressOnly(true);
260             }
261             showTitleBar();
262         }
263     }
264 
265     @Override
setTitleGravity(int gravity)266     protected void setTitleGravity(int gravity) {
267         if (mUseQuickControls) {
268             FrameLayout.LayoutParams lp =
269                     (FrameLayout.LayoutParams) mTitleBar.getLayoutParams();
270             lp.gravity = gravity;
271             mTitleBar.setLayoutParams(lp);
272         } else {
273             super.setTitleGravity(gravity);
274         }
275     }
276 
277     @Override
setUseQuickControls(boolean useQuickControls)278     public void setUseQuickControls(boolean useQuickControls) {
279         mUseQuickControls = useQuickControls;
280         mTitleBar.setUseQuickControls(mUseQuickControls);
281         if (useQuickControls) {
282             mPieControl = new PieControlPhone(mActivity, mUiController, this);
283             mPieControl.attachToContainer(mContentView);
284             WebView web = getWebView();
285             if (web != null) {
286                 web.setEmbeddedTitleBar(null);
287             }
288         } else {
289             if (mPieControl != null) {
290                 mPieControl.removeFromContainer(mContentView);
291             }
292             WebView web = getWebView();
293             if (web != null) {
294                 // make sure we can re-parent titlebar
295                 if ((mTitleBar != null) && (mTitleBar.getParent() != null)) {
296                     ((ViewGroup) mTitleBar.getParent()).removeView(mTitleBar);
297                 }
298                 web.setEmbeddedTitleBar(mTitleBar);
299             }
300             setTitleGravity(Gravity.NO_GRAVITY);
301         }
302         updateUrlBarAutoShowManagerTarget();
303     }
304 
305     @Override
isWebShowing()306     public boolean isWebShowing() {
307         return super.isWebShowing() && !showingNavScreen();
308     }
309 
310     @Override
showWeb(boolean animate)311     public void showWeb(boolean animate) {
312         super.showWeb(animate);
313         hideNavScreen(mUiController.getTabControl().getCurrentPosition(), animate);
314     }
315 
showNavScreen()316     void showNavScreen() {
317         mUiController.setBlockEvents(true);
318         if (mNavScreen == null) {
319             mNavScreen = new NavScreen(mActivity, mUiController, this);
320             mCustomViewContainer.addView(mNavScreen, COVER_SCREEN_PARAMS);
321         } else {
322             mNavScreen.setVisibility(View.VISIBLE);
323             mNavScreen.setAlpha(1f);
324             mNavScreen.refreshAdapter();
325         }
326         mActiveTab.capture();
327         if (mAnimScreen == null) {
328             mAnimScreen = new AnimScreen(mActivity);
329         } else {
330             mAnimScreen.mMain.setAlpha(1f);
331             mAnimScreen.mTitle.setAlpha(1f);
332             mAnimScreen.setScaleFactor(1f);
333         }
334         mAnimScreen.set(getTitleBar(), getWebView());
335         mCustomViewContainer.addView(mAnimScreen.mMain, COVER_SCREEN_PARAMS);
336         mCustomViewContainer.setVisibility(View.VISIBLE);
337         mCustomViewContainer.bringToFront();
338         mAnimScreen.mMain.layout(0, 0, mContentView.getWidth(),
339                 mContentView.getHeight());
340         int fromLeft = 0;
341         int fromTop = getTitleBar().getHeight();
342         int fromRight = mContentView.getWidth();
343         int fromBottom = mContentView.getHeight();
344         int width = mActivity.getResources().getDimensionPixelSize(R.dimen.nav_tab_width);
345         int height = mActivity.getResources().getDimensionPixelSize(R.dimen.nav_tab_height);
346         int ntth = mActivity.getResources().getDimensionPixelSize(R.dimen.nav_tab_titleheight);
347         int toLeft = (mContentView.getWidth() - width) / 2;
348         int toTop = ((fromBottom - (ntth + height)) / 2 + ntth);
349         int toRight = toLeft + width;
350         int toBottom = toTop + height;
351         float scaleFactor = width / (float) mContentView.getWidth();
352         detachTab(mActiveTab);
353         mContentView.setVisibility(View.GONE);
354         AnimatorSet set1 = new AnimatorSet();
355         AnimatorSet inanim = new AnimatorSet();
356         ObjectAnimator tx = ObjectAnimator.ofInt(mAnimScreen.mContent, "left",
357                 fromLeft, toLeft);
358         ObjectAnimator ty = ObjectAnimator.ofInt(mAnimScreen.mContent, "top",
359                 fromTop, toTop);
360         ObjectAnimator tr = ObjectAnimator.ofInt(mAnimScreen.mContent, "right",
361                 fromRight, toRight);
362         ObjectAnimator tb = ObjectAnimator.ofInt(mAnimScreen.mContent, "bottom",
363                 fromBottom, toBottom);
364         ObjectAnimator title = ObjectAnimator.ofFloat(mAnimScreen.mTitle, "alpha",
365                 1f, 0f);
366         ObjectAnimator sx = ObjectAnimator.ofFloat(mAnimScreen, "scaleFactor",
367                 1f, scaleFactor);
368         ObjectAnimator blend1 = ObjectAnimator.ofFloat(mAnimScreen.mMain,
369                 "alpha", 1f, 0f);
370         blend1.setDuration(100);
371 
372         inanim.playTogether(tx, ty, tr, tb, sx, title);
373         inanim.setDuration(200);
374         set1.addListener(new AnimatorListenerAdapter() {
375             @Override
376             public void onAnimationEnd(Animator anim) {
377                 mCustomViewContainer.removeView(mAnimScreen.mMain);
378                 finishAnimationIn();
379                 mUiController.setBlockEvents(false);
380             }
381         });
382         set1.playSequentially(inanim, blend1);
383         set1.start();
384     }
385 
finishAnimationIn()386     private void finishAnimationIn() {
387         if (showingNavScreen()) {
388             // notify accessibility manager about the screen change
389             mNavScreen.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
390             mTabControl.setOnThumbnailUpdatedListener(mNavScreen);
391         }
392     }
393 
hideNavScreen(int position, boolean animate)394     void hideNavScreen(int position, boolean animate) {
395         if (!showingNavScreen()) return;
396         final Tab tab = mUiController.getTabControl().getTab(position);
397         if ((tab == null) || !animate) {
398             if (tab != null) {
399                 setActiveTab(tab);
400             } else if (mTabControl.getTabCount() > 0) {
401                 // use a fallback tab
402                 setActiveTab(mTabControl.getCurrentTab());
403             }
404             mContentView.setVisibility(View.VISIBLE);
405             finishAnimateOut();
406             return;
407         }
408         NavTabView tabview = (NavTabView) mNavScreen.getTabView(position);
409         if (tabview == null) {
410             if (mTabControl.getTabCount() > 0) {
411                 // use a fallback tab
412                 setActiveTab(mTabControl.getCurrentTab());
413             }
414             mContentView.setVisibility(View.VISIBLE);
415             finishAnimateOut();
416             return;
417         }
418         mUiController.setBlockEvents(true);
419         mUiController.setActiveTab(tab);
420         mContentView.setVisibility(View.VISIBLE);
421         if (mAnimScreen == null) {
422             mAnimScreen = new AnimScreen(mActivity);
423         }
424         mAnimScreen.set(tab.getScreenshot());
425         mCustomViewContainer.addView(mAnimScreen.mMain, COVER_SCREEN_PARAMS);
426         mAnimScreen.mMain.layout(0, 0, mContentView.getWidth(),
427                 mContentView.getHeight());
428         mNavScreen.mScroller.finishScroller();
429         ImageView target = tabview.mImage;
430         int toLeft = 0;
431         int toTop = getTitleBar().getHeight();
432         int toRight = mContentView.getWidth();
433         int width = target.getDrawable().getIntrinsicWidth();
434         int height = target.getDrawable().getIntrinsicHeight();
435         int fromLeft = tabview.getLeft() + target.getLeft() - mNavScreen.mScroller.getScrollX();
436         int fromTop = tabview.getTop() + target.getTop() - mNavScreen.mScroller.getScrollY();
437         int fromRight = fromLeft + width;
438         int fromBottom = fromTop + height;
439         float scaleFactor = mContentView.getWidth() / (float) width;
440         int toBottom = toTop + (int) (height * scaleFactor);
441         mAnimScreen.mContent.setLeft(fromLeft);
442         mAnimScreen.mContent.setTop(fromTop);
443         mAnimScreen.mContent.setRight(fromRight);
444         mAnimScreen.mContent.setBottom(fromBottom);
445         mAnimScreen.setScaleFactor(1f);
446         AnimatorSet set1 = new AnimatorSet();
447         ObjectAnimator fade2 = ObjectAnimator.ofFloat(mAnimScreen.mMain, "alpha", 0f, 1f);
448         ObjectAnimator fade1 = ObjectAnimator.ofFloat(mNavScreen, "alpha", 1f, 0f);
449         set1.playTogether(fade1, fade2);
450         set1.setDuration(100);
451         AnimatorSet set2 = new AnimatorSet();
452         ObjectAnimator l = ObjectAnimator.ofInt(mAnimScreen.mContent, "left",
453                 fromLeft, toLeft);
454         ObjectAnimator t = ObjectAnimator.ofInt(mAnimScreen.mContent, "top",
455                 fromTop, toTop);
456         ObjectAnimator r = ObjectAnimator.ofInt(mAnimScreen.mContent, "right",
457                 fromRight, toRight);
458         ObjectAnimator b = ObjectAnimator.ofInt(mAnimScreen.mContent, "bottom",
459                 fromBottom, toBottom);
460         ObjectAnimator scale = ObjectAnimator.ofFloat(mAnimScreen, "scaleFactor",
461                 1f, scaleFactor);
462         ObjectAnimator otheralpha = ObjectAnimator.ofFloat(mCustomViewContainer, "alpha", 1f, 0f);
463         otheralpha.setDuration(100);
464         set2.playTogether(l, t, r, b, scale);
465         set2.setDuration(200);
466         AnimatorSet combo = new AnimatorSet();
467         combo.playSequentially(set1, set2, otheralpha);
468         combo.addListener(new AnimatorListenerAdapter() {
469             @Override
470             public void onAnimationEnd(Animator anim) {
471                 mCustomViewContainer.removeView(mAnimScreen.mMain);
472                 finishAnimateOut();
473                 mUiController.setBlockEvents(false);
474             }
475         });
476         combo.start();
477     }
478 
finishAnimateOut()479     private void finishAnimateOut() {
480         mTabControl.setOnThumbnailUpdatedListener(null);
481         mNavScreen.setVisibility(View.GONE);
482         mCustomViewContainer.setAlpha(1f);
483         mCustomViewContainer.setVisibility(View.GONE);
484     }
485 
486     @Override
needsRestoreAllTabs()487     public boolean needsRestoreAllTabs() {
488         return false;
489     }
490 
toggleNavScreen()491     public void toggleNavScreen() {
492         if (!showingNavScreen()) {
493             showNavScreen();
494         } else {
495             hideNavScreen(mUiController.getTabControl().getCurrentPosition(), false);
496         }
497     }
498 
499     @Override
shouldCaptureThumbnails()500     public boolean shouldCaptureThumbnails() {
501         return true;
502     }
503 
504     static class AnimScreen {
505 
506         private View mMain;
507         private ImageView mTitle;
508         private ImageView mContent;
509         private float mScale;
510         private Bitmap mTitleBarBitmap;
511         private Bitmap mContentBitmap;
512 
AnimScreen(Context ctx)513         public AnimScreen(Context ctx) {
514             mMain = LayoutInflater.from(ctx).inflate(R.layout.anim_screen,
515                     null);
516             mTitle = (ImageView) mMain.findViewById(R.id.title);
517             mContent = (ImageView) mMain.findViewById(R.id.content);
518             mContent.setScaleType(ImageView.ScaleType.MATRIX);
519             mContent.setImageMatrix(new Matrix());
520             mScale = 1.0f;
521             setScaleFactor(getScaleFactor());
522         }
523 
set(TitleBar tbar, WebView web)524         public void set(TitleBar tbar, WebView web) {
525             if (tbar == null || web == null) {
526                 return;
527             }
528             if (tbar.getWidth() > 0 && tbar.getEmbeddedHeight() > 0) {
529                 if (mTitleBarBitmap == null
530                         || mTitleBarBitmap.getWidth() != tbar.getWidth()
531                         || mTitleBarBitmap.getHeight() != tbar.getEmbeddedHeight()) {
532                     mTitleBarBitmap = Bitmap.createBitmap(tbar.getWidth(),
533                             tbar.getEmbeddedHeight(), Bitmap.Config.RGB_565);
534                 }
535                 Canvas c = new Canvas(mTitleBarBitmap);
536                 tbar.draw(c);
537                 c.setBitmap(null);
538             } else {
539                 mTitleBarBitmap = null;
540             }
541             mTitle.setImageBitmap(mTitleBarBitmap);
542             mTitle.setVisibility(View.VISIBLE);
543             int h = web.getHeight() - tbar.getEmbeddedHeight();
544             if (mContentBitmap == null
545                     || mContentBitmap.getWidth() != web.getWidth()
546                     || mContentBitmap.getHeight() != h) {
547                 mContentBitmap = Bitmap.createBitmap(web.getWidth(), h,
548                         Bitmap.Config.RGB_565);
549             }
550             Canvas c = new Canvas(mContentBitmap);
551             int tx = web.getScrollX();
552             int ty = web.getScrollY();
553             c.translate(-tx, -ty - tbar.getEmbeddedHeight());
554             web.draw(c);
555             c.setBitmap(null);
556             mContent.setImageBitmap(mContentBitmap);
557         }
558 
set(Bitmap image)559         public void set(Bitmap image) {
560             mTitle.setVisibility(View.GONE);
561             mContent.setImageBitmap(image);
562         }
563 
setScaleFactor(float sf)564         private void setScaleFactor(float sf) {
565             mScale = sf;
566             Matrix m = new Matrix();
567             m.postScale(sf,sf);
568             mContent.setImageMatrix(m);
569         }
570 
getScaleFactor()571         private float getScaleFactor() {
572             return mScale;
573         }
574 
575     }
576 
577 }
578