Android Browser學習九 快捷菜單模塊: PieControl的架構

今天介紹一下瀏覽器PieMenu的實現, Piemenu是瀏覽器的一個實驗室功能, 可是其效果仍是挺炫的以下所示: java

估計不少app都的扇形菜單都參考過這個東西.並且這個東西一直起來也不難, 解耦作的仍是比較好的~ android

今天這個文章先介紹一下Piemenu的大體架構, 其UML圖以下:(使用了astah 可能有些類型是錯的, ;懶得一個個改了 請諒解, 咱們須要的是大致架構~)_ web


能夠看到, Piemenu實際上是一個FrameLayout, 遮罩在tab的上層, 這樣用戶點擊這個Layout 若是是在屏幕的邊緣, 就能夠顯示這個 瀏覽器

PieMenu了. 架構

這個PieMenu是徹底的draw的, 給定一個點mCenter而後app就以這個點爲中心, 把每一個PieItem也就是扇葉繪製出來. 對於扇葉的組裝, piemenu的顯示等, 都是PieControl來控制的, 時序圖: mvc


按照時序圖來分析一下: app

添加Piemenu的最開始是在PhoneUI的構造函數中: ide

public PhoneUi(Activity browser, UiController controller) {
        super(browser, controller);
        setUseQuickControls(BrowserSettings.getInstance().useQuickControls()); //設置快速控制菜單,就是那個piemenu
        mNavigationBar = (NavigationBarPhone) mTitleBar.getNavigationBar();
        TypedValue heightValue = new TypedValue();
        browser.getTheme().resolveAttribute(
                com.android.internal.R.attr.actionBarSize, heightValue, true);
        mActionBarHeight = TypedValue.complexToDimensionPixelSize(heightValue.data,
                browser.getResources().getDisplayMetrics());
    }



這裏咱們看到 了BrowserSettings的用法, 不過是讀取了Sharepreference的數據而已.  但這樣作實現全局的setting控制仍是很值得學習的.

而後就是添加PieMenu到PhoneUI的頂層了: 函數

if (useQuickControls) {
            mPieControl = new PieControlPhone(mActivity, mUiController, this);
            mPieControl.attachToContainer(mContentView);//把piemenu添加到contentview之上
            WebView web = getWebView();
            if (web != null) {
                web.setEmbeddedTitleBar(null);
            }
        } else {//若是設置的是關閉 可能須要把以前的移除掉
            if (mPieControl != null) {
                mPieControl.removeFromContainer(mContentView);
            }
            WebView web = getWebView();
            if (web != null) {
                // make sure we can re-parent titlebar
                if ((mTitleBar != null) && (mTitleBar.getParent() != null)) {
                    ((ViewGroup) mTitleBar.getParent()).removeView(mTitleBar);
                }
                web.setEmbeddedTitleBar(mTitleBar);
            }
            setTitleGravity(Gravity.NO_GRAVITY);
        }



attachToContainer是真正的添加到PhoneUI的邏輯, 果真是添加到整個瀏覽器的頂層: 學習

protected void attachToContainer(FrameLayout container) {
        if (mPie == null) {
            mPie = new PieMenu(mActivity);
            LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.MATCH_PARENT);
            mPie.setLayoutParams(lp);
            populateMenu();//添加pieitem
            mPie.setController(this);
        }
        container.addView(mPie);//添加到整個瀏覽器的頂層: }



