WMS 窗口属性

news2024/12/23 6:23:03

WMS 窗口属性

  • 1、窗口类型与层级
    • 1.1 Application Window普通应用程序窗口
    • 1.2 Sub Window子窗口
    • 1.3 System Window系统窗口
  • 2、层级值与窗口类型
    • 2.1 WindowState
    • 2.2 WindowManagerPolicy 窗口管理的策略机制
    • 2.3 WindowToken句柄
  • 3、窗口属性 LayoutParams

Activity的预览窗口StartingWindow添加
Activity窗口的添加过程
WMS:系统窗口添加过程
android12-release


1、窗口类型与层级

Android中的“窗口”类型有很多,一般可统一划分三大类:Application WindowSystem WindowSub Window
在这里插入图片描述
frameworks/base/core/java/android/view/WindowManager.java # android.view.WindowManager.LayoutParams
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
frameworks/base/services/core/java/com/android/server/policy/WindowManagerPolicy.java


Application Window窗口类型范围:1-99
System Window窗口类型范围:1000-1999
Sub Window窗口类型范围:2000-2999

1.1 Application Window普通应用程序窗口

应用程序窗口类型 Type 从FIRST_Application_WINDOW到LAST_Application_WINDOW,是普通的顶级应用程序窗口。对于这些类型的窗口,token必须设置为它们所属活动的token

窗口类型 Type描述
FIRST_APPLICATION_WINDOW = 1表示普通应用程序窗口的窗口类型的开始。
TYPE_BASE_APPLICATION = 1窗口类型:作为整个应用的“基础”窗口的应用窗口;所有其他应用程序窗口将出现在其顶部。在多用户系统中,仅在拥有用户的窗口中显示。
TYPE_APPLICATION = 2窗口类型:普通应用窗口。令牌必须是标识窗口所属对象的活动令牌。在多用户系统中,仅在拥有用户的窗口中显示。
TYPE_APPLICATION_STARTING = 3窗口类型:应用程序启动时显示的特殊应用程序窗口。不供应用程序本身使用;系统使用它来显示某些内容,直到应用程序可以显示自己的窗口。在多用户系统中,显示在所有用户的窗口中。
TYPE_DRAWN_APPLICATION = 4窗口类型:TYPE_APPLICATION的变体,可确保窗口管理器在显示应用程序之前等待绘制此窗口。在多用户系统中,仅在拥有用户的窗口中显示。
LAST_APPLICATION_WINDOW = 99应用程序窗口类型的最大值。

窗口属性(LayoutParams)中Type设置:
frameworks/base/core/java/android/app/ActivityThread.java
handleResumeActivity()l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;

1.2 Sub Window子窗口

子窗口类型 Type 从FIRST_Sub_WINDOW到LAST_Sub_WINDOW,与另一个顶级窗口相关联。对于这些类型的窗口,token必须是它所附加的窗口的token

窗口类型 Type描述
FIRST_SUB_WINDOW = 1000子窗口类型的开始。这些窗口的token必须设置为它们附加到的窗口。这些类型的窗口按 Z 顺序保留在其附加窗口旁边,其坐标空间相对于其附加窗口。
TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW窗口类型:应用程序窗口顶部的面板。这些窗口显示在附加窗口的顶部。
TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1窗口类型:用于显示媒体(如视频)的窗口。这些窗口显示在附加的窗口后面。
TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2窗口类型:应用程序窗口顶部的子面板。这些窗口显示在其附加窗口和任何TYPE_APPLICATION_PANEL面板的顶部。
TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3窗口类型:与TYPE_APPLICATION_PANEL类似,但窗口的布局作为顶级窗口的布局发生,而不是作为其容器的子窗口。
TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4窗口类型:用于在媒体窗口顶部显示叠加层的窗口。这些窗口显示在TYPE_APPLICATION_MEDIA和应用程序窗口之间。它们应该是半透明的才能有用。这是一个丑陋的大黑客,所以:@hide
TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5窗口类型:应用程序窗口顶部的上方子面板及其子面板窗口。这些窗口显示在它们附加的窗口和任何TYPE_APPLICATION_SUB_PANEL面板的顶部。
LAST_SUB_WINDOW = 1999子窗口类型的最大值。

1.3 System Window系统窗口

系统窗口类型 Type 从FIRST_System_WINDOW到LAST_System_WINDEW,是系统用于特定目的的特殊类型的窗口。它们通常不应被应用程序使用,并且需要获得特殊许可才能使用。

