6 Şubat 2021 Cumartesi

Android Kütüphane Sistemi Mobil Uygulaması - 4 (Navigation Menu ve Toolbar)

  Merhabalar. Android Kütüphane Sistemi Mobil Uygulaması yazı dizisinin döndüncü yazısı ile yeniden sizlerleyim. Bu yazıda sisteme giriş yaptıktan sonra görülen Navigation Drawer ve Toolbar componentlerinden bahsedeceğim. Tekrar belirtmekte fayda olacak, uygulamanın kodlarına buradan erişebilirsiniz.

Dashboard ekranı sol menüden (Navigation Drawer Menu) erişilebilen bir fragment olmakla birlikte uygulamayı açınca (tabi login olmuş isek) ilk set edilen fragmenttır. Bu menu MainActivity'de ekleniyor olup tüm eventleri burada verilmektedir. 

Dilerseniz ilk olarak sol menüyü, toolbarı ve fragmentleri içeren MainActivity sınıfımıza bir göz atalım.


MainActivity çalışınca sırasıyla aşağıda ki işlemleri yapar;

    1. İzin kontrolü (Kamera kullanım , dosya okuma-yazma ve internet kullanım izni)

    2.Toolbar ın setlenmesi

    3. Navigation Drawer Menü setlenmesi

işlemlerini yapar. Bu activity'nin layoutu aşağıdaki gibidir.


activity_main.xml

<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:openDrawer="start">

<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/barLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ToolbarTheme">

<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbarNav"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:title=" "
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Kütüphane Sistemi"
android:textColor="@color/whiteTextColor"
android:textSize="16sp"
android:textStyle="bold" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:id="@+id/fragmentNavTutucu"
android:fitsSystemWindows="true"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/kitapEkleBtn"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="25dp"
android:clickable="true"
app:srcCompat="@drawable/ic_add_24dp" />


<com.github.clans.fab.FloatingActionMenu
android:id="@+id/hizliErisimFabButton"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:paddingRight="25dp"
android:paddingBottom="35dp"
app:menu_labels_style="@style/MenuLabelsStyle"
app:menu_labels_showAnimation="@anim/fab_scale_up"
app:menu_labels_hideAnimation="@anim/fab_scale_down"
app:menu_animationDelayPerItem="1"
app:menu_shadowColor="#444"
android:paddingLeft="10dp"
app:menu_colorRipple="@color/kirmizi"
app:menu_icon="@drawable/ic_directions_run_white_24dp"
app:menu_labels_ellipsize="end"
app:menu_labels_singleLine="true"
app:menu_backgroundColor="#ccffffff"
app:menu_fab_label="@string/hizliErisimMenuLabel">

<com.github.clans.fab.FloatingActionButton
android:id="@+id/kitapListeFabButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MenuButtonsSmall"
android:src="@drawable/ic_library_books_24dp"
app:fab_size="mini"
app:fab_label="@string/hizliErisimKitapListeLabel" />

<com.github.clans.fab.FloatingActionButton
android:id="@+id/kitapEklemeFabButton"
style="@style/MenuButtonsSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_add_24dp"
app:fab_size="mini"
app:fab_label="@string/hizliErisimKitapEklemeLabel" />

<com.github.clans.fab.FloatingActionButton
android:id="@+id/profilIslemFabButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/MenuButtonsSmall"
android:src="@drawable/ic_person_24dp"
app:fab_size="mini"
app:fab_label="@string/hizliErisimProfilIslemLabel" />

</com.github.clans.fab.FloatingActionMenu>


</androidx.coordinatorlayout.widget.CoordinatorLayout>

<com.google.android.material.navigation.NavigationView
android:id="@+id/navigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@drawable/navigation_background"
app:headerLayout="@layout/kutuphane_sistemi_nav_header_layout"
app:itemIconTint="@color/whiteTextColor"
app:itemBackground="@drawable/navigation_selected_item_background"
app:itemTextAppearance="@style/LeftMenuUiTestTextView"
app:menu="@menu/kutuphane_nav_items"/>
</androidx.drawerlayout.widget.DrawerLayout>


Burada kitap eklemek için bir adet FloatingActionButton ve hızlı menü için ise üçüncü parti bir kütüphane kullandım. Kitap ekleme butonu kitap listesi fragment ı setlenince visible olup sonra önümüzdeki yazılarda bahsedeceğim. 

Hızlı menü için kullandığım componentin detaylarına buradan ulaşabilirsiniz. Bu componenti kullanmak için evvela build.gradle (Module:App) dosyanıza aşağıda ki dependency i eklemeniz gerekmektedir.

                implementation 'com.github.clans:fab:1.6.4'


