Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
ethan
/
appframe
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Commit b41e0803
authored
2026-06-26 16:58:38 +0800
by
tanghuan
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
增加Android系统的虚拟按键安全区
1 parent
bc0457d7
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
84 additions
and
75 deletions
lib/app.dart
lib/ui/pages/media/preview_media_page.dart
lib/app.dart
View file @
b41e080
...
...
@@ -26,6 +26,12 @@ class App extends StatelessWidget {
theme:
ThemeData
(
primarySwatch:
Colors
.
blue
),
supportedLocales:
AppLocalizations
.
supportedLocales
,
localizationsDelegates:
AppLocalizations
.
localizationsDelegates
,
// Android edge-to-edge 模式下虚拟导航键叠在内容上方,
// 通过 builder 统一包裹 SafeArea,所有路由页面自动适配底部安全区域。
builder:
(
context
,
child
)
=>
ColoredBox
(
color:
Colors
.
white
,
child:
SafeArea
(
top:
false
,
child:
child
!),
),
);
// 全局默认状态栏样式兑底:透明背景 + 深色图标。
...
...
lib/ui/pages/media/preview_media_page.dart
View file @
b41e080
...
...
@@ -45,90 +45,93 @@ class _PreviewMediaPageState extends State<PreviewMediaPage> {
_initialized
=
true
;
}
return
Scaffold
(
backgroundColor:
Colors
.
black
,
body:
Stack
(
children:
[
Positioned
.
fill
(
child:
PhotoViewGallery
.
builder
(
pageController:
_pageController
,
itemCount:
_items
.
length
,
onPageChanged:
_onPageChanged
,
backgroundDecoration:
const
BoxDecoration
(
color:
Colors
.
black
),
loadingBuilder:
(
ctx
,
event
)
=>
const
Center
(
child:
CircularProgressIndicator
(
color:
Colors
.
white
),
),
builder:
(
ctx
,
index
)
{
final
MediaItem
item
=
_items
[
index
];
final
String
heroTag
=
'preview_media_
${index}
_
${item.url}
'
;
if
(
item
.
type
==
MediaType
.
video
)
{
final
GlobalKey
<
_VideoItemState
>
key
=
_videoKeys
.
putIfAbsent
(
index
,
()
=>
GlobalKey
<
_VideoItemState
>());
// 视频页:使用 customChild 嵌入自定义视频组件
// disableGestures=true 关闭 PhotoView 的缩放手势,
// 把控制权完全交给 Chewie 自身的进度条/暂停等操作。
return
PhotoViewGalleryPageOptions
.
customChild
(
disableGestures:
true
,
return
ColoredBox
(
color:
Colors
.
black
,
child:
Scaffold
(
backgroundColor:
Colors
.
black
,
body:
Stack
(
children:
[
Positioned
.
fill
(
child:
PhotoViewGallery
.
builder
(
pageController:
_pageController
,
itemCount:
_items
.
length
,
onPageChanged:
_onPageChanged
,
backgroundDecoration:
const
BoxDecoration
(
color:
Colors
.
black
),
loadingBuilder:
(
ctx
,
event
)
=>
const
Center
(
child:
CircularProgressIndicator
(
color:
Colors
.
white
),
),
builder:
(
ctx
,
index
)
{
final
MediaItem
item
=
_items
[
index
];
final
String
heroTag
=
'preview_media_
${index}
_
${item.url}
'
;
if
(
item
.
type
==
MediaType
.
video
)
{
final
GlobalKey
<
_VideoItemState
>
key
=
_videoKeys
.
putIfAbsent
(
index
,
()
=>
GlobalKey
<
_VideoItemState
>());
// 视频页:使用 customChild 嵌入自定义视频组件
// disableGestures=true 关闭 PhotoView 的缩放手势,
// 把控制权完全交给 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
),
child:
_VideoItem
(
key:
key
,
url:
item
.
url
,
poster:
item
.
poster
,
autoPlay:
index
==
_currentIndex
,
onTapUp:
(
_
,
__
,
___
)
=>
_close
(),
errorBuilder:
(
c
,
e
,
s
)
=>
const
Center
(
child:
Icon
(
Icons
.
broken_image
,
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
(
bottom:
MediaQuery
.
of
(
context
).
padding
.
bottom
+
24
,
left:
0
,
right:
0
,
child:
Center
(
child:
Container
(
padding:
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
,
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
(
bottom:
MediaQuery
.
of
(
context
).
viewPadding
.
bottom
+
24
,
left:
0
,
right:
0
,
child:
Center
(
child:
Container
(
padding:
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
,
),
),
),
),
),
)
,
]
,
]
,
)
,
),
);
}
...
...
Write
Preview
Styling with
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment