当前位置: 首页 > news >正文

老鹰网网站建设做网站都需要哪些技术

老鹰网网站建设,做网站都需要哪些技术,上海天华建筑设计有限公司侯岳,网站做图尺寸大小该系列文章总纲链接#xff1a;专题分纲目录 Android SystemUI组件 本章关键点总结 说明#xff1a; 说明#xff1a;本章节持续迭代之前章节思维导图#xff0c;主要关注左侧最上方SystemUiVisibility解读部分即可。 本章节主要讲解SystemUiVisibility的概念及其相…该系列文章总纲链接专题分纲目录 Android SystemUI组件 本章关键点总结 说明 说明本章节持续迭代之前章节思维导图主要关注左侧最上方SystemUiVisibility解读部分即可。 本章节主要讲解SystemUiVisibility的概念及其相关常用的属性以及在应用中如何使用最后研究下在framework层setSystemUiVisibility的具体实现逻辑及涉及到的一些相关内容。 1 理解SystemUIVisibility 1.1 SysIVisibility 简介 在Android系统中SystemUIVisibility 是普通应用用于控制系统UI元素如状态栏和导航栏可见性的机制。通过设置不同的标志开发者可以控制这些UI元素的显示和隐藏以及它们对应用布局的影响。以下是一些与SystemUIVisibility相关的常用属性 SYSTEM_UI_FLAG_LAYOUT_STABLE当系统栏的可见性改变时保持应用的布局稳定避免内容布局随着系统栏的显示和隐藏而跳动。SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION允许应用的布局扩展到导航栏区域即使导航栏可见。SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN允许应用的布局扩展到状态栏区域即使状态栏可见。SYSTEM_UI_FLAG_HIDE_NAVIGATION隐藏导航栏但用户可以通过滑动屏幕边缘来重新显示导航栏。SYSTEM_UI_FLAG_FULLSCREEN隐藏状态栏但用户可以通过下拉屏幕顶部来重新显示状态栏。SYSTEM_UI_FLAG_IMMERSIVE提供一种沉浸式体验系统栏不会自动显示直到用户执行特定的滑动操作。SYSTEM_UI_FLAG_IMMERSIVE_STICKY类似于SYSTEM_UI_FLAG_IMMERSIVE但系统栏会在一定时间后自动隐藏。SYSTEM_UI_FLAG_LIGHT_STATUS_BAR将状态栏的文字和图标颜色设置为深色以便在浅色背景上清晰可见。 使用setSystemUiVisibility方法时可以通过按位或操作|组合多个标志来实现复杂的系统UI控制。 1.2 解读应用中setSystemUiVisibility方法的使用 在Android中setSystemUiVisibility(int visibility)方法是View类的一部分通常在Activity的某个视图上调用以控制系统UI元素如状态栏和导航栏的可见性。以下是一个普通应用中如何使用setSystemUiVisibility方法的步骤 获取布局中的视图 首先你需要获取到Activity主布局或者特定的视图这取决于你想要影响的UI部分。调用setSystemUiVisibility方法 在视图上调用setSystemUiVisibility方法并传入一个或多个标志的组合这些标志定义了系统UI的可见性。处理onWindowFocusChanged回调 在你的Activity中重写onWindowFocusChanged方法并在其中调用setSystemUiVisibility方法。当窗口焦点发生变化时这个方法会被调用。 下面是一个示例代码展示了如何在Activity中隐藏状态栏 Override public void onWindowFocusChanged(boolean hasFocus) {super.onWindowFocusChanged(hasFocus);if (hasFocus) {// 隐藏状态栏getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // 隐藏导航栏| View.SYSTEM_UI_FLAG_FULLSCREEN // 隐藏状态栏| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);} } 在这个例子中当Activity获得窗口焦点时状态栏和导航栏会被隐藏并且布局会扩展到这些UI元素的区域。 注意setSystemUiVisibility方法在API级别11中引入在31中废除所以如果你的应用支持的最低API级别低于11你需要做兼容性处理。 使用setSystemUiVisibility是控制应用内系统UI元素可见性的简单有效方式。 2 setSystemUiVisibility流程解读framework层分析 2.1 从View的setSystemUiVisibility方法开始解读 接下来开始分析setSystemUiVisibility的实现对应的代码实现如下所示 public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource {private static final boolean DBG false;//...public void setSystemUiVisibility(int visibility) {if (visibility ! mSystemUiVisibility) {mSystemUiVisibility visibility;if (mParent ! null mAttachInfo ! null !mAttachInfo.mRecomputeGlobalAttributes) {mParent.recomputeViewAttributes(this);}}}//... } 过程中除了调用View的可能会调用ViewGroup中的recomputeViewAttributes方法对应的代码实现如下所示 //ViewGrouppublic void recomputeViewAttributes(View child) {if (mAttachInfo ! null !mAttachInfo.mRecomputeGlobalAttributes) {ViewParent parent mParent;if (parent ! null) parent.recomputeViewAttributes(this);}} 但是不管怎样最后一定会调用到ViewRootImpl的recomputeViewAttributes方法对应的代码实现如下 //ViewRootImpl//...//关键流程 step1Overridepublic void recomputeViewAttributes(View child) {checkThread(); // 确保该方法在UI线程中调用if (mView child) {mAttachInfo.mRecomputeGlobalAttributes true; // 设置标志表示需要重新计算全局属性if (!mWillDrawSoon) { // 如果当前没有即将进行的绘制操作scheduleTraversals(); // 调度绘制流程以便更新视图}}}//...//关键流程 step2void scheduleTraversals() {if (!mTraversalScheduled) {mTraversalScheduled true;mTraversalBarrier mHandler.getLooper().postSyncBarrier();//等待系统垂直刷新同步信号回调TraversalRunnable对象的run方法mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);if (!mUnbufferedInputDispatch) {scheduleConsumeBatchedInput();}notifyRendererOfFramePending();}}//...//关键流程 step3final class TraversalRunnable implements Runnable {Overridepublic void run() {doTraversal();}}//...//关键流程 step4void doTraversal() {if (mTraversalScheduled) {mTraversalScheduled false;mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);if (mProfile) {Debug.startMethodTracing(ViewAncestor);}Trace.traceBegin(Trace.TRACE_TAG_VIEW, performTraversals);try {//执行performTraversalsperformTraversals();} finally {Trace.traceEnd(Trace.TRACE_TAG_VIEW);}if (mProfile) {Debug.stopMethodTracing();mProfile false;}}}//...//关键流程 step5private void performTraversals() {// cache mView since it is used so much below...final View host mView;if (host null || !mAdded)return;mIsInTraversal true;mWillDrawSoon true;boolean windowSizeMayChange false;boolean newSurface false;boolean surfaceChanged false;WindowManager.LayoutParams lp mWindowAttributes;int desiredWindowWidth;int desiredWindowHeight;final int viewVisibility getHostVisibility();boolean viewVisibilityChanged mViewVisibility ! viewVisibility|| mNewSurfaceNeeded;WindowManager.LayoutParams params null;if (mWindowAttributesChanged) {mWindowAttributesChanged false;surfaceChanged true;params lp;}CompatibilityInfo compatibilityInfo mDisplayAdjustments.getCompatibilityInfo();//...//收集mView的属性判断是否需要更新paramsif (collectViewAttributes()) {params lp;}//...//此方法最终会触发WindowManagerService的relayoutWindow方法relayoutWindow(params, viewVisibility, insetsPending);//... performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);//测量逻辑//... performLayout(lp, mWidth, mHeight);//布局逻辑//... performDraw();//绘制逻辑//...}接下来我们要关注2个关键的方法调用 collectViewAttributes方法重新计算最新的SystemUIVisibility属性。relayoutWindow方法重新布局流程较长最终影响系统状态栏StatusBar对SystemUIVisibility属性的处理。 接下来的2.2 和 2.3 分别以这2个方法为入口进行代码的分析和解读。 2.2 解读collectViewAttributes方法 ViewRootImpl的collectViewAttributes方法代码实现如下 //ViewRootImplprivate boolean collectViewAttributes() {// 检查是否需要重新计算全局属性if (mAttachInfo.mRecomputeGlobalAttributes) {// 重置全局属性重新计算标志mAttachInfo.mRecomputeGlobalAttributes false;// 保存旧的屏幕保持状态boolean oldScreenOn mAttachInfo.mKeepScreenOn;// 初始化屏幕保持标志为falsemAttachInfo.mKeepScreenOn false;// 重置系统UI可见性标志mAttachInfo.mSystemUiVisibility 0;// 重置系统UI监听器标志mAttachInfo.mHasSystemUiListeners false;// 通知视图分发收集视图属性mView.dispatchCollectViewAttributes(mAttachInfo, 0);// 应用视图分发时设置的系统UI可见性标志并考虑被禁用的标志mAttachInfo.mSystemUiVisibility ~mAttachInfo.mDisabledSystemUiVisibility;WindowManager.LayoutParams params mWindowAttributes;// 获取布局参数中隐含的系统UI可见性标志mAttachInfo.mSystemUiVisibility | getImpliedSystemUiVisibility(params);// 检查屏幕保持标志、系统UI可见性标志和系统UI监听器是否有变化if (mAttachInfo.mKeepScreenOn ! oldScreenOn|| mAttachInfo.mSystemUiVisibility ! params.subtreeSystemUiVisibility|| mAttachInfo.mHasSystemUiListeners ! params.hasSystemUiListeners) {// 应用保持屏幕打开的标志applyKeepScreenOnFlag(params);// 更新布局参数中的系统UI可见性标志params.subtreeSystemUiVisibility mAttachInfo.mSystemUiVisibility;// 更新布局参数中的系统UI监听器标志params.hasSystemUiListeners mAttachInfo.mHasSystemUiListeners;// 分发系统UI可见性变化事件mView.dispatchWindowSystemUiVisiblityChanged(mAttachInfo.mSystemUiVisibility);return true;// 返回true表示属性有变化}}return false;// 返回false表示属性没有变化} 该方法会清空当前窗口视图的SystemUiVisibility属性mAttachInfo.mSystemUiVisibility 0然后调用View的dispatchCollectViewAttributes方法重新获取最新的的SystemUiVisibility属性。接下来我们分析View的dispatchCollectViewAttributes和dispatchWindowSystemUiVisiblityChanged方法。 2.2.1 dispatchCollectViewAttributes方法分析 dispatchCollectViewAttributes的目的是遍历视图树并收集所有视图的属性特别是与系统 UI 相关的属性如系统栏的可见性SystemUIVisibility。代码实现如下 //View//...//关键流程 step1void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {performCollectViewAttributes(attachInfo, visibility);}//...//关键流程 step2void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {if ((visibility VISIBILITY_MASK) VISIBLE) {if ((mViewFlags KEEP_SCREEN_ON) KEEP_SCREEN_ON) {attachInfo.mKeepScreenOn true;}//将新的systemuivisiblity赋予attachInfo.mSystemUiVisibilityattachInfo.mSystemUiVisibility | mSystemUiVisibility;ListenerInfo li mListenerInfo;// 如果监听器信息不为空并且设置了系统UI可见性变化的监听器if (li ! null li.mOnSystemUiVisibilityChangeListener ! null) {// 设置AttachInfo的mHasSystemUiListeners为trueattachInfo.mHasSystemUiListeners true;}}}这里performCollectViewAttributes方法的主要作用是收集视图的属性并将这些属性更新到AttachInfo对象中。这些属性包括屏幕保持标志和系统UI可见性标志以及是否有监听器需要响应系统UI可见性的变化。这些信息对于视图的正确显示和系统UI的控制非常重要。 2.2.2 dispatchWindowSystemUiVisiblityChanged方法分析 View的dispatchWindowSystemUiVisiblityChanged方法是在系统 UI 可见性发生变化时分发这些变化通知给视图树中的所有相关视图。这些变化可能包括状态栏和导航栏的显示或隐藏以及它们的外观如颜色、图标颜色等。代码实现如下 //View//...//关键流程 step1public void dispatchWindowSystemUiVisiblityChanged(int visible) {onWindowSystemUiVisibilityChanged(visible);}//关键流程 step2public void onWindowSystemUiVisibilityChanged(int visible) {} 默认的View对onWindowSystemUiVisibilityChanged的实现为空但如果是DecorView则代码实现为 //PhoneWindow//DecorViewOverridepublic void onWindowSystemUiVisibilityChanged(int visible) {updateColorViews(null /* insets */);}private WindowInsets updateColorViews(WindowInsets insets) {WindowManager.LayoutParams attrs getAttributes();int sysUiVisibility attrs.systemUiVisibility | getWindowSystemUiVisibility();if (!mIsFloating ActivityManager.isHighEndGfx()) { //如果不是悬浮窗且设备支持高端图形if (insets ! null) { // 如果有系统窗口插入// 更新状态栏和导航栏底部的插入距离mLastTopInset Math.min(insets.getStableInsetTop(), insets.getSystemWindowInsetTop());mLastBottomInset Math.min(insets.getStableInsetBottom(), insets.getSystemWindowInsetBottom());mLastRightInset Math.min(insets.getStableInsetRight(), insets.getSystemWindowInsetRight());}// 更新状态栏颜色视图mStatusColorView updateColorViewInt(mStatusColorView, sysUiVisibility,SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,mStatusBarColor, mLastTopInset, Gravity.TOP,STATUS_BAR_BACKGROUND_TRANSITION_NAME,com.android.internal.R.id.statusBarBackground,(getAttributes().flags FLAG_FULLSCREEN) ! 0);// 更新导航栏颜色视图mNavigationColorView updateColorViewInt(mNavigationColorView, sysUiVisibility,SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,mNavigationBarColor, mLastBottomInset, Gravity.BOTTOM,NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,com.android.internal.R.id.navigationBarBackground,false /* hiddenByWindowFlag */);}// 处理窗口布局参数和系统UI可见性标志以确定是否消费了导航栏空间boolean consumingNavBar (attrs.flags FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) ! 0 (sysUiVisibility SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) 0 (sysUiVisibility SYSTEM_UI_FLAG_HIDE_NAVIGATION) 0;int consumedRight consumingNavBar ? mLastRightInset : 0;int consumedBottom consumingNavBar ? mLastBottomInset : 0;// 如果内容根视图存在并且其布局参数是MarginLayoutParams类型if (mContentRoot ! null mContentRoot.getLayoutParams() instanceof MarginLayoutParams) {MarginLayoutParams lp (MarginLayoutParams) mContentRoot.getLayoutParams();// 如果消费的右边或底部距离发生变化则更新布局参数if (lp.rightMargin ! consumedRight || lp.bottomMargin ! consumedBottom) {lp.rightMargin consumedRight;lp.bottomMargin consumedBottom;mContentRoot.setLayoutParams(lp);if (insets null) { // 如果当前没有分发系统窗口插入// 请求应用系统窗口插入requestApplyInsets();}}// 如果有系统窗口插入更新插入信息if (insets ! null) {insets insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(),insets.getSystemWindowInsetTop(),insets.getSystemWindowInsetRight() - consumedRight,insets.getSystemWindowInsetBottom() - consumedBottom);}}// 如果有系统窗口插入消费稳定的插入部分if (insets ! null) {insets insets.consumeStableInsets();}return insets; // 返回更新后的系统窗口插入信息} updateColorViews 方法的主要目的是更新窗口中状态栏和导航栏的背景色以及处理系统窗口插入的逻辑。这确保了窗口的 UI 与系统UI可见性标志和窗口布局参数保持同步从而提供一致的用户体验。 2.3 解读relayoutWindow方法 2.3.1 主流程ViewRootImpl的relayoutWindow分析 ViewRootImpl的relayoutWindow代码实现如下所示 //ViewRootImplprivate int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,boolean insetsPending) throws RemoteException {//...int relayoutResult mWindowSession.relayout(mWindow, mSeq, params,(int) (mView.getMeasuredWidth() * appScale 0.5f),(int) (mView.getMeasuredHeight() * appScale 0.5f),viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,mPendingStableInsets, mPendingConfiguration, mSurface);//...return relayoutResult;}调用relayoutWindow方法该方法主要是调用IWindowSession的relayout方法Session的relayout方法代码如下所示 //Sessionpublic int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,int requestedWidth, int requestedHeight, int viewFlags,int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig,Surface outSurface) {//...int res mService.relayoutWindow(this, window, seq, attrs,requestedWidth, requestedHeight, viewFlags, flags,outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,outStableInsets, outConfig, outSurface);//...return res;} 该方法主要是调用WindowManagerService的relayout方法WindowManagerService的relayout方法代码如下所示 //WindowManagerService//...//关键流程step1public int relayoutWindow(Session session, IWindow client, int seq,WindowManager.LayoutParams attrs, int requestedWidth,int requestedHeight, int viewVisibility, int flags,Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig,Surface outSurface) {boolean toBeDisplayed false; // 标记窗口是否将要被显示boolean inTouchMode; // 当前是否处于触摸模式boolean configChanged; // 标记配置是否改变boolean surfaceChanged false; // 标记表面是否改变boolean animating; // 窗口是否正在动画中//是否有状态栏的使用权限boolean hasStatusBarPermission mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) PackageManager.PERMISSION_GRANTED;// 清除调用者身份防止身份伪造long origId Binder.clearCallingIdentity();synchronized(mWindowMap) {//...//如果焦点可能改变更新焦点窗口if (focusMayChange) {if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,false /*updateInputWindows*/)) {imMayMove false;}}//...}//构造返回值表示窗口重新布局的结果return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)| (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)| (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)| (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);}//...//关键流程step2private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {// 计算当前应该获得焦点的窗口WindowState newFocus computeFocusedWindowLocked();// 如果新的焦点窗口与当前的不一样if (mCurrentFocus ! newFocus) {// 移除之前的焦点改变消息发送新的焦点改变消息mH.removeMessages(H.REPORT_FOCUS_CHANGE);mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);// 获取默认显示内容final DisplayContent displayContent getDefaultDisplayContentLocked();// 如果需要移动输入法窗口final boolean imWindowChanged moveInputMethodWindowsIfNeededLocked(mode ! UPDATE_FOCUS_WILL_ASSIGN_LAYERS mode ! UPDATE_FOCUS_WILL_PLACE_SURFACES);// 如果输入法窗口发生了变化重新计算焦点if (imWindowChanged) {displayContent.layoutNeeded true;newFocus computeFocusedWindowLocked();}// 更新当前焦点窗口final WindowState oldFocus mCurrentFocus;mCurrentFocus newFocus;mLosingFocus.remove(newFocus);// 如果启用了辅助功能并且焦点窗口在默认显示上通知辅助功能控制器if (mAccessibilityController ! null displayContent.getDisplayId() Display.DEFAULT_DISPLAY) {mAccessibilityController.onWindowFocusChangedLocked();}// 通知PhoneWindowManager焦点变化int focusChanged mPolicy.focusChangedLw(oldFocus, newFocus);//...// 返回true表示焦点确实发生了变化return true;}// 如果焦点没有变化返回falsereturn false;}relayout方法的主要负责处理窗口的重新布局和显示。它涉及权限检查、同步操作、窗口参数调整、系统 UI 可见性处理、焦点更新等多个关键步骤以确保窗口的正确显示和交互。 这里我们主要关注了updateFocusedWindowLocked方法该方法用于更新获得焦点的窗口并处理与焦点变化相关的一系列操作包括输入法窗口的移动、辅助功能的更新、窗口政策的焦点变化通知、布局执行等。如果焦点发生变化该方法返回true否则返回false。 在updateFocusedWindowLocked方法中我们关注通知PhoneWindowManager焦点变化的方法mPolicy.focusChangedLw。PhoneWindowManager中的focusChangedLw方法代码实现如下 //PhoneWindowManager//...//关键流程 step1Overridepublic int focusChangedLw(WindowState lastFocus, WindowState newFocus) {mFocusedWindow newFocus;if ((updateSystemUiVisibilityLw()SYSTEM_UI_CHANGING_LAYOUT) ! 0) {return FINISH_LAYOUT_REDO_LAYOUT;}return 0;}//...//关键流程 step2private int updateSystemUiVisibilityLw() {WindowState win mFocusedWindow ! null ? mFocusedWindow : mTopFullscreenOpaqueWindowState;int tmpVisibility PolicyControl.getSystemUiVisibility(win, null) ~mResettingSystemUiFlags ~mForceClearedSystemUiFlags;// 如果正在强制显示导航栏并且当前窗口的层次低于强制显示的层次则清除可清除的标记if (mForcingShowNavBar win.getSurfaceLayer() mForcingShowNavBarLayer) {tmpVisibility ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);}// 更新系统栏的可见性final int visibility updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);// 计算新旧可见性标记的差异final int diff visibility ^ mLastSystemUiFlags;// 检查当前窗口是否需要菜单final boolean needsMenu win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);// 如果没有差异并且菜单需求没有变化并且焦点应用没有变化则直接返回if (diff 0 mLastFocusNeedsMenu needsMenu mFocusedApp win.getAppToken()) {return 0;}// 更新最后的系统UI可见性标记mLastSystemUiFlags visibility;mLastFocusNeedsMenu needsMenu;mFocusedApp win.getAppToken();// 在主线程中异步更新状态栏服务mHandler.post(new Runnable() {Overridepublic void run() {try {//获取StatusBarManagerService服务IStatusBarService statusbar getStatusBarService();if (statusbar ! null) {// 调用状态栏服务的setSystemUiVisibility方法更新状态栏和导航栏的可见性statusbar.setSystemUiVisibility(visibility, 0xffffffff);statusbar.topAppWindowChanged(needsMenu);}} catch (RemoteException e) {mStatusBarService null;}}});// 返回差异标记return diff;} updateSystemUiVisibilityLw方法的主要作用是更新系统UI的可见性包括状态栏和导航栏的可见性。它通过计算当前窗口的系统UI可见性标记处理导航栏强制显示的情况然后异步更新状态栏服务来实现。这个方法确保了系统UI的可见性与窗口的状态保持同步。同时这里调用状态栏管理服务StatusBarManagerService的setSystemUiVisibility方法通知状态栏和底部栏进行样式调整。 StatusBarManagerService的setSystemUiVisibility方法代码实现如下 //StatusBarManagerServiceprivate volatile IStatusBar mBar;//...//关键流程 step1public void setSystemUiVisibility(int vis, int mask) {// also allows calls from window manager which is in this process.enforceStatusBarService();synchronized (mLock) {updateUiVisibilityLocked(vis, mask);disableLocked(mCurrentUserId,vis StatusBarManager.DISABLE_MASK,mSysUiVisToken,WindowManager.LayoutParams);}}//...//关键流程 step2private void updateUiVisibilityLocked(final int vis, final int mask) {if (mSystemUiVisibility ! vis) {mSystemUiVisibility vis;mHandler.post(new Runnable() {public void run() {if (mBar ! null) {try {mBar.setSystemUiVisibility(vis, mask);} catch (RemoteException ex) {}}}});}} 这里继续分析mBar.setSystemUiVisibility的方法实现mBar是IStatusBar 类型的参照文章 Android SystemUI组件05状态栏-系统状态图标显示管理中2.2 部分可知。这里涉及到的mBar实际上是 CommandQueue它继承了IStatusBar.Stub类型。因此继续分析mBar对应类型CommandQueue的setSystemUiVisibility方法。具体实现如下 //CommandQueue//...//关键流程 step1public void setSystemUiVisibility(int vis, int mask) {synchronized (mList) {mHandler.removeMessages(MSG_SET_SYSTEMUI_VISIBILITY);mHandler.obtainMessage(MSG_SET_SYSTEMUI_VISIBILITY, vis, mask, null).sendToTarget();}}//...//关键流程 step2,handler处理消息private final class H extends Handler {public void handleMessage(Message msg) {final int what msg.what MSG_MASK;switch (what) {//...case MSG_SET_SYSTEMUI_VISIBILITY:mCallbacks.setSystemUiVisibility(msg.arg1, msg.arg2);break;//...}}} 这个主逻辑线最终执行到了mCallbacks的setSystemUiVisibility。至此这条线就结束了接下来主要看mCallbacks是如何赋值的即可。 2.3.2 基于mCallbacks赋值的分析和深入解读 mCallbacks是在CommandQueue初始化时进行赋值的代码如下所示 //CommandQueue//callback在CommandQueue构造时的初始化public CommandQueue(Callbacks callbacks, StatusBarIconList list) {mCallbacks callbacks;mList list;} 使用CommandQueue初始化的位置只有BaseStatusBar中有一个new的操作代码如下所示 //BaseStatusBarpublic void start() {mWindowManager (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);mWindowManagerService WindowManagerGlobal.getWindowManagerService();mDisplay mWindowManager.getDefaultDisplay();//...mCommandQueue new CommandQueue(this, iconList);//...} 这里传递的this实际上是PhoneStatusBar即BaseStatusBar的子类该部分如不理解可参考文章Android SystemUI组件05状态栏-系统状态图标显示管理。基于此接下来分析PhoneStatusBar的setSystemUiVisibility方法实现代码如下 //PhoneStatusBar//...//关键流程 step1public void setSystemUiVisibility(int vis, int mask) {// 获取旧的系统UI可见性值final int oldVal mSystemUiVisibility;// 计算新的系统UI可见性值final int newVal (oldVal ~mask) | (vis mask);final int diff newVal ^ oldVal;// 如果有差异执行更新操作if (diff ! 0) {// 保存最近应用可见性的状态final boolean wasRecentsVisible (mSystemUiVisibility View.RECENT_APPS_VISIBLE) 0;// 更新系统UI可见性值mSystemUiVisibility newVal;//...// 计算状态栏模式final int sbMode computeBarMode(oldVal, newVal, mStatusBarView.getBarTransitions(),View.STATUS_BAR_TRANSIENT, View.STATUS_BAR_TRANSLUCENT);// 计算导航栏模式final int nbMode mNavigationBarView null ? -1 : computeBarMode(oldVal, newVal, mNavigationBarView.getBarTransitions(),View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT);final boolean sbModeChanged sbMode ! -1;final boolean nbModeChanged nbMode ! -1;boolean checkBarModes false;// 如果状态栏模式发生变化更新状态栏模式if (sbModeChanged sbMode ! mStatusBarMode) {mStatusBarMode sbMode;checkBarModes true;}// 如果导航栏模式发生变化更新导航栏模式if (nbModeChanged nbMode ! mNavigationBarMode) {mNavigationBarMode nbMode;checkBarModes true;}// 如果状态栏或导航栏模式发生变化检查模式if (checkBarModes) {checkBarModes();}// 如果状态栏或导航栏模式发生变化更新显示if (sbModeChanged || nbModeChanged) {// 更新临时栏自动隐藏if (mStatusBarMode MODE_SEMI_TRANSPARENT || mNavigationBarMode MODE_SEMI_TRANSPARENT) {scheduleAutohide();} else {cancelAutohide();}}// 准备取消隐藏if ((vis View.STATUS_BAR_UNHIDE) ! 0) {mSystemUiVisibility ~View.STATUS_BAR_UNHIDE;}if ((vis View.NAVIGATION_BAR_UNHIDE) ! 0) {mSystemUiVisibility ~View.NAVIGATION_BAR_UNHIDE;}// 恢复最近应用可见性的状态if (wasRecentsVisible) {mSystemUiVisibility | View.RECENT_APPS_VISIBLE;}// 通知窗口管理器系统UI可见性发生变化notifyUiVisibilityChanged(mSystemUiVisibility);}}//...//关键流程 step2private void notifyUiVisibilityChanged(int vis) {try {mWindowManagerService.statusBarVisibilityChanged(vis);} catch (RemoteException ex) {}} setSystemUiVisibility方法用于控制系统UI元素的可见性包括状态栏、导航栏和最近应用栏。它通过计算新的可见性值更新低功耗模式计算和更新状态栏和导航栏的模式以及通知窗口管理器可见性变化来实现。 接下来继续分析WindowManagerService.statusBarVisibilityChanged方法的实现代码如下 //WindowManagerService//...//关键流程 step1public void statusBarVisibilityChanged(int visibility) {//...synchronized (mWindowMap) {mLastStatusBarVisibility visibility;//调整可见性visibility mPolicy.adjustSystemUiVisibilityLw(visibility);//更新窗口可见性updateStatusBarVisibilityLocked(visibility);}}//...//关键流程 step2void updateStatusBarVisibilityLocked(int visibility) {// 通知输入管理器系统UI可见性的变化mInputManager.setSystemUiVisibility(visibility);// 获取默认窗口列表final WindowList windows getDefaultWindowListLocked();// 遍历所有窗口final int N windows.size();for (int i 0; i N; i) {WindowState ws windows.get(i);try {// 获取当前窗口的系统UI可见性值int curValue ws.mSystemUiVisibility;// 计算当前值与新值的差异int diff curValue ^ visibility;// 只关注可清除标志位的差异diff View.SYSTEM_UI_CLEARABLE_FLAGS;// 如果标志位实际上已经被清除了diff ~visibility;// 计算新的系统UI可见性值int newValue (curValue ~diff) | (visibility diff);// 如果新值与当前值不同则更新窗口的系统UI可见性值和序列号if (newValue ! curValue) {ws.mSeq;ws.mSystemUiVisibility newValue;}// 如果值有变化或者窗口有系统UI监听器则分发系统UI可见性变化事件if (newValue ! curValue || ws.mAttrs.hasSystemUiListeners) {ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,visibility, newValue, diff);}} catch (RemoteException e) {// 如果发生远程异常忽略该窗口// so sorry}}} updateStatusBarVisibilityLocked方法的主要作用是更新状态栏的可见性。它通过遍历所有窗口计算系统UI可见性的变化然后更新每个窗口的状态并分发系统UI可见性变化事件。这个方法确保了所有窗口的系统UI可见性与当前状态保持同步。至此setSystemUiVisibility的流程基本上就分析结束了。 总之通过上面的一系列流程从View的setSystemUiVisibility方法一直到PhoneStatusBar自己的setSystemUiVisibility方法执行也会通过WMS将对应的SystemUiVisibility属性更新每个窗口的状态。这样下一次UI更新时会根据具体的属性显示对应的样式。
http://www.hkea.cn/news/14372437/

相关文章:

  • 网站设计制作的特点有哪些大型门户网站系统
  • 宝安网站制作网站建设女生做网站编辑好不好
  • 做论坛网站看什么书知末网室内设计效果图
  • 梧州网站建设费用彭州建设局网站
  • 工程机械外贸网站建设wordpress博客搬家
  • title 镇江网站建设安徽seo优化
  • 网站制作网站开发公司徐州网站
  • 注册个网站怎么注册什么是优化设计
  • 豆瓣wordpress主题淘宝seo是什么意思
  • 查找公司信息的网站网站开发与服务器匹配
  • 网站建设策划怎么沟通做一个网站需要多少时间
  • 如何提高网站百度权重在网上怎么开店卖东西
  • 做程序员招聘的网站网课系统软件网站建设费用
  • 华泰保险公司官方网站百度不收录手机网站吗
  • 响应式网站开发工具网页制作实战视频
  • 宁波市住房与城乡建设部网站装修平台代理
  • 西安手机网站建设公司深圳电子烟网站建设
  • 网站开发销售话术呼和浩特住房和城乡建设部网站
  • 广州网站建设工程网站开发都用php
  • 网站网页建设与维护wordpress商城 淘宝客
  • 登烈建站企业电子商务网站建设规划报告
  • php网站运行很慢专业做网站的技术人员
  • seo优化网站教程logo设计网站知乎
  • 做外贸必须知道的网站项目网络图例题
  • 佛山网站建设小程序亚马逊跨境电商开店流程及费用
  • 繁体网站模板顺的品牌网站设计信息
  • 企业营销型网站做的好xp系统做局域网内网站
  • 连云港建网站公司游标卡尺 东莞网站建设
  • PHP网站建设的基本流程网站域名怎么写
  • 网站链接怎么做jquery在网站开发实例运用