Android – Kotlin ile BottomAppBar Örneği
Merhabalar,
Bugünki dersimizde Google I/O2018 ‘de tanıtılan ve benim yeni yeni projelerimde kullandığım BottomAppBar ‘ı detaylı bir şekilde inceleyeceğiz.
BottomAppBar Tasarım olarak aşağıdaki gibidir.

Mevcuttaki toolbar ‘lar en üst ‘te konumlanmış ve kullanım açısından zorken, BottomAppBar kullanım açısından kullanıcılara daha kolay bir arayüz sunuyor. En önemli özelliği tek el kullanımı sağlamasıdır.
MaterialComponent kütüphanesini projemize dahil etmek için;
- Build.gradle (Project) ‘i açın.
- allproject altında google’ ın ekli olduğuna emin olun.
allprojects {
repositories {
google()
jcenter()
}
}
- Projeyi implement ‘e edin.
implementation 'com.google.android.material:material:1.2.0-alpha02
Daha detaylı bilgiye aşağıdaki adresten erişebilirsiniz.
//material.io/develop/android/docs/getting-started/
Son Versiyonları aşağıdan öğrenebilirsiniz.
//maven.google.com/web/index.html
//mvnrepository.com/artifact/com.google.android.material/material
Unutmayın ! : BottomAppBar her zaman Coordinator Layout ‘un içerisinde olmak zorundadır. Detaylı Bilgi için;
//developer.android.com/reference/android/support/design/widget/CoordinatorLayout
Gelelim Tasarımımızı yapmaya,
Layout Dosyamız –> activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="//schemas.android.com/apk/res/android"
xmlns:app="//schemas.android.com/apk/res-auto"
xmlns:tools="//schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottom_app_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
app:backgroundTint="@color/colorPrimary"
style="@style/Widget.MaterialComponents.BottomAppBar"
app:fabAlignmentMode="center"
app:navigationIcon="@drawable/ic_menu"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_add_black_24dp"
app:fabSize="normal"
app:layout_anchor="@id/bottom_app_bar">
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>Burada neler yaptığımızı anlatırsak. Bir tane constraintLayout içerisine text view ve coordinatorLayout ekledik. BottomAppBar Coordinator layout ile entegre ‘dir. Yukarıda daha detaylı bilgiye erişebilirsiniz. İçerisine de bir fab button attık.
Tasarımımız aşağıdaki şekilde olacaktır.

BottomAppBar aşağıdaki özelliklere sahiptir. Sizde bu özellikleri kendi tasarımınıza uygun olacak şekilde güncelleyebilirsiniz.

app:backgroundTint –> Arka Plan rengi için kullanılır.
app:fabAlignmentMode –> End ve Center özelliği sahiptir. Yukardaki resimde center iken herhangi bir işlemde end yapabilirsiniz. Örnek aşağıdaki resimdedir. Bu proje de de örnek olarak uygulanmıştır.

app:fabAttached –> Fab button’un bottomappbar ile bütünleşik mi olacağı yoksa ayrı olarak mı sunulacağına ilişkin ayardır.

app:fabCradleDiameter –> Fab button ile bottomAppBar arasındaki açıyı ayarlıyor.

app:fabCradleRoundedCornerRadius –> Köşe eğrisinin yarıçapının buluşma noktasındaki yarıçapını ve BottomAppBar’ın yatay kısmını belirtir.

app:fabCradleVerticalOffSet –> fab Buttonunun aşağıdaki yerini belirtir.

