SystemUI 调整Recents中全部清除按钮位置

news2024/11/29 4:52:28

Recents 即多任务界面,显示最近使用过的APP List的。下面内容都是基于Android 11平台修改的。Android 11上,Recents 这一部分代码其实都已经被挪到Launcher3中。由于个人习惯,所以将内容分类作为SystemUI部分记录。

多任务界面主要几个文件:

TaskView.java

app卡片

ClearAllButton.java

全部清除Button

OverviewActionsView.java

多任务界面下方View,包含截图等按钮
RecentsView.java主界面,集成PageView,包含所有TaskView与ClearAllButton

 源码中,RecentsView 默认采用 Rtl 布局的方式(猜测这个设计是不是因为Recents按键一般在右下角,用户右手操作多,点进去RecentsView直接右滑更舒服)。界面整体布局如下图:

 默认从左往右滑动,RecentsView 最后一个子View就是 ClearAllButton。我们尝试将 ClearAllButton 放置到 RecentsView 的第一位,做成如下效果。左滑直接可以点击清除,右滑查看历史APP卡片。

 第一步,调整子View顺序。在 RecentsView.java 中,addView 时候换下顺序,先加载  ClearAllButton ,再去加载最新打开的 APP 的 TaskView 控件,最后加载历史 TaskView 控件。调整代码:

@@ -408,7 +408,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
     private boolean mLiveTileOverlayAttached;
 
     // Keeps track of the index where the first TaskView should be
-    private int mTaskViewStartIndex = 0;
+    // 全部清除按钮放置在PageView的0位,TaskView 下标应该从1开始
+    private int mTaskViewStartIndex = 1;
     private OverviewActionsView mActionsView;
 
     private BaseActivity.MultiWindowModeChangedListener mMultiWindowModeChangedListener =
