You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter如何实现类似SlideJoy的亮屏后解锁前显示自定义页面

Flutter实现类SlideJoy锁屏前置自定义页方案

受系统沙箱机制约束,该功能仅可在安卓端实现,iOS端无公开API支持覆盖系统解锁前界面。
整个实现的核心逻辑不是替换系统锁屏,而是在系统解锁界面上层叠加一层可关闭的自定义窗口,用户左滑关闭窗口后即可看到原生解锁界面,和SlideJoy的交互逻辑完全一致。

第一步:安卓端原生配置与桥接

Flutter本身作为UI渲染框架不具备系统级窗口操作能力,需要先在安卓宿主层完成核心配置:

  • 清单文件权限声明,在android/app/src/main/AndroidManifest.xml中添加以下权限:
<!-- 悬浮窗权限,用于在所有应用/锁屏上层显示页面 -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!-- 亮屏/锁屏状态监听 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- 安卓12+ 全屏意图权限,支持锁屏状态拉起页面 -->
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
  • 自定义Flutter承载Activity,给对应的Activity节点添加锁屏显示属性:
<activity
    android:name=".CustomLockActivity"
    android:exported="true"
    android:showOnLockScreen="true"
    android:turnScreenOn="true"
    android:launchMode="singleInstance"
    android:excludeFromRecents="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>
  • 注册屏幕状态广播接收器:监听系统ACTION_SCREEN_ON(屏幕点亮)广播,收到广播后直接拉起上面配置的CustomLockActivity,保证用户亮屏后第一时间看到自定义页面。
  • 配置窗口参数:在CustomLockActivity的onCreate生命周期中添加窗口flag,让页面显示在锁屏层之上:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
    setShowWhenLocked(true)
    setTurnScreenOn(true)
}
window.addFlags(
    WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
    or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
    or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
)
// 注册MethodChannel,接收Flutter侧发来的关闭页面指令
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "lock_screen_channel").setMethodCallHandler { call, result ->
    if (call.method == "dismissLockPage") {
        // 关闭当前自定义锁屏页,底层原生解锁界面自动露出
        finish()
        result.success(null)
    }
}
  • 国产ROM适配:针对小米、华为、OPPO、vivo等定制系统,需要额外引导用户开启「锁屏显示」「后台弹出页面」权限,否则亮屏时无法正常拉起自定义页面。

第二步:Flutter侧交互与UI实现

编写自定义锁屏页,使用GestureDetector监听横向左滑手势,配合跟手动画实现和SlideJoy一致的交互:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class LockScreenPage extends StatefulWidget {
  const LockScreenPage({super.key});

  @override
  State<LockScreenPage> createState() => _LockScreenPageState();
}

class _LockScreenPageState extends State<LockScreenPage> {
  double _dragOffset = 0;
  static const _channel = MethodChannel('lock_screen_channel');

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;
    return Scaffold(
      body: GestureDetector(
        onHorizontalDragUpdate: (details) {
          // 仅响应向左滑动的手势
          if (details.delta.dx < 0) {
            setState(() {
              _dragOffset += details.delta.dx.abs();
            });
          }
        },
        onHorizontalDragEnd: (details) {
          // 滑动距离超过屏幕1/3则触发关闭
          if (_dragOffset > screenWidth * 0.3) {
            _channel.invokeMethod('dismissLockPage');
          } else {
            // 未达阈值则回弹复位
            setState(() {
              _dragOffset = 0;
            });
          }
        },
        child: AnimatedContainer(
          duration: const Duration(milliseconds: 200),
          curve: Curves.easeOut,
          transform: Matrix4.translationValues(-_dragOffset, 0, 0),
          width: double.infinity,
          height: double.infinity,
          color: Colors.white,
          // 替换为你需要展示的自定义内容,比如资讯、广告、快捷功能入口
          child: const Center(
            child: Text("自定义锁屏页面,左滑进入解锁界面", style: TextStyle(fontSize: 18)),
          ),
        ),
      ),
    );
  }
}

关键注意事项

  • 该方案不会修改、绕过系统原生解锁逻辑,自定义页面仅为悬浮在解锁层上方的普通窗口,关闭后用户仍需通过指纹、密码、人脸等系统校验才能进入桌面,不会触发应用商店安全合规风险。
  • 需要额外处理特殊场景中断:检测到来电、闹钟响铃等系统级事件时,主动关闭自定义锁屏页,避免遮挡系统关键界面。
  • 首次启动应用时需要引导用户手动开启悬浮窗、锁屏显示等必要权限,否则功能无法正常运行。

内容的提问来源于stack exchange,提问作者Dennis Washira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 01:27:26