窗口类型 Type描述
FIRST_SYSTEM_WINDOW = 2000系统特定的窗口类型的开始。这些通常不是由应用程序创建的。
TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW窗口类型:状态栏。只能有一个状态栏窗口;它放置在屏幕顶部,所有其他窗口都向下移动,因此它们位于屏幕下方。在多用户系统中,显示在所有用户的窗口中。
TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1窗口类型:搜索栏。只能有一个搜索栏窗口;它位于屏幕顶部。在多用户系统中,显示在所有用户的窗口中。
TYPE_PHONE = FIRST_SYSTEM_WINDOW+2窗口类型:电话。这些是提供用户与电话交互(特别是传入呼叫)的非应用程序窗口。这些窗口通常放置在所有应用程序的上方,但位于状态栏后面。在多用户系统中,显示在所有用户的窗口中。已弃用非系统应用。请改用TYPE_APPLICATION_OVERLAY
TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3窗口类型:系统窗口,如低电量报警。这些窗口始终位于应用程序窗口的顶部。在多用户系统中,仅在拥有用户的窗口中显示。已弃用非系统应用。请改用TYPE_APPLICATION_OVERLAY
TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4窗口类型:键盘锁窗口。在多用户系统中,显示在所有用户的窗口中。
TYPE_TOAST = FIRST_SYSTEM_WINDOW+5窗口类型:瞬态通知。在多用户系统中,仅在拥有用户的窗口中显示。已弃用非系统应用。请改用TYPE_APPLICATION_OVERLAY
TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6窗口类型:系统覆盖窗口,需要显示在其他所有窗口之上。这些窗口不得采用输入焦点,否则会干扰键盘锁。在多用户系统中,仅在拥有用户的窗口中显示。已弃用非系统应用。请改用TYPE_APPLICATION_OVERLAY
TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7窗口类型:优先手机UI,即使键盘锁处于活动状态也需要显示。这些窗口不得采用输入焦点,否则会干扰键盘锁。在多用户系统中,显示在所有用户的窗口中。已弃用非系统应用。请改用TYPE_APPLICATION_OVERLAY
TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8窗口类型:从状态栏中滑出的面板。在多用户系统中显示在所有用户的窗口中。
TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9窗口类型:键盘锁。在多用户系统中显示的对话框显示在所有用户的窗口中。
TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10窗口类型:内部系统错误窗口,出现在所有可能之上。在多用户系统中,仅在拥有用户的窗口中显示。已弃用非系统应用。请改用TYPE_APPLICATION_OVERLAY
TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11窗口类型:内部输入法窗口,显示在普通 UI 上方。可以调整应用程序窗口的大小或平移,以便在显示此窗口时保持输入焦点可见。在多用户系统中,仅在拥有用户的窗口中显示。
TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12窗口类型:内部输入法对话框窗口,显示在当前输入法窗口上方。在多用户系统中,仅在拥有用户的窗口中显示。
TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13窗口类型:墙纸窗口,放置在任何想要坐在墙纸顶部的窗户后面。在多用户系统中,仅在拥有用户的窗口中显示。
TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14窗口类型:从状态栏上方滑出的面板。在多用户系统中显示在所有用户的窗口中。
TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15窗口类型:安全的系统覆盖窗口,需要显示在其他所有窗口之上。这些窗口不得采用输入焦点,否则会干扰键盘锁。这与TYPE_SYSTEM_OVERLAY完全相同,只是只允许系统本身创建这些叠加层。应用程序无法获取创建安全系统覆盖的权限。在多用户系统中,仅在拥有用户的窗口中显示。
TYPE_DRAG = FIRST_SYSTEM_WINDOW+16窗口类型:拖放伪窗口。只有一个拖动层(最多),它放置在所有其他窗口的顶部。在多用户系统中,仅在拥有用户的窗口中显示。
TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17窗口类型:从状态栏上方滑出的面板。 在多用户系统中显示在所有用户的窗口中。这些窗口显示在 stauts 栏和任何TYPE_STATUS_BAR_PANEL窗口的顶部。
TYPE_POINTER = FIRST_SYSTEM_WINDOW+18窗口类型:(鼠标)指针。 在多用户系统中显示在所有用户的窗口中。
TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19窗口类型:导航栏(与状态栏不同时)。在多用户系统中显示在所有用户的窗口中。
TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20窗口类型:用户更改系统音量时显示的音量级别叠加/对话框。在多用户系统中,显示在所有用户的窗口中。
TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21窗口类型:启动进度对话框,位于世界上所有内容的顶部。在多用户系统中,显示在所有用户的窗口中。
TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22隐藏系统UI栏时使用输入事件的窗口类型。在多用户系统中,显示在所有用户的窗口中。
TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24窗口类型:导航栏面板(当导航栏与状态栏不同时)。在多用户系统中显示在所有用户的窗口中。
TYPE_DISPLAY_OVERLAY = FIRST_SYSTEM_WINDOW+26窗口类型:显示叠加窗口。用于模拟辅助显示设备。在多用户系统中,显示在所有用户的窗口中。
TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27窗口类型:放大叠加窗口。用于在启用辅助功能放大时突出显示显示器的放大部分。在多用户系统中,显示在所有用户的窗口中。
TYPE_PRIVATE_PRESENTATION = FIRST_SYSTEM_WINDOW+30窗口类型:用于在私人虚拟显示之上进行演示的窗口
TYPE_VOICE_INTERACTION = FIRST_SYSTEM_WINDOW+31窗口类型:语音交互层中的窗口
TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32窗口类型:仅由连接的 android.accessibilityservice.accessibilityService 覆盖的窗口,用于拦截用户交互,而无需更改辅助功能服务可以自省的窗口。特别是,辅助功能服务只能自省视力正常的用户可以与之交互的窗口,他们可以触摸这些窗口或可以在这些窗口中键入内容。例如,如果存在可触摸的全屏辅助功能叠加层,则辅助功能服务将可自检其下方的窗口,即使它们被可触摸窗口覆盖。
TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33窗口类型:语音交互层的启动窗口
TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34显示用于调整停靠堆栈大小的控点的窗口。此窗口归系统进程所有。
TYPE_QS_DIALOG = FIRST_SYSTEM_WINDOW+35窗口类型:TYPE_APPLICATION_ATTACHED_DIALOG类似,但由快速设置磁贴使用
TYPE_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36窗口类型:直接显示在键盘上方。该图层保留用于屏幕截图动画、区域选择和 UI。在多用户系统中,仅在拥有用户的窗口中显示。
TYPE_PRESENTATION = FIRST_SYSTEM_WINDOW + 37窗口类型:用于在外部显示器上进行演示的窗口
TYPE_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 38窗口类型:应用程序覆盖窗口显示在所有活动窗口(介于 FIRST_APPLICATION_WINDOW LAST_APPLICATION_WINDOW 之间的类型)上方,但显示在状态栏或 IME 等关键系统窗口下方。 系统可以随时更改这些窗口的位置、大小或可见性,以减少用户的视觉混乱并管理资源。 需要 Manifest.permission.SYSTEM_ALERT_WINDOW 许可。 系统将调整具有此窗口类型的进程的重要性,以减少低内存杀手杀死它们的机会。 在多用户系统中,仅在拥有用户的屏幕上显示。
TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39窗口类型:用于在其他窗口上方添加辅助功能窗口放大倍数的窗口。这会将窗口放置在叠加窗口中。
TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40窗口类型:通知栏和键盘锁。只能有一个状态栏窗口;它放置在屏幕顶部,所有其他窗口都向下移动,因此它们位于屏幕下方。在多用户系统中,显示在所有用户的窗口中。
TYPE_STATUS_BAR_ADDITIONAL = FIRST_SYSTEM_WINDOW + 41窗口类型:用于在屏幕的非常规部分(即屏幕的左侧或底部)显示状态栏。在多用户系统中,显示在所有用户的窗口中。
LAST_SYSTEM_WINDOW = 2999系统窗口类型的最大值。
INVALID_WINDOW_TYPE = -1当没有合适的类型可用时,在内部使用。

