Wednesday, May 18, 2022

 

What is Kotlin Multiplatform (KMM)
























Kotlin Multiplatform Mobile is a feature that enables you to use one codebase to write the business logic of iOS and Android apps. Sharing code between multiple mobile app development platforms is one of the major use cases of KMM. With Kotlin Multiplatform Mobile, you can build mobile applications for multiple mobile platforms by sharing code, such as business logic, connectivity etc between Android and iOS.

KMM enforces modularization, thus by forcing mobile app developers to write code in such a way that separates business logic from UI. Kotlin allows a high level of reusability between developers. It allows developers to share knowledge domains and reduce the duplication of native code.

Common Kotlin code is converted into an iOS framework that can be used as any other existing iOS framework in Xcode. For Android, Common Kotlin code is converted in Gradle library that can be used in any Android Project.

Components of Kotlin Multiplatform

A basic KMM project has the following structure and components.

Shared module – a Kotlin module that contains common logic for both Android and iOS applications. Builds into an Android library and an iOS framework. Uses Gradle as a build system.

Android application – a Kotlin module that builds into the Android application. Uses Gradle as a build system.

iOS application – an Xcode project that builds into the iOS application.

Creating a KMM Project in Android Studio

Update Android Studio to the latest or at least version greater than 4.0.1 for installing Kotlin Multplatform plugin.

After installing KMM plugin, Android Studio should be restarted and then we can create a new KMM project.

In this section, you will have to give your project a name, select your minimum SDK, Save location, Package name, and iOS, Android module name.

The root project does not hold source code. You can use it to store global configuration in its build.gradle(.kts) or gradle.properties.

Shared module contains the core application logic used in both target platforms: classes, functions, and so on. This is a Kotlin Multiplatform module that compiles into an Android library and an iOS framework. It uses Gradle with the Kotlin Multiplatform plugin applied and has targets for Android

Kotlin Multiplatform Project Folder Structure

.gradle/ and .idea/ folders: local files that should not be committed to source control for most Android Studio projects. They include local settings for the IDE, project, and dependencies.

androidApp/ folder: the root directory for the Android app project in our larger KMM project that has all of the Android side’s UI logic.

build/ folder: contains output from your KMM builds. There is no need to add this folder in source control.

iosApp/ folder: the root directory of the Xcode project in the larger KMM project.

External Libraries: all of the project’s dependencies. Android and KMM projects differ from iOS projects in that they require far more external dependencies.

Overview of Shared Module

commonMain :- It contains our business logic. For eg :- Network layer, data models etc. It also contains all the expect declarations.

iosMain :- It contains iOS specific implementations. Includes all the actual implementation for iOS part.

androidMain :- It contains android specific implementation. Includes all the actual implementation for android part.

androidTest, commonTest and iosTest :- Used to store unit tests for common and platform-specific source sets accordingly.

Running KMM Application on Android & iOS

In the list of run configurations, select your app, androidApp or iosApp and then click Run.

Pros and Cons of Kotlin Multiplatform

Pros of KMM (+)

  • Native performance – no additional runtime in your app bundle
  • No legacy code – you can start integrating KMM anytime
  • No shared UI – pixel-perfect native views
  • It’s easy to just add iOS to your existing Android app
  • Shared logic allows developers to add new features and fix bugs on both operating systems at the same time
  • Easy to use – Almost all Android developers already use Kotlin, so there is very little additional knowledge requirement for them to start.

Cons of KMM (-)

  • Not many pure Kotlin libraries available in the shared common module
  • Still in alpha, not production-ready,  Many components are still in Alpha/Beta stage and potentially can be unstable or change in future

Kotlin Multiplatform brings that to other platforms to help us create scalable and maintainable apps using a single codebase. Although the code-sharing is slightly less than that with other cross-platform solutions as UI cannot be shared, that gives us the advantage of creating a user experience that is in line with the platform’s guidelines and best practices. It also helps app developers to reduce duplication of business logic, and keep multiple mobile platforms in sync, thus helping product developers to improve time to market, and adopt new features.

Sunday, May 15, 2022

Bottom Navigation Bar in Android


We all have come across apps that have a Bottom Navigation Bar. Some popular examples include Instagram, WhatsApp, etcIn this article, let’s learn how to implement such a functional Bottom Navigation Bar in the Android app. Below is the preview of a sample Bottom Navigation Bar:

BottomNavigationBar

Why do we need a Bottom Navigation Bar?

  • It allows the user to switch to different activities/fragments easily.
  • It makes the user aware of the different screens available in the app.
  • The user is able to check which screen are they on at the moment.

The following is an anatomy diagram for the Bottom Navigation Bar:

BottonNavigationView

Steps for Creating Bottom Navigation Bar

Step 1: Create a new Android Studio project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio

Step 2: Adding the dependency to the build.gradle(:app) file

We will be using Android’s Material Design Library so we need to import it in the build.gradle(:app) fileHere’s the dependency we need to add:

implementation ‘com.google.android.material:material:1.2.0’

Step 3: Working with activity_main.xml file

