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