How to create a new Toolbar (Component)

By | 9 Nisan 2022

Bu içerikte yeni bir Toolbar’ı nasıl oluşturabileceğimizi öğreneceğiz. Sizin de muhtemelen çokça karşılaştığınız bir durum olan bir component’i app’in farklı yerlerinde tekrar ve tekrar kullanılması durumunda her şeyi sürekli yeniden yazmak zorlu ve önerilmeyen yöntemdir.

Bu dersimizin sonunda aşağıdaki gibi toolbarınız olacak ve istediğiniz ekran için istediğiniz şekilde düzenleyebilirsiniz. İhtiyaç doğrultusunda yeni özellikler de ekleyebilirsiniz. (YOUTUBE VİDEOSU İÇİN TIKLAYIN)

Farklı ekran ve durumlar için toolbar’ınıza ekleyip çıkarabileceğiniz birçok olasılık.


Şimdi bu dersimizde kendimize has bir Toolbar’ı nasıl sıfırdan yazabiliriz ve ona farklı farklı özellikleri nasıl verebiliriz hızlıdan yapmaya başlayalım.

Toolbar İçin Hazırlık

Yeni bir projeyi oluşturmuşsunuzdur şimdiye kadar 🙂

İlk olarak aşağıdaki gibi build.gradle dosyasında plugin şu şekilde olsun

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
    id 'kotlin-kapt'
}

burada önemli olan kapt‘tır. BindingAdapter için bize lazım olacaktır.

yine aynı dosyada android{} içerisinde en altta aşağıdaki buildFeatures‘i yerleştirelim.

android {
    ...
    buildFeatures{
        dataBinding true
    }
}

Sağ üstte çıkan Sync Now‘a tıklayın ve yaptıklarımızı kabul etsin 🙂
Gerekli ön adımlarımızı yaptığımıza göre artık başlayabiliriz.

Toolbarı Oluşturalım

res>layout>New>Layout Resource File ile my_toolbar isminde bir dosya oluşturalım ve içini aşağıdaki gibi düzenleyelim. Bu dosyada bizim toolbar’da yer alacak her şeyi barındırıyoruz. Neler bulundurabiliriz mesela?
Geri butonu, uygulama ismi için bir text, uygulama logosu için imageView, toolbarın ortasında kullanabileceğimiz bir text(ben sayaç için yerleştirmiştim), menü ikonu, yardım ikonu, arama barı vs.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
    </data>
    <androidx.appcompat.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="?android:attr/actionBarSize"
        android:background="@color/bg_dark"
        app:contentInsetStart="0dp">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/login_action_bar"
            android:layout_width="match_parent"
            android:paddingStart="12dp"
            android:layout_height="match_parent"
            android:background="@color/transparent"
            android:contentInsetStart="0dp">

            <ImageView
                android:id="@+id/ivToolbarLogo"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_baseline_attractions_24"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"/>

            <ImageView
                android:id="@+id/ivBack"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:visibility="gone"
                android:padding="10dp"
                android:src="@drawable/ic_baseline_arrow_back_24"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"/>

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/tvToolbarText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/app_name"
                android:textSize="16sp"
                style="@style/textYellow"
                app:layout_constraintStart_toEndOf="@+id/ivBack"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/tvCounter"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                style="@style/textYellow"
                android:visibility="gone"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="@+id/tvToolbarText"/>

            <ImageView
                android:id="@+id/ivHelp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_baseline_help_center_24"
                android:visibility="gone"
                app:layout_constraintEnd_toStartOf="@+id/ivMenu"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"/>

            <ImageView
                android:id="@+id/ivMenu"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_baseline_menu_24"
                android:visibility="gone"
                android:layout_marginEnd="12dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"/>

        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.appcompat.widget.Toolbar>
</layout>

Bunu yaptığınızda ekranınızda birçok yer kırmızı olacaktır ama basit işler. Neler istemişse aşağıda hepsini veriyor olacağım size.

color için colors.xml dosyasına aşağıdakileri ekliyoruz.

<color name="bg_dark">#0D2A43</color>
<color name="transparent">#00A6A7A9</color>
<color name="yellow">#FFC107</color>

style için themes.xml dosyasına aşağıdakileri yerleştiriyoruz.

<style name="textYellow" parent="TextAppearance.AppCompat">
    <item name="android:textColor">@color/yellow</item>
</style>

Hazır themes.xml dosyasına gelmişten temayı NoActionBar olarak değiştirin ki uygulamada 2 toolbar gözükmesin 🙂

parent="Theme.MaterialComponents.DayNight.NoActionBar"

imageView yani drawable istenen yerleri de istediğin iconu indirip yerleştirebilirsiniz.

Tasarım dosyamız hazır olduğuna göre şimdi de bunu yönetebileceğimiz MyToolbar isminde bir sınıf oluşturalım ve içini aşağıdaki gibi dolduralım.

/**
 * Created by Şahin Karakulak on 9.04.2022
 */
