博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Browser学习五 多窗口: Tab 整体结构
阅读量:6415 次
发布时间:2019-06-23

本文共 7791 字,大约阅读时间需要 25 分钟。

hot3.png

前面说了这么多却发现我们的Tab还没有介绍, Tab到底是个什么东西呢?

其实是一个含有两个WebView 成员一个WebViewController成员的类: 其中PageState用来真正存储这个tab网页的一些信息,包括url 标题 图标等

// Main WebView wrapper tab的容器    private View mContainer;    // Main WebView 显示网页的webview    private WebView mMainView;     // Subwindow container     private View mSubViewContainer;    // Subwindow WebView在一个tab可能会弹出 另一个WebView的dialog  使用subwebview实现 (True if the new        window should be a dialog, rather than a full-size window.)    private WebView mSubView;

其中mContainer就是tab的主Ui 了 他一般是一个形如"

这样的布局, 通过 BaseUI的onSetWebView设置:

@Override    public void onSetWebView(Tab tab, WebView webView) {        View container = tab.getViewContainer();        if (container == null) {            // The tab consists of a container view, which contains the main            // WebView, as well as any other UI elements associated with the tab.            container = mActivity.getLayoutInflat().inflate(R.layout.tab,                    mContentView, false);//把tab的ContainerView  Attach到Activity            tab.setViewContainer(container);        }        if (tab.getWebView() != webView) { //如果tab当前的 mMainWebview 和 以前的webview不一样就把以前的那个webview 从 Container 移除掉            // Just remove the old one.            FrameLayout wrapper =                    (FrameLayout) container.findViewById(R.id.webview_wrapper);            wrapper.removeView(tab.getWebView());        }    }

这个函数是谁调用的呢? 终归肯定是Controller进行的, 但是这里设计就有点乱了:

顺序是这样:  Controller::setActiveTab -> TabControl::setCurrentTab -> Tab::setWebView -> Controler ::onSetWebView  -> BaseUI::onSetWebView 

 Controller调用 BaseUI 的setActiveTab函数 (其实最后是attachTabToContentView)把Tab的mWebView和container 关联起来:

protected void attachTabToContentView(Tab tab) {        if ((tab == null) || (tab.getWebView() == null)) {            return;        }        View container = tab.getViewContainer(); //对应tab的layout        WebView mainView  = tab.getWebView();        // Attach the WebView to the container and then attach the        // container to the content view.        //把Tab的container添加到mContentView        FrameLayout wrapper =                (FrameLayout) container.findViewById(R.id.webview_wrapper);        ViewGroup parent = (ViewGroup) mainView.getParent();        if (parent != wrapper) {            if (parent != null) {                Log.w(LOGTAG, "mMainView already has a parent in"                        + " attachTabToContentView!");                parent.removeView(mainView);            }            wrapper.addView(mainView);        } else {            Log.w(LOGTAG, "mMainView is already attached to wrapper in"                    + " attachTabToContentView!");        }        parent = (ViewGroup) container.getParent();        if (parent != mContentView) {            if (parent != null) {                Log.w(LOGTAG, "mContainer already has a parent in"                        + " attachTabToContentView!");                parent.removeView(container);            }            mContentView.addView(container, COVER_SCREEN_PARAMS);        } else {            Log.w(LOGTAG, "mContainer is already attached to content in"                    + " attachTabToContentView!");        }        mUiController.attachSubWindow(tab);    }

这样我们就明白了, Activity只是一个容器, 当哪个Tab放到前台, BaseUI就拿到对应Tab的Container和Webview , 把这两个空间attach到Activity的ContentView中去

之所以这样做, 可能是因为作者想让  BaseUI来进行把View attach到Activity上的操作 , Tab只做控制Webview load网页的操作; 他们之间的交互由Controller来控制.但是感觉这个设计可能有些乱了.

Tab获取当前快照的函数:

protected void capture() {        if (mMainView == null || mCapture == null) return;        if (mMainView.getContentWidth() <= 0 || mMainView.getContentHeight() <= 0) {            return;        }        Canvas c = new Canvas(mCapture);        final int left = mMainView.getScrollX(); //快照抓取的是tab的顶部        final int top = mMainView.getScrollY() + mMainView.getVisibleTitleHeight();        int state = c.save();        c.translate(-left, -top);        float scale = mCaptureWidth / (float) mMainView.getWidth();        c.scale(scale, scale, left, top);        if (mMainView instanceof BrowserWebView) {            ((BrowserWebView)mMainView).drawContent(c);        } else {            mMainView.draw(c);        }        c.restoreToCount(state);        // manually anti-alias the edges for the tilt        c.drawRect(0, 0, 1, mCapture.getHeight(), sAlphaPaint);        c.drawRect(mCapture.getWidth() - 1, 0, mCapture.getWidth(),                mCapture.getHeight(), sAlphaPaint);        c.drawRect(0, 0, mCapture.getWidth(), 1, sAlphaPaint);        c.drawRect(0, mCapture.getHeight() - 1, mCapture.getWidth(),                mCapture.getHeight(), sAlphaPaint);        c.setBitmap(null);//释放canvas绘制的bitmap        mHandler.removeMessages(MSG_CAPTURE);        persistThumbnail();        TabControl tc = mWebViewController.getTabControl();        if (tc != null) {            OnThumbnailUpdatedListener updateListener                    = tc.getOnThumbnailUpdatedListener();            if (updateListener != null) {//通知更新了缩略图                updateListener.onThumbnailUpdated(this);            }        }    }

Tab 保存 当前网页的函数

/**     * 保存离线阅读的一些数据     * @return     */    public ContentValues createSnapshotValues() {        if (mMainView == null) return null;        SnapshotByteArrayOutputStream bos = new SnapshotByteArrayOutputStream();        try {            GZIPOutputStream stream = new GZIPOutputStream(bos);            if (!mMainView.saveViewState(stream)) {                return null;            }            stream.flush();            stream.close();        } catch (Exception e) {            Log.w(LOGTAG, "Failed to save view state", e);            return null;        }        byte[] data = bos.toByteArray();        ContentValues values = new ContentValues();        values.put(Snapshots.TITLE, mCurrentState.mTitle);//标题        values.put(Snapshots.URL, mCurrentState.mUrl);//url        values.put(Snapshots.VIEWSTATE, data);        values.put(Snapshots.BACKGROUND, mMainView.getPageBackgroundColor());//背景        values.put(Snapshots.DATE_CREATED, System.currentTimeMillis());//时间        values.put(Snapshots.FAVICON, compressBitmap(getFavicon()));//网址图标        Bitmap screenshot = Controller.createScreenshot(mMainView,                Controller.getDesiredThumbnailWidth(mContext),                Controller.getDesiredThumbnailHeight(mContext));        values.put(Snapshots.THUMBNAIL, compressBitmap(screenshot));        return values;    }    public byte[] compressBitmap(Bitmap bitmap) {        if (bitmap == null) {            return null;        }        ByteArrayOutputStream stream = new ByteArrayOutputStream();        bitmap.compress(CompressFormat.PNG, 100, stream);        return stream.toByteArray();    }

处理SSLError的函数

private void handleProceededAfterSslError(SslError error) {        if (error.getUrl().equals(mCurrentState.mUrl)) {            // The security state should currently be SECURITY_STATE_SECURE.            setSecurityState(SecurityState.SECURITY_STATE_BAD_CERTIFICATE);            mCurrentState.mSslCertificateError = error;        } else if (getSecurityState() == SecurityState.SECURITY_STATE_SECURE) {            // The page's main resource is secure and this error is for a            // sub-resource.            setSecurityState(SecurityState.SECURITY_STATE_MIXED);        }    }

/**         * Called when an SSL error occurred while loading a resource, but the         * WebView but chose to proceed anyway based on a decision retained         * from a previous response to onReceivedSslError(). We update our         * security state to reflect this.         */        @Override        public void onProceededAfterSslError(WebView view, SslError error) {            handleProceededAfterSslError(error);        }

转载于:https://my.oschina.net/sfshine/blog/198022

你可能感兴趣的文章
彼得原理
查看>>
如何利用【百度地图API】,制作房产酒店地图?(下)——结合自己的数据库...
查看>>
[20171113]修改表结构删除列相关问题3.txt
查看>>
特征选择
查看>>
在Winform程序中设置管理员权限及为用户组添加写入权限
查看>>
RTMP直播到FMS中的AAC音频直播
查看>>
多能互补提速 加快我国能源转型和现代能源体系建设
查看>>
《JavaScript设计模式》——2.5 多种调用方式——多态
查看>>
Redis开发运维实践高可用和集群架构与实践(二)
查看>>
程序员的常见“谎话”:对,这是一个已知 Bug
查看>>
如何侦查SQL执行状态
查看>>
CentOS 7 命令行如何连接无线网络
查看>>
Ubuntu 12.04上享用新版本Linux的功能
查看>>
logstash + grok 正则语法
查看>>
Zimbra开源版(v8.6)安装说明
查看>>
Android性能优化之TraceView和Lint使用详解
查看>>
linux centos7.2 安装mysq,nginx,php
查看>>
myrocks之事务处理
查看>>
基于pgrouting的路径规划之一
查看>>
LBS核心技术解析
查看>>