@@ -622,7 +623,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
         if (!(affectingView instanceof TaskView) && !(affectingView instanceof ClearAllButton)) {
             int childCount = getChildCount();
 
-            mTaskViewStartIndex = 0;
+            // 全部清除按钮放置在PageView的0位,TaskView 下标应该从1开始
+            mTaskViewStartIndex = 1;
             while (mTaskViewStartIndex < childCount
                     && !(getChildAt(mTaskViewStartIndex) instanceof TaskView)) {
                 mTaskViewStartIndex++;
@@ -679,13 +681,17 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
     @Override
     protected void onPageBeginTransition() {
         super.onPageBeginTransition();
+        // 滑动开始的时候,会把截图按钮设置为禁用状态,防止误点击
+    android.util.Log.i("TA", "onPageBeginTransition true " + OverviewActionsView.DISABLED_SCROLLING);
         mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, true);
     }
 
     @Override
     protected void onPageEndTransition() {
         super.onPageEndTransition();
+        // 滑动结束的时候,如果isClearAllHidden为true(即当前不在全部清除按钮界面)。将截图按钮设置为可用状态
         if (isClearAllHidden()) {
+    android.util.Log.i("TA", "onPageEndTransition false " + OverviewActionsView.DISABLED_SCROLLING);
             mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
         }
         if (getNextPage() > 0) {
@@ -782,18 +788,20 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
 
         final int requiredTaskCount = tasks.size();
         if (getTaskViewCount() != requiredTaskCount) {
-            if (indexOfChild(mClearAllButton) != -1) {
+            /*if (indexOfChild(mClearAllButton) != -1) {
                 removeView(mClearAllButton);
-            }
+            }*/
+            //逐个添加TaskView到PageView
             for (int i = getTaskViewCount(); i < requiredTaskCount; i++) {
                 addView(mTaskViewPool.getView());
             }
+            //全部清除Button提前到前面添加,保证是PageView的第0个Child View
+            /*if (requiredTaskCount > 0) {
+                addView(mClearAllButton);
+            }*/
             while (getTaskViewCount() > requiredTaskCount) {
                 removeView(getChildAt(getChildCount() - 1));
             }
-            if (requiredTaskCount > 0) {
-                addView(mClearAllButton);
-            }
         }
 
         // Rebind and reset all task views
@@ -840,9 +848,10 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
 
     public int getTaskViewCount() {
         int taskViewCount = getChildCount() - mTaskViewStartIndex;
-        if (indexOfChild(mClearAllButton) != -1) {
+        // mClearAllButton放置在0位了,所以taskViewCount直接 = getChildCount() - mTaskViewStartIndex,不用再--
+        /*if (indexOfChild(mClearAllButton) != -1) {
             taskViewCount--;
-        }
+        }*/
         return taskViewCount;
     }
 
@@ -854,7 +863,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
     public void resetTaskVisuals() {
         for (int i = getTaskViewCount() - 1; i >= 0; i--) {
             TaskView taskView = getTaskViewAt(i);
-            if (mIgnoreResetTaskId != taskView.getTask().key.id) {
+            if (taskView.getTask() == null || taskView.getTask().key.id != mIgnoreResetTaskId) {
                 taskView.resetViewTransforms();
                 taskView.setStableAlpha(mContentAlpha);
                 taskView.setFullscreenProgress(mFullscreenProgress);
@@ -955,6 +964,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
             return;
         }
         mOrientationHandler.getCurveProperties(this, mInsets, mScrollState);
+        mScrollState.maxScroll = mMaxScroll;
         mScrollState.scrollFromEdge =
                 mIsRtl ? mScrollState.scroll : (mMaxScroll - mScrollState.scroll);
 
@@ -1193,14 +1203,15 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
      * is called.  Also scrolls the view to this task.
      */
     public void showCurrentTask(RunningTaskInfo runningTaskInfo) {
-        if (shouldAddDummyTaskView(runningTaskInfo)) {
-            boolean wasEmpty = getChildCount() == 0;
-            // Add an empty view for now until the task plan is loaded and applied
+        //全部清除Button提前到前面添加,保证是PageView的第0个Child View
+        if (indexOfChild(mClearAllButton) != -1) {
+            removeView(mClearAllButton);
+        }
+        addView(mClearAllButton, 0);
+        if (shouldAddDummyTaskView(runningTaskInfo)) {//有新增app
             final TaskView taskView = mTaskViewPool.getView();
+            //添加最新的app taskview,是PageView的第1个Child View
             addView(taskView, mTaskViewStartIndex);
-            if (wasEmpty) {
-                addView(mClearAllButton);
-            }
             // The temporary running task is only used for the duration between the start of the
             // gesture and the task list is loaded and applied
             mTmpRunningTask = Task.from(new TaskKey(runningTaskInfo), runningTaskInfo, false);
@@ -1381,6 +1392,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
          */
         public float scrollFromEdge;
 
+        public float maxScroll;
+
         /**
          * Updates linearInterpolation for the provided child position
          */
@@ -2272,7 +2285,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
     }
 
     @Override
-    protected int computeMinScroll() {
+    protected int computeMinScroll() {//获取最左边的范围
         if (getTaskViewCount() > 0) {
             if (mDisallowScrollToClearAll) {
                 // We aren't showing the clear all button,
@@ -2283,7 +2296,8 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
                 return getScrollForPage(mTaskViewStartIndex);
             }
             if (mIsRtl) {
-                return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
+                //获取可以滑动的范围,ClearAllButton换到0位后,最后一个就是 TaskView ,无需+1了
+                return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
             }
             return getScrollForPage(mTaskViewStartIndex);
         }
@@ -2291,20 +2305,21 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
     }
 
     @Override
-    protected int computeMaxScroll() {
+    protected int computeMaxScroll() {//获取最右边的范围
         if (getTaskViewCount() > 0) {
             if (mDisallowScrollToClearAll) {
                 // We aren't showing the clear all button,
                 // so use the rightmost task as the min scroll.
                 if (mIsRtl) {
-                    return getScrollForPage(mTaskViewStartIndex);
+                    return getScrollForPage(0);
                 }
                 return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
             }
             if (mIsRtl) {
-                return getScrollForPage(mTaskViewStartIndex);
+                //获取可以滑动的范围,mTaskViewStartIndex当前是1,所以直接这里写死成0就行
+                return getScrollForPage(0);
             }
-            return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
+            return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
         }
         return super.computeMaxScroll();
     }

修改顺序后,会导致 ClearAllButton 是否显示的计算方法不匹配(默认是滑到最左边显示),导致 ClearAllButton 不显示。同时,OverviewActionsView 中截图功能也是根据 ClearAllButton 的状态判断当前能否显示截图。所以需要再调整下 ClearAllButton 的显示计算方法。

@@ -100,13 +102,16 @@ public class ClearAllButton extends Button implements PageCallbacks {
         float shift = Math.min(scrollState.scrollFromEdge, orientationSize);
         float translation = mIsRtl ? (mScrollOffset - shift) : (mScrollOffset + shift);
         orientationHandler.setPrimaryAndResetSecondaryTranslate(this, translation);
-        mScrollAlpha = 1 - shift / orientationSize;
+        // 这里是左右滑动时候,按照View滑动的距离,确定clearAllbutton是否需要显示
+        mScrollAlpha = scrollState.maxScroll == scrollState.scrollFromEdge ? 1.0f : 0.0f;
         updateAlpha();
     }
 
     private void updateAlpha() {
         final float alpha = mScrollAlpha * mContentAlpha * mVisibilityAlpha;
         setAlpha(alpha);
+        // 根据mScrollAlpha(滑动参数)、mContentAlpha(是否存在)、mVisibilityAlpha(是否设置不可见)来确定clearAllbutton是否可见
+        android.util.Log.i("TA", "updateAlpha " + alpha);
         setClickable(alpha == 1);
     }

这里新加一个属性 scrollState.maxScroll  表示最大滑动范围值, scrollFromEdge 等于 maxScroll 时,表示滑到最右边了,此时是 ClearAllButton 界面,ClearAllButton 显示。其他界面就不显示了。

计算 ClearAllButton 显示方法上面这种的话,你是必须滑到最右边才行。如果在第一个APP卡片界面,是不显示,看着不太好看,如下图:

 

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

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

相关文章

工欲善其事,必先利其器,推荐5款效率神器

有句老话这样讲&#xff0c;工欲善其事&#xff0c;必先利其器&#xff0c;好的工具可以让你工作起来事半功倍。 1.全能翻译神器——智能翻译官 这是一款超级强大的翻译软件&#xff0c;什么文本、图片、文档&#xff0c;视频、音频&#xff0c;统统都可以翻&#xff0c;像我…

JAVA毕业设计——基于Springboot+vue的音乐网站系统(源代码+数据库)

github代码地址 https://github.com/ynwynw/music-server-public 毕业设计所有选题地址 https://github.com/ynwynw/allProject 基于Springbootvue的音乐网站系统(源代码数据库)046 一、系统介绍 本项目分为管理员与普通用户两种角色 管理员角色包含以下功能&#xff1a; …

绿色固体ICG-DBCO,凯新生物聚甲基菁染料,仅用于科学研究或者工业应用等非医疗目的,不可用于人类或动物的临床或诊断,非药用,非食用

【外观以及性质】&#xff1a; ICG-DBCO绿色固体&#xff0c;ICG是一种带负电荷的聚甲基菁染料&#xff08;三碳菁染料&#xff09;具有良好的水溶性&#xff0c;其次花菁染料毒性&#xff0c;安全性更好及更的光稳定性。 【试剂物理数据】&#xff1a; 货号&#xff1a;Y-R…

Java面试题(六)腾讯Spring夺命7连问(灵魂拷问)

腾讯面试题&#xff1a;Spring1.谈一谈spring IOC的理解&#xff0c;原理与实现&#xff1f;2.谈一谈Spring IOC的底层实现&#xff1f;3.描述下Bean的生命周期4.Spring如何解决循环依赖问题&#xff1f;5.BeanFactory 和FactoryBean有什么区别&#xff1f;6.Spring 中用到哪些…

ELK日志系统搭建

文章目录ES安装ES启动ES错误处理验证Kibana安装Kibana启动 KibanaLogstash安装Logstash启动Logstash项目整合引入依赖logback-spring.xml启动项目在Kibana中查看链接&#xff1a;点击 提取码&#xff1a;yyds ES 安装ES cat >> /etc/sysctl.conf<<- EOF net.ipv…

基于微信小程序的小区疫情防控系统-计算机毕业设计

随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受业主的喜爱&#xff0c;小区疫情防控小程序被业主普遍使用&#xff0c;为方便业主能够可…

G1D33-BTG复现重跑实验

一、复现BTG 复现很简单&#xff0c;所以就记录一些乱七八糟的叭 &#xff08;一&#xff09;传参 传是否使用cuda的参数的时候&#xff0c;发现传True会报错&#xff0c;后来查到链接 https://stackoverflow.com/questions/43381710/unrecognized-arguments-true 如果什么都…

web前端课程设计 基于HTML+CSS+JavaScript汽车自驾游(10个页面)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

web前端网页设计期末课程大作业:中华传统文化题材网页源码——基于HTML实现中国水墨风书画艺术网站(12个页面)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

关于自动化测试的误区——希望能帮助新手正确的了解自动化一些概念。

自动化测试作为软件测试的一种技术手段&#xff0c;时常被大家讨论。本人在自动化技术方面有过略有小成&#xff0c;今天聊一聊关于自动化的一些误区&#xff0c;以帮助新手能正确的了解和认识自动化一些概念。 测试的行为本质是什么&#xff1f; 为什么先从这个概念开始谈起…

React 入门:实战案例 TodoList 删除一条 Item

文章目录目标实现效果实现思路实现步骤第一步&#xff1a;App 组件中定义删除 Todo 的组件方法第二步&#xff1a;App 组件通过 props 传递删除 Todo 的方法到子组件 List第三步&#xff1a;List 组件接收删除 Todo 的方法&#xff0c;并传递给 Item 子组件第四步&#xff1a;I…

JAVA毕业设计——基于Springboot+vue的图书管理系统(源代码+数据库)

github代码地址 https://github.com/ynwynw/bookmanage2-public 毕业设计所有选题地址 https://github.com/ynwynw/allProject 基于Springbootvue的图书管理系统(源代码数据库) 一、系统介绍 本项目分为管理员与普通用户两种角色 体实现功能如下: 用户系统权限控制管理:主要…

热插拔技术--以ADM1177为例说明

综述 ADM1177是一款热插拔控制器&#xff0c;并且还支持电压电流采集&#xff08;12bitADC&#xff09;和传输(IIC).本文着重说明热插拔技术&#xff0c;所以仅说明ADM热插拔处理过程&#xff0c;对于ADC和IIC部分不予说明&#xff0c;请读者自行研究。 热插拔的应用背景 服务…

【GRU回归预测】基于粒子群优化门控循环单元PSO-GRU神经网络实现多输入单输出回归预测附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

SeleniumUI自动化的POM三层架构

目录 1、定义log.py日志 2、在基础封装层初始化类uitls.__init__.py中选择了日志的打印级别, 3、定义页面基础类base_page.py&#xff0c;定义了页面找元素的方法&#xff0c; 4、将百度页面的元素以代码形式保存&#xff0c;baidu.py 5、重新封装浏览器方法, browser.py …

ChatGPT版微信个人号搭建流程

[TOC] 参考链接&#xff1a; github仓库 准备服务器 进入腾讯云服务器官网&#xff0c;搜索“轻量应用服务器”立即选购 注意&#xff0c;地区要选海外&#xff0c;镜像选Docker镜像 购买之后&#xff0c;就进入控制台 然后登陆到shell 安装部署 查看一下docker&#xff0…

【探索Spring底层】11.切点匹配

文章目录1. 前言2. 给一个类中的其中一个方法增强3. 根据注解给方法增强4. Spring中Transactional的底层实现1. 前言 这里主要讲述一些切点匹配的相关例子&#xff0c;其主要是关于切点表达式匹配的实现。 主要有三种例子&#xff1a; 给一个类中的其中一个方法增强根据注解…

Gitee创建自己的仓库并且上传项目

Gitee创建自己的仓库并且上传项目前言在码云上创建仓库上传项目到远程仓库前言 之前用了一段时间的Gitee&#xff08;码云&#xff09;一直想写一篇文章记录下&#xff0c;结果赶上世界杯 被人把苦茶子给抢走了。。。正好这几天筹钱&#xff0c;那就简单记录下。 这里的Git的安…

[附源码]Python计算机毕业设计动漫网站Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

机器人开发--Pepperl+Fuchs倍加福激光雷达系列

机器人开发--PepperlFuchs倍加福激光雷达系列1 介绍2 R2000系列2.1 按键操作2.2 测量方法2.3 协议2.3.1 文档2.3.2 特点2.3.3 控制 HTTP收发报文格式get_protocol_info设置传感器参数list_parameters – list parametersget_parameter – read a parameterset_parameter – cha…