30 Ocak 2021 Cumartesi

Android Kütüphane Sistemi Mobil Uygulaması - 3 (Register İşlemi)

 Merhabalar. Android Kütüphane Sistemi Mobil Uygulaması yazı dizisinin üçüncü yazısı ile yeniden sizlerleyim. Bu yazıda sisteme kayıt işlemini yapacağız.Tekrar belirtmekte fayda olacak, uygulamanın kodlarına buradan erişebilirsiniz.

Register İşlemi

Kaydet işleminde senaryomuz aşağıda ki gibi olacaktır.

1.Zorunlu alan kontrolü yapılır.

2.Kayıt işlemi yapılır

    2.1 Kayıt başarılı ise kişiye bilgilendirme mesajı verilip login ekranına yönlendirilir.

    2.2 Kayıt başarısız ise kullanıcıya bilgilendirme mesajı verilir.


Şimdi ilk olarak register ekranının layout dosyasına göz atalım.

activity_register.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
style="@style/loginParent"
tools:context=".RegisterActivity">
<ScrollView
style="@style/parent">
<RelativeLayout
style="@style/parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:weightSum="12">

<LinearLayout
style="@style/parent"
android:layout_height="match_parent"
android:layout_weight="3"
android:background="@drawable/login_shape_bk"
android:orientation="vertical">

<ImageView
style="@style/parent"
android:background="@drawable/ic_login_bk"
android:contentDescription="login background" />

</LinearLayout>

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:orientation="vertical">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="@string/registerTitle"
android:layout_gravity="center_horizontal"
android:textAlignment="center"
android:textColor="@color/whiteTextColor"
android:textSize="18sp"
android:textStyle="bold"></TextView>

<androidx.cardview.widget.CardView
style="@style/loginCard"
android:layout_gravity="center"
android:layout_marginTop="@dimen/loginViewsMargin"
android:layout_marginBottom="@dimen/loginViewsMargin"
android:background="@color/whiteCardColor"
android:elevation="5dp"
app:cardCornerRadius="@dimen/loginCardRadius">

<LinearLayout
style="@style/linearParent"
android:layout_gravity="center"
android:padding="@dimen/loginViewsMargin">

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/registerProfilKullaniciAd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/profilKullaniciAdi"
style="@style/modifiedEditText"
android:maxLines="1"/>
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/registerSifreTextInput"
style="@style/parent"
app:errorEnabled="true"
app:passwordToggleEnabled="true"
android:layout_marginTop="@dimen/loginViewsMargin">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/registerEditTextSifre"
style="@style/modifiedEditText"
android:hint="@string/login_password_hint"
android:maxLines="1"
android:inputType="textPassword"/>
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/registerProfilAdText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/profilAd"
style="@style/modifiedEditText"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/registerProfilSoyadText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/profilSoyad"
style="@style/modifiedEditText"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/registerProfilEposta"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textEmailAddress"
android:hint="@string/profilEpostaHint"
style="@style/modifiedEditText"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/registerProfilDogumTarih"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="false"
android:hint="@string/profilDogumTarihi"
style="@style/modifiedEditText"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>

<libs.mjn.fieldset.FieldSetView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="10dp"
android:padding="8dp"
app:fsv_borderAlpha="0.75"
app:fsv_borderColor="@color/colorAccent"
app:fsv_borderRadius="12dp"
app:fsv_borderWidth="1dp"
app:fsv_legend="@string/cinsiyetLabel"
app:fsv_legendColor="@color/colorAccent"
app:fsv_legendFont="lobster.ttf"
app:fsv_legendPosition="left">

<RadioGroup
android:id="@+id/registerCinsiyetRadioGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">

<RadioButton
android:id="@+id/registerErkekRadioButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/cinsiyetErkekLabel"
android:buttonTint="@color/colorAccent"
android:theme="@style/KutSisRaidoButton" />

<RadioButton
android:id="@+id/registerKadinRadioButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="@string/cinsiyetKadinLabel"
android:buttonTint="@color/colorAccent"
android:theme="@style/KutSisRaidoButton" />
</RadioGroup>