Gelelim MainActivity Kısmına :
package com.umiitkose.todolist.bottomappbarexample
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.annotation.RequiresApi
import com.google.android.material.bottomappbar.BottomAppBar
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.umiitkose.todolist.bottomappbarexample.utils.toast
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private var currentFabAlignmentMode = BottomAppBar.FAB_ALIGNMENT_MODE_CENTER
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(bottom_app_bar)
val addVisibilityChanged: FloatingActionButton.OnVisibilityChangedListener = object : FloatingActionButton.OnVisibilityChangedListener() {
override fun onShown(fab: FloatingActionButton?) {
super.onShown(fab)
}
override fun onHidden(fab: FloatingActionButton?) {
super.onHidden(fab)
bottom_app_bar.toggleFabAlignment()
bottom_app_bar.replaceMenu(
if(currentFabAlignmentMode == BottomAppBar.FAB_ALIGNMENT_MODE_CENTER) R.menu.bottomappbar_menu_two
else R.menu.bottomappbar_menu
)
fab?.setImageDrawable(
if(currentFabAlignmentMode == BottomAppBar.FAB_ALIGNMENT_MODE_CENTER) getDrawable(R.drawable.ic_save_black_24dp)
else getDrawable(R.drawable.ic_add_black_24dp)
)
fab?.show()
}
}
fab.setOnClickListener {
Toast.makeText(this,"Fab Click", Toast.LENGTH_LONG).show()
fab.hide(addVisibilityChanged)
invalidateOptionsMenu()
bottom_app_bar.navigationIcon = if (bottom_app_bar.navigationIcon != null) null
else getDrawable(R.drawable.ic_search)
when(tv_text.text) {
getString(R.string.primary_screen_text) -> tv_text.text = getString(R.string.secondary_sceen_text)
getString(R.string.secondary_sceen_text) -> tv_text.text = getString(R.string.primary_screen_text)
}
}
}
private fun BottomAppBar.toggleFabAlignment() {
currentFabAlignmentMode = fabAlignmentMode
fabAlignmentMode = currentFabAlignmentMode.xor(1)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val inflater = menuInflater.inflate(R.menu.bottomappbar_menu,menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item!!.itemId){
R.id.app_bar_fav ->toast("Fav Menu item ",this)
R.id.app_bar_settings ->toast("Settings Menu item ",this)
R.id.app_bar_search ->toast("Search Menu item ",this)
android.R.id.home -> {
val bottomNavDrawerFragment = BottomNavigationDrawerFragment()
bottomNavDrawerFragment.show(supportFragmentManager, bottomNavDrawerFragment.tag)
}
}
return true
}
}
menu kısmı için –> bottomappbar
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="//schemas.android.com/tools"
xmlns:app="//schemas.android.com/apk/res-auto"
xmlns:android="//schemas.android.com/apk/res/android">
<item
android:id="@+id/app_bar_fav"
android:icon="@drawable/ic_favorite_border_black_24dp"
android:title="Favori"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/app_bar_search"
android:icon="@drawable/ic_search"
android:title="Search"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/app_bar_settings"
android:title="Settings"
app:showAsAction="never"/>
</menu>CoordinatorLayout ‘un bir child elemanı olan BottomSheet ‘i ekleyeceğiz. Detaylı Bilgi için;
//material.io/develop/android/components/bottom-sheet-behavior/
O zaman hadi başlayalım tasarıma :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="//schemas.android.com/apk/res/android"
xmlns:app="//schemas.android.com/apk/res-auto"
xmlns:tools="//schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottom_app_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
app:backgroundTint="@color/colorPrimary"
style="@style/Widget.MaterialComponents.BottomAppBar"
app:fabAlignmentMode="center"
app:navigationIcon="@drawable/ic_menu"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_add_black_24dp"
app:fabSize="normal"
app:layout_anchor="@id/bottom_app_bar">
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>Menü Kısmı :
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="//schemas.android.com/apk/res/android"
xmlns:app="//schemas.android.com/apk/res-auto">
<group android:checkableBehavior="none">
<item
android:id="@+id/nav1"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
<item
android:id="@+id/nav2"
android:icon="@drawable/ic_search"
android:title="@string/nav_item2">
<item
android:id="@+id/nav3"
android:icon="@drawable/ic_search"
android:title="@string/nav_item3">
<item
android:id="@+id/nav4"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
<item
android:id="@+id/nav5"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
<item
android:id="@+id/nav6"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
<item
android:id="@+id/nav7"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
<item
android:id="@+id/nav8"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
<item
android:id="@+id/nav9"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
<item
android:id="@+id/nav10"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
<item
android:id="@+id/nav11"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
<item
android:id="@+id/nav12"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
<item
android:id="@+id/nav13"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
<item
android:id="@+id/nav14"
android:icon="@drawable/ic_search"
android:title="@string/nav_item1">
</group>
</menu>
ve son olarak Bottom Navigation Drawer ‘ı görüntülemek için Fragment yazmaya..
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_bottomsheet, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
navigation_view.setNavigationItemSelectedListener { menuItem ->
// Bottom Navigation Drawer menu item clicks
when (menuItem.itemId) {
R.id.nav1 -> toast(getString(R.string.nav_item1),requireContext())
}
// Add code here to update the UI based on the item selected
// For example, swap UI fragments here
true
}
close_imageview.setOnClickListener {
this.dismiss()
}
disableNavigationViewScrollbars(navigation_view)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
dialog.setOnShowListener { dialog ->
val d = dialog as BottomSheetDialog
val bottomSheet = d.findViewById<View>(R.id.design_bottom_sheet) as FrameLayout?
val bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet!!)
bottomSheetBehavior.setBottomSheetCallback(object :
BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) {
if (slideOffset > 0.5) {
close_imageview.visibility = View.VISIBLE
} else {
close_imageview.visibility = View.GONE
}
}
override fun onStateChanged(bottomSheet: View, newState: Int) {
when (newState) {
BottomSheetBehavior.STATE_HIDDEN -> dismiss()
// else -> close_imageview.visibility = View.GONE
}
}
})
}
return dialog
}
private fun disableNavigationViewScrollbars(navigationView: NavigationView?) {
val navigationMenuView = navigationView?.getChildAt(0) as NavigationMenuView
navigationMenuView.isVerticalScrollBarEnabled = false
}
}
Uygulama Resimleri :
Projeyle ilgili tüm kodlara aşağıdaki adresten ulaşabilirsiniz.
//github.com/umiitkose/BottomAppBar
Okuduğunuz için teşekkür ederim, İyi Çalışmalar Herkese..









