Android Collapsing Toolbar Kotlin

With the new Design support library for Android, it has become easier for us to create some great animations with minimal effort , CollapsingToolbarLayout is the newly introduced in Lollipop , using which you can create awesome scrolling effects . With the new Design support library for Android, it has become easier for us to create some great animations with minimal effort .


Build Gradle


Add the following lines to the dependencies section in your project's build.grade file and sync .
It include design support library , cardview library and palette library .

file : build.gradle
dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.1'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation "androidx.palette:palette:1.0.0"
}

XML Layout


Create  XML layout file in res/layout and name it activity_main.xml

file : activity_main.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout 
    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="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <androidx.appcompat.widget.AppCompatImageView
                android:id="@+id/profile_id"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/pic1"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax" />

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin" />

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ffe5e5e5"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <!-- Scrollable content -->
        <include layout="@layout/content" />

    </androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Lets Understand the XML Tags in the above xml layout .


1. CoordinatorLayout
A powerful FrameLayout that specifies behavior for child views for various interactions. Allows floating views to be anchored in layout.

2. AppBarLayout 
Is essentially a LinearLayout (vertical). It helps respond to its children’s scroll events (scroll gestures). Responsible for implementing many features of material design’s app bar. Depends heavily on being used as a direct child within CoordinatorLayout.

3. CollapsingToolbarLayout 
Wrapper for Toolbar that makes the header image collapse into the Toolbar adjusting its title size.
What’s left is the ImageView which holds our actual header’s image and Toolbar which we’re familiar with.

4. NestedScrollView
It’s an special scroll view for the smooth scrolling effect, inside this place the desired content . Here in this example will add several Cards as its children.

Straight from the developer’s blog:

Flags include :
  1. scroll: this flag should be set for all views that want to scroll off the screen - for views that do not use this flag, they’ll remain pinned to the top of the screen.
  2. enterAlways: this flag ensures that any downward scroll will cause this view to become visible, enabling the ‘quick return’ pattern .
  3. enterAlwaysCollapsed: When your view has declared a minHeight and you use this flag, your View will only enter at its minimum height (i.e., ‘collapsed’), only re-expanding to its full height when the scrolling view has reached it’s top.
  4. exitUntilCollapsed: this flag causes the view to scroll off until it is ‘collapsed’ (its minHeight) before exiting .
Note : all views using the scroll flag must be declared before views that do not use the flag.This ensures that all views exit from the top, leaving the fixed elements behind.

For CollapsingToolbarLayout XML Tag set the layout_scrollFlags property with
 scroll|exitUntilCollapsed 

Collapse Mode
  • Parallax scrolling with the ImageView is achieved by simply setting its layout_collapseMode to parallax.
  • The Toolbar must use pin as its collapseMode because we want the Toolbar to persist and remain on top as the user scrolls down.
