0
2

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 1 year has passed since last update.

SwiftUIでiOSの純正のパスワード入力画面を実装

Last updated at Posted at 2023-02-27

このコードでは、PasswordDigitViewとPasswordButtonViewという2つのビューを作成し、それらをPasswordViewの中で組み合わせてパスワード入力画面を構築しています。

PasswordDigitViewは、パスワードの各桁を表示するためのビューで、PasswordButtonViewは数字ボタンや削除ボタン、リセットボタンなどの入力用のボタンを表示するためのビューです。PasswordButtonViewでは、ボタンのスタイルを定義するためのPasswordButtonStyleも定義されています。

PasswordViewでは、状態を管理するための@Stateというプロパティラッパーを使って、現在のパスワードを表す配列passwordを宣言しています。パスワードを追加するappendPassword、削除するdeletePassword、リセットするresetPasswordという3つの関数が実装されており、数字ボタンや削除ボタン、リセットボタンがタップされたときにそれぞれ呼び出されます。

最後に、プレビュー用のコードが定義されています。これにより、Xcodeのプレビュー画面でパスワード入力画面を確認することができます。


import SwiftUI

// パスワードを表示するためのビュー
struct PasswordDigitView: View {
    var digit: Character?
    
    var body: some View {
        RoundedRectangle(cornerRadius: 8)
            .frame(width: 40, height: 40)
            .overlay(
                Text(digit.map(String.init) ?? "")
                    .font(.title)
                    .foregroundColor(.primary)
            )
            .foregroundColor(.secondary.opacity(0.2))
    }
}

// パスワード入力用のボタン
struct PasswordButtonView: View {
    let title: String
    let systemImageName: String?
    let action: () -> Void
    
    init(title: String, systemImageName: String? = nil, action: @escaping () -> Void) {
        self.title = title
        self.systemImageName = systemImageName
        self.action = action
    }
    
    var body: some View {
        Button(action: action) {
            if let systemImageName = systemImageName {
                Image(systemName: systemImageName)
            } else {
                Text(title)
                    .font(.title)
            }
        }
        .buttonStyle(PasswordButtonStyle())
    }
}

// ボタンのスタイル
struct PasswordButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .padding(8)
            .frame(width: 80, height: 80)
            .background(Color.secondary.opacity(0.2))
            .clipShape(Circle())
            .scaleEffect(configuration.isPressed ? 0.9 : 1.0)
    }
}

// パスワード入力画面
struct PasswordView: View {
    @State private var password = Array(repeating: Character("_"), count: 6)
    
    var body: some View {
        VStack(spacing: 16) {
            Text("Enter your passcode")
                .font(.title)
                .fontWeight(.bold)
            
            HStack(spacing: 16) {
                ForEach(password.indices) { index in
                    PasswordDigitView(digit: password[index])
                }
            }
            
            VStack(spacing: 16) {
                HStack(spacing: 16) {
                    PasswordButtonView(title: "1") { appendPassword("1") }
                    PasswordButtonView(title: "2") { appendPassword("2") }
                    PasswordButtonView(title: "3") { appendPassword("3") }
                }
                HStack(spacing: 16) {
                    PasswordButtonView(title: "4") { appendPassword("4") }
                    PasswordButtonView(title: "5") { appendPassword("5") }
                    PasswordButtonView(title: "6") { appendPassword("6") }
                }
                HStack(spacing: 16) {
                    PasswordButtonView(title: "7") { appendPassword("7") }
                    PasswordButtonView(title: "8") { appendPassword("8") }
                    PasswordButtonView(title: "9") { appendPassword("9") }
                }
                HStack(spacing: 16) {
                    PasswordButtonView(systemImageName: "delete.left") { deletePassword() }
                    PasswordButtonView(title: "0") { appendPassword("0") }
                    PasswordButtonView(systemImageName: "arrow.counterclockwise") { resetPassword() }
                }
            }
            .padding(.bottom)
        }



    // パスワードを追加する
    private func appendPassword(_ digit: String) {
        for i in password.indices {
            if password[i] == "_" {
                password[i] = Character(digit)
                if i == password.count - 1 {
                    // 入力が完了したら何か処理をする
                    print("Password entered: \(String(password))")
                }
                break
            }
        }
    }
    
    // パスワードを削除する
    private func deletePassword() {
        for i in (0..<password.count).reversed() {
            if password[i] != "_" {
                password[i] = Character("_")
                break
            }
        }
    }
    
    // パスワードをリセットする
    private func resetPassword() {
        password = Array(repeating: Character("_"), count: password.count)
    }
}

// プレビュー用のコード
struct PasswordView_Previews: PreviewProvider {
    static var previews: some View {
        PasswordView()
    }
}



0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?