Kotlin ile Email Girişli Uygulama Örneği
Aşağıda Kotlin'de (Android için) email ile giriş yapılan bir uygulamanın temel yapısını ve arayüzünü gösteren bir örnek bulabilirsiniz.
1. XML Arayüz Dosyası (activity_login.xml)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="24dp" tools:context=".LoginActivity"> <ImageView android:layout_width="120dp" android:layout_height="120dp" android:layout_gravity="center_horizontal" android:layout_marginBottom="32dp" android:src="@mipmap/ic_launcher" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginBottom="24dp" android:text="Hoş Geldiniz" android:textSize="24sp" android:textStyle="bold" /> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/etEmail" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Email" android:inputType="textEmailAddress" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="24dp"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/etPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Şifre" android:inputType="textPassword" /> </com.google.android.material.textfield.TextInputLayout> <Button android:id="@+id/btnLogin" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" android:text="Giriş Yap" /> <TextView android:id="@+id/tvForgotPassword" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="Şifremi Unuttum" android:textColor="@color/purple_500" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginVertical="24dp" android:background="#E0E0E0" /> <Button android:id="@+id/btnRegister" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Hesap Oluştur" android:backgroundTint="@color/gray" android:textColor="@color/white" /> </LinearLayout>
2. Kotlin Activity (LoginActivity.kt)
import android.content.Intent import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.google.android.material.textfield.TextInputEditText import com.google.firebase.auth.FirebaseAuth class LoginActivity : AppCompatActivity() { private lateinit var auth: FirebaseAuth override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) // Firebase Auth başlatma auth = FirebaseAuth.getInstance() val etEmail = findViewById<TextInputEditText>(R.id.etEmail) val etPassword = findViewById<TextInputEditText>(R.id.etPassword) val btnLogin = findViewById<Button>(R.id.btnLogin) val tvForgotPassword = findViewById<TextView>(R.id.tvForgotPassword) val btnRegister = findViewById<Button>(R.id.btnRegister) btnLogin.setOnClickListener { val email = etEmail.text.toString().trim() val password = etPassword.text.toString().trim() if (email.isEmpty() || password.isEmpty()) { Toast.makeText(this, "Email ve şifre giriniz", Toast.LENGTH_SHORT).show() return@setOnClickListener } loginUser(email, password) } tvForgotPassword.setOnClickListener { // Şifremi unuttum ekranına yönlendir startActivity(Intent(this, ForgotPasswordActivity::class.java)) } btnRegister.setOnClickListener { // Kayıt ekranına yönlendir startActivity(Intent(this, RegisterActivity::class.java)) } } private fun loginUser(email: String, password: String) { auth.signInWithEmailAndPassword(email, password) .addOnCompleteListener(this) { task -> if (task.isSuccessful) { // Giriş başarılı, ana ekrana yönlendir val intent = Intent(this, MainActivity::class.java) startActivity(intent) finish() } else { // Giriş başarısız Toast.makeText( this, "Giriş başarısız: ${task.exception?.message}", Toast.LENGTH_SHORT ).show() } } } override fun onStart() { super.onStart() // Kullanıcı zaten giriş yapmışsa ana ekrana yönlendir if (auth.currentUser != null) { startActivity(Intent(this, MainActivity::class.java)) finish() } } }
3. Firebase Bağımlılıkları (build.gradle)
implementation 'com.google.firebase:firebase-auth-ktx:22.3.1' implementation 'com.google.android.material:material:1.11.0'
4. Ekran Görüntüsü
Bu tasarım şu öğeleri içerir:
Uygulama logosu
"Hoş Geldiniz" başlığı
Email giriş alanı
Şifre giriş alanı
Giriş yap butonu
Şifremi unuttum bağlantısı
Hesap oluştur butonu
Hesap Oluşturma Aktivitesi (SignUpActivity)
İşte genişletilmiş bir Hesap Oluşturma aktivitesi örneği:
1. XML Arayüzü (activity_sign_up.xml)
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="24dp" tools:context=".SignUpActivity"> <ImageView android:layout_width="120dp" android:layout_height="120dp" android:layout_gravity="center_horizontal" android:layout_marginBottom="32dp" android:src="@drawable/ic_account_circle" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginBottom="24dp" android:text="Hesap Oluştur" android:textColor="@color/primaryColor" android:textSize="28sp" android:textStyle="bold" /> <!-- Ad Soyad --> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="8dp" app:errorEnabled="true"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/etFullName" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Ad Soyad" android:inputType="textPersonName" android:maxLines="1" /> </com.google.android.material.textfield.TextInputLayout> <!-- Email --> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="8dp" app:errorEnabled="true"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/etEmail" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Email" android:inputType="textEmailAddress" android:maxLines="1" /> </com.google.android.material.textfield.TextInputLayout> <!-- Şifre --> <com.google.android.material.textfield.TextInputLayout android:id="@+id/tilPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="8dp" app:errorEnabled="true" app:passwordToggleEnabled="true"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/etPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Şifre" android:inputType="textPassword" android:maxLines="1" /> </com.google.android.material.textfield.TextInputLayout> <!-- Şifre Tekrar --> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" app:errorEnabled="true" app:passwordToggleEnabled="true"> <com.google.android.material.textfield.TextInputEditText android:id="@+id/etConfirmPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Şifre Tekrar" android:inputType="textPassword" android:maxLines="1" /> </com.google.android.material.textfield.TextInputLayout> <!-- Kullanım Koşulları --> <CheckBox android:id="@+id/cbTerms" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" android:text="Kullanım koşullarını kabul ediyorum" /> <!-- Kayıt Butonu --> <Button android:id="@+id/btnSignUp" android:layout_width="match_parent" android:layout_height="48dp" android:layout_marginBottom="16dp" android:backgroundTint="@color/primaryColor" android:text="Kayıt Ol" android:textColor="@android:color/white" /> <!-- Giriş Yap Linki --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="Zaten hesabınız var mı? Giriş Yap" android:textColor="@color/primaryColor"> <androidx.appcompat.widget.AppCompatTextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColorLink="@color/primaryColor" android:text="Zaten hesabınız var mı? Giriş Yap" /> </TextView> </LinearLayout> </ScrollView>
2. Kotlin Kodu (SignUpActivity.kt)
import android.content.Intent import android.os.Bundle import android.text.Editable import android.text.TextWatcher import android.util.Patterns import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.google.android.material.textfield.TextInputLayout import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.UserProfileChangeRequest import com.google.firebase.firestore.FirebaseFirestore import kotlinx.android.synthetic.main.activity_sign_up.* class SignUpActivity : AppCompatActivity() { private lateinit var auth: FirebaseAuth private lateinit var db: FirebaseFirestore override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_sign_up) // Firebase başlat auth = FirebaseAuth.getInstance() db = FirebaseFirestore.getInstance() // Input validasyonları setupFormValidation() btnSignUp.setOnClickListener { attemptSignUp() } // Giriş yap linki findViewById<TextView>(R.id.textView).setOnClickListener { startActivity(Intent(this, LoginActivity::class.java)) finish() } } private fun setupFormValidation() { // Ad soyad validasyonu etFullName.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(s: Editable?) { validateName() } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} }) // Email validasyonu etEmail.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(s: Editable?) { validateEmail() } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} }) // Şifre validasyonu etPassword.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(s: Editable?) { validatePassword() validateConfirmPassword() } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} }) // Şifre tekrar validasyonu etConfirmPassword.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(s: Editable?) { validateConfirmPassword() } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} }) } private fun validateName(): Boolean { return if (etFullName.text.toString().trim().isEmpty()) { (etFullName.parent.parent as TextInputLayout).error = "Ad soyad giriniz" false } else { (etFullName.parent.parent as TextInputLayout).error = null true } } private fun validateEmail(): Boolean { val email = etEmail.text.toString().trim() return when { email.isEmpty() -> { (etEmail.parent.parent as TextInputLayout).error = "Email giriniz" false } !Patterns.EMAIL_ADDRESS.matcher(email).matches() -> { (etEmail.parent.parent as TextInputLayout).error = "Geçerli bir email giriniz" false } else -> { (etEmail.parent.parent as TextInputLayout).error = null true } } } private fun validatePassword(): Boolean { val password = etPassword.text.toString() return when { password.isEmpty() -> { tilPassword.error = "Şifre giriniz" false } password.length < 6 -> { tilPassword.error = "Şifre en az 6 karakter olmalı" false } else -> { tilPassword.error = null true } } } private fun validateConfirmPassword(): Boolean { val password = etPassword.text.toString() val confirmPassword = etConfirmPassword.text.toString() return when { confirmPassword.isEmpty() -> { (etConfirmPassword.parent.parent as TextInputLayout).error = "Şifre tekrar giriniz" false } confirmPassword != password -> { (etConfirmPassword.parent.parent as TextInputLayout).error = "Şifreler uyuşmuyor" false } else -> { (etConfirmPassword.parent.parent as TextInputLayout).error = null true } } } private fun validateTerms(): Boolean { return if (!cbTerms.isChecked) { Toast.makeText(this, "Kullanım koşullarını kabul etmelisiniz", Toast.LENGTH_SHORT).show() false } else { true } } private fun attemptSignUp() { if (!validateName() || !validateEmail() || !validatePassword() || !validateConfirmPassword() || !validateTerms()) { return } val name = etFullName.text.toString().trim() val email = etEmail.text.toString().trim() val password = etPassword.text.toString() btnSignUp.isEnabled = false btnSignUp.text = "Hesap oluşturuluyor..." auth.createUserWithEmailAndPassword(email, password) .addOnCompleteListener(this) { task -> if (task.isSuccessful) { // Kullanıcı adını güncelle val user = auth.currentUser val profileUpdates = UserProfileChangeRequest.Builder() .setDisplayName(name) .build() user?.updateProfile(profileUpdates) ?.addOnCompleteListener { profileTask -> if (profileTask.isSuccessful) { // Firestore'a ek bilgileri kaydet saveAdditionalUserData(user.uid, name, email) } else { btnSignUp.isEnabled = true btnSignUp.text = "Kayıt Ol" Toast.makeText( this, "Profil güncelleme hatası: ${profileTask.exception?.message}", Toast.LENGTH_SHORT ).show() } } } else { btnSignUp.isEnabled = true btnSignUp.text = "Kayıt Ol" Toast.makeText( this, "Kayıt başarısız: ${task.exception?.message}", Toast.LENGTH_SHORT ).show() } } } private fun saveAdditionalUserData(userId: String, name: String, email: String) { val user = hashMapOf( "name" to name, "email" to email, "createdAt" to System.currentTimeMillis() ) db.collection("users").document(userId) .set(user) .addOnSuccessListener { Toast.makeText(this, "Kayıt başarılı!", Toast.LENGTH_SHORT).show() startActivity(Intent(this, MainActivity::class.java)) finishAffinity() } .addOnFailureListener { e -> btnSignUp.isEnabled = true btnSignUp.text = "Kayıt Ol" Toast.makeText( this, "Veri kaydetme hatası: ${e.message}", Toast.LENGTH_SHORT ).show() } } }
3. Özellikler
Kapsamlı Form Validasyonu:
Gerçek zamanlı input validasyonu
Email format kontrolü
Şifre eşleşme kontrolü
Minimum şifre uzunluğu kontrolü (6 karakter)
Zorunlu alan kontrolü
Kullanıcı Deneyimi:
ScrollView ile uzun form desteği
Şifre göster/gizle butonu
Buton durum yönetimi (yükleme durumunda devre dışı bırakma)
Kullanıcı dostu hata mesajları
Firebase Entegrasyonu:
Email/şifre ile kullanıcı kaydı
Kullanıcı profil bilgilerini güncelleme
Firestore'a ek kullanıcı verilerini kaydetme
Güvenlik:
Kullanım koşulları onayı zorunluluğu
Firebase Authentication güvenlik kuralları
Geçişler:
Giriş ekranına kolay dönüş
Başarılı kayıt sonrası ana ekrana yönlendirme
Kotlin Kodu (RegisterActivity.kt)
import android.content.Intent import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.google.android.material.textfield.TextInputEditText import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.UserProfileChangeRequest class RegisterActivity : AppCompatActivity() { private lateinit var auth: FirebaseAuth override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_register) auth = FirebaseAuth.getInstance() val etName = findViewById<TextInputEditText>(R.id.etName) val etEmail = findViewById<TextInputEditText>(R.id.etEmail) val etPassword = findViewById<TextInputEditText>(R.id.etPassword) val etConfirmPassword = findViewById<TextInputEditText>(R.id.etConfirmPassword) val btnRegister = findViewById<Button>(R.id.btnRegister) val tvLogin = findViewById<TextView>(R.id.tvLogin) btnRegister.setOnClickListener { val name = etName.text.toString().trim() val email = etEmail.text.toString().trim() val password = etPassword.text.toString().trim() val confirmPassword = etConfirmPassword.text.toString().trim() if (name.isEmpty() || email.isEmpty() || password.isEmpty()) { Toast.makeText(this, "Tüm alanları doldurunuz", Toast.LENGTH_SHORT).show() return@setOnClickListener } if (password != confirmPassword) { Toast.makeText(this, "Şifreler uyuşmuyor", Toast.LENGTH_SHORT).show() return@setOnClickListener } if (password.length < 6) { Toast.makeText(this, "Şifre en az 6 karakter olmalı", Toast.LENGTH_SHORT).show() return@setOnClickListener } registerUser(name, email, password) } tvLogin.setOnClickListener { startActivity(Intent(this, LoginActivity::class.java)) finish() } } private fun registerUser(name: String, email: String, password: String) { auth.createUserWithEmailAndPassword(email, password) .addOnCompleteListener(this) { task -> if (task.isSuccessful) { // Kullanıcı adını güncelle val user = auth.currentUser val profileUpdates = UserProfileChangeRequest.Builder() .setDisplayName(name) .build() user?.updateProfile(profileUpdates) ?.addOnCompleteListener { profileTask -> if (profileTask.isSuccessful) { // Kayıt başarılı, giriş ekranına yönlendir Toast.makeText( this, "Kayıt başarılı. Giriş yapabilirsiniz.", Toast.LENGTH_SHORT ).show() startActivity(Intent(this, LoginActivity::class.java)) finish() } } } else { Toast.makeText( this, "Kayıt başarısız: ${task.exception?.message}", Toast.LENGTH_SHORT ).show() } } } }
Özellikler
Email Doğrulama: Email alanı otomatik olarak email formatını kontrol eder.
Şifre Gizleme: Şifre alanı girilen karakterleri gizler.
Firebase Entegrasyonu: Firebase Authentication ile email/şifre doğrulaması yapar.
Oturum Kontrolü: Kullanıcı zaten giriş yapmışsa direkt ana ekrana yönlendirir.
Hata Yönetimi: Giriş hatalarını kullanıcıya gösterir.
ForgotPasswordActivity:
Email doğrulama
Firebase şifre sıfırlama emaili gönderme
Kullanıcı dostu geri bildirim mesajları
Giriş ekranına kolay dönüş
RegisterActivity:
Ad, email, şifre ve şifre tekrar alanları
Şifre doğrulama (eşleşme kontrolü)
Minimum şifre uzunluğu kontrolü
Firebase kullanıcı kaydı
Kullanıcı adı (display name) güncelleme
Başarılı kayıt sonrası giriş ekranına yönlendirme
0 Yorumlar