Android 基于自由窗口实现小窗模式的分析(Android 10)

这篇具有很好参考价值的文章主要介绍了Android 基于自由窗口实现小窗模式的分析(Android 10)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Android 基于自由窗口实现小窗模式分析(Android 10)

在小窗口模式定制过程中,难免会遇到一些奇怪的问题,需要系统层去做支持。

1 如何更新 TOP RESUMED 窗口UI

在多窗口模式下,如何在最顶部(TOP RESUMED状态)的应用更新时获取到通知,以便我们去更新窗口的相关UI。这里有两种思路:

  1. 获取当前resumed窗口列表,提供接口与窗口通信,并通知窗口更新。
  2. 当top resumed 更新时,通知当前窗口做相关更新。

以下均使用伪代码 FreeformManager.isInSmallScreen() 代表处于小窗模式。

//frameworks/base/core/java/android/app/freeform/FreeformManager.java
public class FreeformManager {
   
// 启动自由窗口
public static void startFreeSplit(Context context, Intent intent, Rect rect, int position) {
   
    if (intent == null || context == null) {
   
        return;
    }
    intent.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
    ActivityOptions options = ActivityOptions.makeBasic();
    options.setLaunchWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
    if (rect != null) {
   
        options.setLaunchBounds(rect);
    }
    context.startActivity(intent, options.toBundle());
}
// 是否处于小窗模式
public static void isInSmallScreen() {
   
    if (intent == null || context == null) {
   
        return;
    }
    intent.setFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
    ActivityOptions options = ActivityOptions.makeBasic();
    options.setLaunchWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
    if (rect != null) {
   
        options.setLaunchBounds(rect);
    }
    context.startActivity(intent, options.toBundle());
}

这里提供思路2的相关实现:
Top resumed activity 更新时通知UI更新:

//frameworks/base/core/java/android/app/Activity.java
final void performTopResumedActivityChanged(boolean isTopResumedActivity, String reason) {
   
	//当活动获得或失去系统中的顶部恢复位置时调用。从 AndroidQ 开始,可以在多窗口和多显示模式下同时恢复多个活动。
	//应使用此回调而不是 onResume 来指示活动可以尝试打开独占访问设备(如相机)。它将始终在活动恢复之后和暂停之前传递。
	onTopResumedActivityChanged(isTopResumedActivity);

	// add by ian4u: top resumed activity 更新时通知UI更新
	if (isInMultiWindowMode() && FreeformManager.isInSmallScreen()) {
   
   		updateDecorCaption();
	}
}

private void updateDecorCaption() {
   
    mHandler.postDelayed(() -> {
   
        if (mDecor != null) {
   
            DecorView decorView = (DecorView) this.mDecor;
            // 更新 decorView UI, decorView包含了自由窗口的UI实现,有兴趣的自行分析。。。
            decorView.updateDecorTitle();
        }
    }, 30);
 }

以下是 DecorView 的修改:

// frameworks/base/core/java/com/android/internal/policy/DecorView.java
private View mForegroundView;
public void updateDecorTitle() {
   
   boolean inCenterScale = FreeformManager.isInSmallScreen();
   //设置小窗口顶部控制栏是否显示
   if (mDecorCaptionView != null) {
   
       mDecorCaptionView.updateCaption(inCenterScale ? View.VISIBLE : View.GONE);
   }
   Drawable foreDrawable = mContext.getDrawable(inCenterScale
           ? R.drawable.decor_caption_content_unfocused
           : R.drawable.decor_caption_content);
//        setForeground(foreDrawable);

	// 设置小窗口的焦点样式
   LayoutInflater layoutInflater = mWindow.getLayoutInflater();
   if (mForegroundView == null) {
   
       mForegroundView = layoutInflater.inflate(R.layout.decor_foreground, null);
       addView(mForegroundView, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
   }
   mForegroundView.setForeground(foreDrawable);

	// 设置小窗口圆角
   ViewOutlineProvider viewOutlineProvider = new ViewOutlineProvider() {
   
       @Override
       public void getOutline(View view, Outline outline) {
   
           if (view.getWidth() != 0 && view.getHeight() != 0) {
   
               outline.setRoundRect(new Rect(0, 0, view.getMeasuredWidth(),
                       view.getMeasuredHeight()), 26);
           }
       }
   };
   setOutlineProvider(inCenterScale ? viewOutlineProvider : null);
   setClipToOutline(inCenterScale);
}

以下是 DecorCaptionView 的修改,该类是顶部控制栏控件, 布局文件在
frameworks/base/core/res/res/layout/decor_caption.xml

// frameworks/base/core/java/com/android/internal/widget/DecorCaptionView.java
public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
         GestureDetector.OnGestureListener {
   
	private View mSwitch;
	public void updateCaption(int visible) {
   
	    if (mCaption != null) {
   
	        mCaption.setVisibility(visible);
	    }
	}

}

ResizeTask 时,发送广播通知activity 更新UI:文章来源地址https://www.toymoban.com/news/detail-501119.html

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
   
    dispatchActivityPreCreated(icicle);
    mCanEnterPictureInPicture = true;
    restoreHasCurrentPermissionRequest(icicle);
    if (persistentState != null) {
   
        onCreate(icicle, persistentState);
    } else {
   
        onCreate(icicle);
    }
    //省略代码。。。
    mFragments.dispatchActivityCreated();
    mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
    dispatchActivityPostCreated(icicle);
    // add by ian4u:
    //当任务栈大小改变(ATMS.resizeTask)时,发送广播, 通知当前窗口做修改
    if (isInMultiWindowMode() &&  FreeformManager.isInSmallScreen() ) {
   
        IntentFilter filter = new IntentFilter(Intent.ACTION_CAPTION_UPDATE);
        registerReceiver(mBroadcastReceiver, filter);
    }
}

final void performDestroy() {
   
	// 销毁广播注册
	if (isInMultiWindowMode() && FreeformManager.isInSmallScreen()) {
   
           unregisterReceiver(mBroadcastReceiver);
    }
    dispatchActivityPreDestroyed();
    mDestroyed = true;
    mWindow.destroy()

到了这里,关于Android 基于自由窗口实现小窗模式的分析(Android 10)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 窗口实现原理

    1、窗口显示架构图 【Id:0】Home Stack,这个是Launcher所在的Stack。 其实还有一些系统界面也运行在这个Stack上,例如近期任务 【Id:1】FullScren Stack,全屏的Activity所在的Stack。 但其实在分屏模式下,Id为1的Stack只占了半个屏幕。 【Id:2】Freeform模式的Activity所在Stack 【Id:3】D

    2024年02月10日
    浏览(36)
  • android 窗口级模糊实现方式

    在Android上实现窗口级模糊效果有多种方法,下面列出了其中两种常用的实现方式: RenderScript模糊效果: 使用 ScriptIntrinsicBlur 类在RenderScript中实现模糊效果。 创建一个RenderScript实例并将要模糊的图像传递给它。 创建一个 ScriptIntrinsicBlur 实例并设置模糊的半径。 使用 setInput

    2024年02月13日
    浏览(44)
  • Android10.0 人脸解锁流程分析

    人脸解锁概述 人脸解锁即用户通过注视设备的正面方便地解锁手机或平板。Android 10 为支持人脸解锁的设备在人脸认证期间添加了一个新的可以安全处理相机帧、保持隐私与安全的人脸认证栈的支持,也为安全合规地启用集成交易的应用(网上银行或其他服务)提供了一种容

    2024年02月03日
    浏览(43)
  • 学会在Android Studio使用窗口跳转实现用户登录

    基于 Empty Activity 模板创建安卓应用 将背景图片 background.png 拷贝到 drawable 目录   基于 Empty Activity 模板创建 LoginActivity ,要生成对应的布局文件,并且要设置为启动Activity 切换到Design视图查看预览效果 (1)输入用户名与密码正确的情况 - 用户名:howard - 密码:903213 (2)输入

    2023年04月15日
    浏览(57)
  • Android 系统启动过程纪要(基于Android 10)

    看过源码的都知道,Launcher系统启动都会经过这三个进程 init -zygote - system_server。今天我们就来讲解一下这三个进程以及Launcher系统启动。 准备Android虚拟机环境:创建和挂载系统文件目录; 初始化属性服务; 设置子进程信号处理函数(防止init的子进程出现僵尸进程,在子进

    2024年01月19日
    浏览(38)
  • 10分钟搞懂商业模式画布:9张分析图、6张模板

    新入职、新行业,新人如何快速搞懂它的业务?新领域、新业务,投资人如何快速搞明白一个公司?新商机、新模式,创业者如何快速一个业务的商业前景? 推荐大家使用商业模式画布,它可以让你轻松看透商业模式。对新入职员工、想快速了解一个领域的投资者、了解一个

    2024年02月04日
    浏览(46)
  • C++(12) 模板类、模板继承(严格模式和自由模式)

    模版类 1. 模版类 2. 模版参数限制 双重限制 限制外部类型 限制模版类型 3. 模版继承 3.1 严格模式 3.2 自由模式 4. 模版类的模版函数 5. 返回值类型带有模版

    2024年02月22日
    浏览(38)
  • 【基于FFT的自由响应非线性检测方案】使用归零早期FFT的非线性检测研究(Matlab代码实现)

     💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码及详细文章

    2024年02月15日
    浏览(49)
  • Android 10.0 系统systemui下拉通知栏的通知布局相关源码分析

     在android10.0的系统rom开发中,在进行systemui中的下拉通知栏的布局自定义的时候,对于原生systemui的 系统的下拉通知栏的通知布局的了解也是非常重要的,接下来就来分析下相关的下拉通知栏的通知布局的相关 源码流程,了解这些才方便对通知栏的布局做修改   在10.0的系统

    2023年04月21日
    浏览(44)
  • Android:RecyclerView自由拖动item

    原生就自带有可拖动item的工具:ItemTouchHelper 看下效果: 可拖动RecyclerView预览效果 接下来我们看如何使用。 其中判断条件中的item.isMovable这边是记录该item是否可以拖动,也可以换成其他判断条件比如根据位置判断等。 另外,需要留意一点,如果你是在onBindViewHolder中有设置点

    2024年01月23日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包