swiftbuttonswiftuiviewuitextfield

How to show one view on another view in SwiftUI


I have created one green coloured view with back button and imageview and two texs and search button. now if i click on searchBtn i need to show one white coloured view with textfield and close button. on that green view itself by hiding imageview and text and search, just want to show only back button

code: with this i am able to create green colour view but if i click search button i need to show white coloured view with textfield and close button on the same greenview but with out hiding back arrow. how to do it? please guide me

struct MessageListView: View {
@Environment(\.dismiss) var dismiss
@StateObject private var viewModel = AllMessagesListViewModel()
@State var id: String = ""
var body: some View {
    ZStack {
        Color.hexF4F4FC
            .ignoresSafeArea()
        VStack(spacing: 0) {
            
            VStack {
                HStack {
                    Button  {
                        dismiss()
                    } label: {
                        Image(systemName: "arrow.left")
                            .font(.system(size: 25))
                            .tint(.white)
                            .padding(.trailing, 6)
                    }
                    URLImageView(url: viewModel.senderDtl?.photo ?? "", placeholder: "NoProfilePic", width: 37, height: 37)
                        .clipShape(Circle())
                    VStack (alignment: .leading){
                        Text(viewModel.senderDtl?.name ?? "N/A")
                            .font(.calibriRegular(with: 16))
                            .foregroundStyle(.white)
                        
                        Text(viewModel.senderDtl?.designation ?? "N/A")
                            .font(.calibriRegular(with: 14))
                            .foregroundStyle(.white)
                    }
                    Spacer()
                    
                    Button(action: {}, label: {
                        Image("icn_search")
                    })
                }
                .padding(16)
            }
            .background(
                Color.appGreen2
                    .ignoresSafeArea()
            )
            Spacer()
        }
        Spacer()
    }
}
}

o/p: left side i want like right side just white view with textfield and close button no need that black border. how to do that please guide me

enter image description here. enter image description here


Solution

  • One way would be to put a container, such as a nested HStack, around the parts of the view that you want to cover. Then show the search view as an overlay over this container. A boolean state variable can be used to control when the overlay is shown.

    Instead of an overlay, you could also choose to use a ZStack. However, the advantage of an overlay is that the detail view can be used to form the footprint, the search view (in the overlay) is then constrained to the same frame size. This way, the height of the header does not change when the search field is shown. If a ZStack would be used instead, you would probably need to fix the height of either the search view or the ZStack itself.

    The changes are illustrated here. The two subviews have been factored out into separate computed properties, which is one way to organise the code.

    @State private var showingSearchField = false
    
    private var senderDetailView: some View {
        HStack {
            URLImageView(url: viewModel.senderDtl?.photo ?? "", placeholder: "NoProfilePic", width: 37, height: 37)
                .clipShape(Circle())
            VStack(alignment: .leading) {
                // ...
            }
            Spacer()
    
            Button {
                showingSearchField = true
            } label: {
                Image("icn_search")
            }
        }
    }
    
    private var searchFieldView: some View {
        // dummy implementation
        Rectangle()
            .fill(.white)
            .border(.black, width: 3)
            .onTapGesture { showingSearchField = false }
    }
    

    Inside body, the HStack then becomes:

    HStack {
        Button  {
            dismiss()
        } label: {
            Image(systemName: "arrow.left")
                .font(.system(size: 25))
                .tint(.white)
                .padding(.trailing, 6)
        }
        senderDetailView
            .overlay {
                if showingSearchField {
                    searchFieldView
                }
            }
    }
    .padding(16)
    

    Animation