class MyToolbar: ConstraintLayout {

    private var binding: MyToolbarBinding

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)

    init {
        val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        binding = DataBindingUtil.inflate(inflater, R.layout.my_toolbar, this, true)
    }

    fun getMenuIcon(): ImageView = binding.ivMenu
    fun getBackIcon(): ImageView = binding.ivBack
    fun getTitle(): TextView = binding.tvToolbarText
    fun getCounter(): TextView = binding.tvCounter
    fun getHelpIcon(): ImageView = binding.ivHelp
    fun getToolbarLogo(): ImageView = binding.ivToolbarLogo
    fun hide() = binding.root.gone()
    fun show() = binding.root.visible()
}

MyToolbar sınıfında sizde kırmızı yanacak olan 2 yer var. gone() ve visible() extension’larını da hızlıca yazalım. Bunun için ViewExtensions isminde bir dosya oluşturalım ve içini aşağıdaki gibi dolduralım. (Başka bir dersimizde de extensions yazmayı detaylıca inceleriz)

/**
 * Created by Şahin Karakulak on 19.03.2022
 */

fun View.visible(){
    this.visibility = View.VISIBLE
}

fun View.invisible(){
    this.visibility = View.INVISIBLE
}

fun View.gone(){
    this.visibility = View.GONE
}

MyToolbar isminde bir toolbar’ımız artık var ama asıl amacımız neydi? Tamamen bizim yönetip özellik verip kaldırabileceğimiz bir toolbar olmasıydı. O halde şimdi de bindingAdapter’ı oluşturalım.

ToolbarBindingAdapter isminde bir dosya oluşturalım ve içini aşağıdaki gibi dolduralım.

/**
 * Created by Şahin Karakulak on 9.04.2022
 */

@BindingAdapter("bind:setToolbarTitle")
fun setToolbarTitle(view: MyToolbar, title: String?) {
    view.getToolbarLogo().gone()
    view.getTitle().text = title
    view.getTitle().visible()
}

@BindingAdapter("bind:setBackIcon")
fun setBackIcon(view: MyToolbar, isVisible: Boolean){
    if(isVisible) view.getBackIcon().visible() else view.getBackIcon().gone()
}

@BindingAdapter("bind:setCounter")
fun setCounter(view: MyToolbar, counterText: String?){
    view.getCounter().text = counterText
}

Burada setToolbarTitle, setBackIcon ve setCounter şeklinde attributes var. Bunları nasıl kullanacağımızı birazdan aşağıda göreceğiz.

Toolbar’ı Nasıl Kullanırız?

Tüm yapımızı kurduk. Artık toolbar’ı activity veya fragment ekranlarında nasıl kullanabiliriz onu görelim. Örneğin activity_main.xml dosyamızda kullanmaya çalışalım. Burada dikkat edilmesi gereken şey tüm layoutları kapsayacak olan

<layout></layout>

tag’ını yerleştirmek ve xmlns’leri oraya taşımak. Aşağıdaki bir örnek.

<?xml version="1.0" encoding="utf-8"?>
<layout
    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"
    xmlns:bind="http://schemas.android.com/tools">

    <data>
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <com.mrcaracal.myapplicationfornewtoolbar.MyToolbar
            android:id="@+id/myNewToolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            bind:setBackIcon="@{false}"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Bizim oluşturduğumuz toolbarda göze çarpan bir şey varmı? VAR 🙂

bind:setBackIcon="@{false}"

Az önce bunları nasıl kullanabileceğimizi göreceğiz demiştim. Burda ToolbarBindingAdapter dosyasındaki setBackIcon‘a false değerini göndererek oradaki işlemin yapılmasını sağladık. Böylelikle geri butonunu gizledik. Farklı bir ekranda true göndererek geri butonu gösterebiliriz

Diğer bir attribute’mızı da görelim.

bind:setToolbarTitle="@{@string/login}"

Burada da string.xml dosyamızdaki bir string’i çağırdık. Böylelikle Toolbarımızda istediğimiz yazı gözükecektir.

Toolbar’ımızda yer alacak geri butonunu, text’i ve diğerlerini bu şekilde ayarlayabiliriz ama bunları kod tarafında da nasıl düzenleyebileceğimizi de görelim. MainActivity sınıfı içerisinde örnek olarak aşağıdaki gibi istediğimiz şekilde düzenlemeler yapabiliriz.

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.myNewToolbar.getToolbarLogo().gone()
        binding.myNewToolbar.getTitle().text = "Create a new toolbar"
        binding.myNewToolbar.getMenuIcon().visible()
        
        binding.myNewToolbar.getMenuIcon().setOnClickListener {
            Toast.makeText(this, "Menu Clicked!", Toast.LENGTH_SHORT).show()
        }
    }
}

Bu içeriğin de sonuna geldik. Umarım faydalı bir kaynak olmuştur. İyi günler dilerim 🙂

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir