Merge pull request #60 from SDWebImage/example_detail_scale_image

Example - Supports zoom-in in the detail page image
This commit is contained in:
DreamPiggy 2019-11-17 02:17:54 +08:00 committed by GitHub
commit c1d572a5fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 5 deletions

View File

@ -13,34 +13,79 @@ struct DetailView: View {
let url: String let url: String
let animated: Bool let animated: Bool
@State var isAnimating: Bool = true @State var isAnimating: Bool = true
@State var lastScaleValue: CGFloat = 1.0
@State var scale: CGFloat = 1.0
@Environment(\.presentationMode) var presentationMode
var body: some View { var body: some View {
VStack { VStack {
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS)
if animated { if animated {
contentView() zoomView()
.navigationBarItems(trailing: Button(isAnimating ? "Stop" : "Start") { .navigationBarItems(trailing: Button(isAnimating ? "Stop" : "Start") {
self.isAnimating.toggle() self.isAnimating.toggle()
}) })
} else { } else {
contentView() zoomView()
} }
#endif #endif
#if os(macOS) || os(watchOS) #if os(macOS) || os(watchOS)
if animated { if animated {
contentView() zoomView()
.contextMenu { .contextMenu {
Button(isAnimating ? "Stop" : "Start") { Button(isAnimating ? "Stop" : "Start") {
self.isAnimating.toggle() self.isAnimating.toggle()
} }
} }
} else { } else {
contentView() zoomView()
} }
#endif #endif
} }
} }
func zoomView() -> some View {
#if os(macOS) || os(iOS)
return contentView()
.scaleEffect(self.scale)
.gesture(MagnificationGesture(minimumScaleDelta: 0.1).onChanged { value in
let delta = value / self.lastScaleValue
self.lastScaleValue = value
let newScale = self.scale * delta
self.scale = min(max(newScale, 0.5), 2)
}.onEnded { value in
self.lastScaleValue = 1.0
})
#endif
#if os(tvOS)
return contentView()
.scaleEffect(self.scale)
.focusable(true)
.onPlayPauseCommand {
switch self.scale {
case 1:
self.scale = 2
case 2:
self.scale = 1
default: break
}
}
#endif
#if os(watchOS)
return contentView()
// SwiftUI's bug workaround (watchOS 6.1)
// If use `.focusable(true)` here, after pop the Detail view, the Content view's List does not get focus again
// After some debug, I found that the pipeline to change focus becomes:
// Detail Pop (resign focus) -> Content Appear (List view become focus) -> Detail Disappear (become focus again) -> End
// Even you use `onDisappear`, it's too late because `.focusable` is called firstly
// Sadly, Content view's List focus is managed by SwiftUI (a UICollectionView actually), call `focusable` on Content view does nothing as well
// So, here we must use environment or binding, to not become focus during pop :)
.focusable(self.presentationMode.wrappedValue.isPresented)
.scaleEffect(self.scale)
.digitalCrownRotation($scale, from: 0.5, through: 2, by: 0.1, sensitivity: .low, isHapticFeedbackEnabled: false)
#endif
}
func contentView() -> some View { func contentView() -> some View {
HStack { HStack {
if animated { if animated {

View File

@ -268,7 +268,8 @@ Demo Tips:
1. Use `Switch` (right-click on macOS/force press on watchOS) to switch between `WebImage` and `AnimatedImage`. 1. Use `Switch` (right-click on macOS/force press on watchOS) to switch between `WebImage` and `AnimatedImage`.
2. Use `Reload` (right-click on macOS/force press on watchOS) to clear cache. 2. Use `Reload` (right-click on macOS/force press on watchOS) to clear cache.
3. Use `Swipe` to delete one image item. 3. Use `Swipe` to delete one image item.
4. Clear cache and go to detail page to see progressive loading. 4. Pinch gesture (Digital Crown on watchOS, play button on tvOS) to zoom-in detail page image.
5. Clear cache and go to detail page to see progressive loading.
## Screenshot ## Screenshot