Commit b41e0803 by tanghuan

增加Android系统的虚拟按键安全区

1 parent bc0457d7
...@@ -26,6 +26,12 @@ class App extends StatelessWidget { ...@@ -26,6 +26,12 @@ class App extends StatelessWidget {
theme: ThemeData(primarySwatch: Colors.blue), theme: ThemeData(primarySwatch: Colors.blue),
supportedLocales: AppLocalizations.supportedLocales, supportedLocales: AppLocalizations.supportedLocales,
localizationsDelegates: AppLocalizations.localizationsDelegates, localizationsDelegates: AppLocalizations.localizationsDelegates,
// Android edge-to-edge 模式下虚拟导航键叠在内容上方,
// 通过 builder 统一包裹 SafeArea,所有路由页面自动适配底部安全区域。
builder: (context, child) => ColoredBox(
color: Colors.white,
child: SafeArea(top: false, child: child!),
),
); );
// 全局默认状态栏样式兑底:透明背景 + 深色图标。 // 全局默认状态栏样式兑底:透明背景 + 深色图标。
......
...@@ -45,90 +45,93 @@ class _PreviewMediaPageState extends State<PreviewMediaPage> { ...@@ -45,90 +45,93 @@ class _PreviewMediaPageState extends State<PreviewMediaPage> {
_initialized = true; _initialized = true;
} }
return Scaffold( return ColoredBox(
backgroundColor: Colors.black, color: Colors.black,
body: Stack( child: Scaffold(
children: [ backgroundColor: Colors.black,
Positioned.fill( body: Stack(
child: PhotoViewGallery.builder( children: [
pageController: _pageController, Positioned.fill(
itemCount: _items.length, child: PhotoViewGallery.builder(
onPageChanged: _onPageChanged, pageController: _pageController,
backgroundDecoration: const BoxDecoration(color: Colors.black), itemCount: _items.length,
loadingBuilder: (ctx, event) => const Center( onPageChanged: _onPageChanged,
child: CircularProgressIndicator(color: Colors.white), backgroundDecoration: const BoxDecoration(color: Colors.black),
), loadingBuilder: (ctx, event) => const Center(
builder: (ctx, index) { child: CircularProgressIndicator(color: Colors.white),
final MediaItem item = _items[index]; ),
final String heroTag = 'preview_media_${index}_${item.url}'; builder: (ctx, index) {
if (item.type == MediaType.video) { final MediaItem item = _items[index];
final GlobalKey<_VideoItemState> key = _videoKeys final String heroTag = 'preview_media_${index}_${item.url}';
.putIfAbsent(index, () => GlobalKey<_VideoItemState>()); if (item.type == MediaType.video) {
// 视频页:使用 customChild 嵌入自定义视频组件 final GlobalKey<_VideoItemState> key = _videoKeys
// disableGestures=true 关闭 PhotoView 的缩放手势, .putIfAbsent(index, () => GlobalKey<_VideoItemState>());
// 把控制权完全交给 Chewie 自身的进度条/暂停等操作。 // 视频页:使用 customChild 嵌入自定义视频组件
return PhotoViewGalleryPageOptions.customChild( // disableGestures=true 关闭 PhotoView 的缩放手势,
disableGestures: true, // 把控制权完全交给 Chewie 自身的进度条/暂停等操作。
return PhotoViewGalleryPageOptions.customChild(
disableGestures: true,
heroAttributes: PhotoViewHeroAttributes(tag: heroTag),
child: _VideoItem(
key: key,
url: item.url,
poster: item.poster,
autoPlay: index == _currentIndex,
),
);
}
// 图片页:标准 PhotoView 配置
return PhotoViewGalleryPageOptions(
imageProvider: CachedNetworkImageProvider(item.url),
minScale: PhotoViewComputedScale.contained,
maxScale: PhotoViewComputedScale.covered * 3,
initialScale: PhotoViewComputedScale.contained,
heroAttributes: PhotoViewHeroAttributes(tag: heroTag), heroAttributes: PhotoViewHeroAttributes(tag: heroTag),
child: _VideoItem( onTapUp: (_, __, ___) => _close(),
key: key, errorBuilder: (c, e, s) => const Center(
url: item.url, child: Icon(
poster: item.poster, Icons.broken_image,
autoPlay: index == _currentIndex, color: Colors.white54,
size: 48,
),
), ),
); );
} },
// 图片页:标准 PhotoView 配置 ),
return PhotoViewGalleryPageOptions(
imageProvider: CachedNetworkImageProvider(item.url),
minScale: PhotoViewComputedScale.contained,
maxScale: PhotoViewComputedScale.covered * 3,
initialScale: PhotoViewComputedScale.contained,
heroAttributes: PhotoViewHeroAttributes(tag: heroTag),
onTapUp: (_, __, ___) => _close(),
errorBuilder: (c, e, s) => const Center(
child: Icon(
Icons.broken_image,
color: Colors.white54,
size: 48,
),
),
);
},
),
),
Positioned(
top: MediaQuery.of(context).padding.top + 8,
right: 8,
child: IconButton(
icon: const Icon(Icons.close, color: Colors.white, size: 28),
onPressed: _close,
), ),
),
if (_items.length > 1)
Positioned( Positioned(
bottom: MediaQuery.of(context).padding.bottom + 24, top: MediaQuery.of(context).padding.top + 8,
left: 0, right: 8,
right: 0, child: IconButton(
child: Center( icon: const Icon(Icons.close, color: Colors.white, size: 28),
child: Container( onPressed: _close,
padding: ),
const EdgeInsets.symmetric(horizontal: 12, vertical: 6), ),
decoration: BoxDecoration( if (_items.length > 1)
color: Colors.black54, Positioned(
borderRadius: BorderRadius.circular(12), bottom: MediaQuery.of(context).viewPadding.bottom + 24,
), left: 0,
child: Text( right: 0,
'${_currentIndex + 1} / ${_items.length}', child: Center(
style: const TextStyle( child: Container(
color: Colors.white, padding:
fontSize: 14, const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.black54,
borderRadius: BorderRadius.circular(12),
),
child: Text(
'${_currentIndex + 1} / ${_items.length}',
style: const TextStyle(
color: Colors.white,
fontSize: 14,
),
), ),
), ),
), ),
), ),
), ],
], ),
), ),
); );
} }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!