Bu hızlı menünün açılmış hali aşağıda ki gibidir.


Şimdide bütün bu componentlere, menülere ve toolbarda ki search e nasıl event veridliğini bu layout u içeren activity olan MainActivity yi anlatarak devam edelim.


MainActivity.kt

class MainActivity : AppCompatActivity() {

private lateinit var kullaniciAdSoyad:TextView;
private lateinit var kullaniciResim:ImageView;
private lateinit var tempFragment:Fragment;
private lateinit var kitapService: IKitapIslemService;
private lateinit var pd:Dialog;

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

checkPermissions();

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);
pd.show();

setSupportActionBar(toolbarNav);
val toggle = ActionBarDrawerToggle(this,drawer, toolbarNav as Toolbar?,0,0);
drawer.addDrawerListener(toggle);
toggle.setDrawerIndicatorEnabled(true);
toggle.syncState();

val navHeaderView:View =navigationView.getHeaderView(0);

this.kullaniciAdSoyad = navHeaderView.findViewById(R.id.kullaniciAdSoyadTextView) as TextView;
this.kullaniciResim = navHeaderView.findViewById(R.id.userImage) as ImageView;
kitapService = WebApiUtil.getKitapService(this);

setNavigationHeaderValues(applicationContext,pd);
setFABButtonMenuActions();
if(ProjectUtil.getStringDataFromSharedPreferences(this,ProjectUtil.SHARED_PREF_FILE,"navfragment") != null
&&ProjectUtil.getStringDataFromSharedPreferences(this,ProjectUtil.SHARED_PREF_FILE,"navfragment")
.equals("KitapIslemFragment") ){
ProjectUtil.removeFromSharedPreferences(this,ProjectUtil.SHARED_PREF_FILE,"navfragment");
tempFragment = KitapIslemFragment();
supportFragmentManager.beginTransaction()
.replace(R.id.fragmentNavTutucu,tempFragment).commit();
}else{
hizliErisimFabButton.visibility = View.VISIBLE;
kitapEkleBtn.visibility = View.GONE;
tempFragment = AnasayfaFragment();
supportFragmentManager.beginTransaction()
.replace(R.id.fragmentNavTutucu,tempFragment).commit();
}
navigationView.setNavigationItemSelectedListener {item ->
pd.show();
if(item.itemId == R.id.anasayfaItem){
item.setCheckable(true);
kitapEkleBtn.visibility = View.GONE;
hizliErisimFabButton.visibility = View.VISIBLE;
tempFragment = AnasayfaFragment();
}else if(item.itemId == R.id.kitapIslemlerItem){
hizliErisimFabButton.visibility = View.GONE;
item.setCheckable(true);
tempFragment = KitapIslemFragment();
}else if(item.itemId == R.id.parametreIslemlerItem){
kitapEkleBtn.visibility = View.GONE;
hizliErisimFabButton.visibility = View.GONE;
ProjectUtil.activityYonlendir(this,ParametreActivity());
}else if(item.itemId == R.id.profilIslemlerItem){
item.setCheckable(true);
hizliErisimFabButton.visibility = View.GONE;
kitapEkleBtn.visibility = View.GONE;
tempFragment = ProfilIslemleriFragment();
}else if(item.itemId == R.id.cikisItem){
val ad = AlertDialog.Builder(navigationView.context);
ad.setMessage(resources.getString(R.string.cikisYapmakIstiyormusunuz));
ad.setPositiveButton(resources.getString(R.string.evet)){ dialogInterface, i ->
ProjectUtil.deleteAllSharedPreferencesData(applicationContext,ProjectUtil.SHARED_PREF_FILE);
ProjectUtil.activityYonlendir(applicationContext,LoginActivity());
}

ad.setNegativeButton(resources.getString(R.string.hayir)){dialogInterface, i ->
}

ad.create().show();

}

if(item.itemId != R.id.cikisItem){
supportFragmentManager.beginTransaction()
.replace(R.id.fragmentNavTutucu,tempFragment).commit();
}

pd.dismiss();
drawer.closeDrawer(GravityCompat.START);
true;
}

pd.dismiss();
}

private fun setFABButtonMenuActions() {
kitapListeFabButton.setOnClickListener {
hizliErisimFabButton.toggle(false);
hizliErisimFabButton.visibility = View.GONE;
tempFragment = KitapIslemFragment();
supportFragmentManager.beginTransaction()
.replace(R.id.fragmentNavTutucu,tempFragment).commit();
}

kitapEklemeFabButton.setOnClickListener {
hizliErisimFabButton.toggle(false);
ProjectUtil.activityYonlendir(this, KitapEklemeActivity());
}

profilIslemFabButton.setOnClickListener {
hizliErisimFabButton.toggle(false);
hizliErisimFabButton.visibility = View.GONE;
tempFragment = ProfilIslemleriFragment();
supportFragmentManager.beginTransaction()
.replace(R.id.fragmentNavTutucu,tempFragment).commit();
}
}

private fun checkPermissions() {
var camPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if(camPermission != PackageManager.PERMISSION_GRANTED){//İzin aktif edilmemişse
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),12345);
}

camPermission = ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE);
if(camPermission != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),54321);
}

camPermission = ContextCompat.checkSelfPermission(this,Manifest.permission.INTERNET);
if(camPermission != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.INTERNET),100);
}
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.kutuphane_toolbar_head_menu,menu);
val searchItem:MenuItem = menu.findItem(R.id.app_bar_search);
val searchView:SearchView = searchItem.actionView as SearchView;
searchView.queryHint = resources.getString(R.string.araHeaderLabel);

searchView.findViewById<AutoCompleteTextView>(R.id.search_src_text).threshold = 2;

searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}

override fun onQueryTextChange(query: String?): Boolean {
if(query?.length!! >2){
var liste:ArrayList<KitapModel> = ArrayList<KitapModel>();
val jsonObj: JSONObject = JSONObject();
jsonObj.put("kitapAd",query);
jsonObj.put("yazaarAd",query);
kitapService.getKitapListe(jsonObj.toString()).enqueue(object:
Callback<ArrayList<KitapModel>> {
override fun onFailure(call: Call<ArrayList<KitapModel>>?, t: Throwable) {
SimpleToast.error(applicationContext, resources.getString(R.string.kitapListeHata), "{fa-times-circle}");
}

override fun onResponse(call: Call<ArrayList<KitapModel>>?, response: Response<ArrayList<KitapModel>>) {
if(response.body() != null){
liste = response.body() as ArrayList<KitapModel>;
searchView.findViewById<AutoCompleteTextView>(R.id.search_src_text).setAdapter(KitapFiltreAdapter(applicationContext,R.layout.kitap_search_item_layout,liste));
}
}
});
}

return true;
}
})


return true;
}



private fun setNavigationHeaderValues(c:Context,pd:Dialog){
this.kullaniciAdSoyad.text = resources.getString(R.string.hosGeldiniz)+ProjectUtil.getStringDataFromSharedPreferences(c,ProjectUtil.SHARED_PREF_FILE,"adSoyad");
this.getKullaniciResim(c,pd,this.kullaniciResim);
}

private fun getKullaniciResim(
applicationContext: Context,
pd: Dialog,
kullaniciResim: ImageView
) {
val kullaniciService: IKullaniciService = WebApiUtil.getKullaniciService(applicationContext);
kullaniciService.getKullaniciResim().enqueue(object: Callback<KullaniciResimModel> {
override fun onFailure(call: Call<KullaniciResimModel>?, t: Throwable) {
SimpleToast.error(applicationContext, resources.getString(R.string.resimGetirmeHata), "{fa-times-circle}");
pd.dismiss();
}

override fun onResponse(call: Call<KullaniciResimModel>?, response: Response<KullaniciResimModel>) {
val kullaniciResimModel: KullaniciResimModel = response.body() as KullaniciResimModel;
kullaniciResim.setImageBitmap(ProjectUtil.getBitmapResourceFromBase64(kullaniciResimModel.userImageBase64));
pd.dismiss();
}
});
}

override fun onBackPressed() {
val ad = AlertDialog.Builder(navigationView.context);
ad.setMessage(resources.getString(R.string.kapatmakIstiyormusunuz));
ad.setPositiveButton(resources.getString(R.string.evet)){ dialogInterface, i ->
finishAffinity();
}

ad.setNegativeButton(resources.getString(R.string.hayir)){dialogInterface, i ->
}

ad.create().show();
}
}

Burada ki en temel işlem gerek hızlı menüden yapılan seçimde gerek navigation menüden yapılan seçimde FrameLayout'a aşağıda ki kod ile gerekli fragment ın setlenme işlemidir.

supportFragmentManager.beginTransaction()
.replace(R.id.fragmentNavTutucu,tempFragment).commit();


Bir diğer işlem ise onCreateOptionsMenu metodunda yapılan auto complete search işlemidir. Toolbarda ki inputtext'e yazar adı ya da kitap adı yazdığımız zaman servisten sonuçları alıp custom bir formatta sonuç gösteriyorum. Bu format custom bir format olduğu için bir adapter ve bu adapter da inflate edilen bir layout a sahiptir. Gelen sonuça tıklandığı zaman ise seçilen kitabın detayı açılmaktadır. Dilerseniz adapter kodlarına bakalım.