The XML Layout Inflate the view as below.



    MainActivity


    Now Inside the Activity we will see how to change the TextAppearance and Coloring of Toolbar Dynamically when Collapsing Toolbar  expands and collapse .

    1. Dynamic TextAppearance :

    A title which is larger when the layout is fully visible but collapses and becomes smaller as the layout is scrolled off screen. The title appearance can be tweaked via the collapsedTextAppearance and expandedTextAppearance attributes .

    Add the following style code inside the style.xml .
    <resources>
        <!-- Base application theme. -->
        <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
            <!-- Customize your theme here. -->
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
            <item name="colorAccent">@color/colorAccent</item>
            <item name="windowActionBar">false</item>
            <item name="windowNoTitle">true</item>
        </style>
        
        <style name="expandedappbar" parent="@android:style/TextAppearance.Medium">
            <item name="android:textSize">36sp</item>
            <item name="android:textColor">@color/white</item>
            <item name="android:textStyle">bold</item>
        </style>
    
        <style name="collapsedappbar" parent="@android:style/TextAppearance.Medium">
            <item name="android:textSize">18sp</item>
            <item name="android:textColor">@color/white</item>
        </style>
    
    </resources>
    

     collapsingToolbarLayout.setCollapsedTitleTextAppearance(R.style.collapsedappbar);
     collapsingToolbarLayout.setExpandedTitleTextAppearance(R.style.expandedappbar);


    2. Dynamic Toolbar Coloring :  

    We’ll pass our image view’s bitmap to the Palette API, which will generate colors based on the image in an PaletteAsyncListener. Upon completion, we can fetch the color we want and set it to our CollapsingToolbarLayout,  which in turn will color our Toolbar when we scroll up.

    val bitmap = profile_id.background.toBitmap()
    
            Palette.from(bitmap).generate { palette ->
                collapsing_toolbar.setContentScrimColor(palette!!.getMutedColor(R.attr.colorPrimary))
                collapsing_toolbar.setStatusBarScrimColor(palette.getMutedColor(R.attr.colorPrimaryDark))
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    window.statusBarColor = palette.getMutedColor(R.attr.colorPrimaryDark)
                }
            }
    The Complete MainActivity Source code

    file : MainActivity.java
    package com.tutorialsbuzz.collapsetoolbarexample
    
    import android.os.Build
    import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity
    import androidx.core.graphics.drawable.toBitmap
    import androidx.palette.graphics.Palette
    import kotlinx.android.synthetic.main.activity_main.*
    
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            setSupportActionBar(toolbar)
            val actionBar = supportActionBar
            actionBar?.setDisplayHomeAsUpEnabled(true)
    
            collapsing_toolbar.setTitle(getResources().getString(R.string.user_name));
            dynamicToolbarColor()
            toolbarTextAppernce()
        }
    
        private fun dynamicToolbarColor() {
    
            val bitmap = profile_id.background.toBitmap()
    
            Palette.from(bitmap).generate { palette ->
                collapsing_toolbar.setContentScrimColor(palette!!.getMutedColor(R.attr.colorPrimary))
                collapsing_toolbar.setStatusBarScrimColor(palette.getMutedColor(R.attr.colorPrimaryDark))
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    window.statusBarColor = palette.getMutedColor(R.attr.colorPrimaryDark)
                }
            }
        }
    
    
        private fun toolbarTextAppernce() {
            collapsing_toolbar.setCollapsedTitleTextAppearance(R.style.collapsedappbar)
            collapsing_toolbar.setExpandedTitleTextAppearance(R.style.expandedappbar)
        }
    }
    Scrolling Effect with Dynamic TextAppearance and Toolbar Coloring According to Image


    Read More »

    Android Kotlin Coroutines For Beginners

    Kotlin coroutines enable you to write clean, simplified asynchronous code that keeps your app responsive while managing long-running tasks such as network calls or disk operations.

    Coroutines, a very efficient and complete framework to manage concurrency in a more effective and simple way.  It simplify your code by reducing the need for callbacks .

    1. Features


    Coroutines is recommended solution for asynchronous programming on Android .
    • Lightweight : You can run many coroutines on a single thread , Coroutines are not thread instead they are like jobs inside thread 
    • Fewer memory leaks : Use structured concurrency to run operations within a scope.
    • Built-in cancellation support : When using custom co-coroutine scope you can stop or cancel the execution at any point of time and cancellation is propagated automatically through the running coroutine hierarchy.
    • Jetpack integration : Many Jetpack libraries provide full coroutines support , which will simply your code with less boiler plate code . Use Kotlin coroutines with Architecture components For ViewModelScope , LifecycleScope , liveData When using room peristense functions and working with networking like retrofit .

    2. Coroutine Suspend and Resume


    To handle long running tasks , we will park tasks in worker thread by suspending from current main thread and then using callback will resumes to caller which is main thread , Coroutines build upon regular functions by adding two operations to handle long-running tasks . 

    By just prefixing suspend keyword to a fuction , when that function is called it pauses the execution of the current coroutine, saving all local variables. and resumes from the place where it was suspended.
    coroutineScope.launch(Dispatchers.Main) {
    	Log.d(TAG, "Inside Thread ${Thread.currentThread().name}")
    	val responseData = fetchData()
    	displayData(responseData);
    }

    In this example, fetchData() called on the main thread but it suspends the coroutine before it starts the network request. When the network request completes , fetchData() resumes the suspended coroutine instead of using a callback to notify the main thread.


    3. Start a coroutine


    You can start coroutines in two ways :

    a. launch : starts a new coroutine and doesn't return the result to the caller , It is like fire and forgot .
     
    b. async : starts a new coroutine and allows you to return a result with a suspend function called await, It is like launch and return result  .

    4. Dispatcher


    Dispatcher is used to Decide which thread the corotuine should execute .

    To specify where the coroutines should run, Kotlin provides three dispatchers that you can use:
    • Dispatchers.Main : Execute Coroutine on Main Android Thread , This is used for performing quick UI Update .
    • Dispatchers.IO : Execute Coroutine outside outside of the main thread , This is mainly used for performing network and disk operations .
    • Dispatchers.Default : Execute Coroutine outside outside of the main thread , This is used to perform CPU-intensive work for ex image processing , performing sort / search on a list . 

    5. CoroutineScope


    A CoroutineScope keeps track of any coroutine it creates using launch or async . The on going co-coroutine execution can be cancelled using by calling  scope.cancel() at any point of time .

    If you need to create your own CoroutineScope to control the lifecycle of coroutines in a particular
     
    Creating Custom CoroutineScope gives the control of the lifecycle of co-coroutine in your application , 

    Example In activity onCreate create custom co-coroutine and in ondestroy cancel the co-coroutine .

    6. CoroutineContext


    CoroutineContext has set of elements that defines the behavior of co-coroutine.
    • Job  : Each coroutine that you create with launch or async returns a Job instance that uniquely identifies the coroutine and manages its lifecycle
    • Coroutine dispatcher :  Above mentioned .
    • Coroutine Exception : Handles uncaught exceptions.

    Lets see how to create corotuine scope by pass passing courtine context .
    //1. Job
    private var job = Job()
    
    //2. coroutine Exception
    val handler = CoroutineExceptionHandler { _, exception ->
    	Log.d(TAG, "$exception handled !")
    }
    
    //3. coroutine context
    val coroutineContext: CoroutineContext 
           get() = Dispatchers.Main + job + handler
    
    //4. coroutine scope
    private val coroutineScope = CoroutineScope(coroutineContext)

    7. Coroutine parallel and serial execute


    a) Async and Await :  If multiple tasks have to happen in parallel and final result depends on completion of all of them, then use async. You should use async/await when you want to execute multiple tasks concurrently .

    val resultOne = coroutineScope.async(Dispatchers.IO) { funtion1()}
    val resultTwo= coroutineScope.async(Dispatchers.IO) {function2() }
    
    val result=resultOne.await()+resultTwo.await()

    b) withContext : For returning the result of a single task, use withContext.

    val result= withContext(Dispatchers.IO) { function1() }

    Both withContext and async can be used to get the result which is not possible with the launch.

    Lets see sample example .

    1. XML Layout


    file : activity_main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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="match_parent"
        android:layout_centerHorizontal="true"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <Button
            android:id="@+id/fetchdataBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Fetch Data" />
    
        <TextView
            android:id="@+id/resultText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

    1. Activity


    • In this example we will make api request "https://api.github.com/users/tutorialsbuzz" and set the response to TextView .
    • In MainActivity On Click of Button launch a co-coroutine by mentioning Main dispatcher and  call fetchData() .
    • Now inside fetchData function launch another coroutine using async function by mentioning I/O dispatcher which returns Deferred<String?> .
    • The from the returned Deferred<String?.> call await() and pass it to displayData() .

    file : MainActivity.kt 
    package com.tutorialsbuzz.coroutinesdemo
    
    class MainActivity : AppCompatActivity() {
    
        private val TAG = MainActivity::class.simpleName.toString()
        private var job = Job()
    
        //coroutine Exception
        val handler = CoroutineExceptionHandler { _, exception ->
            Log.d(TAG, "$exception handled !")
        }
    
        //coroutine context
        val coroutineContext: CoroutineContext get() = Dispatchers.Main + job + handler
    
        //coroutine scope
        private val coroutineScope = CoroutineScope(coroutineContext)
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            fetchdataBtn.setOnClickListener {
    
                coroutineScope.launch(Dispatchers.Main) {
                    Log.d(TAG, "Inside Thread ${Thread.currentThread().name}")
    
                    //async returning Deferred < dataType >
                    val responseData = fetchData()
                    displayData(responseData.await());
                }
            }
        }
    
       
        fun fetchData(): Deferred<String?> {
            val loginUrl = "https://api.github.com/users/tutorialsbuzz"
    
            return coroutineScope.async(Dispatchers.IO) {
                val url = URL(loginUrl)
                val urlConnection =
                    url.openConnection() as HttpURLConnection
                val inputAsString =
                    urlConnection.inputStream?.bufferedReader().use { it?.readText() }
                inputAsString
            }
    
        }
    
        fun displayData(data: String?) {
            resultText.setText(data)
        }
    	
    }






    In the above example lets see another way of writing fetchData and calling it from main coroutine dispatcher 

    1. async returning dataType

    coroutineScope.launch(Dispatchers.Main) {
     val responseData = fetchData()
     displayData(responseData);
    }
    
    suspend fun fetchData(): String? {
    	val loginUrl = "https://api.github.com/users/tutorialsbuzz"
    
    	val response = coroutineScope.async(Dispatchers.IO) {
    		Log.d(TAG, "Inside Thread ${Thread.currentThread().name}")
    
    		val url = URL(loginUrl)
    		val urlConnection =
    			url.openConnection() as HttpURLConnection
    		val inputAsString =
    			urlConnection.inputStream?.bufferedReader().use { it?.readText() }
    		inputAsString
    	}.await()
    	return response
    }

    2. withContext returning dataType

    coroutineScope.launch(Dispatchers.Main) {
     val responseData = fetchData()
     displayData(responseData);
    }
    
    suspend fun fetchData(): String? {
    	val loginUrl = "https://api.github.com/users/tutorialsbuzz"
    
    	return withContext(Dispatchers.IO) {
    		val url = URL(loginUrl)
    		val urlConnection =
    			url.openConnection() as HttpURLConnection
    		val inputAsString =
    			urlConnection.inputStream?.bufferedReader().use { it?.readText() }
    		inputAsString
    	}
    }


    Read More »

    Reliance JioBrowser 2.0 New Avatar Named JioPages Major Update

    Year Ago Reliance Jio Launched Its first browser , after that there were many updates for it , recently jiobrowser made officially announcement in its twitter handle about major changes .


    JioPages’, Made-in-India mobile browser supports 8 Indian languages

    Jio Pages features :

    The highlights of the JioPages include a Private Browsing mode with a secure PIN, ability to bookmark content while browsing in Private Mode as well as an advanced download manager for files that you may download using the app. There are also Quick Links that allows users to quickly access their most visited websites, and this is completely customizable. The JioBrowser is optimized for web browser-based gaming and streaming of high-resolution videos as well.


    IPL Cricket Scorecard :



    8 Indian Region Language Support



    Personalized Feeds



    Dark Mode



    TopSites ShortCuts



    TopSites Regional Shortcut .



    Adblocker




    Download The APK From Below PlayStore Link :

    https://play.google.com/store/apps/details?id=com.jio.web


    Read More »

    Android RecyclerView OnScroll Show Hide Toolbar BottomNavigationView

    In the previous tutorial we have seen how to show hide toolbar on scrolling reyclerview , In this tutorial we will see how to show hide both toolbar and bottomnavigationview on scrolling reyclerview . 
    Here we will use CoordinatorLayout as the parent layout and place Toolbar , RecyclerView and BottomNavigationView as child view. 
     



    CoordinatorLayout:


    CoordinatorLayout is a super-powered FrameLayout , CoordinatorLayout is intended for two primary use cases .
    • As a top-level application decor layout .
    • As a container for a specific interaction with one or more child views .


    XML Layout


    file : activity_main.xml
    <androidx.coordinatorlayout.widget.CoordinatorLayout 
        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="match_parent">
    
        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_scrollFlags="scroll|enterAlways" />
    
        </com.google.android.material.appbar.AppBarLayout>
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
        
        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/nav_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:background="?android:attr/windowBackground"
            app:layout_behavior="com.tutorialsbuzz.recyclerviewbottomnavshowhide.BottomNavigationBehavior"
            app:menu="@menu/bottom_nav_menu" />
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>

    Specifying Scroll Behaviors


    1. For Toolbar widget set the layout scroll flag  
           app:layout_scrollFlags="scroll|enterAlways" .

    2. For RecyclerView Set the layout behavior 
       app:layout_behavior="@string/appbar_scrolling_view_behavior" .

    3. For BottomNavigationView Set the custom layout behavior 
            app:layout_behavior="pkg.BottomNavigationBehavior" .

    Custom Layout Behaviors For BottomNavigationBehavior


    file : BottomNavigationBehavior.kt
    package com.tutorialsbuzz.recyclerviewbottomnavshowhide
    
    import android.content.Context
    import android.util.AttributeSet
    import android.view.View
    import androidx.coordinatorlayout.widget.CoordinatorLayout
    import androidx.core.view.ViewCompat
    import kotlin.math.max
    import kotlin.math.min
    
    class BottomNavigationBehavior<V : View>(context: Context, attrs: AttributeSet) :
        CoordinatorLayout.Behavior<V>(context, attrs) {
    
        override fun onStartNestedScroll(
            coordinatorLayout: CoordinatorLayout,
            child: V,
            directTargetChild: View,
            target: View,
            axes: Int,
            type: Int
        ): Boolean {
            return axes == ViewCompat.SCROLL_AXIS_VERTICAL
        }
    
        override fun onNestedPreScroll(
            coordinatorLayout: CoordinatorLayout,
            child: V,
            target: View,
            dx: Int,
            dy: Int,
            consumed: IntArray,
            type: Int
        ) {
            super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
            child.translationY = max(0f, min(child.height.toFloat(), child.translationY + dy))
        }
    }


    Setting Up RecyclerView


    1. XML Layout for RecyclerView Row Item 
     
    file : row_item.xml
    <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/txt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="8dp"
        android:paddingTop="16dp"
        android:paddingRight="8dp"
        android:paddingBottom="16dp"
        android:textSize="20sp" />

    2. Data class 

    file : Model.kt
    package com.tutorialsbuzz.recyclerviewbottomnavshowhide
    
    data class Model(val name: String) {}

    3. ViewHolder Adapter for RecyclerView 

    file : CustomAdapter.kt
    package com.tutorialsbuzz.recyclerviewbottomnavshowhide
    
    import android.content.Context
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import androidx.recyclerview.widget.RecyclerView
    import kotlinx.android.synthetic.main.row_item.view.*
    
    class CustomAdapter(val modelList: List<Model>, val context: Context) :
        RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    
        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            (holder as ViewHolder).bind(modelList.get(position));
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            val layoutInflater = LayoutInflater.from(parent.context)
            return ViewHolder(layoutInflater.inflate(R.layout.row_item, parent, false))
        }
    
        override fun getItemCount(): Int {
            return modelList.size
        }
    
        inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            fun bind(model: Model): Unit {
                itemView.txt.text = model.name
            }
        }
    
    }

    Style


    Add the below style property for the Activity theme in which your implementing scroll behavior
     <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <item name="android:windowFullscreen">true</item>
    
    
    And call setSupportActionBar(toolbar) inside activity onCreate by passing toolbar reference.

    Activity


    In MainActivity we will initialize and set adapter to reyclerview . 

    file : MainActivity.kt  
    package com.tutorialsbuzz.recyclerviewbottomnavshowhide
    
    import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity
    import androidx.recyclerview.widget.LinearLayoutManager
    import androidx.recyclerview.widget.RecyclerView
    import kotlinx.android.synthetic.main.activity_main.*
    import java.util.*
    
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            setSupportActionBar(toolbar)
    
            recyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
            recyclerView.addItemDecoration(SimpleDividerItemDecoration(this))
    
            val adapter = CustomAdapter(getCountries(), this)
            recyclerView.adapter = adapter;
    
        }
    
        private fun getCountries(): MutableList<Model> {
            val mdList = mutableListOf<Model>()
            for (countryISO in Locale.getISOCountries()) {
                val locale = Locale("", countryISO)
                if (!locale.displayCountry.isEmpty()) {
                    mdList.add(Model(locale.displayCountry + "  " + counrtyFlag(countryISO)) )
                }
            }
            return mdList
        }
    
        private fun counrtyFlag(countryCode: String): String {
            val flagOffset = 0x1F1E6
            val asciiOffset = 0x41
            val firstChar = Character.codePointAt(countryCode, 0) - asciiOffset + flagOffset
            val secondChar = Character.codePointAt(countryCode, 1) - asciiOffset + flagOffset
            val flag =
                (String(Character.toChars(firstChar)) + String(Character.toChars(secondChar)))
    
            return flag
        }
    
    }

    Read More »

    Android RecyclerView OnScroll Show hide Toolbar

    In the previous series of tutorial we have seen implementation of recyclerview , In this tutorial we will how to show hide toolbar on scrolling reyclerview , i.e on scroll-up hide toolbar 
    and scroll down show toolbar .

    Here we will use CoordinatorLayout as the parent layout and place toolbar and recyclerview as child view.  and set the scroll flag and behavior .




    CoordinatorLayout


    CoordinatorLayout is a super-powered FrameLayout , CoordinatorLayout is intended for two primary use cases.
    • As a top-level application decor layout .
    • As a container for a specific interaction with one or more child views .

    XML Layout



    1.  Add CoordinatorLayout as parent or root layout 
    2.  Add Toolbar and RecyclerView as child view to CoordinatorLayout
    Specifying Scroll Behaviors  

    1. For Toolbar widget set the layout scroll flag  
           app:layout_scrollFlags="scroll|enterAlways"

    2. For RecyclerView Set the layout behavior 
        app:layout_behavior="@string/appbar_scrolling_view_behavior"

    file : activity_main.xml
    <androidx.coordinatorlayout.widget.CoordinatorLayout 
        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="match_parent">
    
        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_scrollFlags="scroll|enterAlways" />
    
        </com.google.android.material.appbar.AppBarLayout>
        
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingTop="6dp"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
        
    </androidx.coordinatorlayout.widget.CoordinatorLayout>


    Setting Up RecyclerView


    1 XML Layout for RecyclerView Row Item 

    file : row_item.xml
    <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/txt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="8dp"
        android:paddingTop="16dp"
        android:paddingRight="8dp"
        android:paddingBottom="16dp"
        android:textSize="20sp" />

    2. Data class

    file : Model.kt
    package com.tutorialsbuzz.recyclerviewtoolbarshowhide
    
    data class Model(val name: String) {}

    3 ViewHolder Adapter for RecyclerView

    file : CustomAdapter.kt
    package com.tutorialsbuzz.recyclerviewtoolbarshowhide
    
    import android.content.Context
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import androidx.recyclerview.widget.RecyclerView
    import kotlinx.android.synthetic.main.row_item.view.*
    
    class CustomAdapter(val modelList: List<Model>, val context: Context) :
        RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    
        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            (holder as ViewHolder).bind(modelList.get(position));
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            val layoutInflater = LayoutInflater.from(parent.context)
            return ViewHolder(layoutInflater.inflate(R.layout.row_item, parent, false))
        }
    
        override fun getItemCount(): Int {
            return modelList.size
        }
    
        inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            fun bind(model: Model): Unit {
                itemView.txt.text = model.name
            }
        }
    
    }

    Activity


    In MainActivity we will initialize and set adapter to reyclerview .

    file : MainActivity.kt
    package com.tutorialsbuzz.recyclerviewtoolbarshowhide
    
    import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity
    import androidx.recyclerview.widget.LinearLayoutManager
    import androidx.recyclerview.widget.RecyclerView
    import kotlinx.android.synthetic.main.activity_main.*
    import java.util.*
    
    class MainActivity : AppCompatActivity() {
        
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            setSupportActionBar(toolbar)
    
            recyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
            recyclerView.addItemDecoration(SimpleDividerItemDecoration(this))
    
            val adapter = CustomAdapter(getCountries(), this)
            recyclerView.adapter = adapter;
        }
    
        private fun getCountries(): MutableList<Model> {
            val mdList = mutableListOf<Model>()
            for (countryISO in Locale.getISOCountries()) {
                val locale = Locale("", countryISO)
                if (!locale.displayCountry.isEmpty()) {
                    mdList.add(Model(locale.displayCountry + "  " + counrtyFlag(countryISO)))
                }
            }
            return mdList
        }
    
        private fun counrtyFlag(countryCode: String): String {
            val flagOffset = 0x1F1E6
            val asciiOffset = 0x41
            val firstChar = Character.codePointAt(countryCode, 0) - asciiOffset + flagOffset
            val secondChar = Character.codePointAt(countryCode, 1) - asciiOffset + flagOffset
            val flag =
                (String(Character.toChars(firstChar)) + String(Character.toChars(secondChar)))
    
            return flag
        }
    
    }

    Read More »

    Android BottomNavigationView Kotlin

    Android BottomNavigationView Represents a standard bottom navigation bar for application. It is an implementation of  material design bottom navigation Bottom navigation bars make it easy for users to explore and switch between top-level views in a single tap.They should be used when an application has three to five top-level destinations .


    While Creating New Project In Android Studio  File > New Project . Select a Project Template "Bottom Navigation Activity


    1. MENU


    The BottomNavigationView bar contents can be populated by specifying a menu resource file. Each menu item title,icon and enabled state will be used for displaying bottom navigation bar items. Menu items can also be used for pragmatically selecting which destination is currently active.  
     
    file : bottom_nav_menu.xml
    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item
            android:id="@+id/navigation_home"
            android:icon="@drawable/ic_home_black_24dp"
            android:title="@string/title_home" />
    
        <item
            android:id="@+id/navigation_dashboard"
            android:icon="@drawable/ic_dashboard_black_24dp"
            android:title="@string/title_dashboard" />
    
        <item
            android:id="@+id/navigation_notifications"
            android:icon="@drawable/ic_notifications_black_24dp"
            android:title="@string/title_notifications" />
    
    </menu>


    2. Drawable


    Place Drawable inside res/drawable 

    3. XML Layout


    Main layout contains BottomNavigationView and fragment .

    1. The Above defined menu is set to BottomNavigationView .
    2. Fragment is set to NavHostFragment  and mapped to below defined navigation graph  .

    file : activity_main.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"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="?attr/actionBarSize">
    
        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/nav_view"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="0dp"
            android:layout_marginEnd="0dp"
            android:background="?android:attr/windowBackground"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:menu="@menu/bottom_nav_menu" />
    
        <fragment
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toTopOf="@id/nav_view"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navGraph="@navigation/mobile_navigation" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>

    XML Layout for each fragment .


           

    The below diagram is very explaintory how BottomNavigationView is mapped to menu with navigation graph .

    4. NavigationGraph

    •  NavHostFragment provides an area within your layout for self-contained navigation to occur .
    •  NavHostFragment is intended to be used as the content area within a layout resource .
    •  NavHostFragment has NavController  that defines valid navigation within Navigation host .
    file : res/navigation/mobile_navigation.xml
    <?xml version="1.0" encoding="utf-8"?>
    <navigation
        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/mobile_navigation"
        app:startDestination="@+id/navigation_home">
    
        <fragment
            android:id="@+id/navigation_home"
            android:name="com.tutorialsbuzz.bottomnavexample.ui.home.HomeFragment"
            android:label="@string/title_home"
            tools:layout="@layout/fragment_home" />
    
        <fragment
            android:id="@+id/navigation_dashboard"
            android:name="com.tutorialsbuzz.bottomnavexample.ui.dashboard.DashboardFragment"
            android:label="@string/title_dashboard"
            tools:layout="@layout/fragment_dashboard" />
    
        <fragment
            android:id="@+id/navigation_notifications"
            android:name="com.tutorialsbuzz.bottomnavexample.ui.notifications.NotificationsFragment"
            android:label="@string/title_notifications"
            tools:layout="@layout/fragment_notifications" />
            
    </navigation>

    5. Activity


    1. Get the reference of BottomNavigationView and call setupWithNavController by passing NavHostFragment instance .
    val navController = findNavController(R.id.nav_host_fragment)
    navView.setupWithNavController(navController)

    2. Update ActionBar title when there is navigation , just call setupActionBarWithNavController by passing navController and appBarConfiguration instance. 
    val appBarConfiguration = AppBarConfiguration(setOf(
    	R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications))
    setupActionBarWithNavController(navController, appBarConfiguration)

    MainActivity Full code

    file : MainActivity.kt
    package com.tutorialsbuzz.bottomnavexample
    
    import android.os.Bundle
    import com.google.android.material.bottomnavigation.BottomNavigationView
    import androidx.appcompat.app.AppCompatActivity
    import androidx.navigation.findNavController
    import androidx.navigation.ui.AppBarConfiguration
    import androidx.navigation.ui.setupActionBarWithNavController
    import androidx.navigation.ui.setupWithNavController
    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            val navView: BottomNavigationView = findViewById(R.id.nav_view)
    
            val navController = findNavController(R.id.nav_host_fragment)
            navView.setupWithNavController(navController)
    
            // Passing each menu ID as a set of Ids because each
            // menu should be considered as top level destinations.
            val appBarConfiguration = AppBarConfiguration(setOf(
                R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications))
            setupActionBarWithNavController(navController, appBarConfiguration)
        }
    }


    Read More »

    Android RecyclerView Collection




    Sample RecyclerView Example
    RecyclerView Item Click Ripple Effect
    RecyclerView Item
    Divider
    RecyclerView With CardView
    RecyclerView GridLayout
    RecyclerView StaggeredgridLayout
    RecyclerView Swipe to delete
    RecyclerView Swipe to delete With Undo
    RecyclerView Interactive Swipe Like Gmail
    Android RecyclerView Buttons Under Swipe
    RecyclerView MultiViewType
    RecyclerView Item Drag and Drop
    RecyclerView GridLayout Drag and Drop
    Filter RecyclerView Using SearchView In Java
    RecyclerView Filter Animation
    Android RecyclerView Filter Using Filterable

    More To Come...
    Read More »