PhoneUi.java revision 08a687a75ef5164483ccfb3e144772c59bb14d83
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
17package com.android.browser;
18
19import android.animation.Animator;
20import android.animation.Animator.AnimatorListener;
21import android.animation.AnimatorSet;
22import android.animation.ObjectAnimator;
23import android.app.Activity;
24import android.util.Log;
25import android.view.ActionMode;
26import android.view.Gravity;
27import android.view.KeyEvent;
28import android.view.Menu;
29import android.view.View;
30import android.webkit.WebView;
31import android.widget.FrameLayout;
32
33/**
34 * Ui for regular phone screen sizes
35 */
36public class PhoneUi extends BaseUi {
37
38    private static final String LOGTAG = "PhoneUi";
39    private static final float NAV_TAB_SCALE = 0.75f;
40
41    private TitleBarPhone mTitleBar;
42    private ActiveTabsPage mActiveTabsPage;
43    private boolean mUseQuickControls;
44    private PieControl mPieControl;
45    private NavScreen mNavScreen;
46
47    boolean mExtendedMenuOpen;
48    boolean mOptionsMenuOpen;
49    boolean mAnimating;
50
51    /**
52     * @param browser
53     * @param controller
54     */
55    public PhoneUi(Activity browser, UiController controller) {
56        super(browser, controller);
57        mTitleBar = new TitleBarPhone(mActivity, mUiController, this,
58                mContentView);
59        // mTitleBar will be always be shown in the fully loaded mode on
60        // phone
61        mTitleBar.setProgress(100);
62        mActivity.getActionBar().hide();
63        setUseQuickControls(BrowserSettings.getInstance().useQuickControls());
64    }
65
66    @Override
67    public void hideComboView() {
68        super.hideComboView();
69        mActivity.getActionBar().hide();
70    }
71
72    // lifecycle
73
74    @Override
75    public void onPause() {
76        // FIXME: This removes the active tabs page and resets the menu to
77        // MAIN_MENU.  A better solution might be to do this work in onNewIntent
78        // but then we would need to save it in onSaveInstanceState and restore
79        // it in onCreate/onRestoreInstanceState
80        if (mActiveTabsPage != null) {
81            mUiController.removeActiveTabsPage(true);
82        }
83        super.onPause();
84    }
85
86    @Override
87    public void onDestroy() {
88        hideTitleBar();
89    }
90
91    @Override
92    public void editUrl(boolean clearInput) {
93        if (mUseQuickControls) {
94            getTitleBar().setShowProgressOnly(false);
95        }
96        super.editUrl(clearInput);
97    }
98
99    @Override
100    public boolean onBackKey() {
101        if (mActiveTabsPage != null) {
102            // if tab page is showing, hide it
103            mUiController.removeActiveTabsPage(true);
104            return true;
105        } else if (mNavScreen != null) {
106            mNavScreen.close();
107            return true;
108        }
109        return super.onBackKey();
110    }
111
112    @Override
113    public boolean dispatchKey(int code, KeyEvent event) {
114        if (!isComboViewShowing()) {
115            switch (code) {
116                case KeyEvent.KEYCODE_MENU:
117                    if (mNavScreen == null) {
118                        showNavScreen();
119                        return true;
120                    } else {
121                        mNavScreen.close();
122                        return true;
123                    }
124            }
125        }
126        return false;
127    }
128
129    @Override
130    public void onProgressChanged(Tab tab) {
131        if (tab.inForeground()) {
132            int progress = tab.getLoadProgress();
133            mTitleBar.setProgress(progress);
134            if (progress == 100) {
135                if (!mOptionsMenuOpen || !mExtendedMenuOpen) {
136                    hideTitleBar();
137                    if (mUseQuickControls) {
138                        mTitleBar.setShowProgressOnly(false);
139                    }
140                }
141            } else {
142                if (!mOptionsMenuOpen || mExtendedMenuOpen) {
143                    if (mUseQuickControls && !mTitleBar.isEditingUrl()) {
144                        mTitleBar.setShowProgressOnly(true);
145                        setTitleGravity(Gravity.TOP);
146                    }
147                    showTitleBar();
148                }
149            }
150        }
151    }
152
153    @Override
154    public void setActiveTab(final Tab tab) {
155        captureTab(mActiveTab);
156        super.setActiveTab(tab, true);
157        setActiveTab(tab, true);
158    }
159
160    @Override
161    void setActiveTab(Tab tab, boolean needsAttaching) {
162        BrowserWebView view = (BrowserWebView) tab.getWebView();
163        // TabControl.setCurrentTab has been called before this,
164        // so the tab is guaranteed to have a webview
165        if (view == null) {
166            Log.e(LOGTAG, "active tab with no webview detected");
167            return;
168        }
169        // Request focus on the top window.
170        if (mUseQuickControls) {
171            mPieControl.forceToTop(mContentView);
172            view.setScrollListener(null);
173        } else {
174            // check if title bar is already attached by animation
175            if (mTitleBar.getParent() == null) {
176                view.setEmbeddedTitleBar(mTitleBar);
177            }
178        }
179        if (tab.isInVoiceSearchMode()) {
180            showVoiceTitleBar(tab.getVoiceDisplayTitle(), tab.getVoiceSearchResults());
181        } else {
182            revertVoiceTitleBar(tab);
183        }
184        updateLockIconToLatest(tab);
185        tab.getTopWindow().requestFocus();
186    }
187
188    @Override
189    protected TitleBarBase getTitleBar() {
190        return mTitleBar;
191    }
192
193    // active tabs page
194
195    @Override
196    public void showActiveTabsPage() {
197        captureTab(mActiveTab);
198        mActiveTabsPage = new ActiveTabsPage(mActivity, mUiController);
199        mTitleBar.setVisibility(View.GONE);
200        hideTitleBar();
201        mContentView.addView(mActiveTabsPage, COVER_SCREEN_PARAMS);
202        mActiveTabsPage.requestFocus();
203    }
204
205    /**
206     * Remove the active tabs page.
207     */
208    @Override
209    public void removeActiveTabsPage() {
210        mContentView.removeView(mActiveTabsPage);
211        mTitleBar.setVisibility(View.VISIBLE);
212        mActiveTabsPage = null;
213    }
214
215    @Override
216    public boolean showsWeb() {
217        return super.showsWeb() && mActiveTabsPage == null;
218    }
219
220    // menu handling callbacks
221
222    @Override
223    public void onContextMenuCreated(Menu menu) {
224        hideTitleBar();
225    }
226
227    @Override
228    public void onContextMenuClosed(Menu menu, boolean inLoad) {
229        if (inLoad) {
230            showTitleBar();
231        }
232    }
233
234    // action mode callbacks
235
236    @Override
237    public void onActionModeStarted(ActionMode mode) {
238        hideTitleBar();
239    }
240
241    @Override
242    public void onActionModeFinished(boolean inLoad) {
243        if (inLoad) {
244            if (mUseQuickControls) {
245                mTitleBar.setShowProgressOnly(true);
246            }
247            showTitleBar();
248        }
249        mActivity.getActionBar().hide();
250    }
251
252    @Override
253    protected void setTitleGravity(int gravity) {
254        if (mUseQuickControls) {
255            FrameLayout.LayoutParams lp =
256                    (FrameLayout.LayoutParams) getTitleBar().getLayoutParams();
257            lp.gravity = gravity;
258            getTitleBar().setLayoutParams(lp);
259        } else {
260            super.setTitleGravity(gravity);
261        }
262    }
263
264    private void setUseQuickControls(boolean useQuickControls) {
265        mUseQuickControls = useQuickControls;
266        getTitleBar().setUseQuickControls(mUseQuickControls);
267        if (useQuickControls) {
268            mPieControl = new PieControl(mActivity, mUiController, this);
269            mPieControl.attachToContainer(mContentView);
270            WebView web = getWebView();
271            if (web != null) {
272                web.setEmbeddedTitleBar(null);
273            }
274        } else {
275            if (mPieControl != null) {
276                mPieControl.removeFromContainer(mContentView);
277            }
278            WebView web = getWebView();
279            if (web != null) {
280                web.setEmbeddedTitleBar(mTitleBar);
281            }
282            setTitleGravity(Gravity.NO_GRAVITY);
283        }
284    }
285
286    @Override
287    public boolean onPrepareOptionsMenu(Menu menu) {
288        if (mUseQuickControls) {
289            menu.setGroupVisible(R.id.NAV_MENU, false);
290            mPieControl.onMenuOpened(menu);
291            return false;
292        }
293        return true;
294    }
295
296    @Override
297    protected void captureTab(final Tab tab) {
298        if (mUseQuickControls) {
299            super.captureTab(tab);
300        } else {
301            captureTab(tab,
302                    mActivity.getWindowManager().getDefaultDisplay().getWidth(),
303                    mActivity.getWindowManager().getDefaultDisplay().getHeight());
304        }
305    }
306
307    void showNavScreen() {
308        if (mAnimating) return;
309        mAnimating = true;
310        mNavScreen = new NavScreen(mActivity, mUiController, this);
311        mNavScreen.startTask(new Runnable() {
312            public void run() {
313                BrowserWebView web = (BrowserWebView) getWebView();
314                if (web != null) {
315                    mActiveTab.setScreenshot(web.capture());
316                }
317                mNavScreen.finishTask();
318            }
319        });
320        WebView web = getWebView();
321        if (web != null) {
322            int w = web.getWidth();
323            int h = web.getHeight();
324            mNavScreen.setTabDimensions((int) (w * NAV_TAB_SCALE),
325                    (int) (h * NAV_TAB_SCALE));
326        }
327        // Add the custom view to its container.
328        mCustomViewContainer.addView(mNavScreen, COVER_SCREEN_GRAVITY_CENTER);
329        mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
330        ObjectAnimator animx = ObjectAnimator.ofFloat(mContentView,
331                "scaleX", 1.0f, 0.85f);
332        ObjectAnimator animy = ObjectAnimator.ofFloat(mContentView,
333                "scaleY", 1.0f, 0.85f);
334        AnimatorSet anims = new AnimatorSet();
335        anims.setDuration(200);
336        anims.addListener(new AnimatorListener() {
337
338            @Override
339            public void onAnimationCancel(Animator animation) {
340            }
341
342            @Override
343            public void onAnimationEnd(Animator animation) {
344                finishShowNavScreen();
345            }
346
347            @Override
348            public void onAnimationRepeat(Animator animation) {
349            }
350
351            @Override
352            public void onAnimationStart(Animator animation) {
353            }
354        });
355        anims.playTogether(animx, animy);
356        anims.start();
357    }
358
359    private void finishShowNavScreen() {
360        // Hide the content view.
361        mContentView.setLayerType(View.LAYER_TYPE_NONE, null);
362        mContentView.setVisibility(View.GONE);
363        mContentView.setScaleX(1.0f);
364        mContentView.setScaleY(1.0f);
365        mNavScreen.waitForTask();
366        // Finally show the custom view container.
367        mCustomViewContainer.setVisibility(View.VISIBLE);
368        mCustomViewContainer.bringToFront();
369        mAnimating = false;
370    }
371
372    void hideNavScreen(boolean animateToPage) {
373        if (mAnimating || mNavScreen == null) return;
374        mAnimating = true;
375        mNavScreen.setLayerType(View.LAYER_TYPE_HARDWARE, null);
376        if (animateToPage) {
377            ObjectAnimator animx = ObjectAnimator.ofFloat(mNavScreen, "scaleX",
378                    1.0f, 1.2f);
379            ObjectAnimator animy = ObjectAnimator.ofFloat(mNavScreen, "scaleY",
380                    1.0f, 1.2f);
381            AnimatorSet anims = new AnimatorSet();
382            anims.setDuration(200);
383            anims.addListener(new AnimatorListener() {
384
385                @Override
386                public void onAnimationCancel(Animator animation) {
387                }
388
389                @Override
390                public void onAnimationEnd(Animator animation) {
391                    finishHideNavScreen();
392                }
393
394                @Override
395                public void onAnimationRepeat(Animator animation) {
396                }
397
398                @Override
399                public void onAnimationStart(Animator animation) {
400                }
401            });
402            anims.playTogether(animx, animy);
403            anims.start();
404        } else {
405            finishHideNavScreen();
406        }
407
408    }
409
410    private void finishHideNavScreen() {
411        // Hide the custom view.
412        mNavScreen.setVisibility(View.GONE);
413        mNavScreen.setLayerType(View.LAYER_TYPE_NONE, null);
414        // Remove the custom view from its container.
415        mCustomViewContainer.removeView(mNavScreen);
416        mNavScreen = null;
417        mCustomViewContainer.setVisibility(View.GONE);
418        // Show the content view.
419        mContentView.setVisibility(View.VISIBLE);
420        mAnimating = false;
421    }
422
423}
424