Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions app/src/main/java/com/nikhilpanju/fabfilter/main/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.recyclerview.widget.LinearLayoutManager
Expand All @@ -29,17 +28,20 @@ class MainActivity : AppCompatActivity() {

private val recyclerView: RecyclerView by bindView(R.id.recycler_view)
private val appbar: AppBarLayout by bindView(R.id.appbar)
private val toolbar: View by bindView(R.id.appbar_container)
private val toolbarTitle: View by bindView(R.id.toolbar_title)
private val placeHolderToolbar: View by bindView(R.id.place_holder_toolbar)
private val drawerIcon: View by bindView(R.id.drawer_icon)

// layout/nav_drawer views
private val drawerLayout: DrawerLayout by bindView(R.id.drawer_layout)
private val animationSpeedSeekbar: CrystalSeekbar by bindView(R.id.animation_speed_seekbar)

private val animationSpeedText: TextView by bindView(R.id.animation_speed_text)
private val githubCodeLink: TextView by bindView(R.id.github_code_link)
private val githubMeLink: TextView by bindView(R.id.github_me_link)


private lateinit var mainListAdapter: MainListAdapter
private lateinit var onToolbarOffsetChangedListener: OnToolbarOffsetChangedListener

/**
* Used by FiltersLayout since we don't want to expose mainListAdapter (why?)
Expand All @@ -56,8 +58,13 @@ class MainActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// Appbar behavior init
(appbar.layoutParams as CoordinatorLayout.LayoutParams).behavior = ToolbarBehavior()
onToolbarOffsetChangedListener = OnToolbarOffsetChangedListener(
toolbar,
toolbarTitle,
drawerIcon,
placeHolderToolbar
)
appbar.addOnOffsetChangedListener(onToolbarOffsetChangedListener)

// RecyclerView Init
mainListAdapter = MainListAdapter(this)
Expand Down Expand Up @@ -86,6 +93,13 @@ class MainActivity : AppCompatActivity() {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(resId))))
}

override fun onDestroy() {
if (::onToolbarOffsetChangedListener.isInitialized) {
appbar.removeOnOffsetChangedListener(onToolbarOffsetChangedListener)
}
super.onDestroy()
}

/**
* Called from FiltersLayout to get adapter scale down animator
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.nikhilpanju.fabfilter.main

import android.view.View
import com.google.android.material.appbar.AppBarLayout
import kotlin.math.roundToInt

class OnToolbarOffsetChangedListener(
private val toolbar: View,
private val toolbarTitle: View,
private val drawerIcon: View,
/**
* [placeHolderToolbar] is a dummy invisible view to make sure that whole toolbar will not
* be hidden in scroll up
*/
private val placeHolderToolbar: View
) : AppBarLayout.OnOffsetChangedListener {
companion object {
private const val SCALE = 0.6F
}

private var toolbarCollapsedHeight: Int = -1
private var toolbarOriginalHeight: Int = -1

private var initialized: Boolean = false

init {
/**
* Post a function that set calculated collapsed size on [placeHolderToolbar]
*/
placeHolderToolbar.post {
initToolbarSize()

placeHolderToolbar.layoutParams.height = toolbarCollapsedHeight
placeHolderToolbar.requestLayout()
}

}

override fun onOffsetChanged(appBarLayout: AppBarLayout?, verticalOffset: Int) {
if (appBarLayout == null || appBarLayout.totalScrollRange <= 0) {
// views are not initialized yet
return
}

/**
* Calculate Toolbar collapse offset from 1 (Expanded) to 0 (fully collapsed)
*/
updateToolbarView(
(appBarLayout.totalScrollRange + verticalOffset).toFloat()
/ appBarLayout.totalScrollRange
)
}

/**
* Tales [offset] and calculates related toolbar height and drawer icon translation
* and toolbarTitle scale
*
* @param [offset] Toolbar collapse offset from 1 (Expanded) to 0 (fully collapsed)
*/
private fun updateToolbarView(
offset: Float
) {
initToolbarSize()
val newHeight = toolbarCollapsedHeight + (offset * (toolbarOriginalHeight - toolbarCollapsedHeight)).roundToInt()
if (newHeight != toolbar.layoutParams.height) {
toolbar.layoutParams.height = newHeight
toolbar.requestLayout()
}

// Hamburger menu transition
drawerIcon.translationY = -((1 - offset) * toolbarOriginalHeight)

/**
* It will map [0, 1] range to [0.6, 1] range
* Title scale should not be less than 0.6
*/
val ratio = SCALE + (offset * (1 - SCALE))

// Title scale
toolbarTitle.scaleX = ratio
toolbarTitle.scaleY = toolbarTitle.scaleX
}

/**
* Set the required view variables. Only will be accessed once because of the [initialized] variable.
*/
private fun initToolbarSize() {
if (initialized) return
initialized = true

toolbarOriginalHeight = toolbar.layoutParams.height
toolbarCollapsedHeight = (toolbarOriginalHeight * SCALE).roundToInt()
}
}
101 changes: 0 additions & 101 deletions app/src/main/java/com/nikhilpanju/fabfilter/main/ToolbarBehavior.kt

This file was deleted.

35 changes: 2 additions & 33 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
Expand All @@ -12,37 +11,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="0dp"
android:theme="@style/AppTheme.AppBarOverlay"
app:elevation="0dp">

<FrameLayout
android:id="@+id/appbar_container"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize">

<ImageView
android:id="@+id/drawer_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:padding="16dp"
android:tint="@color/toolbar_title_color"
app:srcCompat="@drawable/ic_drawer_icon" />

<View
android:id="@+id/toolbar_title"
android:layout_width="140dp"
android:layout_height="14dp"
android:layout_gravity="center"
android:background="@drawable/ic_pill"
android:backgroundTint="@color/toolbar_title_color" />
</FrameLayout>
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/collapsing_toolbar" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
Expand Down
70 changes: 70 additions & 0 deletions app/src/main/res/layout/collapsing_toolbar.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.appbar.AppBarLayout 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/appbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="@style/AppTheme.AppBarOverlay"
tools:showIn="@layout/activity_main">

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

<!-- First child of collapsing toolbar will be hidden in collapse state,
so we put a dummy useless view here-->
<View
android:id="@+id/useless"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<!--
Heights of this view will be between
[attr/actionBarSize] in expanded mode
and
[OnToolbarOffsetChangedListener.SCALE * ?attr/actionBarSize] in collapsed mode
-->
<FrameLayout
android:id="@+id/appbar_container"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom">

<ImageView
android:id="@+id/drawer_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:tint="@color/toolbar_title_color"
app:srcCompat="@drawable/ic_drawer_icon" />

<View
android:id="@+id/toolbar_title"
android:layout_width="140dp"
android:layout_height="14dp"
android:layout_gravity="center"
android:background="@drawable/ic_pill"
android:backgroundTint="@color/toolbar_title_color" />
</FrameLayout>


<!--
This is a useless toolbar to just make sure minimum size of Appbar
will not be less than collapsed size.
Heights of this view will change to [OnToolbarOffsetChangedListener.SCALE * ?attr/actionBarSize]
in first run
-->
<androidx.appcompat.widget.Toolbar
android:id="@+id/place_holder_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:visibility="invisible"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>