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

Android 13 Launcher3最近任务列表“全部清除“按钮位置优化实战

一、问题背景与实现难点

在Android 13横屏设备开发中,系统默认将最近任务列表的"全部清除"按钮布局在屏幕左侧,这与用户习惯的底部布局存在明显差异。相较于Android 8.1时代SystemUI模块的实现,Android 13将相关逻辑迁移至Launcher3模块,需要重点修改以下核心文件:

  1. 布局结构重构:需处理原有左侧按钮与新底部按钮的共存问题

  2. 事件传递机制:确保新按钮触发正确的清除逻辑

  3. 动画兼容处理:保持清除动画的连贯性

  4. 多语言适配:确保新增按钮的文本适配

二、关键技术实现路径
1. 布局文件重构(overview_actions_container.xml)

xml

复制

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_alignParentBottom="true">

    <!-- 原有操作按钮容器 -->
    <LinearLayout
        android:id="@+id/action_buttons"
        android:orientation="horizontal">
        <!-- 截图、分屏等按钮 -->
    </LinearLayout>

    <!-- 新增底部清除按钮 -->
    <Button
        android:id="@+id/recents_clear_all_btn"
        style="@style/OverviewActionButton"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:text="@string/recents_clear_all"
        android:drawableStart="@drawable/ic_clear_all"
        android:gravity="center_vertical|start"/>
</LinearLayout>

运行 HTML

2. 事件处理层改造(OverviewActionsView.java)

java

复制

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    // 绑定新按钮
    View clearAllBtn = findViewById(R.id.recents_clear_all_btn);
    clearAllBtn.setOnClickListener(this);
    
    // 隐藏旧版按钮
    View oldClearAll = findViewById(R.id.old_clear_all);
    oldClearAll.setVisibility(GONE);
}

@Override
public void onClick(View v) {
    if (mCallbacks == null) return;
    
    switch(v.getId()) {
        case R.id.recents_clear_all_btn:
            // 执行新版清除逻辑
            mCallbacks.onClearAllRequested();
            break;
        // 其他按钮处理...
    }
}
3. 清除逻辑改造(RecentsView.java)

java

复制

public void dismissAllTasks(View triggerView) {
    // 添加平移动画
    AnimatorSet animSet = new AnimatorSet();
    animSet.playTogether(
        ObjectAnimator.ofFloat(triggerView, "translationY", 0, 100),
        ObjectAnimator.ofFloat(triggerView, "alpha", 1, 0)
    );
    animSet.setDuration(200);
    
    // 执行清除逻辑
    animSet.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            mActivity.getModel().getTasks().clearAll();
        }
    });
    animSet.start();
}
4. 工厂类适配(TaskOverlayFactory.java)

java

复制

public class TaskOverlayFactory {
    private final ClearAllPositionHandler mPositionHandler;

    public interface ClearAllPositionHandler {
        void updatePosition(Rect displayRect);
    }

    @Override
    public void onTaskViewUpdated(TaskView taskView) {
        // 根据当前方向调整位置
        if (mPositionHandler != null) {
            mPositionHandler.updatePosition(taskView.getDisplayRect());
        }
    }
}
三、兼容性处理方案
  1. 多方向适配:通过DisplayRotationListener检测屏幕方向

java

复制

public class RotationAwareButton extends Button {
    private final DisplayRotationListener mRotationListener = rotation -> {
        updateLayoutParams(rotation);
    };

    private void updateLayoutParams(int rotation) {
        LayoutParams params = (LayoutParams) getLayoutParams();
        switch(rotation) {
            case Surface.ROTATION_90:
                params.gravity = Gravity.BOTTOM|Gravity.START;
                break;
            case Surface.ROTATION_270:
                params.gravity = Gravity.BOTTOM|Gravity.END;
                break;
            default:
                params.gravity = Gravity.BOTTOM|Gravity.CENTER;
        }
        requestLayout();
    }
}
  1. 内存泄漏防护:使用WeakReference包装回调

java

复制

private static class SafeCallbackWrapper implements Callback {
    private final WeakReference<Callback> mWeakRef;

    SafeCallbackWrapper(Callback original) {
        mWeakRef = new WeakReference<>(original);
    }

    @Override
    public void onClearAll() {
        Callback cb = mWeakRef.get();
        if (cb != null) cb.onClearAll();
    }
}
四、性能优化建议
  1. 布局层级优化:使用ConstraintLayout代替多层LinearLayout

  2. 动画资源复用:通过AnimatorSet缓存复用清除动画

  3. 异步加载机制:对清除操作采用后台线程处理

java

复制

private final Executor mBgExecutor = Executors.newSingleThreadExecutor();

void performClearAll() {
    mBgExecutor.execute(() -> {
        // 执行耗时操作
        SystemServicesProxy.getInstance().killAllRecentTasks();
        
        // 更新UI
        mMainHandler.post(() -> {
            mAdapter.notifyDataSetChanged();
        });
    });
}
五、测试验证方案
  1. 自动化测试用例

java

复制

@Test
public void testClearAllButtonPosition() {
    onView(withId(R.id.recents_view)).perform(swipeUp());
    
    onView(withId(R.id.recents_clear_all_btn))
        .check(isCompletelyDisplayed())
        .check(isBottomAligned());
    
    rotateDeviceToLandscape();
    onView(withId(R.id.recents_clear_all_btn))
        .check(isBottomAligned());
}
  1. 手动测试矩阵

测试场景预期结果
横屏模式按钮居底显示
任务数量为0时按钮自动隐藏
快速点击防抖处理,仅响应一次点击
低内存状态保持正常响应

通过以上技术方案的实施,可有效实现Android 13横屏设备最近任务列表"全部清除"按钮的底部布局优化,同时保证系统的稳定性和操作流畅性。建议在代码修改完成后进行多场景压力测试,重点验证横竖屏切换时的布局稳定性及多任务场景下的内存表现。

转载请注明出处Android 13 Launcher3最近任务列表“全部清除“按钮位置优化实战-CSDN博客,谢谢! 

相关文章:

  • Spring(7)——MyBatis入门(1)
  • 7、vue3做了什么
  • Java 大视界 -- Java 大数据在智能家居设备联动与场景自动化中的应用(140)
  • 关系数据库设计理论
  • Android Fresco 框架兼容模块源码深度剖析(六)
  • 在鸿蒙Next中开发一个月历组件
  • AcWing 3533:查找第K小数 ← sort+unique
  • Linux并发程序设计(5):线程的相关操作
  • 高频SQL 50 题(持续更新)
  • Deepseek X 文心智能体:谐音梗广告创意大师
  • vue3 函数式弹窗
  • 文件管理系统
  • Spring Boot 配置属性 (Configuration Properties) 详解:优雅地管理应用配置
  • 创建多模块教程
  • ARMv8.x-M架构计算能力概览
  • react路由5和6新增及区别
  • 【论文阅读】FairCLIP - 医疗视觉语言学习中的公平性提升
  • 基于香橙派 KunpengPro学习CANN(2)——Ascend Extension for PyTorch 配置与安装
  • 深度学习框架PyTorch——从入门到精通(5)自动微分
  • Web3游戏行业报告
  • 甘肃白银煤矿透水事故最新进展:3名被困矿工已无生命体征
  • 马上评|房屋“注胶堵漏”骗局何以屡屡得逞
  • 脱欧后首次英欧峰会召开前夕,双方却因渔业和青年流动议题僵住了
  • 消费维权周报丨上周涉汽车类投诉较多,涉加油“跳枪”等问题
  • 家国万里·时光故事会|科学家伉俪,用玉米书写家国情怀
  • 高温最强时段来了!北方局地高温有明显极端性