那塊看一下Piemenu的初始化, 是把PieMenu的畫筆, 顏色. 大小等都初始化了出來:
public PieMenu(Context context) {
        super(context);
        init(context);
    }

    private void init(Context ctx) {
        mItems = new ArrayList<PieItem>();//初始化pie中的item
        mLevels = 0;//peimenu能夠有幾層. 用這個標誌位來標誌是一級菜單仍是二級菜單
        mCounts = new int[MAX_LEVELS];
        Resources res = ctx.getResources();
        mRadius = (int) res.getDimension(R.dimen.qc_radius_start); //內徑
        mRadiusInc = (int) res.getDimension(R.dimen.qc_radius_increment);//外徑 
        mSlop = (int) res.getDimension(R.dimen.qc_slop); //應該是光暈, 周圍有一部分光暈
        mTouchOffset = (int) res.getDimension(R.dimen.qc_touch_offset); //其實這個點擊的中心並非圓形的正中
        mOpen = false;
        setWillNotDraw(false);//自定義了viewgroup的 ondraw  要設置這個爲false這樣才能調用ondraw
        setDrawingCacheEnabled(false); //當調用setDrawingCacheEnabled方法設置爲false, 系統會自動把原來的cache銷燬。減少資源佔用
        mCenter = new Point(0,0);
        mBackground = res.getDrawable(R.drawable.qc_background_normal);//背景
        mNormalPaint = new Paint();
        mNormalPaint.setColor(res.getColor(R.color.qc_normal));//默認是藍色
        mNormalPaint.setAntiAlias(true);
        mSelectedPaint = new Paint();
        mSelectedPaint.setColor(res.getColor(R.color.qc_selected));//選中是黃色
        mSelectedPaint.setAntiAlias(true);
    }



前面說過, PieMenu的填充items是PieContrl來控制的, 也就是populateMenu這個函數來實現的填充扇子,

這個操做在不一樣的設備上展現是不一樣的, 咱們只看在Phone上的展示也就是PieControlPhone:

protected void populateMenu() {
        mUrl = makeItem(R.drawable.ic_web_holo_dark, 1);
        View tabs = makeTabsView();
        mShowTabs = new PieItem(tabs, 1);
        mTabAdapter = new TabAdapter(mActivity, mUiController);//這是展現那個tab的小listview
        PieStackView stack = new PieStackView(mActivity); //這個東西其實是 piemenu 選擇tab的時候顯示的那個tab listview 後面講解.
        stack.setLayoutListener(new OnLayoutListener() {
            @Override
            public void onLayout(int ax, int ay, boolean left) {
                buildTabs();
            }
        });
        stack.setOnCurrentListener(mTabAdapter);
        stack.setAdapter(mTabAdapter);
        mShowTabs.setPieView(stack);//設置tab多窗口的列表
        mOptions = makeItem(com.android.internal.R.drawable.ic_menu_moreoverflow_normal_holo_dark,
                1);

        // level 1
        mNewTab = makeItem(R.drawable.ic_new_window_holo_dark, 1);
        mBookmarks = makeItem(R.drawable.ic_bookmarks_holo_dark, 1);
        mPie.addItem(mNewTab);
        mPie.addItem(mShowTabs);
        mPie.addItem(mUrl);
        mPie.addItem(mBookmarks);
        mPie.addItem(mOptions);
        setClickListener(this, mUrl, mShowTabs, mOptions, mNewTab, mBookmarks);
        mPopup = new PopupMenu(mActivity, mUi.getTitleBar());
        Menu menu = mPopup.getMenu();//顯示menu菜單
        mPopup.getMenuInflater().inflate(R.menu.browser, menu);
        mPopup.setOnMenuItemClickListener(this);
    }



真正的製造Item是在makeItem等函數中:
//生成各類piemenuitem的圖標
    protected PieItem makeItem(int image, int l) {
        ImageView view = new ImageView(mActivity);
        view.setImageResource(image);
        view.setMinimumWidth(mItemSize);
        view.setMinimumHeight(mItemSize);
        view.setScaleType(ScaleType.CENTER);
        LayoutParams lp = new LayoutParams(mItemSize, mItemSize);
        view.setLayoutParams(lp);
        return new PieItem(view, l);
    }



這就是大體的PieMenu的架構了,能夠看到仍是谷歌經常使用的mvc架構, 感受這個架構設計的挺好的, 思路很清晰以及: 

統一的setting模塊.  

業務和展現分開, 

使用繼承來實現手機和平板的適配, 

每一個扇形都是一個PieItem類, 方便未來繪製邏輯以及事件分發邏輯的處理等,

在這個app的頂部遮罩framelayout, 從而實現點擊任何屏幕編譯均可以顯示piemenu

這些都是值得咱們學習的.

這裏還有個移植的小案例:http://blog.csdn.net/libre923045/article/details/7800227

相關文章
相關標籤/搜索