1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【初心者】Swift UIを勉強する その⑩ ーーー disabledとDispatchQueueアニメーションをもっと自由に

Last updated at Posted at 2021-04-10

はじめに

前回は選択されたCardをタップしたら、リスト一覧を出せるようにしました。
しかし、選択されたcoursesは固定のままで、今回はそれぞれのCardをそれぞれのリストを出せるようにします。

完成品↓
  

目次

  1. disabledとDispatchQueue
  2. まとめ
  3. 参考文献

disabledとDispatchQueue

・まずはCourse.swiftCourseを新たに作ったModelGroupに移動します。(MVVM)
・現状では、showがtrueかflaseかを条件としてCardの状態を管理しています。
全てのCardは自分が持つリストを認識させるように、まずはseletedItemを作ります。
デフォルトでnil(Optional)をつめて、Cardがまだ選択されていない状態を意味します。

CoursesView.swift

@State var show = false
@Namespace var namespace
@State var selectedItem: Course? = nil

・タップジェスチャーはまだループの外にあるので、Cardの中に移動します。
また、どのCardをタップしたのかをわかってもらうために、クロージャのitemselectedItemにつめていきます。

CoursesView.swift

ForEach(courses) { item in
    CourseItem(course: item)
        .matchedGeometryEffect(
               id: item.id, in: namespace, isSource: !show
        )
           .frame(width: 335, height: 250)
           .onTapGesture {
                  withAnimation(.spring()) {
                         show.toggle()
                         selectedItem = item
                   }
            }
}

・Card中のListは↑上からselectedItemをもらって、自分専属のリストゲットできるようになりました。
・ただ、今はCardを開くことしかできなくて、閉じる場合はCardと同じく、ListもonTapGesture()を使います。また、Cardを閉じることによって、selectedItemもいらなくなるので、nilをつめていきます。

CoursesView.swift

if selectedItem != nil {
     ScrollView {
          CourseItem(course: selectedItem!)
               .matchedGeometryEffect(
                    id: selectedItem!.id, in: namespace
                )
               .frame(height: 300)
               .onTapGesture {
                    withAnimation(.spring()) {
                          show.toggle()
                          selectedItem = nil
                     }
                }
.......

 


・これで9割ができましたが、タップするスピードが早すぎですと、CardとCardが重なってしまいます。 解決するロジックもシンプルですが、Card①のアニメーションが終わるまで他のCardをdisableにします。
CoursesView.swift

@State var isDisabled = false

ForEach(courses) { item in
    CourseItem(course: item)
        .matchedGeometryEffect(
               id: item.id, in: namespace, isSource: !show
        )
           .frame(width: 335, height: 250)
           .onTapGesture {
                  withAnimation(.spring()) {
                         show.toggle()
                         selectedItem = item
                         isDisabled = true
                   }
            }
            .disabled(isDisabled)
}

・同様に、Cardの中でdisableにしたため、Listでdisableを外します。
DispatchQueueを使ってアニメーションを自由に遅らせることができるので、0.5秒を遅らせば綺麗にできました。

CoursesView.swift

if selectedItem != nil {
     ScrollView {
          CourseItem(course: selectedItem!)
               .matchedGeometryEffect(
                    id: selectedItem!.id, in: namespace
                )
               .frame(height: 300)
               .onTapGesture {
                    withAnimation(.spring()) {
                          show.toggle()
                          selectedItem = nil
                          DispatchQueue.main.asyncAfter(
                               deadline: .now() + 0.5
                           ) {
                               isDisabled = false
                            }
                     }
                }
.......

まとめ

ソースコードGithub

参考文献

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?