</libs.mjn.fieldset.FieldSetView>

<Spinner
android:id="@+id/registerIlgiAlanlariSpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
style="@style/spinner_style"/>

<CheckBox
android:id="@+id/registerHaberdarCheckBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/gelismeHabderdarLabel"
android:textStyle="italic"
android:buttonTint="@color/colorAccent"
android:theme="@style/KutSisCheckBox" />

<Button
android:id="@+id/profilKaydetButton"
android:text="@string/kaydetLabel"
android:background="@drawable/login_button_background"
android:textColor="@color/whiteTextColor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/loginViewsMargin"/>

</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</RelativeLayout>
</ScrollView>
</RelativeLayout>

Bu layout un çıktısı aşağıda ki gibidir.



Burada "İlgi alanlarınız" Spinner ' ı custom bir layout'a sahip olup seçim simgesi ise style.xml dosyasında setlenmiştir. Dilerseniz activity'nin kodlarını yazıp, zaten bu activity içerisinde dolan ve custom layout'a sahip olan bu spinner'ı anlatalım.

RegisterActivity.kt

class RegisterActivity : AppCompatActivity() {

private lateinit var ilgiAlanlariListe:ArrayList<IlgiAlanlariParametreModel>;
private var selectedIlgiAlanlar:ArrayList<Int> = ArrayList<Int>();
private lateinit var pd: Dialog;
private lateinit var kullaniciService:IKullaniciService;

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_register);

initializeComponents();

}

private fun initializeComponents() {
pd = Dialog(this);
val pdView: View = layoutInflater.inflate(R.layout.custom_progress_dialog,null);
pd.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
pd.setTitle(null);
pd.setContentView(pdView);
pd.setCancelable(false);

kullaniciService = WebApiUtil.getKullaniciService();

initDatePicker();
fillIlgiAlanlariListe();

registerProfilKullaniciAd.editText!!.addTextChangedListener(TextInputErrorClearListener(registerProfilKullaniciAd));
registerSifreTextInput.editText!!.addTextChangedListener(TextInputErrorClearListener(registerSifreTextInput));
registerProfilAdText.editText!!.addTextChangedListener(TextInputErrorClearListener(registerProfilAdText));
registerProfilSoyadText.editText!!.addTextChangedListener(TextInputErrorClearListener(registerProfilSoyadText));
registerProfilDogumTarih.editText!!.addTextChangedListener(TextInputErrorClearListener(registerProfilDogumTarih));
registerProfilEposta.editText!!.addTextChangedListener(TextInputErrorClearListener(registerProfilEposta));

profilKaydetButton.setOnClickListener {
val kullaniciAdi:String = registerProfilKullaniciAd.editText!!.text.toString();
val sifre:String = registerSifreTextInput.editText!!.text.toString();
val ad:String = registerProfilAdText.editText!!.text.toString();
val soyad:String = registerProfilSoyadText.editText!!.text.toString();
val dogumTar:String = registerProfilDogumTarih.editText!!.text.toString();
val cinsiyet:Int = registerCinsiyetRadioGroup.checkedRadioButtonId;
val eposta:String = registerProfilEposta.editText!!.text.toString();
val haberdarMi:Boolean = registerHaberdarCheckBox.isChecked;

if(TextUtils.isEmpty(kullaniciAdi)){
registerProfilKullaniciAd.error = resources.getString(R.string.registerKullaniciAdiHata);
return@setOnClickListener;
}

if(TextUtils.isEmpty(sifre)){
registerSifreTextInput.error = resources.getString(R.string.registerSifreHata);
return@setOnClickListener;
}

if(TextUtils.isEmpty(ad)){
registerProfilAdText.error = resources.getString(R.string.registerAdHata);
return@setOnClickListener;
}

if(TextUtils.isEmpty(soyad)){
registerProfilSoyadText.error = resources.getString(R.string.registerSoyadHata);
return@setOnClickListener;
}

if(TextUtils.isEmpty(eposta)){
registerProfilEposta.error = resources.getString(R.string.epostaHata);
return@setOnClickListener;
}

if(TextUtils.isEmpty(dogumTar)){
registerProfilDogumTarih.error = resources.getString(R.string.registerDogumtarihHata);
return@setOnClickListener;
}

if(cinsiyet == -1){
SimpleToast.warning(applicationContext, resources.getString(R.string.cinsiyetHata), "{fa-exclamation-triangle}");
return@setOnClickListener;
}

if(this.selectedIlgiAlanlar == null || this.selectedIlgiAlanlar.isEmpty()){
SimpleToast.warning(applicationContext, resources.getString(R.string.ilgiAlanHata), "{fa-exclamation-triangle}");
return@setOnClickListener;
}

val cal:Calendar = Calendar.getInstance();
val dtarArr = dogumTar.split(".");
cal.set(Calendar.YEAR,dtarArr[2].toInt());
cal.set(Calendar.MONTH,dtarArr[1].toInt()-1);
cal.set(Calendar.DAY_OF_MONTH,dtarArr[0].toInt());

val jsonObj: JSONObject = JSONObject();
val iaArr: JSONArray = JSONArray();
var iaJsonObj: JSONObject = JSONObject();

jsonObj.put("username",kullaniciAdi);
jsonObj.put("password",sifre);
jsonObj.put("ad",ad)
jsonObj.put("soyad",soyad);
jsonObj.put("dogumTarihi", ProjectUtil.formatDate(cal.time,"yyyy-MM-dd"));
jsonObj.put("eposta",eposta);
jsonObj.put("haberdarmi",haberdarMi);

if(cinsiyet == R.id.erkekRadioButton){
jsonObj.put("cinsiyet","E");
}else{
jsonObj.put("cinsiyet","K");
}

for(s in selectedIlgiAlanlar){
iaJsonObj.put("id",s);
iaArr.put(iaJsonObj);
iaJsonObj = JSONObject();
}

jsonObj.put("ilgiAlanlari",iaArr);

pd.show();

Log.d("JSON",jsonObj.toString());

kullaniciService.kullaniciKaydet(jsonObj.toString()).enqueue(object:
Callback<ResponseStatusModel> {
override fun onFailure(call: Call<ResponseStatusModel>?, t: Throwable) {
SimpleToast.error(applicationContext, resources.getString(R.string.kullaniciKayitHata), "{fa-times-circle}");
pd.dismiss();
}

override fun onResponse(call: Call<ResponseStatusModel>?, response: Response<ResponseStatusModel>) {
if(response.body() != null){
val respModel = response.body() as ResponseStatusModel;
SimpleToast.info(applicationContext, resources.getString(R.string.kullaniciKayitBasarili), "{fa-check}");
pd.dismiss();
ProjectUtil.activityYonlendir(applicationContext,LoginActivity());
}
}
});
}
}

private fun fillIlgiAlanlariListe() {
pd.show();
kullaniciService.getKitapturListe().enqueue(object:
Callback<ArrayList<IlgiAlanlariParametreModel>> {
override fun onFailure(call: Call<ArrayList<IlgiAlanlariParametreModel>>?, t: Throwable) {
SimpleToast.error(applicationContext, resources.getString(R.string.kitapTurListeHata), "{fa-times-circle}");
pd.dismiss();
}

override fun onResponse(call: Call<ArrayList<IlgiAlanlariParametreModel>>?, response: Response<ArrayList<IlgiAlanlariParametreModel>>) {
ilgiAlanlariListe = response.body() as ArrayList<IlgiAlanlariParametreModel>;
ilgiAlanlariListe.add(IlgiAlanlariParametreModel(0,"",ilgiAlanlariListe.get(0).durum,ilgiAlanlariListe.get(0).olusturan,ilgiAlanlariListe.get(0).resim));
val ilgiAlanlariListe2 = ilgiAlanlariListe.sortedWith(compareBy({it.id}));
ilgiAlanlariListe.clear();
for(i in ilgiAlanlariListe2){
ilgiAlanlariListe.add(i);
}
val adapter = IlgiAlanlariSpinnerAdapter(application,ilgiAlanlariListe,null,selectedIlgiAlanlar);
registerIlgiAlanlariSpinner.adapter = adapter;
pd.dismiss();
}
});
}

private fun initDatePicker() {
val cal: Calendar = Calendar.getInstance();
val yil: Int = cal.get(Calendar.YEAR);
val ay: Int = cal.get(Calendar.MONTH);
val gun: Int = cal.get(Calendar.DAY_OF_MONTH);

registerProfilDogumTarih.editText!!.setOnClickListener { it: View ->
var datePicker = DatePickerDialog(it.context, R.style.DatePickerTheme,
DatePickerDialog.OnDateSetListener { datePicker, y, a, g ->
registerProfilDogumTarih.editText!!.setText("$g.${a + 1}.$y");
}, yil, ay - 1, gun
);

datePicker.setTitle(resources.getString(R.string.selectTarih));
datePicker.setButton(
DialogInterface.BUTTON_POSITIVE,
resources.getString(R.string.ayarlaLabel),
datePicker
);
datePicker.setButton(
DialogInterface.BUTTON_NEGATIVE,
resources.getString(R.string.iptalLabel),
datePicker
);

datePicker.show();
}
}
}


Burada ilgi alanları spinner ı yukarıdan da anlaşılacağı üzere fillIlgiAlanlariListe metodu ile başlamaktadır. Şimdi bu metodu yakından inceleyelim.

private fun fillIlgiAlanlariListe() {
pd.show();
kullaniciService.getKitapturListe().enqueue(object:
Callback<ArrayList<IlgiAlanlariParametreModel>> {
override fun onFailure(call: Call<ArrayList<IlgiAlanlariParametreModel>>?, t: Throwable) {
SimpleToast.error(applicationContext, resources.getString(R.string.kitapTurListeHata), "{fa-times-circle}");
pd.dismiss();
}

override fun onResponse(call: Call<ArrayList<IlgiAlanlariParametreModel>>?, response: Response<ArrayList<IlgiAlanlariParametreModel>>) {
ilgiAlanlariListe = response.body() as ArrayList<IlgiAlanlariParametreModel>;
ilgiAlanlariListe.add(IlgiAlanlariParametreModel(0,"",ilgiAlanlariListe.get(0).durum,ilgiAlanlariListe.get(0).olusturan,ilgiAlanlariListe.get(0).resim));
val ilgiAlanlariListe2 = ilgiAlanlariListe.sortedWith(compareBy({it.id}));
ilgiAlanlariListe.clear();
for(i in ilgiAlanlariListe2){
ilgiAlanlariListe.add(i);
}
val adapter = IlgiAlanlariSpinnerAdapter(application,ilgiAlanlariListe,null,selectedIlgiAlanlar);
registerIlgiAlanlariSpinner.adapter = adapter;
pd.dismiss();
}
});
}


kullaniciService 'den bir önceki yazımda bahsetmiştim. Bu servisteki getKitapturListe metodu bize kitap türlerini yani ilgi alanlarını dönüyor. Bu servis başarılı bir sonuç dönünce kitap türlerine aşağıda ki eleman ekleniyor.

    ilgiAlanlariListe.add(IlgiAlanlariParametreModel(0,"",ilgiAlanlariListe.get(0).durum,ilgiAlanlariListe.get(0).olusturan,ilgiAlanlariListe.get(0).resim));

Bu elemanın eklenme amacı defaultta seçiniz gibi boş bir eleman gelmesini istememden kaynaklıdır.

Daha sonra liste id ye göre sort edilip custom layout un uygulanacağı adapter çağırılır ve spinner'a setlenir. Android adapterlar hakkında buradan bilgi alabilirsiniz. Adapterımız aşağıda ki gibi olacaktır.

IlgiAlanlariSpinnerAdapter.kt

