skip to Main Content

I want to create a TikTok comments clone, meaning:

  • background content should stay in place
  • sheet should slide from the bottom
  • there should be comment box at the bottom
  • tapping on comment box should open a keyboard and the comment box should slide up

Run below code and tap on blue square to active comments. You will see how red background slides to the top


import SwiftUI

struct TikTokView: View {
  
  @State var isPresented: Bool = false
  
  var body: some View {
    ZStack {
      Color.red
      
      VStack {
        RoundedRectangle(cornerRadius: 15)
          .fill(Color.blue)
          .frame(width: 50, height: 50)
          .onTapGesture {
            isPresented.toggle()
          }
      }
      .ignoresSafeArea(.keyboard)
      CommentsSheetView(isPresented: $isPresented)
    }
  }
}

struct CommentsSheetView: View {
  
  @Binding var isPresented: Bool
  @State private var text: String = ""
  
  var transition: AnyTransition = .move(edge: .bottom)
  
  var body: some View {
    ZStack {
      if isPresented {
        Color.black.opacity(0.5).ignoresSafeArea()
        
        VStack {
          Spacer()
          ScrollView(.vertical, content: {
            VStack {
              
              ForEach(0...50, id: .self) { i in
                Text("Comment").foregroundStyle(.pink)
                Spacer()
              }
            }
            .frame(maxWidth: .infinity)
          })
          .frame(height: (550 - 80))
          .frame(maxWidth: .infinity)
          .padding(.bottom, 80)
          .background(.white.opacity(0.1))
        }
        .ignoresSafeArea(.keyboard)
        .fixedSize()
        .transition(transition)
        
        VStack {
          Spacer()
          HStack {
            Text("LOREM")
            
            TextField("TESTING", text: $text, axis: .vertical)
              .keyboardType(.asciiCapable)
              .autocorrectionDisabled(true)
              .foregroundStyle(.pink)
          }
          .frame(minHeight: 50, maxHeight: 100)
          .background(.green.opacity(0.1 ))
        }
        .frame(maxWidth: .infinity)
        .transition(transition)
      }
    }
  }
}

#Preview {
  TikTokView()
}

2

Answers


  1. Chosen as BEST ANSWER

    I have a working solution, if anyone need it, here's the code:

    
    //
    //  TikTokView.swift
    //
    //  Created by breq on 22/12/2023.
    //  https://stackoverflow.com/q/77700651/1251563
    //
    
    import SwiftUI
    
    struct TikTokView: View {
      
      @State var isPresented: Bool = false
      @State private var name: String = ""
      
      var body: some View {
        ZStack {
          Color.red.ignoresSafeArea()
          
          VStack {
            Color.green
              .onTapGesture {
                isPresented.toggle()
              }
            TextField("Name:", text: $name)
            Color.yellow
          }
          .ignoresSafeArea(.keyboard)
          
          CommentsTestSheetView(isPresented: $isPresented)
        }
      }
    }
    
    struct CommentsTestSheetView: View {
      
      @Binding var isPresented: Bool
      @State private var text: String = ""
      
      var transition: AnyTransition = .move(edge: .bottom)
      
      var body: some View {
        ZStack(alignment: .bottom) {
          if isPresented {
            Color.black.opacity(0.5).ignoresSafeArea()
              .onTapGesture {
                isPresented.toggle()
              }
            
            ZStack(alignment: .bottom, content: {
              GeometryReader(content: {
                ScrollView(.vertical, content: {
                  
                  VStack {
                    ForEach(0...50, id: .self) { i in
                      Text("Comment").foregroundStyle(.pink)
                      Spacer()
                    }
                  }
                  .frame(maxWidth: .infinity)
                })
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .padding(.bottom, 110)
                .background(.blue)
                .padding(.top, 1/3 * $0.size.height)
                
              })
              .ignoresSafeArea(.keyboard)
              
              HStack {
                Text("LOREM")
                
                TextField("TESTING", text: $text, axis: .vertical)
                  .keyboardType(.asciiCapable)
                  .autocorrectionDisabled(true)
                  .foregroundStyle(.pink)
              }
              .frame(minHeight: 50, maxHeight: 100)
              .frame(maxWidth: .infinity)
              .background(.white)
            })
            .transition(transition)
          }
        }
        .animation(.smooth(duration: 0.2), value: isPresented)
      }
    }
    
    #Preview {
      TikTokView()
    }
    

  2. No need to build this by hand, SwiftUI has build in Viewmodifier for this. So what you want can be written like this:

    struct TikTokView: View {
        
        @State private var showComments: Bool = true
        
        var body: some View {
            Button{
                showComments.toggle()
            } label: {
                Text("show comments")
            } // a .sheet is used to show content above the current view
            .sheet(isPresented: $showComments){
                CommentView()
                    .presentationDetents([.fraction(0.7)]) // with this you can
                                                           // determine how much space sheet takes
                    .presentationBackground(.clear) // <-- add this to hide the background
            }
        }
    }
    
    struct CommentView: View {
        
        @State private var commentToAdd: String = ""
        
        var body: some View {
            ScrollView{
                VStack{
                    ForEach(0...100, id: .self){ index in
                        Text("comment (index)")
                    }
            }
                .frame(maxWidth: .infinity)
            }.safeAreaInset(edge: .bottom) { // the safe area inset places the view at the bottom
                                             // and will move it up when keyboard appears
                TextField("", text: $commentToAdd)
                    .textFieldStyle(.roundedBorder)
                    .background(.ultraThinMaterial)
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search