鍒涘缓Window

鍦ˋctivity鐨刟ttach鏂规硶涓€氳繃璋冪敤PolicyManager.makeNewWindo鍒涘缓Window,灏嗕竴涓猇iew add鍒癢indowManager鏃讹紝WindowManagerImpl鍒涘缓涓€涓猇iewRoot鏉ョ鐞嗚绐楀彛鐨勬牴View銆傚苟閫氳繃ViewRoot.setView鏂规硶鎶婅View浼犵粰ViewRoot銆?/span>

        final void attach(Context context, ActivityThread aThread,            Instrumentation instr, IBinder token, int ident,            Application application, Intent intent, ActivityInfo info,            CharSequence title, Activity parent, String id,            NonConfigurationInstances lastNonConfigurationInstances,            Configuration config) {        attachBaseContext(context);        mFragments.attachActivity(this, mContainer, null);                mWindow = PolicyManager.makeNewWindow(this);        mWindow.setCallback(this);        mWindow.getLayoutInflater().setPrivateFactory(this);

鍒涘缓DecorView

DecorView涓烘暣涓猈indow鐣岄潰鐨勬渶椤跺眰View銆?br>

Activity涓殑Window瀵硅薄甯垜浠垱寤轰簡涓€涓狿honeWindow鍐呴儴绫籇ecorView锛堢埗绫讳负FrameLayout锛夌獥鍙i《灞傝鍥撅紝鐒跺悗閫氳繃LayoutInflater灏唜ml鍐呭甯冨眬瑙f瀽鎴怴iew鏍戝舰缁撴瀯娣诲姞鍒癉ecorView椤跺眰瑙嗗浘涓璱d涓篶ontent鐨凢rameLayout鐖跺鍣ㄤ笂闈€侫ctivity鐨刢ontent鍐呭甯冨眬鏈€缁堜細娣诲姞鍒癉ecorView绐楀彛椤跺眰瑙嗗浘涓婇潰銆?/span>

    protected boolean initializePanelDecor(PanelFeatureState st) {        st.decorView = new DecorView(getContext(), st.featureId);        st.gravity = Gravity.CENTER | Gravity.BOTTOM;        st.setStyle(getContext());        return true;    }

鍒涘缓ViewRoot骞跺叧鑱擵iew

WindowManagerImpl淇濆瓨DecorView鍒癿Views锛屽垱寤哄搴旂殑ViewRoot锛?br>

ViewRoot鐢ㄤ簬绠$悊绐楀彛鐨勬牴View锛屽苟鍜実lobal window manger杩涜浜や簰銆俈iewRoot涓湁涓€涓猲ested class锛?W锛學鏄竴涓狟inder瀛愮被锛岀敤浜庢帴鏀秅lobal window manager鐨勫悇绉嶆秷鎭紝 濡傛寜閿秷鎭紝 瑙︽懜娑堟伅绛夈€?ViewRoot鏈変竴涓猈绫诲瀷鐨勬垚鍛榤Window锛孷iewRoot鍦–onstructor涓垱寤轰竴涓猈鐨刬nstance骞惰祴鍊肩粰mWindow銆?ViewRoot鏄疕andler鐨勫瓙绫伙紝 W浼氶€氳繃Looper鎶婃秷鎭紶閫掔粰ViewRoot銆?ViewRoot鍦╯etView鏂规硶涓妸mWindow浼犵粰sWindowSession銆?br>

    public void addView(View view, ViewGroup.LayoutParams params,            Display display, Window parentWindow) {        if (view == null) {            throw new IllegalArgumentException("view must not be null");        }        if (display == null) {            throw new IllegalArgumentException("display must not be null");        }        if (!(params instanceof WindowManager.LayoutParams)) {            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");        }        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;        if (parentWindow != null) {            parentWindow.adjustLayoutParamsForSubWindow(wparams);        }        ViewRootImpl root;        View panelParentView = null;        synchronized (mLock) {            // Start watching for system property changes.            if (mSystemPropertyUpdater == null) {                mSystemPropertyUpdater = new Runnable() {                    @Override public void run() {                        synchronized (mLock) {                            for (ViewRootImpl viewRoot : mRoots) {                                viewRoot.loadSystemProperties();                            }                        }                    }                };                SystemProperties.addChangeCallback(mSystemPropertyUpdater);            }            int index = findViewLocked(view, false);            if (index >= 0) {                throw new IllegalStateException("View " + view                        + " has already been added to the window manager.");            }            // If this is a panel window, then find the window it is being            // attached to for future reference.            if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&                    wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {                final int count = mViews != null ? mViews.length : 0;                for (int i=0; i<count; i++) {                    if (mRoots[i].mWindow.asBinder() == wparams.token) {                        panelParentView = mViews[i];                    }                }            }            root = new ViewRootImpl(view.getContext(), display);            view.setLayoutParams(wparams);            if (mViews == null) {                index = 1;                mViews = new View[1];                mRoots = new ViewRootImpl[1];                mParams = new WindowManager.LayoutParams[1];            } else {                index = mViews.length + 1;                Object[] old = mViews;                mViews = new View[index];                System.arraycopy(old, 0, mViews, 0, index-1);                old = mRoots;                mRoots = new ViewRootImpl[index];                System.arraycopy(old, 0, mRoots, 0, index-1);                old = mParams;                mParams = new WindowManager.LayoutParams[index];                System.arraycopy(old, 0, mParams, 0, index-1);            }            index--;            mViews[index] = view;            mRoots[index] = root;            mParams[index] = wparams;        }        // do this last because it fires off messages to start doing things        try {            root.setView(view, wparams, panelParentView);        } catch (RuntimeException e) {            // BadTokenException or InvalidDisplayException, clean up.            synchronized (mLock) {                final int index = findViewLocked(view, false);                if (index >= 0) {                    removeViewLocked(index, true);                }            }            throw e;        }    }


ViewRoot鏄疓UI绠$悊绯荤粺涓嶨UI鍛堢幇绯荤粺涔嬮棿鐨勬ˉ姊侊紝闇€瑕佹敞鎰忓畠骞朵笉鏄竴涓猇iew绫诲瀷锛屻€?br> 瀹冪殑涓昏浣滅敤濡備笅锛?br> 1銆佸悜DecorView鍒嗗彂鏀跺埌鐨勭敤鎴峰彂璧风殑event浜嬩欢锛屽鎸夐敭锛岃Е灞忥紝杞ㄨ抗鐞冪瓑浜嬩欢锛?br> 2銆佷笌WindowManagerService浜や簰锛屽畬鎴愭暣涓狝ctivity鐨凣UI鐨勭粯鍒躲€?br>

View缁樺埗鍩烘湰娴佺▼

杩欓噷鍏堢粰鍑篈ndroid绯荤粺View鐨勭粯鍒舵祦绋嬶細渚濇鎵цView绫婚噷闈㈢殑濡備笅涓変釜鏂规硶锛?br> measure(int ,int) :娴嬮噺View鐨勫ぇ灏?br> layout(int ,int ,int ,int) 锛氳缃瓙View鐨勪綅缃?br> draw(Canvas) 锛氱粯鍒禫iew鍐呭鍒癈anvas鐢诲竷涓?br>


鏁翠釜View鏍戠殑缁樺浘娴佺▼鏄湪ViewRoot.java绫荤殑performTraversals()鍑芥暟灞曞紑鐨勶紝璇ュ嚱鏁板仛鐨勬墽琛岃繃绋嬪彲绠€鍗曟鍐典负鏍规嵁涔嬪墠璁剧疆鐨勭姸鎬侊紝鍒ゆ柇鏄惁闇€瑕侀噸鏂拌绠楄鍥惧ぇ灏?measure)銆佹槸鍚﹂噸鏂伴渶瑕佸畨缃鍥剧殑浣嶇疆(layout)銆佷互鍙婃槸鍚﹂渶瑕侀噸缁?(draw)

mesarue()娴嬮噺杩囩▼

涓昏浣滅敤锛氫负鏁翠釜View鏍戣绠楀疄闄呯殑澶у皬锛屽嵆璁剧疆瀹為檯鐨勯珮(mMeasuredHeight)鍜屽(mMeasureWidth)锛屾瘡涓猇iew鐨勬帶浠剁殑瀹為檯瀹介珮閮芥槸鐢辩埗瑙嗗浘鍜屾湰韬鍥惧喅瀹氱殑銆?br> 鍏蜂綋鐨勮皟鐢ㄥ涓嬶細

ViewRootImpl 鐨刾erformTraversals鏂规硶涓紝璋冪敤measureHierarchy锛岀劧鍚庤皟鐢╬erformMeasure

 private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");        try {            mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);        } finally {            Trace.traceEnd(Trace.TRACE_TAG_VIEW);        }    }
ViewRoot鏍瑰璞″湴灞炴€View(鍏剁被鍨嬩竴鑸负ViewGroup绫诲瀷)璋冪敤measure()鏂规硶鍘昏绠梀iew鏍戠殑澶у皬锛屽洖璋?
View/ViewGroup瀵硅薄鐨刼nMeasure()鏂规硶锛岃鏂规硶瀹炵幇鐨勫姛鑳藉涓嬶細
1銆佽缃湰View瑙嗗浘鐨勬渶缁堝ぇ灏忥紝璇ュ姛鑳界殑瀹炵幇閫氳繃璋冪敤setMeasuredDimension()鏂规硶鍘昏缃疄闄呯殑楂? (mMeasuredHeight)鍜屽(mMeasureWidth)

2銆佸鏋滆View瀵硅薄鏄釜ViewGroup绫诲瀷锛岄渶瑕侀噸鍐檕nMeasure()鏂规硶锛屽鍏跺瓙瑙嗗浘杩涜閬嶅巻鐨刴easure()杩囩▼銆?br> 瀵规瘡涓瓙瑙嗗浘鐨刴easure()杩囩▼锛屾槸閫氳繃璋冪敤鐖剁被ViewGroup.java绫婚噷鐨刴easureChildWithMargins()鏂规硶鍘诲疄鐜帮紝璇ユ柟娉曞唴閮ㄥ彧鏄畝鍗曞湴璋冪敤浜哣iew瀵硅薄鐨刴easure()鏂规硶銆?br> 鏁翠釜measure璋冪敤娴佺▼灏辨槸涓爲褰㈢殑閫掑綊杩囩▼
measure()鏂规硶涓や釜鍙傛暟閮芥槸鐖禫iew浼犻€掕繃鏉ョ殑锛屼篃灏辨槸浠h〃浜嗙埗view鐨勮鏍笺€備粬鐢变袱閮ㄥ垎缁勬垚锛岄珮2浣嶈〃绀篗ODE锛屽畾涔夊湪MeasureSpec绫伙紙View鐨勫唴閮ㄧ被锛変腑锛屾湁涓夌绫诲瀷锛孧easureSpec.EXACTLY琛ㄧず纭畾澶у皬锛?MeasureSpec.AT_MOST琛ㄧず鏈€澶уぇ灏忥紝 MeasureSpec.UNSPECIFIED涓嶇‘瀹氥€備綆30浣嶈〃绀簊ize锛屼篃灏辨槸鐖禫iew鐨勫ぇ灏忋€傚浜庣郴缁焀indow绫荤殑DecorVIew瀵硅薄Mode涓€鑸兘涓篗easureSpec.EXACTLY 锛岃€宻ize鍒嗗埆瀵瑰簲灞忓箷瀹介珮銆傚浜庡瓙View鏉ヨ澶у皬鏄敱鐖禫iew鍜屽瓙View鍏卞悓鍐冲畾鐨勩€?/span>

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));    }
   protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {        boolean optical = isLayoutModeOptical(this);        if (optical != isLayoutModeOptical(mParent)) {            Insets insets = getOpticalInsets();            int opticalWidth  = insets.left + insets.right;            int opticalHeight = insets.top  + insets.bottom;            measuredWidth  += optical ? opticalWidth  : -opticalWidth;            measuredHeight += optical ? opticalHeight : -opticalHeight;        }        mMeasuredWidth = measuredWidth;        mMeasuredHeight = measuredHeight;        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;    }