class IlgiAlanlariSpinnerAdapter(val context:Context,var ilgiAlanListe:ArrayList<IlgiAlanlariParametreModel>,var kisiIlgiAlanIdListe:ArrayList<Int>?,var selectedIlgiAlanIdListe:ArrayList<Int>):BaseAdapter() {

private val inflater: LayoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater;

override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view: View;
if (convertView == null) {
view = inflater.inflate(R.layout.ilgi_alanlari_spinner, parent, false);
} else {
view = convertView;
}

val cb:CheckBox = view.findViewById(R.id.ilgiAlanCheckBox) as CheckBox;
val ia:IlgiAlanlariParametreModel = getItem(position) as IlgiAlanlariParametreModel;
val tw:TextView = view.findViewById(R.id.tvIlgiAlanCombo) as TextView;

if(ia.id == 0){
tw.visibility = View.VISIBLE;
cb.visibility = View.GONE;
}else{
cb.visibility = View.VISIBLE;
cb.setText(ia.aciklama);
tw.visibility = View.GONE;
}


if(kisiIlgiAlanIdListe != null && kisiIlgiAlanIdListe!!.size>0){
for (i in kisiIlgiAlanIdListe!!){
if(controlIsListedeMevcut(i,ia)){
cb.isChecked = true;
selectedIlgiAlanIdListe.remove(ia.id);
selectedIlgiAlanIdListe.add(ia.id);
}
}
}

cb.setOnCheckedChangeListener { compoundButton, b ->
if(b && ia.id>0){
selectedIlgiAlanIdListe.add(ia.id);
}else{
selectedIlgiAlanIdListe.remove(ia.id);
if(kisiIlgiAlanIdListe != null){
val res = kisiIlgiAlanIdListe!!.find { id -> id == ia.id};
if(res != null && res>0){
val ia: StringBuilder = StringBuilder();
kisiIlgiAlanIdListe!!.remove(res);
ProjectUtil.removeFromSharedPreferences(context,ProjectUtil.SHARED_PREF_FILE,"ilgialanlar");
for(i in kisiIlgiAlanIdListe!!){
ia.append(res).append(",");
}
ProjectUtil.putStringDataToSharedPreferences(context,ProjectUtil.SHARED_PREF_FILE,"ilgialanlar",ia.toString());
}
}

}
}

return view;
}

override fun getItem(position: Int): Any {
return ilgiAlanListe.get(position);
}

override fun getItemId(position: Int): Long {
return position.toLong();
}

override fun getCount(): Int {
return ilgiAlanListe.size;
}

private fun controlIsListedeMevcut(id:Int,ia:IlgiAlanlariParametreModel):Boolean{
if(ia.id == id){
return true;
}
return false;
}
}


Bu adapter da kullandığımız ilgi_alanlari_spinner layoutu aşağıda ki gibidir.

ilgi_alanlari_spinner.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content">

<CheckBox
android:id="@+id/ilgiAlanCheckBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="40dp"
android:theme="@style/KutSisCheckBox"
android:buttonTint="@color/colorAccent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvIlgiAlanCombo" />

<TextView
android:id="@+id/tvIlgiAlanCombo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/ilgiAlanCombo"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Adapter  spinnera setlendiği zaman aşağıda ki gibi görünüm elde edilecektir.


Bu adaptera geçilen kisiIlgiAlanIdListe parametresinin null geçilmesinin sebebi kişinin daha yeni kayıt olduğu için henüz ilgi alanlarının olmayışından kaynaklanmaktadır. Bu parametre profil güncelleme ekranında dolu olarak gönderilecektir.

Ekranda ki validasyonlar tıpkı login ekranında yapıldığı gibi yapılmaktadır. Tüm bilgiler doldurulduktan sonra kaydet butonuna basılır ve servisin başarılı dönmesi durumunda yani sisteme kayıt işleminin başarıyla gerçekleştiği durumda bilgi mesajı verilip kişi giriş ekranına yönlendirilir.

Soru,istek ve önerilerinizi mesutemrecelenk@gmail.com adresine yazabilirsiniz. Bir sonraki yazıda görüşmek üzere hoşça kalın...

Hiç yorum yok:

Yorum Gönder