CharacterDetailView에 갤러리 탭을 추가하고, 갤러리 화면/상태 관리/네트워킹을 구현했습니다. 소유/미소유 UI, 페이지네이션, 이미지 뷰어, 오류 토스트를 포함합니다. TODO: 이미지 구매 API 연동
		
			
				
	
	
		
			69 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
//
 | 
						|
//  ImageViewerView.swift
 | 
						|
//  SodaLive
 | 
						|
//
 | 
						|
//  Created by klaus on 9/2/25.
 | 
						|
//
 | 
						|
 | 
						|
import SwiftUI
 | 
						|
 | 
						|
struct ImageViewerView: View {
 | 
						|
    let images: [String]
 | 
						|
    @Binding var selectedIndex: Int
 | 
						|
    @Environment(\.dismiss) private var dismiss
 | 
						|
    
 | 
						|
    var body: some View {
 | 
						|
        ZStack {
 | 
						|
            Color.black.ignoresSafeArea()
 | 
						|
            
 | 
						|
            TabView(selection: $selectedIndex) {
 | 
						|
                ForEach(Array(images.enumerated()), id: \.offset) { index, imageUrl in
 | 
						|
                    AsyncImage(url: URL(string: imageUrl)) { image in
 | 
						|
                        image
 | 
						|
                            .resizable()
 | 
						|
                            .aspectRatio(contentMode: .fit)
 | 
						|
                    } placeholder: {
 | 
						|
                        ProgressView()
 | 
						|
                            .tint(.white)
 | 
						|
                    }
 | 
						|
                    .tag(index)
 | 
						|
                }
 | 
						|
            }
 | 
						|
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
 | 
						|
            
 | 
						|
            VStack {
 | 
						|
                HStack {
 | 
						|
                    Spacer()
 | 
						|
                    
 | 
						|
                    Button {
 | 
						|
                        dismiss()
 | 
						|
                    } label: {
 | 
						|
                        Image(systemName: "xmark")
 | 
						|
                            .font(.title2)
 | 
						|
                            .foregroundColor(.white)
 | 
						|
                            .padding()
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                
 | 
						|
                Spacer()
 | 
						|
                
 | 
						|
                // 페이지 인디케이터
 | 
						|
                HStack(spacing: 8) {
 | 
						|
                    ForEach(0..<images.count, id: \.self) { index in
 | 
						|
                        Circle()
 | 
						|
                            .fill(selectedIndex == index ? Color.white : Color.white.opacity(0.3))
 | 
						|
                            .frame(width: 8, height: 8)
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                .padding(.bottom, 50)
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#Preview {
 | 
						|
    ImageViewerView(
 | 
						|
        images: ["https://picsum.photos/400/500"],
 | 
						|
        selectedIndex: .constant(0)
 | 
						|
    )
 | 
						|
} |