layout甯冨眬杩囩▼

涓昏浣滅敤 锛氫负灏嗘暣涓牴鎹瓙瑙嗗浘鐨勫ぇ灏忎互鍙婂竷灞€鍙傛暟灏哣iew鏍戞斁鍒板悎閫傜殑浣嶇疆涓娿€?br> 鍏蜂綋鐨勮皟鐢ㄥ涓嬶細
ViewRootImpl 鐨刾erformTraversals鏂规硶涓紝璋冪敤performLayout
    private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,            int desiredWindowHeight) {        mLayoutRequested = false;        mScrollMayChange = true;        mInLayout = true;        final View host = mView;        if (DEBUG_ORIENTATION || DEBUG_LAYOUT) {            Log.v(TAG, "Laying out " + host + " to (" +                    host.getMeasuredWidth() + ", " + host.getMeasuredHeight() + ")");        }        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "layout");        try {            host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());            mInLayout = false;            int numViewsRequestingLayout = mLayoutRequesters.size();            if (numViewsRequestingLayout > 0) {                // requestLayout() was called during layout.                // If no layout-request flags are set on the requesting views, there is no problem.                // If some requests are still pending, then we need to clear those flags and do                // a full request/measure/layout pass to handle this situation.                ArrayList<View> validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters,                        false);                if (validLayoutRequesters != null) {                    // Set this flag to indicate that any further requests are happening during                    // the second pass, which may result in posting those requests to the next                    // frame instead                    mHandlingLayoutInLayoutRequest = true;                    // Process fresh layout requests, then measure and layout                    int numValidRequests = validLayoutRequesters.size();                    for (int i = 0; i < numValidRequests; ++i) {                        final View view = validLayoutRequesters.get(i);                        Log.w("View", "requestLayout() improperly called by " + view +                                " during layout: running second layout pass");                        view.requestLayout();                    }                    measureHierarchy(host, lp, mView.getContext().getResources(),                            desiredWindowWidth, desiredWindowHeight);                    mInLayout = true;                    host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());                    mHandlingLayoutInLayoutRequest = false;                    // Check the valid requests again, this time without checking/clearing the                    // layout flags, since requests happening during the second pass get noop'd                    validLayoutRequesters = getValidLayoutRequesters(mLayoutRequesters, true);                    if (validLayoutRequesters != null) {                        final ArrayList<View> finalRequesters = validLayoutRequesters;                        // Post second-pass requests to the next frame                        getRunQueue().post(new Runnable() {                            @Override                            public void run() {                                int numValidRequests = finalRequesters.size();                                for (int i = 0; i < numValidRequests; ++i) {                                    final View view = finalRequesters.get(i);                                    Log.w("View", "requestLayout() improperly called by " + view +                                            " during second layout pass: posting in next frame");                                    view.requestLayout();                                }                            }                        });                    }                }            }        } finally {            Trace.traceEnd(Trace.TRACE_TAG_VIEW);        }        mInLayout = false;    }
host.layout()寮€濮媀iew鏍戠殑甯冨眬锛岀户鑰屽洖璋冪粰View/ViewGroup绫讳腑鐨刲ayout()鏂规硶銆傚叿浣撴祦绋嬪涓?
1 銆乴ayout鏂规硶浼氳缃View瑙嗗浘浣嶄簬鐖惰鍥剧殑鍧愭爣杞达紝鍗砿Left锛宮Top锛宮Left锛宮Bottom(璋冪敤setFrame()鍑芥暟鍘诲疄鐜?锛屾帴涓嬫潵鍥炶皟onLayout()鏂规硶(濡傛灉璇iew鏄疺iewGroup瀵硅薄锛岄渶瑕佸疄鐜拌鏂规硶锛屽姣忎釜瀛愯鍥捐繘琛屽竷灞€)銆?
2銆佸鏋滆View鏄釜ViewGroup绫诲瀷锛岄渶瑕侀亶鍘嗘瘡涓瓙瑙嗗浘chiildView锛岃皟鐢ㄨ瀛愯鍥剧殑layout()鏂规硶鍘昏缃畠鐨勫潗鏍囧€笺€?
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {    }
    public void layout(int l, int t, int r, int b) {        int oldL = mLeft;        int oldT = mTop;        int oldB = mBottom;        int oldR = mRight;        boolean changed = isLayoutModeOptical(mParent) ?                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {            onLayout(changed, l, t, r, b);            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;            ListenerInfo li = mListenerInfo;            if (li != null && li.mOnLayoutChangeListeners != null) {                ArrayList<OnLayoutChangeListener> listenersCopy =                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();                int numListeners = listenersCopy.size();                for (int i = 0; i < numListeners; ++i) {                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);                }            }        }        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;    }

draw()缁樺浘杩囩▼

ViewRootImpl 鐨刾erformTraversals鏂规硶涓紝璋冪敤浜唌View鐨刣raw鏂规硶 mView.draw()寮€濮嬬粯鍒讹紝draw()鏂规硶瀹炵幇鐨勫姛鑳藉涓嬶細
1 銆佺粯鍒惰View鐨勮儗鏅?br> 2 銆佷负鏄剧ず娓愬彉妗嗗仛涓€浜涘噯澶囨搷浣?
3銆佽皟鐢╫nDraw()鏂规硶缁樺埗瑙嗗浘鏈韩 (姣忎釜View閮介渶瑕侀噸杞借鏂规硶锛孷iewGroup涓嶉渶瑕佸疄鐜拌鏂规硶)
4銆佽皟鐢╠ispatchDraw ()鏂规硶缁樺埗瀛愯鍥?濡傛灉璇iew绫诲瀷涓嶄负ViewGroup锛屽嵆涓嶅寘鍚瓙瑙嗗浘锛屼笉闇€瑕侀噸杞借鏂规硶)
鍊煎緱璇存槑鐨勬槸锛孷iewGroup绫诲凡缁忎负鎴戜滑閲嶅啓浜哾ispatchDraw ()鐨勫姛鑳藉疄鐜帮紝搴旂敤绋嬪簭涓€鑸笉闇€瑕侀噸鍐欒鏂规硶锛屼絾鍙互閲嶈浇鐖剁被鍑芥暟瀹炵幇鍏蜂綋鐨勫姛鑳姐€?br> dispatchDraw()鏂规硶鍐呴儴浼氶亶鍘嗘瘡涓瓙瑙嗗浘锛岃皟鐢╠rawChild()鍘婚噸鏂板洖璋冩瘡涓瓙瑙嗗浘鐨刣raw()鏂规硶銆?br> 5銆佺粯鍒舵粴鍔ㄦ潯

鍒锋柊瑙嗗浘

Android涓疄鐜皏iew鐨勬洿鏂版湁涓や釜鏂规硶锛屼竴涓槸invalidate锛屽彟涓€涓槸postInvalidate锛屽叾涓墠鑰呮槸鍦║I绾跨▼鑷韩涓娇鐢紝鑰屽悗鑰呭湪闈濽I绾跨▼涓娇鐢ㄣ€?nbsp;
requestLayout()鏂规硶 锛氫細瀵艰嚧璋冪敤measure()杩囩▼ 鍜?layout()杩囩▼ 銆?br> 璇存槑锛氬彧鏄View鏍戦噸鏂板竷灞€layout杩囩▼鍖呮嫭measure()鍜宭ayout()杩囩▼锛屼笉浼氳皟鐢╠raw()杩囩▼锛屼絾涓嶄細閲嶆柊缁樺埗
浠讳綍瑙嗗浘鍖呮嫭璇ヨ皟鐢ㄨ€呮湰韬€?br>

涓€鑸紩璧穒nvalidate()鎿嶄綔鐨勫嚱鏁板涓嬶細
1銆佺洿鎺ヨ皟鐢╥nvalidate()鏂规硶锛岃姹傞噸鏂癲raw()锛屼絾鍙細缁樺埗璋冪敤鑰呮湰韬€?br> 2銆乻etSelection()鏂规硶 锛氳姹傞噸鏂癲raw()锛屼絾鍙細缁樺埗璋冪敤鑰呮湰韬€?br> 3銆乻etVisibility()鏂规硶 锛?褰揤iew鍙鐘舵€佸湪INVISIBLE杞崲VISIBLE鏃讹紝浼氶棿鎺ヨ皟鐢╥nvalidate()鏂规硶锛岀户鑰岀粯鍒惰View銆?br> 4 銆乻etEnabled()鏂规硶 锛?璇锋眰閲嶆柊draw()锛屼絾涓嶄細閲嶆柊缁樺埗浠讳綍瑙嗗浘鍖呮嫭璇ヨ皟鐢ㄨ€呮湰韬€?br>

鍐呭鍙傝€冩簮鐮侊紝鍊熼壌浜嗙綉涓婄殑涓€浜涘垎鏋愩€?/span>


娆㈣繋鎵弿浜岀淮鐮侊紝鍏虫敞鍏紬璐﹀彿


更多相关文章

  1. 代码中设置drawableleft
  2. android 3.0 隐藏 系统标题栏
  3. Android开发中activity切换动画的实现
  4. Android(安卓)学习 笔记_05. 文件下载
  5. Android中直播视频技术探究之—摄像头Camera视频源数据采集解析
  6. 技术博客汇总
  7. android 2.3 wifi (一)
  8. AndRoid Notification的清空和修改
  9. Android中的Chronometer

随机推荐

  1. First Android(安卓)application
  2. 自定义android 机器人
  3. Android_经典控件
  4. 【android】解决Viewpager设置高度为wrap
  5. Android:用ViewPager实现广告栏
  6. 我学习android参考的资料
  7. Android(安卓)JNI入门第三篇——jni头文
  8. 经纬度转度分秒 Java/Android
  9. android 自定义权限
  10. Android(安卓)Studio 配置多个代码仓库(m