質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Q&A

0回答

595閲覧

AnimatedImageを利用したカードViewをDragGestureするとスムーズに動かない

tomaa

総合スコア84

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

0グッド

0クリップ

投稿2021/06/01 16:59

編集2021/06/01 18:29

現在、SwiftUIを使用して、パン(カードの横移動)の動きができるビューを作成しようとしています。

DragGesture で移動するカードでViewでAnimatedImage()を使用すると、パン ジェスチャがスムーズに動作しません。(表示する画像はFirebase Storageに保存されており、URLはFirestoreの方法でダウンロードします)

  • シミュレーターで動作確認をするとスムーズに動くのですが、実機でやると上手くいきません。

  • AnimatedImageを使わなければ実機で操作しても問題なく動きます。

このような問題を解決するにはどのような方法がありますでしょうか?


  • NG:

イメージ説明

  • OK:

イメージ説明


PanGesture.swift

swift

1import SwiftUI 2import SDWebImageSwiftUI 3import FirebaseStorage 4 5struct PanListView: View { 6 7 @ObservedObject var viewModel:ViewModel 8 9 var body: some View { 10 NavigationView{ 11 VStack{ 12 List(self.viewModel.posts.indices, id: .self){index in 13 ZStack{ 14 Button(action: { 15 viewModel.selectedDetailIndex = Double(index) 16 viewModel.initialIndex = (Double(viewModel.posts.count) - 0.5) - viewModel.selectedDetailIndex 17 18 self.viewModel.initialX = CGFloat((Double(UIScreen.main.bounds.width) - 15) * self.viewModel.initialIndex) 19 self.viewModel.x = self.viewModel.initialX 20 21 self.viewModel.swipePostsCount = CGFloat(viewModel.initialIndex + 0.5) 22 23 self.viewModel.detailShowArray[Int(viewModel.selectedDetailIndex)] = true 24 25 }, label: { 26 Text(self.viewModel.posts[index].word) 27 }) 28 NavigationLink( 29 30 destination: PanSwipeView( 31 viewModel: viewModel, posts: self.viewModel.posts 32 ) 33 ){ 34 EmptyView() 35 }.frame(width:0).opacity(0) 36 } 37 } 38 } 39 .navigationBarTitle("ListView",displayMode: .inline) 40 } 41 .navigationViewStyle(StackNavigationViewStyle()) 42 43 .onAppear(){ 44 self.viewModel.getAllPosts(){(status) in 45 for _ in 0..<self.viewModel.posts.count{ 46 self.viewModel.detailShowArray.append(false) 47 } 48 } 49 } 50 } 51} 52 53 54 55struct PanSwipeView: View { 56 57 @ObservedObject var viewModel:ViewModel 58 @State var posts:[Post] 59 @State var screen = UIScreen.main.bounds.width - 30 60 61 var body: some View { 62 HStack(spacing:15){ 63 Spacer() 64 ForEach(self.posts.indices, id: .self){ index in 65 PanDetailCard( 66 viewModel: viewModel, 67 index: index, 68 imageURL: posts[index].image_url ?? "", 69 word:posts[index].word 70 ) 71 72 .offset(x:self.viewModel.x) 73 .highPriorityGesture(DragGesture(minimumDistance: 20) 74 .onChanged({(value) in 75 if value.translation.width > 0{ 76 self.viewModel.x = value.location.x 77 }else { 78 self.viewModel.x = value.location.x - self.screen 79 } 80 }) 81 .onEnded({(value) in 82 83 if value.translation.width > 0{ 84 if value.translation.width > ((self.viewModel.swipePostsCount - 80) / 2) && Int(viewModel.swipePostsCount) != self.getMid(){ 85 86 self.viewModel.swipePostsCount += 1 87 self.updateHeight(value: Int(viewModel.swipePostsCount)) 88 89 self.viewModel.x = (self.screen + 15 ) * (self.viewModel.swipePostsCount - 0.5) 90 91 }else{ 92 self.viewModel.x = (self.screen + 15 ) * (self.viewModel.swipePostsCount - 0.5) 93 } 94 95 }else{ 96 97 if -value.translation.width > ((self.viewModel.swipePostsCount - 80) / 2) && -Int(viewModel.swipePostsCount) != self.getMid() - 1{ 98 self.viewModel.swipePostsCount -= 1 99 self.updateHeight(value: Int(viewModel.swipePostsCount)) 100 self.viewModel.x = (self.screen + 15 ) * (self.viewModel.swipePostsCount - 0.5) 101 102 }else{ 103 self.viewModel.x = (self.screen + 15 ) * (self.viewModel.swipePostsCount - 0.5) 104 } 105 } 106 }) 107 ) 108 } 109 Spacer() 110 } 111 .frame(width: UIScreen.main.bounds.width,height: UIScreen.main.bounds.height) 112 .background(Color.black.opacity(0.2)) 113 .animation(.spring()) 114 115 .navigationBarTitle("Detail",displayMode: .inline) 116 117 118 119 } 120 121 func getMid() -> Int{ 122 return viewModel.posts.count / 2 123 } 124 125 func updateHeight(value:Int){ 126 var id : Int 127 128 if value < 0 { 129 id = -value + getMid() 130 }else{ 131 id = getMid() - value 132 } 133 134 for i in 0..<viewModel.posts.count{ 135 self.viewModel.detailShowArray[i] = false 136 } 137 self.viewModel.detailShowArray[id] = true 138 } 139} 140 141 142struct PanDetailCard: View { 143 144 @ObservedObject var viewModel:ViewModel 145 @State var screen = UIScreen.main.bounds.width - 30 146 @State var url:String = "" 147 148 var index:Int 149 var imageURL:String 150 var word:String 151 152 153 var body: some View { 154 ScrollView{ 155 Group{ 156 HStack{ 157 Text("Test") 158 Spacer() 159 } 160 HStack{ 161 Spacer() 162 Text(Date(),style: .date) 163 .font(.footnote) 164 .foregroundColor(.secondary) 165 } 166 HStack{ 167 Button(action: { 168 }, label: { 169 HStack{ 170 Image(systemName: "person.circle") 171 .foregroundColor(Color.black) 172 173 Text("user_name") 174 .foregroundColor(Color.black) 175 } 176 }) 177 Spacer() 178 } 179 } 180 Group{ 181 AnimatedImage(url: URL(string: url)) 182 .resizable() 183 .scaledToFit() 184 .frame(width: ScreenSize.screenWidth * 0.8, height: ScreenSize.screenWidth * 0.8) 185 186 Text("test") 187 .font(.title2) 188 .fontWeight(.bold) 189 190 VStack(alignment: .leading){ 191 Text("test") 192 .fontWeight(.bold) 193 .foregroundColor(Color.black) 194 195 Text(word) 196 .font(.title) 197 .fontWeight(.bold) 198 .foregroundColor(.blue) 199 200 Text("test") 201 .font(.title2) 202 .fontWeight(.bold) 203 .foregroundColor(Color.black) 204 } 205 Divider() 206 VStack(alignment: .leading){ 207 Text("sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample") 208 .foregroundColor(Color.black) 209 } 210 } 211 } 212 .frame(width: UIScreen.main.bounds.width - 30, height: viewModel.detailShowArray[index] ? (UIScreen.main.bounds.height * 0.7) + 60 : (UIScreen.main.bounds.height * 0.7) ) 213 .background(Color.white) 214 .cornerRadius(10) 215 216 .onAppear(){ 217 218 if imageURL != "" { 219 let storage = Storage.storage().reference() 220 storage.child(imageURL).downloadURL(completion: {(url,err) in 221 if err != nil{ 222 print((err?.localizedDescription)!) 223 return 224 } 225 self.url = "(url!)" 226 }) 227 } 228 } 229 } 230} 231

ViewModel.swift

swift

1import Foundation 2import SwiftUI 3import Firebase 4 5class ViewModel: ObservableObject { 6 func getAllPosts(completion:@escaping(Bool) -> ()){ 7 8 ref.collection("Posts").getDocuments{ 9 (snap, err) in 10 guard let docs = snap else{ 11 completion(false) 12 return 13 } 14 self.posts = [] 15 docs.documentChanges.forEach{ (doc) in 16 let post = try! doc.document.data(as:Post.self) 17 self.posts.append(post!) 18 } 19 completion(true) 20 } 21 } 22}

Xcode: Version 12.3

iOS: 14.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問