For this example, create a basic app with a FrameLayout and a Bottom Navigation Bar. The  FrameLayout will contain Fragments which will change as the user click on the items in the Bottom Navigation Bar. This is how the activity_main.xml looks like:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <FrameLayout
        android:id="@+id/flFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNavigationView"
        android:layout_width="match_parent"
        android:layout_height="75dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/bottom_nav_menu"/>
     
</androidx.constraintlayout.widget.ConstraintLayout>

Step 4: Creating a menu for the Bottom Navigation Bar

The Navigation Bar needs to have some items which will create using Menu. To create a Menu, first, create a Menu Directory by clicking on the app -> res(right-click) -> New -> Android Resource Directory and select Menu in the Resource Type. 

Menu Directory

To create a Menu Resource File , click on the app -> res -> menu(right-click) -> New -> Menu Resource File and name it bottom_nav_menu

menu resource file

Now the user can create as many items as he wants in the bottom_nav_menu.xml file. The user also needs to create an icon for each of these items. To create an icon, click on the app -> res -> drawable(right-click) -> New -> Image Asset.

image asset

In the window that opens, the user can name the icon whatever he wants but it should not comprise any uppercase letter. The user can select the icon he wants by searching it and when the user is done, click Next-> Finish. 

Now add these items in the bottom_nav_menu.xml. This is how the bottom_nav_menu.xml file looks like after adding the items:

<?xml version="1.0" encoding="utf-8"?>
    <item
        android:id="@+id/person"
        android:title="Person"
        android:icon="@drawable/ic_person_foreground"/>
    <item
        android:id="@+id/home"
        android:title="Home"
        android:icon="@drawable/ic_home_foreground"/>
    <item
        android:id="@+id/settings"
        android:title="Settings"
        android:icon="@drawable/ic_settings_foreground"/>
</menu>

Step 5: Changing the Action Bar style

Since we are using Google’s Material Design Library, we need to change the action bar’s style to use the same library otherwise the Bottom Navigation Bar will be black and its items will be invisible. To change it, navigate to styles.xml by clicking on the app -> res -> values -> styles.xml and change the style opening tag as: 

 <style name=”AppTheme” parent=”Theme.MaterialComponents.Light.DarkActionBar”>

This is how the styles.xml file looks like: 

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
 
</resources>

Step 6: Creating Fragments to display 

Now that we have our Bottom Navigation Bar, we would want it to be functional by taking us to a different fragment/activity when an item is clicked. In this example, create a fragment for each item and navigate to them whenever a corresponding item is clicked. Since we created three items in the Bottom Navigation Bar, we will be creating three Fragments. To create a Fragment, click on the app(right-click) -> New -> Fragment -> Fragment (Blank). Name the fragment as FirstFragment and the corresponding XML file as fragment_first. To keep things simple, all three of the fragments will just contain a TextView. However, we can tweak this as we want it to be in the app. This is how the fragment_first.xml looks like after adding a TextView:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <TextView
        android:id="@+id/firstFragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Geeks for Geeks"
        android:textColor="#43a047"
        android:textSize="40sp"
        android:textStyle="italic|bold"
        app:layout_constraintBottom_toBottomOf="parent"
        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>

Next, code the FirstFragment to display the fragment_first.xml. For this, delete all the previously written code in FirstFragment and replace it with the below code. The below code just takes the layout we created for our fragment and inflates it. 

Note: If we want our fragment to have any logic or perform any task, we will add that code in our FirstFragment.

import androidx.fragment.app.Fragment
 
class FirstFragment:Fragment(R.layout.fragment_first) {
}

Similarly, create two more fragments for the remaining two items. Below are the fragment_second.xml, SecondFragment, fragment_third.xml, and ThirdFragment files respectively. 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <TextView
        android:id="@+id/secondFragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Data Structures"
        android:textColor="#43a047"
        android:textSize="40sp"
        android:textStyle="italic|bold"
        app:layout_constraintBottom_toBottomOf="parent"
        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>

Step 7: Working with the MainActivity file 

Now we have everything that we need and lastly, we just need to code the MainActivity to connect everything to the application. Here, first, create a function called setCurrentFragment() that takes a Fragment as an argument and sets it in our FrameLayout of activity_main.xml file. Add a click listener to the items of the Bottom Navigation Bar so that we display the corresponding Fragment when an item is clicked. After adding all these codes, the MainActivity looks like this:


import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.activity_main.*
 
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 
        val firstFragment=FirstFragment()
        val secondFragment=SecondFragment()
        val thirdFragment=ThirdFragment()
 
        setCurrentFragment(firstFragment)
 
        bottomNavigationView.setOnNavigationItemSelectedListener {
            when(it.itemId){
                R.id.home->setCurrentFragment(firstFragment)
                R.id.person->setCurrentFragment(secondFragment)
                R.id.settings->setCurrentFragment(thirdFragment)
 
            }
            true
        }
 
    }
 
    private fun setCurrentFragment(fragment:Fragment)=
        supportFragmentManager.beginTransaction().apply {
            replace(R.id.flFragment,fragment)
            commit()
        }
     
}

Output:

Video Player
00:00
00:21