如状态栏窗口添加类型:
StatusBarWindowController.javaWindowManager.LayoutParams.TYPE_STATUS_BAR

       mLp = new WindowManager.LayoutParams(
               ViewGroup.LayoutParams.MATCH_PARENT,
               mBarHeight,
               WindowManager.LayoutParams.TYPE_STATUS_BAR,
               WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                       | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                       | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
               PixelFormat.TRANSLUCENT);
       mLp.privateFlags |= PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
       mLp.token = new Binder();
       mLp.gravity = Gravity.TOP;
       mLp.setFitInsetsTypes(0 /* types */);
       mLp.setTitle("StatusBar");
       mLp.packageName = mContext.getPackageName();
       mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;

       mWindowManager.addView(mStatusBarView, mLp);

2、层级值与窗口类型

2.1 WindowState

frameworks/base/services/core/java/com/android/server/wm/WindowState.java


WMS侧添加界面 添加窗口(WindowManagerImpl.java#addView -> WindowManagerGlobal.java#addView -> ViewRootImpl.java#setView -> Session extends IWindowSession.Stub#addToDisplayAsUser -> WindowManagerService.java#addWindow)时初始化一个窗口的WindowState,窗口管理器中的一个窗口。记录一个窗口应该有的全部属性

final WindowState win = new WindowState(this, session, client, token, parentWindow,
                    appOp[0], attrs, viewVisibility, session.mUid, userId,
                    session.mCanAddInternalSystemWindow);

win.attach();
mWindowMap.put(client.asBinder(), win);
  • mToken = token是WindowToken句柄,用于显示窗口的活动的句柄。
  • mSession = s此类表示活动的客户端会话。通常每个进程都有一个与窗口管理器交互的会话对象。
  • mAttrs.copyFrom(a)窗口属性WindowManager.LayoutParams
  • mBaseLayer 根据窗口类型在屏幕上的排序方式。mBaseLayer = mPolicy.getWindowLayerLw(parentWindow) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSETTYPE_LAYER_MULTIPLIER 将策略的类型层乘以多少,以便为相同类型的多个窗口保留空间,并使用TYPE_LAYER_OFFSET进行 Z 排序调整。TYPE_LAYER_OFFSET 偏移TYPE_LAYER_MULTIPLIER,用于将一组窗口移动到同一图层中其他窗口的上方或下方。
  • mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type) 根据子窗口附加到的窗口对子窗口进行 Z 排序。返回正数以将它们排在前面,负数在后面排序。
  • mIsChildWindow:是否是子窗口;mIsImWindow:是否是输入法窗口;mIsWallpaper:是否是壁纸窗口。
  • mWinAnimator = new WindowStateAnimator(this)跟踪单个 WindowState 的动画和图面操作。
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
        WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility,
        int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow,
        PowerManagerWrapper powerManagerWrapper) {
    super(service);
    mTmpTransaction = service.mTransactionFactory.get();
    mSession = s;
    mClient = c;
    mAppOp = appOp;
    mToken = token;
    mActivityRecord = mToken.asActivityRecord();
    mOwnerUid = ownerId;
    mShowUserId = showUserId;
    mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
    mWindowId = new WindowId(this);
    mAttrs.copyFrom(a);
    mLastSurfaceInsets.set(mAttrs.surfaceInsets);
    mViewVisibility = viewVisibility;
    mPolicy = mWmService.mPolicy;
    mContext = mWmService.mContext;
    DeathRecipient deathRecipient = new DeathRecipient();
    mPowerManagerWrapper = powerManagerWrapper;
    mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
    mInputWindowHandle = new InputWindowHandleWrapper(new InputWindowHandle(
            mActivityRecord != null
                    ? mActivityRecord.getInputApplicationHandle(false /* update */) : null,
            getDisplayId()));
    mInputWindowHandle.setOwnerPid(s.mPid);
    mInputWindowHandle.setOwnerUid(s.mUid);
    mInputWindowHandle.setName(getName());
    mInputWindowHandle.setPackageName(mAttrs.packageName);
    mInputWindowHandle.setLayoutParamsType(mAttrs.type);
    // Check private trusted overlay flag and window type to set trustedOverlay variable of
    // input window handle.
    mInputWindowHandle.setTrustedOverlay(
            ((mAttrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0
                    && mOwnerCanAddInternalSystemWindow)
                    || InputMonitor.isTrustedOverlay(mAttrs.type));
    if (DEBUG) {
        Slog.v(TAG, "Window " + this + " client=" + c.asBinder()
                        + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
    }
    try {
        c.asBinder().linkToDeath(deathRecipient, 0);
    } catch (RemoteException e) {
        mDeathRecipient = null;
        mIsChildWindow = false;
        mLayoutAttached = false;
        mIsImWindow = false;
        mIsWallpaper = false;
        mIsFloatingLayer = false;
        mBaseLayer = 0;
        mSubLayer = 0;
        mWinAnimator = null;
        mWpcForDisplayAreaConfigChanges = null;
        return;
    }
    mDeathRecipient = deathRecipient;

    if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
        // The multiplier here is to reserve space for multiple
        // windows in the same type layer.
        mBaseLayer = mPolicy.getWindowLayerLw(parentWindow)
                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
        mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
        mIsChildWindow = true;

        mLayoutAttached = mAttrs.type !=
                WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
        mIsImWindow = parentWindow.mAttrs.type == TYPE_INPUT_METHOD
                || parentWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
        mIsWallpaper = parentWindow.mAttrs.type == TYPE_WALLPAPER;
    } else {
        // The multiplier here is to reserve space for multiple
        // windows in the same type layer.
        mBaseLayer = mPolicy.getWindowLayerLw(this)
                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
        mSubLayer = 0;
        mIsChildWindow = false;
        mLayoutAttached = false;
        mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
                || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
        mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
    }
    mIsFloatingLayer = mIsImWindow || mIsWallpaper;

    if (mActivityRecord != null && mActivityRecord.mShowForAllUsers) {
        // Windows for apps that can show for all users should also show when the device is
        // locked.
        mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
    }

    mWinAnimator = new WindowStateAnimator(this);
    mWinAnimator.mAlpha = a.alpha;

    mRequestedWidth = 0;
    mRequestedHeight = 0;
    mLastRequestedWidth = 0;
    mLastRequestedHeight = 0;
    mLayer = 0;
    mOverrideScale = mWmService.mAtmService.mCompatModePackages.getCompatScale(
            mAttrs.packageName, s.mUid);

    // Make sure we initial all fields before adding to parentWindow, to prevent exception
    // during onDisplayChanged.
    if (mIsChildWindow) {
        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", this, parentWindow);
        parentWindow.addChild(this, sWindowSubLayerComparator);
    }

    // System process or invalid process cannot register to display area config change.
    mWpcForDisplayAreaConfigChanges = (s.mPid == MY_PID || s.mPid < 0)
            ? null
            : service.mAtmService.getProcessController(s.mPid, s.mUid);
}

2.2 WindowManagerPolicy 窗口管理的策略机制

窗 口 管 理 的 策 略 机 制


frameworks/base/services/core/java/com/android/server/policy/WindowManagerPolicy.java
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java


getWindowLayerFromTypeLw 方法,窗口类型的图层分配。允许您控制不同类型的窗口在屏幕上的排序方式。上面mBaseLayer以该返回值为基础计算。

  • 窗口类型Type在FIRST_APPLICATION_WINDOW~LAST_APPLICATION_WINDOW之间(即Application Window普通应用程序窗口1~99),返回APPLICATION_LAYER = 2
  • getMaxWindowLayer()最大窗口图层。请注意,最大窗口层应高于 getWindowLayerFromTypeLw 报告的最大值。(最大图层值是36,这里1~35被使用,其中APPLICATION_LAYER = 2Application Window普通应用程序窗口使用
    在这里插入图片描述
窗口类型 Type返回的基础层级值
FIRST_APPLICATION_WINDOW ~ LAST_APPLICATION_WINDOWAPPLICATION_LAYER = 2
TYPE_WALLPAPER1
TYPE_PRESENTATION
TYPE_PRIVATE_PRESENTATION
TYPE_DOCK_DIVIDER
TYPE_QS_DIALOG
TYPE_PHONE
3
TYPE_SEARCH_BAR
TYPE_VOICE_INTERACTION_STARTING
4
TYPE_VOICE_INTERACTION5
TYPE_INPUT_CONSUMER6
TYPE_SYSTEM_DIALOG7
TYPE_TOAST8
TYPE_PRIORITY_PHONE9
TYPE_SYSTEM_ALERTcanAddInternalSystemWindow ? 13 : 10
TYPE_APPLICATION_OVERLAY12
TYPE_INPUT_METHOD15
TYPE_INPUT_METHOD_DIALOG16
TYPE_STATUS_BAR17
TYPE_STATUS_BAR_ADDITIONAL18
TYPE_NOTIFICATION_SHADE19
TYPE_STATUS_BAR_SUB_PANEL20
TYPE_KEYGUARD_DIALOG21
TYPE_VOLUME_OVERLAY22
TYPE_SYSTEM_OVERLAYcanAddInternalSystemWindow ? 23 : 11
TYPE_NAVIGATION_BAR24
TYPE_NAVIGATION_BAR_PANEL25
TYPE_SCREENSHOT26
TYPE_SYSTEM_ERRORcanAddInternalSystemWindow ? 27 : 10
TYPE_MAGNIFICATION_OVERLAY28
TYPE_DISPLAY_OVERLAY29
TYPE_DRAG30
TYPE_ACCESSIBILITY_OVERLAY31
TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY32
TYPE_SECURE_SYSTEM_OVERLAY33
TYPE_BOOT_PROGRESS34
TYPE_POINTER35
默认情况default3
default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow,
         boolean roundedCornerOverlay) {
     // Always put the rounded corner layer to the top most.
     if (roundedCornerOverlay && canAddInternalSystemWindow) {
         return getMaxWindowLayer();
     }
     if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
         return APPLICATION_LAYER;
     }

     switch (type) {
         case TYPE_WALLPAPER:
             // wallpaper is at the bottom, though the window manager may move it.
             return  1;
         case TYPE_PRESENTATION:
         case TYPE_PRIVATE_PRESENTATION:
         case TYPE_DOCK_DIVIDER:
         case TYPE_QS_DIALOG:
         case TYPE_PHONE:
             return  3;
         case TYPE_SEARCH_BAR:
         case TYPE_VOICE_INTERACTION_STARTING:
             return  4;
         case TYPE_VOICE_INTERACTION:
             // voice interaction layer is almost immediately above apps.
             return  5;
         case TYPE_INPUT_CONSUMER:
             return  6;
         case TYPE_SYSTEM_DIALOG:
             return  7;
         case TYPE_TOAST:
             // toasts and the plugged-in battery thing
             return  8;
         case TYPE_PRIORITY_PHONE:
             // SIM errors and unlock.  Not sure if this really should be in a high layer.
             return  9;
         case TYPE_SYSTEM_ALERT:
             // like the ANR / app crashed dialogs
             // Type is deprecated for non-system apps. For system apps, this type should be
             // in a higher layer than TYPE_APPLICATION_OVERLAY.
             return  canAddInternalSystemWindow ? 13 : 10;
         case TYPE_APPLICATION_OVERLAY:
             return  12;
         case TYPE_INPUT_METHOD:
             // on-screen keyboards and other such input method user interfaces go here.
             return  15;
         case TYPE_INPUT_METHOD_DIALOG:
             // on-screen keyboards and other such input method user interfaces go here.
             return  16;
         case TYPE_STATUS_BAR:
             return  17;
         case TYPE_STATUS_BAR_ADDITIONAL:
             return  18;
         case TYPE_NOTIFICATION_SHADE:
             return  19;
         case TYPE_STATUS_BAR_SUB_PANEL:
             return  20;
         case TYPE_KEYGUARD_DIALOG:
             return  21;
         case TYPE_VOLUME_OVERLAY:
             // the on-screen volume indicator and controller shown when the user
             // changes the device volume
             return  22;
         case TYPE_SYSTEM_OVERLAY:
             // the on-screen volume indicator and controller shown when the user
             // changes the device volume
             return  canAddInternalSystemWindow ? 23 : 11;
         case TYPE_NAVIGATION_BAR:
             // the navigation bar, if available, shows atop most things
             return  24;
         case TYPE_NAVIGATION_BAR_PANEL:
             // some panels (e.g. search) need to show on top of the navigation bar
             return  25;
         case TYPE_SCREENSHOT:
             // screenshot selection layer shouldn't go above system error, but it should cover
             // navigation bars at the very least.
             return  26;
         case TYPE_SYSTEM_ERROR:
             // system-level error dialogs
             return  canAddInternalSystemWindow ? 27 : 10;
         case TYPE_MAGNIFICATION_OVERLAY:
             // used to highlight the magnified portion of a display
             return  28;
         case TYPE_DISPLAY_OVERLAY:
             // used to simulate secondary display devices
             return  29;
         case TYPE_DRAG:
             // the drag layer: input for drag-and-drop is associated with this window,
             // which sits above all other focusable windows
             return  30;
         case TYPE_ACCESSIBILITY_OVERLAY:
             // overlay put by accessibility services to intercept user interaction
             return  31;
         case TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY:
             return 32;
         case TYPE_SECURE_SYSTEM_OVERLAY:
             return  33;
         case TYPE_BOOT_PROGRESS:
             return  34;
         case TYPE_POINTER:
             // the (mouse) pointer layer
             return  35;
         default:
             Slog.e("WindowManager", "Unknown window type: " + type);
             return 3;
     }
 }

2.3 WindowToken句柄

frameworks/base/services/core/java/com/android/server/wm/WindowToken.java
窗口管理器中一组相关窗口的容器。通常,这是一个 AppWindowToken,它是用于显示窗口的活动的句柄。对于嵌套窗口,为父窗口创建了一个 WindowToken 来管理其子窗口。

WindowToken build() {
    return new WindowToken(mService, mToken, mType, mPersistOnEmpty, mDisplayContent,
            mOwnerCanManageAppTokens, mRoundedCornerOverlay, mFromClientToken, mOptions);
}

在这里插入图片描述

3、窗口属性 LayoutParams

android/view/WindowManager.java # WindowManager.LayoutParams

  • type 如目录1,不在赘述

  • flags 窗口的标志

    flags描述
    FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001窗口标志:只要此窗口对用户可见,就允许在屏幕打开时激活锁定屏幕。这可以单独使用,也可以与FLAG_KEEP_SCREEN_ONFLAG_SHOW_WHEN_LOCKED结合使用
    FLAG_DIM_BEHIND = 0x00000002窗口标志:此窗口后面的所有内容都将变暗。使用 dimAmount 控制 dim 的量。
    FLAG_BLUR_BEHIND = 0x00000004窗口标志:为此窗口启用后面的模糊。
    FLAG_NOT_FOCUSABLE = 0x00000008窗口标志:此窗口永远不会获取键输入焦点,因此用户无法向其发送键或其他按钮事件。相反,这些将转到它后面的任何可聚焦窗口。此标志还将启用FLAG_NOT_TOUCH_MODAL是否显式设置。设置此标志还意味着窗口不需要与软输入法交互,因此它将独立于任何活动输入法进行 Z 排序和定位(通常这意味着它在输入法的顶部获得 Z 排序,因此它可以对其内容使用全屏并在需要时覆盖输入法。可以使用FLAG_ALT_FOCUSABLE_IM来修改此行为。
    FLAG_NOT_TOUCHABLE = 0x00000010窗口标志:此窗口永远无法接收触摸事件。此标志的目的是让触摸由此窗口下方的某个窗口处理(按 Z 顺序)。
    FLAG_NOT_TOUCH_MODAL = 0x00000020窗口标志:即使此窗口可聚焦(未设置其FLAG_NOT_FOCUSABLE),也允许将窗口外的任何指针事件发送到其后面的窗口。否则,它将使用所有指针事件本身,无论它们是否在窗口内。
    FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040窗口标志:设置后,如果按下触摸屏时设备处于睡眠状态,您将收到此第一个触摸事件。通常,系统使用第一个触摸事件,因为用户看不到他们正在按下的内容。已弃用 此标志不起作用
    FLAG_KEEP_SCREEN_ON = 0x00000080窗口标志:只要此窗口对用户可见,请保持设备的屏幕打开并明亮。
    FLAG_LAYOUT_IN_SCREEN = 0x00000100附加窗口的窗口标志:将窗口放在整个屏幕内,忽略父窗口的任何约束。
    FLAG_LAYOUT_NO_LIMITS = 0x00000200窗口标志:允许窗口延伸到屏幕之外。
    FLAG_FULLSCREEN = 0x00000400窗口标志:显示此窗口时隐藏所有屏幕装饰(如状态栏)。这允许窗口将整个显示空间用于自身 - 当设置了此标志的应用窗口位于顶层时,状态栏将被隐藏。全屏窗口将忽略窗口的软输入模式字段的值 SOFT_INPUT_ADJUST_RESIZE;窗口将保持全屏显示,并且不会调整大小。
    可以通过安卓在您的主题中控制此标志。R.attr.windowFullscreen 属性;此属性在标准全屏主题中自动为您设置,例如android.R.style.Theme_NoTitleBar_Fullscreen, android.R.style.Theme_Black_NoTitleBar_Fullscreen, android.R.style.Theme_Light_NoTitleBar_Fullscreen, android.R.style.Theme_Holo_NoActionBar_Fullscreen, android.R.style.Theme_Holo_Light_NoActionBar_Fullscreen, android.R.style.Theme_DeviceDefault_NoActionBar_Fullscreen, and android.R.style.Theme_DeviceDefault_Light_NoActionBar_Fullscreen
    已弃用 WindowInsetsController.hide(int) 和 WindowInsets.Type.statusBars() 代替
    FLAG_FORCE_NOT_FULLSCREEN = 0x00000800窗口标志:覆盖FLAG_FULLSCREEN并强制显示屏幕装饰(如状态栏)。已弃用 此值“意外”成为 API,不应由第三方应用程序使用
    FLAG_DITHER = 0x00001000窗口标志:将此窗口合成到屏幕时打开抖动。已弃用 不再使用此标志
    FLAG_SECURE = 0x00002000窗口标志:将窗口内容视为安全内容,防止其显示在屏幕截图中或在不安全的显示器上查看。有关安全表面和安全显示器的更多详细信息,请参阅Display.FLAG_SECURE
    FLAG_SCALED = 0x00004000窗口标志:一种特殊模式,其中布局参数用于在将表面合成到屏幕时对表面执行缩放。
    FLAG_IGNORE_CHEEK_PRESSES = 0x00008000窗口标志:用于当用户将屏幕靠在脸上时经常使用的窗口,它将主动过滤事件流以防止在这种情况下意外按下特定窗口可能不需要,当检测到此类事件流时,应用程序将收到 CANCEL 运动事件以指示这一点,以便应用程序可以通过不对事件执行任何操作来相应地处理此问题,直到松开手指。
    FLAG_LAYOUT_INSET_DECOR = 0x00010000窗口标志:仅与FLAG_LAYOUT_IN_SCREEN结合使用的特殊选项。在屏幕中请求布局时,您的窗口可能会显示在屏幕装饰(如状态栏)的顶部或后面。通过包含此标志,窗口管理器将报告确保您的内容未被屏幕装饰覆盖所需的内嵌矩形。此标志通常由 Window 为您设置,如 Window.setFlags 中所述。已弃用
    FLAG_ALT_FOCUSABLE_IM = 0x00020000窗口标志:设置后,反转窗口的输入法可聚焦性。设置此标志的效果取决于是否设置了FLAG_NOT_FOCUSABLE
    如果未设置FLAG_NOT_FOCUSABLE,即当窗口可聚焦时,设置此标志可防止此窗口成为输入法的目标。因此,它将无法与输入法交互,并且将分层在输入法之上(除非它上面有另一个输入法目标)。
    如果设置了FLAG_NOT_FOCUSABLE,则设置此标志会将窗口请求为输入法目标,即使窗口不可聚焦也是如此。因此,它将在输入法下方分层。注意: 设置FLAG_NOT_FOCUSABLE的窗口无法与输入法交互,无论此标志如何。
    FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000窗口标志:如果已设置FLAG_NOT_TOUCH_MODAL,则可以将此标志设置为接收单个特殊的 MotionEvent,其中包含针对窗外发生的触摸的操作MotionEvent.ACTION_OUTSIDE。请注意,您不会收到完整的向下/移动/向上手势,只会收到第一次向下的位置作为ACTION_OUTSIDE
    FLAG_SHOW_WHEN_LOCKED = 0x00080000窗口标志:在屏幕锁定时允许显示窗口的特殊标志。这将使应用程序窗口优先于密钥保护或任何其他锁定屏幕。可与FLAG_KEEP_SCREEN_ON一起使用,在显示钥匙保护窗口之前直接打开屏幕和显示窗口。可与FLAG_DISMISS_KEYGUARD一起使用,以自动完全关闭不安全的键盘锁。此标志仅适用于最顶层的全屏窗口。已弃用 使用android.R.attr.showWhenLockedandroid.app.Activity.setShowWhenLocked(boolean),以防止无意的双重生命周期事件
    FLAG_SHOW_WALLPAPER = 0x00100000窗口标志:要求在窗口后面显示系统墙纸。窗口表面必须是半透明的,才能实际看到它后面的墙纸;此标志只是确保如果此窗口实际上具有半透明区域,则墙纸表面将在那里。
    可以通过安卓在您的主题中控制此标志。R.attr.windowShowWallpaper 属性;此属性在标准壁纸主题中自动为您设置,例如android.R.style.Theme_Wallpaper, android.R.style.Theme_Wallpaper_NoTitleBar, android.R.style.Theme_Wallpaper_NoTitleBar_Fullscreen, android.R.style.Theme_Holo_Wallpaper, android.R.style.Theme_Holo_Wallpaper_NoTitleBar, android.R.style.Theme_DeviceDefault_Wallpaper, and android.R.style.Theme_DeviceDefault_Wallpaper_NoTitleBar.
    FLAG_TURN_SCREEN_ON = 0x00200000窗口标志:当设置为正在添加或使其可见的窗口时,一旦窗口显示,系统将戳电源管理器的用户活动(就好像用户唤醒了设备)以打开屏幕。
    已弃用 使用android.R.attr.turnScreenOnandroid.app.Activity.setTurnScreenOn(boolean),以防止意外的双重生命周期事件
    FLAG_DISMISS_KEYGUARD = 0x00400000窗口标志:设置窗口时,仅当它不是安全锁键盘锁时,窗口才会导致键盘锁被关闭。由于安全不需要此类键盘锁,因此如果用户导航到另一个窗口,它将永远不会重新出现(与FLAG_SHOW_WHEN_LOCKED相反,只会暂时隐藏安全和非安全键盘锁,但确保当用户移动到另一个不隐藏它们的 UI 时它们会重新出现)。如果键盘锁当前处于活动状态且安全(需要解锁凭据),则用户仍需要在看到此窗口之前进行确认,除非还设置了FLAG_SHOW_WHEN_LOCKED
    已弃用 FLAG_SHOW_WHEN_LOCKEDKeyguardManager.requestDismissKeyguard。由于只要窗口上有此标志的活动聚焦,键盘锁就会一直被关闭,因此键盘卫士无法防止无意中触摸屏幕,这是不希望的
    FLAG_SPLIT_TOUCH = 0x00800000窗口标志:设置后,窗口将接受将超出其边界的触摸事件发送到也支持拆分触摸的其他窗口。如果未设置此标志,则第一个向下的指针确定所有后续触摸都指向的窗口,直到所有指针上升为止。设置此标志后,每个指针(不一定是第一个指针)将确定该指针的所有后续触摸将转到的窗口,直到该指针上升,从而使具有多个指针的触摸能够拆分到多个窗口。
    FLAG_HARDWARE_ACCELERATED = 0x01000000指示是否应对此窗口进行硬件加速。请求硬件加速并不能保证它会发生。
    只能以编程方式控制此标志以启用硬件加速。若要以编程方式为给定窗口启用硬件加速,请执行以下操作:
    Window w = activity.getWindow(); // in Activity's onCreate()例如w.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
    请务必记住,在设置活动或对话框的内容视图之前,必须设置此标志。
    此标志不能用于禁用硬件加速,因为它在您的清单中使用android.R.attr.hardwareAccelerated。如果需要有选择地以编程方式禁用硬件加速(例如,用于自动测试),请确保在清单中将其关闭,并在需要时使用上述方法在活动或对话框中启用它。
    如果在活动或应用程序上将 android:hardwareAccelerated XML 属性设置为 true,则系统会自动设置此标志。
    FLAG_LAYOUT_IN_OVERSCAN = 0x02000000窗口标志:允许窗口内容延伸到屏幕的过扫描区域(如果有)。窗口仍应正确定位其内容,以考虑过扫描区域。
    可以通过android.R.attr.windowOverscan 属性;此属性在标准过扫描主题中自动为您设置,例如android.R.style.Theme_Holo_NoActionBar_Overscan, android.R.style.Theme_Holo_Light_NoActionBar_Overscan, android.R.style.Theme_DeviceDefault_NoActionBar_Overscan, and android.R.style.Theme_DeviceDefault_Light_NoActionBar_Overscan.
    为窗口启用此标志时,其正常内容可能会被显示器的过扫描区域在某种程度上遮挡。若要确保该内容的关键部分对用户可见,可以使用View.setFitsSystemWindows(boolean)在视图层次结构中设置应应用适当偏移量的点。(这可以通过直接调用此函数来完成,使用android.R.attr.fitsSystemWindows属性在您的视图层次结构中,或实现您自己的View.fitSystemWindows(Rect)方法)。
    这种定位内容元素的机制与布局和View.setSystemUiVisibility(int)的等效用法相同;下面是一个示例布局,它将正确定位其 UI 元素,并设置了此过扫描标志:
    已弃用 从Android 11开始,任何Android产品都不再设置过扫描区域
    FLAG_TRANSLUCENT_STATUS = 0x04000000窗口标志:请求具有最少系统提供的背景保护的半透明状态栏。
    可以通过android.R.attr.windowTranslucentStatus属性;此属性会在标准半透明装饰主题中自动为您设置,例如android.R.style.Theme_Holo_NoActionBar_TranslucentDecor, android.R.style.Theme_Holo_Light_NoActionBar_TranslucentDecor, android.R.style.Theme_DeviceDefault_NoActionBar_TranslucentDecor, and android.R.style.Theme_DeviceDefault_Light_NoActionBar_TranslucentDecor.
    为窗口启用此标志后,它会自动将系统 UI 可见性标志设置为View.SYSTEM_UI_FLAG_LAYOUT_STABLEView.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    已弃用 改用半透明颜色的 Window.setStatusBarColor(int)
    FLAG_TRANSLUCENT_NAVIGATION = 0x08000000窗口标志:请求具有最少系统提供的背景保护的半透明导航栏。
    已弃用 改用半透明颜色的Window.setNavigationBarColor(int)
    FLAG_LOCAL_FOCUS_MODE = 0x10000000标记本地焦点模式下的窗口。本地焦点模式下的窗口可以使用Window.setLocalFocus(boolean, boolean)独立于窗口管理器控制焦点。通常,此模式下的窗口不会从窗口管理器获取触摸/键事件,但只能通过使用Window.injectInputEvent(InputEvent)通过本地注入获取事件。
    FLAG_SLIPPERY = 0x20000000窗口标志:使触摸能够在手势中间从窗口滑出到相邻窗口,而不是在手势持续时间内被捕获。此标志仅更改此窗口的触摸焦点的行为。触摸可以滑出窗口,但不一定能滑回窗口(除非具有触摸焦点的另一个窗口允许)。
    FLAG_LAYOUT_ATTACHED_IN_DECOR = 0x40000000窗口标志:请求使用附加窗口进行布局时,附加的窗口可能与父窗口(如导航栏)的屏幕修饰重叠。通过包含此标志,窗口管理器将在父窗口的装饰框架内布局附加的窗口,使其不与屏幕装饰重叠。
    已弃用 使用 setFitInsetsTypes(int) 来确定附加的窗口是否与系统栏重叠
    FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = 0x80000000指示此窗口负责绘制系统条形的背景的标志。如果设置,系统栏将以透明背景绘制,并且此窗口中的相应区域将用Window.getStatusBarColor()Window.getNavigationBarColor()中指定的颜色填充。
  • softInputMode : 任何软输入区域所需的操作模式。可以是以下各项的任意组合:其中一个可见性状态SOFT_INPUT_STATE_UNSPECIFIED、SOFT_INPUT_STATE_UNCHANGED、SOFT_INPUT_STATE_HIDDEN、SOFT_INPUT_STATE_ALWAYS_HIDDEN、SOFT_INPUT_STATE_VISIBLE或SOFT_INPUT_STATE_ALWAYS_VISIBLE。其中一个调整选项SOFT_INPUT_ADJUST_UNSPECIFIED、SOFT_INPUT_ADJUST_RESIZE、SOFT_INPUT_ADJUST_PAN或SOFT_INPUT_ADJUST_NOTHING。可以通过android.R.attr.windowSoftInputMode属性。

  • alpha = 1.0f 要应用于整个窗口的 alpha 值。alpha 为 1.0 表示完全不透明,0.0 表示完全透明

  • systemUiVisibility 控制状态栏的可见性。已弃用:SystemUiVisibility标志已弃用。请改用WindowInsetsController 。另请参阅:View.STATUS_BAR_VISIBLEView.STATUS_BAR_HIDDEN

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/702393.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于51单片机的秒表系统

目录 基于51单片机的秒表系统一、原理图二、部分代码三、视频演示 基于51单片机的秒表系统 一、原理图 二、部分代码 #include <reg52.h>#define duanxuan P2 #define weixuan P1unsigned char code wxcode[]{0X01, 0x02, 0x04, 0x08, 0X10, 0X20, 0X40, 0X80};…

C# WPF 路径动画

路径动画&#xff1a;一个东西沿着你画的的线跑。 微软对这个有很详细的说明&#xff0c;有需要请参照微软Learn网站 cs的代码 PathGeometry pathGeometry new PathGeometry();PathFigure pathFigure new PathFigure();//pathFigure.IsClosed true;pathFigure.StartPoint…

试着攻击自己写的网站

背景介绍 概念简介 CSRF XSS攻击是一种常见的安全攻击&#xff0c;它通过伪造用户输入&#xff0c;利用CSRF漏洞获取用户的敏感信息或者执行恶意操作。CSRF XSS攻击不仅会给用户带来损失&#xff0c;还会对互联网安全造成威胁。因此&#xff0c;防范CSRF XSS攻击已经成为了当…

C++ - 20230629

一. 思维导图 二. 练习 #include <iostream> using namespace std;class Person { private:int age;int *p; public://无参构造Person():p(new int(89)){age 18;}//有参构造Person(int age,int num){this->age age;this->pnew int(num);}//拷贝构造函数Person(P…

jmeter:BeanShell预处理程序获取/设置/引用变量

BeanShell预处理程序 1、局部变量 获取局部变量&#xff1a;vars.get("变量名") 设置局部变量&#xff1a;vars.put("变量名",变量值) 调用 ${变量名} 2、全局变量 获取局部变量&#xff1a;props.get("变量名") 设置局部变量&#xff1a…

使用 JCommander 解析命令行参数

前言 如果你想构建一个支持命令行参数的程序&#xff0c;那么 jcommander 非常适合你&#xff0c;jcommander 是一个只有几十 kb 的 Java 命令行参数解析工具&#xff0c;可以通过注解的方式快速实现命令行参数解析。 这篇教程会通过介绍 jcommadner &#xff0c;快速的创建一…

【WinRAR技巧】如何合并RAR分卷压缩文件?

很多小伙伴在压缩RAR文件的时候&#xff0c;会选择分卷压缩&#xff0c;便于网上上传、下载或邮件发送。 那如果后续不需要分卷压缩了&#xff0c;如何将RAR分卷压缩文件重新合并成一个文件呢&#xff1f;下面小编来分享一下具体的操作方法。 一般来说&#xff0c;我们都会选…

【C++初阶】C++STL详解(三)—— vector的介绍及使用

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;C初阶 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【C初阶】…

(三)灌溉系统WIFI通信部分

ESP8266 ESP8266S烧录器&#xff1a;CH430C arduino离线配置esp8266参考&#xff1a;参考文章 灯光闪烁就是烧录成功 ESP8266调试入门&#xff1a;参考文章 ESP8266调试&#xff1a;参考文章 人麻了已经&#xff0c;尝试半天了&#xff0c;AT指令没回应&#xff0c;尝试刷固…

Feed流实现

关注推送 关注推送也称为Feed流(直译为投喂)&#xff0c;为用户持续的提供“沉浸式”的体验&#xff0c;通过无限下拉刷新获取新的信息(如&#xff0c;短视频、博客等)。 获取信息的两种模式 传统模式&#xff1a;需要用户自己去根据所需去查询内容。 Feed模式&#xff1a;…

八、Docker安装MySQL主从

学习参考&#xff1a;尚硅谷Docker实战教程、Docker官网、其他优秀博客(参考过的在文章最后列出) 目录 前言一、pull一个mysql镜像二、主服务器master配置2.1 新建主服务器容器实例2.2 配置master的my.cnf2.3 重启master容器实例并验证2.4 master容器实例内创建数据同步用户 三…

JVM知识扫盲篇

JVM扫盲 一&#xff1a;故事背景二&#xff1a;知识点主要构成2.1 JVM为什么能跨平台2.2 JVM整体结构2.1 类加载子系统2.1.1 概述2.1.2 具体类加载器2.1.3 双亲委派机制2.1.4 Tomcat为什么要自定义类加载器 2.2 运行时数据区2.2.1 整体概念2.2.2 程序计数器的作用2.2.3 虚拟机栈…

MySQL - 数据库级别的外键

1. 外键 FOREIGN KEY (了解) 测试数据 &#xff1a; 学生表 CREATE TABLE IF NOT EXISTS student (id INT(4) NOT NULL AUTO_INCREMENT COMMENT 学号,name VARCHAR(30) NOT NULL DEFAULT 匿名 COMMENT 姓名,pwd VARCHAR(20) NOT NULL DEFAULT 123456 COMMENT 密码,sex VARC…

在 Mac 上安装 K8S

本篇文章将介绍如何在 Mac 上使用 minikube 搭建单机版的 Kubernetes。 安装步骤 安装 Docker 安装 docker 主要是用于提供容器引擎。直接下载安装即可。 下载地址 安装 Kubectl 推荐使用 home brew 安装 brew install kubectl可以使用下面的命令查看是否已经安装完毕 …

MAYA粒子圈

无法修改 完成一圈的时间

【C51】基于51单片机的自动输液监控系统设计与实现

摘 要 随着科技进步&#xff0c;我国的医疗设施不断完善&#xff0c;逐渐达到现代化水平。在当今的医疗环境下&#xff0c;病患更关心自己是否能够及时进行有效的治疗&#xff0c;医护人员对患者进行输液过程的全程监控。医生治疗的效果明显提高&#xff0c;不仅节约大量的时间…

Linux: 进程管理

一&#xff0c;快速上手&#xff0c;结束一个失控的进程 在主目录中&#xff0c;用文本编辑器创建一个文本文件badpro&#xff0c;如下&#xff1a; #! /bin/bash while echo "Im making files!!" domkdir adircd adirtouch afilesleep 2s done将该文件设定为可执行…

Leetcode 刷题 动态规划 子序列问题

300. 最长递增子序列 首先明确什么是子序列 子序列是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序 不一定要连续 可以删除部分元素 但是要保证相对顺序 1. dp[i]的定义 dp[i]表示i之前包括i的以nums[i]结尾的最长…

Hutool 30

Hutool是一个Java工具包&#xff0c;提供了丰富的工具类库和简化开发的工具方法。它的目标是提供一套丰富、实用、高效和易用的Java工具类&#xff0c;以提升开发者的开发效率和开发质量。以下是Hutool的一些主要特点和功能模块&#xff1a; 常用工具类&#xff1a;Hutool提供了…