KitapFiltreAdapter.kt

class KitapFiltreAdapter(context:Context,
@LayoutRes private val layoutRes:Int,
val kitapListe:ArrayList<KitapModel>):ArrayAdapter<KitapModel>(context,layoutRes,kitapListe){

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;
view = inflater.inflate(layoutRes, parent, false);

val kitapImage:ImageView = view.findViewById(R.id.searchItemImageId) as ImageView;
val kitapAdTw:TextView = view.findViewById(R.id.searchKitapAdItemId) as TextView;
val yazarAdTw:TextView = view.findViewById(R.id.searchKitapYazarAdItemId) as TextView;
val mainLayout:ConstraintLayout = view.findViewById(R.id.mainSearchLayout);
val kitap:KitapModel = getItem(position) as KitapModel;

Glide.with(context).load(kitap.kitapResimPath).into(kitapImage);
if(kitap.kitapAd!!.length>24){
kitapAdTw.text = kitap.kitapAd!!.substring(0,23)+"...";
}else{
kitapAdTw.text = kitap.kitapAd;
}

yazarAdTw.text = kitap.yazarAd;

mainLayout.setOnClickListener {
putKitapDetayIntoSharedPreferences(context,kitap);
ProjectUtil.activityYonlendir(context,KitapDetayActivity());
}

return view;
}

override fun getItem(position: Int): KitapModel? {
return kitapListe.get(position);
}

private fun putKitapDetayIntoSharedPreferences(mContext: Context, kitap: KitapModel) {
kitap.id?.let {
ProjectUtil.putIntDataToSharedPreferences(mContext,ProjectUtil.SHARED_PREF_FILE,"kitapId",
it
)
};
ProjectUtil.putStringDataToSharedPreferences(mContext,
ProjectUtil.SHARED_PREF_FILE,"kitapAd",kitap.kitapAd.toString());
ProjectUtil.putStringDataToSharedPreferences(mContext,
ProjectUtil.SHARED_PREF_FILE,"yazarAd",kitap.yazarAd.toString());
ProjectUtil.putStringDataToSharedPreferences(mContext,
ProjectUtil.SHARED_PREF_FILE,"kitapAciklama",kitap.kitapAciklama.toString());
ProjectUtil.putStringDataToSharedPreferences(mContext,
ProjectUtil.SHARED_PREF_FILE,"kitapTur",kitap.kitapTur!!.aciklama.toString());
ProjectUtil.putStringDataToSharedPreferences(mContext,
ProjectUtil.SHARED_PREF_FILE,"kitapYayinevi",kitap.yayinEvi!!.aciklama.toString());
ProjectUtil.putStringDataToSharedPreferences(mContext,
ProjectUtil.SHARED_PREF_FILE,"kitapResim",kitap.kitapResimPath.toString());
kitap.kayittarihi?.let { ProjectUtil.formatDate(it,"dd.MM.yyyy") }?.let {
ProjectUtil.putStringDataToSharedPreferences(mContext, ProjectUtil.SHARED_PREF_FILE,"kitapAlinmaTarih",
it
)
};
ProjectUtil.putDoubleDataToSharedPreferences(mContext,ProjectUtil.SHARED_PREF_FILE,"kitapPuan",kitap.kitapPuan);
}

}

Burada URL den resmi direk göstermek için Glide kütüphanesinden faydalandım. Bu kütüphaneyi kullanmak için build.gradle (Module:App) dosyanıza aşağıda ki dependency i eklemeniz gerekmektedir.

         implementation 'com.github.bumptech.glide:glide:4.6.1'   

Bu adapter da inflate edilen layout ise aşağıda ki gibidir.

kitap_search_item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/mainSearchLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/whiteTextColor">


<ImageView
android:id="@+id/searchItemImageId"
android:layout_width="106dp"
android:layout_height="102dp"
android:layout_marginTop="5dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/edit_text_border" />

<TextView
android:id="@+id/searchKitapAdItemId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="TextView"
android:textAllCaps="false"
android:textColor="@color/siyah"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/searchItemImageId"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/searchKitapYazarAdItemId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="TextView"
android:textSize="12sp"
android:textStyle="italic"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/searchItemImageId"
app:layout_constraintTop_toBottomOf="@+id/searchKitapAdItemId" />

<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginTop="1dp"
android:background="@color/imageShadow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/searchItemImageId" />

</androidx.constraintlayout.widget.ConstraintLayout>

Burada yapılan search sonuçları ise aşağıda ki gibi listelenir.


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