Fix status bar colors for Huawei, Samsung, KitKat, Jelly Bean. Fix bottom sheet dragging. Add & fix MaterialDrawer fullscreen with custom container. Add more switches/options, bottomsheet items & recyclerview WIP. BottomBar custom view & config options. Removed all bugs, added one bug.

This commit is contained in:
kubasz 2019-08-16 22:26:34 +02:00
parent f2fef9ddbd
commit adb45d8e7e
42 changed files with 2081 additions and 427 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@
/build
/captures
.externalNativeBuild
/_hakerskie

View File

@ -0,0 +1,8 @@
<component name="ProjectDictionaryState">
<dictionary name="Kuba">
<words>
<w>navlib</w>
<w>samsung</w>
</words>
</dictionary>
</component>

View File

@ -8,7 +8,6 @@
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/MaterialDrawer" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/navlib" />
</set>

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../MaterialDrawer" vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -31,10 +31,11 @@ dependencies {
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "com.mikepenz:materialdrawer:6.1.2"
implementation "com.mikepenz:crossfader:1.6.0" // do not update
implementation "com.mikepenz:iconics-core:${iconics}" // do not update. >3.1.0 Breaks jelly bean
implementation "com.mikepenz:iconics-views:${iconics}" // do not update
implementation "com.mikepenz:community-material-typeface:3.5.95.1@aar"
implementation "com.mikepenz:community-material-typeface:3.5.95.1-kotlin@aar"
implementation 'androidx.core:core-ktx:1.0.1'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation "com.google.android.material:material:$material_version"

View File

@ -1,6 +1,6 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
# proguardFiles setting in init.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

View File

@ -2,13 +2,16 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pl.szczodrzynski.navigation">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme.Light">
android:theme="@style/AppTheme.Light"
android:windowSoftInputMode="adjustResize">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@ -1,21 +1,20 @@
package pl.szczodrzynski.navigation
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.widget.Switch
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.floatingactionbutton.FloatingActionButton
import android.widget.Toast
import androidx.core.widget.NestedScrollView
import com.google.android.material.bottomappbar.BottomAppBar
import android.view.WindowManager
import android.os.Build
import android.view.Gravity
import kotlinx.android.synthetic.main.sample_nav_view.*
import pl.szczodrzynski.navlib.SystemBarsUtil
import pl.szczodrzynski.navlib.SystemBarsUtil.Companion.COLOR_DO_NOT_CHANGE
import pl.szczodrzynski.navlib.SystemBarsUtil.Companion.COLOR_HALF_TRANSPARENT
import pl.szczodrzynski.navlib.SystemBarsUtil.Companion.COLOR_PRIMARY_DARK
import pl.szczodrzynski.navlib.getColorFromAttr
class MainActivity : AppCompatActivity() {
@ -23,8 +22,7 @@ class MainActivity : AppCompatActivity() {
var darkTheme: Boolean? = null
}
var showing = false
@SuppressLint("ApplySharedPref")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -36,19 +34,30 @@ class MainActivity : AppCompatActivity() {
setContentView(R.layout.sample_nav_view)
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or (when {
darkTheme == true -> 0
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
else -> 0
})
appFullscreen.isChecked = getSharedPreferences("prefs", Context.MODE_PRIVATE).getBoolean("appFullscreen", false)
statusBarDarker.isChecked = getSharedPreferences("prefs", Context.MODE_PRIVATE).getBoolean("statusBarDarker", false)
statusBarTranslucent.isChecked = getSharedPreferences("prefs", Context.MODE_PRIVATE).getBoolean("statusBarTranslucent", false)
navigationBarTransparent.isChecked = getSharedPreferences("prefs", Context.MODE_PRIVATE).getBoolean("navigationBarTransparent", true)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val w = window // in Activity's onCreate() for instance
w.setFlags(
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
)
}
statusBarColor.check(when (getSharedPreferences("prefs", Context.MODE_PRIVATE).getString("statusBarColor", "colorBackground")) {
"colorPrimaryDark" -> R.id.colorPrimaryDark
"colorPrimary" -> R.id.colorPrimary
"colorAccent" -> R.id.colorAccent
"colorBackground" -> R.id.colorBackground
else -> R.id.colorBackground
})
statusBarFallbackLight.check(when (getSharedPreferences("prefs", Context.MODE_PRIVATE).getString("statusBarFallbackLight", "lightHalfTransparent")) {
"lightHalfTransparent" -> R.id.lightHalfTransparent
"lightPrimaryDark" -> R.id.lightPrimaryDark
"lightDoNotChange" -> R.id.lightDoNotChange
else -> R.id.lightHalfTransparent
})
statusBarFallbackGradient.check(when (getSharedPreferences("prefs", Context.MODE_PRIVATE).getString("statusBarFallbackGradient", "gradientDoNotChange")) {
"gradientHalfTransparent" -> R.id.gradientHalfTransparent
"gradientPrimaryDark" -> R.id.gradientPrimaryDark
"gradientDoNotChange" -> R.id.gradientDoNotChange
else -> R.id.gradientDoNotChange
})
button.setOnClickListener {
// use commit instead of apply because of recreating the activity
@ -57,62 +66,136 @@ class MainActivity : AppCompatActivity() {
recreate()
}
/*val dim = findViewById<View>(R.id.view)
val nestedScrollView = findViewById<View>(R.id.nestedScrollView)
val bottomSheetBehavior = BottomSheetBehavior.from(nestedScrollView)
//navView.init(this)
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
// init the drawer before SystemBarsUtil
navView.addDrawer(activity = this)
val fab = findViewById<FloatingActionButton>(R.id.floatingActionButton)
fab.setOnClickListener {
if (bottomSheetBehavior.state == BottomSheetBehavior.STATE_HIDDEN) {
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
SystemBarsUtil(this).apply {
paddingByKeyboard = navView
appFullscreen = this@MainActivity.appFullscreen.isChecked
statusBarColor = when (this@MainActivity.statusBarColor.checkedRadioButtonId) {
R.id.colorPrimaryDark -> COLOR_PRIMARY_DARK
R.id.colorPrimary -> getColorFromAttr(this@MainActivity, R.attr.colorPrimary)
R.id.colorAccent -> getColorFromAttr(this@MainActivity, R.attr.colorAccent)
R.id.colorBackground -> getColorFromAttr(this@MainActivity, android.R.attr.colorBackground)
else -> 0xffff00ff.toInt()
}
else {
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
statusBarDarker = this@MainActivity.statusBarDarker.isChecked
statusBarFallbackLight = when (this@MainActivity.statusBarFallbackLight.checkedRadioButtonId) {
R.id.lightHalfTransparent -> COLOR_HALF_TRANSPARENT
R.id.lightPrimaryDark -> COLOR_PRIMARY_DARK
R.id.lightDoNotChange -> COLOR_DO_NOT_CHANGE
else -> 0xff00ffff.toInt()
}
statusBarFallbackGradient = when (this@MainActivity.statusBarFallbackGradient.checkedRadioButtonId) {
R.id.gradientHalfTransparent -> COLOR_HALF_TRANSPARENT
R.id.gradientPrimaryDark -> COLOR_PRIMARY_DARK
R.id.gradientDoNotChange -> COLOR_DO_NOT_CHANGE
else -> 0xffffff00.toInt()
}
statusBarTranslucent = this@MainActivity.statusBarTranslucent.isChecked
navigationBarTransparent = this@MainActivity.navigationBarTransparent.isChecked
navView.configSystemBarsUtil(this)
commit()
}
dim.setOnClickListener {
appFullscreen.setOnCheckedChangeListener { _, isChecked ->
getSharedPreferences("prefs", Context.MODE_PRIVATE).edit().putBoolean("appFullscreen", isChecked).commit()
recreate()
}
dim.setOnTouchListener { v, event ->
if (event.action == MotionEvent.ACTION_UP) {
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
}
true
statusBarDarker.setOnCheckedChangeListener { _, isChecked ->
getSharedPreferences("prefs", Context.MODE_PRIVATE).edit().putBoolean("statusBarDarker", isChecked).commit()
recreate()
}
statusBarTranslucent.setOnCheckedChangeListener { _, isChecked ->
getSharedPreferences("prefs", Context.MODE_PRIVATE).edit().putBoolean("statusBarTranslucent", isChecked).commit()
recreate()
}
navigationBarTransparent.setOnCheckedChangeListener { _, isChecked ->
getSharedPreferences("prefs", Context.MODE_PRIVATE).edit().putBoolean("navigationBarTransparent", isChecked).commit()
recreate()
}
val bottomAppBar = findViewById<BottomAppBar>(R.id.bottomAppBar)
bottomAppBar.setOnTouchListener { v, event ->
Log.d("Main", "Y: ${event.y}, Raw Y: ${event.rawY}")
event.setLocation(event.rawX, event.rawY)
nestedScrollView.dispatchTouchEvent(event)
statusBarColor.setOnCheckedChangeListener { _, checkedId ->
getSharedPreferences("prefs", Context.MODE_PRIVATE).edit().putString("statusBarColor",
when (checkedId) {
R.id.colorPrimaryDark -> "colorPrimaryDark"
R.id.colorPrimary -> "colorPrimary"
R.id.colorAccent -> "colorAccent"
R.id.colorBackground -> "colorBackground"
else -> "colorBackground"
}).commit()
recreate()
}
statusBarFallbackLight.setOnCheckedChangeListener { _, checkedId ->
getSharedPreferences("prefs", Context.MODE_PRIVATE).edit().putString("statusBarFallbackLight",
when (checkedId) {
R.id.lightHalfTransparent -> "lightHalfTransparent"
R.id.lightPrimaryDark -> "lightPrimaryDark"
R.id.lightDoNotChange -> "lightDoNotChange"
else -> "lightHalfTransparent"
}).commit()
recreate()
}
statusBarFallbackGradient.setOnCheckedChangeListener { _, checkedId ->
getSharedPreferences("prefs", Context.MODE_PRIVATE).edit().putString("statusBarFallbackGradient",
when (checkedId) {
R.id.gradientHalfTransparent -> "gradientHalfTransparent"
R.id.gradientPrimaryDark -> "gradientPrimaryDark"
R.id.gradientDoNotChange -> "gradientDoNotChange"
else -> "gradientDoNotChange"
}).commit()
recreate()
}
bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) {
navView.enableBottomSheetDrag = true
navView.enableBottomSheet = true
}
switchToolbar.setOnCheckedChangeListener { _, isChecked ->
navView.showToolbar = isChecked
}
switchBottomAppBar.setOnCheckedChangeListener { _, isChecked ->
navView.bottomBarEnable = isChecked
}
switchFab.setOnCheckedChangeListener { _, isChecked ->
navView.bottomBar.fabEnable = isChecked
}
extendFab.setOnCheckedChangeListener { _, isChecked ->
navView.bottomBar.fabExtended = isChecked
}
override fun onStateChanged(bottomSheet: View, newState: Int) {
when (newState) {
BottomSheetBehavior.STATE_HIDDEN -> {
if (showing) {
showing = false
Anim.fadeOut(dim, 300, null)
}
}
else -> {
if (!showing) {
showing = true
Anim.fadeIn(dim, 300, null)
}
}
}
//Toast.makeText(this@MainActivity, "Bottom Sheet State Changed to: $state", Toast.LENGTH_SHORT).show()
}
})*/
navView.setFabOnClickListener(View.OnClickListener {
Toast.makeText(this, "FAB clicked", Toast.LENGTH_SHORT).show()
})
scrimClose.setOnCheckedChangeListener { _, isChecked ->
navView.bottomSheet.scrimViewTapToClose = isChecked
}
scrimEnable.setOnCheckedChangeListener {_, isChecked ->
navView.bottomSheet.scrimViewEnabled = isChecked
}
fabPosition.setOnCheckedChangeListener { _, checkedId ->
navView.bottomBar.fabGravity = if (checkedId == R.id.fabCenter) Gravity.CENTER else Gravity.END
}
extendable.setOnCheckedChangeListener { _, isChecked ->
navView.bottomBar.fabExtendable = isChecked
}
bsEnable.setOnCheckedChangeListener {_, isChecked ->
navView.bottomSheet.enable = isChecked
}
bsDrag.setOnCheckedChangeListener {_, isChecked ->
navView.bottomSheet.enableDragToOpen = isChecked
}
navView.bottomBar.fabExtendedText = "Compose"
navView.bottomBar.fabExtended = false
}
}

View File

@ -1,34 +0,0 @@
package pl.szczodrzynski.navigation
import android.app.Dialog
import android.view.LayoutInflater
import android.view.View
import androidx.fragment.app.FragmentManager
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
class ThemeInfoBottomSheetDialog : BottomSheetDialogFragment() {
override fun setupDialog(dialog: Dialog, style: Int) {
val view = LayoutInflater.from(requireContext()).inflate(R.layout.bottom_sheet_fragment_theme_info, null)
setupViews(view)
dialog.setContentView(view)
}
private fun setupViews(view: View) {
}
fun showIfNeed(fragmentManager: FragmentManager) {
if (fragmentManager.findFragmentByTag(TAG) != null) {
return
}
show(fragmentManager, TAG)
}
companion object {
private const val TAG = "ThemeInfoBottomSheetDialog"
fun newInstance(): ThemeInfoBottomSheetDialog = ThemeInfoBottomSheetDialog()
}
}

View File

@ -5,58 +5,303 @@
xmlns:tools="http://schemas.android.com/tools">
<pl.szczodrzynski.navlib.NavView
android:id="@+id/navView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:text="booton" />
<Switch
android:id="@+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Switch" />
<ProgressBar
android:id="@+id/progressBar2"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.google.android.material.card.MaterialCardView
style="@style/Widget.MaterialComponents.CardView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iconImageView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:contentDescription="Card Icon"
app:tint="?attr/colorOnSurface" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:text="Switch theme" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/titleTextView"
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textAppearance="?attr/textAppearanceHeadline6"
android:textColor="?attr/colorOnSurface"
tools:text="Title" />
android:text="NavView config"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchToolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Toolbar" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchBottomAppBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Bottom app bar" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="FAB" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/extendable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="FAB extendable" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/extendFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:text="FAB extended" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="FAB config"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<RadioGroup
android:id="@+id/fabPosition"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/fabCenter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:text="FAB center" />
<RadioButton
android:id="@+id/fabEnd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="FAB end" />
</RadioGroup>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="BottomSheet config"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/bsEnable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Enable Bottom sheet" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/bsDrag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Enable BS drag to open" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/scrimEnable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Enable ScrimView" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/scrimClose"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="ScrimView on click close" />
<TextView
android:id="@+id/textView6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="System bars config"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/appFullscreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:text="App is fullscreen" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Status bar color"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="5.0+ with dark SB color, 6.0+" />
<RadioGroup
android:id="@+id/statusBarColor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/colorPrimaryDark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="false"
android:text="COLOR_PRIMARY_DARK" />
<RadioButton
android:id="@+id/colorPrimary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="false"
android:text="\?colorPrimary" />
<RadioButton
android:id="@+id/colorAccent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="false"
android:text="\?colorAccent" />
<RadioButton
android:id="@+id/colorBackground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:text="\?colorBackground" />
</RadioGroup>
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/statusBarDarker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:text="Status bar darker" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Status bar fallback if light"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="5.0 with SB color white, TouchWiz 4.1-4.3" />
<RadioGroup
android:id="@+id/statusBarFallbackLight"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/lightHalfTransparent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:text="COLOR_HALF_TRANSPARENT" />
<RadioButton
android:id="@+id/lightPrimaryDark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="false"
android:text="COLOR_PRIMARY_DARK" />
<RadioButton
android:id="@+id/lightDoNotChange"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="false"
android:text="COLOR_DO_NOT_CHANGE" />
</RadioGroup>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Status bar fallback if gradient"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="4.4, 5.0 Huawei" />
<RadioGroup
android:id="@+id/statusBarFallbackGradient"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/gradientHalfTransparent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="false"
android:text="COLOR_HALF_TRANSPARENT" />
<RadioButton
android:id="@+id/gradientPrimaryDark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="false"
android:text="COLOR_PRIMARY_DARK" />
<RadioButton
android:id="@+id/gradientDoNotChange"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:checked="true"
android:text="COLOR_DO_NOT_CHANGE" />
</RadioGroup>
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/statusBarTranslucent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:text="SB color mode - translucent (not transparent)" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/navigationBarTransparent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Nav bar fully transparent" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</ScrollView>
</pl.szczodrzynski.navlib.NavView>

View File

@ -1,26 +1,34 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="AppTheme.Widget" />
<style name="AppTheme.Widget.ExtendedFloatingActionButton" parent="Widget.MaterialComponents.ExtendedFloatingActionButton">
<item name="android:textColor">?colorOnSecondary</item>
<item name="android:iconTint" tools:targetApi="o">?colorSecondaryVariant</item>
<item name="iconTint">?colorSecondaryVariant</item>
</style>
<!-- Base application theme. -->
<style name="AppTheme" parent="NavView">
<!-- Customize your theme here. -->
<item name="colorPrimary">#64b5f6</item>
<item name="colorPrimaryDark">#1976d2</item>
<item name="colorPrimaryVariant">#1976d2</item>
<item name="colorAccent">#ff6e40</item>
<item name="colorSecondary">#ff6e40</item>
<item name="colorSecondaryVariant">#ff3d00</item>
<item name="colorPrimaryVariant">#2196f3</item>
<item name="colorAccent">#ffb300</item>
<item name="colorSecondary">?colorAccent</item>
<item name="colorSecondaryVariant">#fff59d</item>
<item name="android:colorBackground">@color/black</item>
<item name="android:windowBackground">?android:colorBackground</item>
<item name="colorSurface">#1f1f1f</item>
<item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
<!--<item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
<item name="android:windowTranslucentStatus" tools:targetApi="kitkat">false</item>
<item name="android:navigationBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
<item name="android:windowTranslucentNavigation" tools:targetApi="kitkat">false</item>
&lt;!&ndash;<item name="android:navigationBarColor" tools:targetApi="lollipop">@android:color/transparent</item>&ndash;&gt;
<item name="android:windowTranslucentNavigation" tools:targetApi="kitkat">true</item>-->
<item name="colorOnPrimary">#000000</item>
<item name="colorOnSecondary">#000000</item>
<item name="colorOnPrimary">#ffffff</item>
<item name="colorOnSecondary">#ffffff</item>
<item name="colorOnBackground">#ffffff</item>
<item name="colorOnSurface">#ffffff</item>
@ -28,35 +36,37 @@
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="extendedFloatingActionButtonStyle">@style/AppTheme.Widget.ExtendedFloatingActionButton</item>
</style>
<style name="AppTheme.Light" parent="NavView.Light">
<!-- Customize your theme here. -->
<item name="colorPrimary">#2196f3</item>
<item name="colorPrimaryDark">#1976d2</item>
<item name="colorPrimaryVariant">#90caf9</item>
<item name="colorAccent">#ff6e40</item>
<item name="colorSecondary">#ff6e40</item>
<item name="colorSecondaryVariant">#ff3d00</item>
<item name="colorPrimaryVariant">#2196f3</item>
<item name="colorAccent">#ffb300</item>
<item name="colorSecondary">?colorAccent</item>
<item name="colorSecondaryVariant">#fff59d</item>
<item name="android:colorBackground">@color/white</item>
<item name="android:windowBackground">?android:colorBackground</item>
<item name="colorSurface">#ffffff</item>
<item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
<!--<item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
<item name="android:windowTranslucentStatus" tools:targetApi="kitkat">false</item>
<item name="android:navigationBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
<item name="android:windowTranslucentNavigation" tools:targetApi="kitkat">false</item>
&lt;!&ndash;<item name="android:navigationBarColor" tools:targetApi="lollipop">@android:color/transparent</item>&ndash;&gt;
<item name="android:windowTranslucentNavigation" tools:targetApi="kitkat">true</item>-->
<item name="colorOnPrimary">#000000</item>
<item name="colorOnSecondary">#000000</item>
<item name="colorOnPrimary">#ffffff</item>
<item name="colorOnSecondary">#ffffff</item>
<item name="colorOnBackground">#000000</item>
<item name="colorOnSurface">#000000</item>
<item name="nv_actionBarBackground">?colorSurface</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="extendedFloatingActionButtonStyle">@style/AppTheme.Widget.ExtendedFloatingActionButton</item>
</style>
</resources>

View File

@ -6,11 +6,11 @@ buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0-rc03'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
@ -20,7 +20,7 @@ allprojects {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
}
@ -36,9 +36,9 @@ ext {
androidXCardView = '1.0.0'
androidXGridLayout = '1.0.0'
androidXConstraintLayout = '1.1.3'
googleMaterial = '1.1.0-alpha07'
googleMaterial = '1.1.0-alpha09'
iconics = '3.2.5'
iconics = '4.0.1-b01'
}
task clean(type: Delete) {

View File

@ -1,5 +1,6 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 28
@ -23,6 +24,13 @@ android {
}
}
dataBinding {
enabled = true
}
packagingOptions {
exclude 'META-INF/library-core_release.kotlin_module'
}
}
dependencies {
@ -32,4 +40,14 @@ dependencies {
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'com.google.android.material:material:1.1.0-alpha09'
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "com.mikepenz:materialdrawer:6.1.2"
implementation "com.mikepenz:iconics-core:4.0.1-b01"
implementation 'com.mikepenz:community-material-typeface:3.5.95.1-kotlin@aar'
implementation "androidx.appcompat:appcompat:${androidXAppCompat}"
implementation "androidx.recyclerview:recyclerview:${androidXRecyclerView}"
implementation "androidx.annotation:annotation:1.1.0"
implementation "com.google.android.material:material:${googleMaterial}"
implementation "androidx.constraintlayout:constraintlayout:${androidXConstraintLayout}"
}

View File

@ -1,6 +1,6 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
# proguardFiles setting in init.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

View File

@ -0,0 +1,177 @@
package pl.szczodrzynski.navlib
import android.content.Context
import android.system.Os.close
import android.util.AttributeSet
import android.view.Gravity
import android.view.MenuItem
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.bottomappbar.BottomAppBar
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp
import com.mikepenz.materialdrawer.Drawer
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
class NavBottomBar : BottomAppBar {
constructor(context: Context) : super(context) {
create(null, 0)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
create(attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
create(attrs, defStyle)
}
var drawer: Drawer? = null
var bottomSheet: NavBottomSheet? = null
var fabView: FloatingActionButton? = null
var fabExtendedView: ExtendedFloatingActionButton? = null
/**
* Shows the BottomAppBar and sets the contentView's margin to be
* above the BottomAppBar.
*/
var enable = true
set(value) {
field = value
visibility = if (value) View.VISIBLE else View.GONE
setFabParams()
}
/**
* Whether the FAB should be visible.
*/
var fabEnable = true
set(value) {
field = value
setFabVisibility()
}
/**
* Whether an ExtendableFloatingActionButton should be used
* instead of a normal FloatingActionButton.
* Note that the extendable button does not support end alignment/gravity
* when used together with the bottom app bar.
*/
var fabExtendable = true
set(value) {
field = value
setFabParams()
}
/**
* If BottomAppBar is enabled, sets its fabAlignmentMode.
* Else, sets the actual FAB's gravity.
*/
var fabGravity = Gravity.CENTER
set(value) {
field = value
setFabParams()
}
/**
* Whether the FAB should be extended and its text visible.
*/
var fabExtended = false
set(value) {
field = value
if (fabExtended)
fabExtendedView?.extend()
else
fabExtendedView?.shrink()
}
/**
* Set the ExtendedFAB's text.
*/
var fabExtendedText
get() = fabExtendedView?.text
set(value) {
fabExtendedView?.text = value
}
private fun create(attrs: AttributeSet?, defStyle: Int) {
setOnTouchListener { _, event ->
if (bottomSheet?.enable != true || bottomSheet?.enableDragToOpen != true)
return@setOnTouchListener false
bottomSheet?.dispatchBottomBarEvent(event)
true
}
navigationIcon = IconicsDrawable(context)
.icon(CommunityMaterial.Icon2.cmd_menu)
.sizeDp(20)
.colorInt(getColorFromAttr(context, R.attr.colorOnPrimary))
menu.add(0, -1, 0, "Menu")
.setIcon(
IconicsDrawable(context)
.icon(CommunityMaterial.Icon.cmd_dots_vertical)
.sizeDp(20)
.colorInt(getColorFromAttr(context, R.attr.colorOnPrimary)))
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
setNavigationOnClickListener {
if (drawer?.isDrawerOpen == true)
drawer?.closeDrawer()
else
drawer?.openDrawer()
}
super.setOnMenuItemClickListener {
if (it.itemId == -1 && bottomSheet?.enable == true) {
bottomSheet?.toggle()
}
else {
onMenuItemClickListener?.onMenuItemClick(it)
}
true
}
}
private fun setFabParams() {
val layoutParams =
((if (fabExtendable) fabExtendedView?.layoutParams else fabView?.layoutParams) ?: return) as CoordinatorLayout.LayoutParams
if (enable) {
layoutParams.anchorId = this.id
if (fabExtendable)
layoutParams.anchorGravity = if (fabExtendable) fabGravity or Gravity.TOP else Gravity.NO_GRAVITY
layoutParams.gravity = Gravity.NO_GRAVITY
}
else {
layoutParams.anchorId = View.NO_ID
if (fabExtendable)
layoutParams.anchorGravity = Gravity.NO_GRAVITY
layoutParams.gravity = fabGravity or Gravity.BOTTOM
}
fabAlignmentMode = if (fabGravity == Gravity.END) FAB_ALIGNMENT_MODE_END else FAB_ALIGNMENT_MODE_CENTER
if (fabExtendable)
fabExtendedView?.layoutParams = layoutParams
else
fabView?.layoutParams = layoutParams
setFabVisibility()
}
private fun setFabVisibility() {
if (fabEnable && fabExtendable) {
fabView?.hide()
fabExtendedView?.show()
}
else if (fabEnable) {
fabView?.show()
fabExtendedView?.hide()
}
else {
fabView?.hide()
fabExtendedView?.hide()
}
}
private var onMenuItemClickListener: OnMenuItemClickListener? = null
override fun setOnMenuItemClickListener(listener: OnMenuItemClickListener?) {
onMenuItemClickListener = listener
}
}

View File

@ -0,0 +1,23 @@
package pl.szczodrzynski.navlib
import android.content.Context
import android.util.AttributeSet
import com.google.android.material.appbar.MaterialToolbar
class NavToolbar : MaterialToolbar {
constructor(context: Context) : super(context) {
create(null, 0)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
create(attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
create(attrs, defStyle)
}
private fun create(attrs: AttributeSet?, defStyle: Int) {
}
}

View File

@ -1,86 +1,55 @@
package pl.szczodrzynski.navlib
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.*
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.SeekBar
import android.widget.*
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.*
import androidx.core.widget.NestedScrollView
import com.google.android.material.bottomappbar.BottomAppBar
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
import androidx.core.view.ViewCompat
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.mikepenz.materialdrawer.Drawer
import com.mikepenz.materialdrawer.DrawerBuilder
import com.mikepenz.materialdrawer.model.DividerDrawerItem
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem
import kotlinx.android.synthetic.main.nav_view.view.*
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
class NavView : FrameLayout {
private var contentView: LinearLayout? = null
private lateinit var bottomAppBar: BottomAppBar
private lateinit var statusBarBackground: View
private lateinit var navigationBarBackground: View
private lateinit var mainView: CoordinatorLayout
private lateinit var floatingActionButton: FloatingActionButton
private lateinit var scrimView: View
private lateinit var bottomSheet: NestedScrollView
private lateinit var bottomSheetBehavior: BottomSheetBehavior<View>
private var bottomSheetVisible = false
private lateinit var extendedFloatingActionButton: ExtendedFloatingActionButton
var drawer: Drawer? = null
lateinit var topBar: NavToolbar
lateinit var bottomBar: NavBottomBar
lateinit var bottomSheet: NavBottomSheet
private val displayMetrics by lazy {
context.resources.displayMetrics
}
private val configuration by lazy { context.resources.configuration }
private val displayWidth: Int by lazy { configuration.screenWidthDp }
private val displayHeight: Int by lazy { configuration.screenHeightDp }
fun getTopInset(view: View): Float {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
(view.rootWindowInsets?.systemWindowInsetTop ?: 24)
} else {
24
}*displayMetrics.density
}
fun getLeftInset(view: View): Float {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
(view.rootWindowInsets?.systemWindowInsetLeft ?: 0)
} else {
0
} * displayMetrics.density
}
fun getRightInset(view: View): Float {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
(view.rootWindowInsets?.systemWindowInsetRight ?: 0)
} else {
0
} * displayMetrics.density
}
fun getBottomInset(view: View): Float {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
(view.rootWindowInsets?.systemWindowInsetBottom ?: 48)
} else {
48
} * displayMetrics.density
}
constructor(context: Context) : super(context) {
init(null, 0)
create(null, 0)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init(attrs, 0)
create(attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
init(attrs, defStyle)
create(attrs, defStyle)
}
private fun init(attrs: AttributeSet?, defStyle: Int) {
private fun create(attrs: AttributeSet?, defStyle: Int) {
// Load attributes
val a = context.obtainStyledAttributes(attrs, R.styleable.NavView, defStyle, 0)
/*_exampleString = a.getString(
@ -93,78 +62,117 @@ class NavView : FrameLayout {
contentView = findViewById<LinearLayout>(R.id.nv_content)
//findViewById<TextView>(R.id.textView).text = "${displayWidth}dp x ${displayHeight}dp"
// TODO add vars for status/navigation bar background
bottomAppBar = findViewById(R.id.nv_bottomAppBar)
statusBarBackground = findViewById(R.id.nv_statusBarBackground)
navigationBarBackground = findViewById(R.id.nv_navigationBarBackground)
mainView = findViewById(R.id.nv_main)
floatingActionButton = findViewById(R.id.nv_floatingActionButton)
scrimView = findViewById(R.id.nv_scrim)
extendedFloatingActionButton = findViewById(R.id.nv_extendedFloatingActionButton)
topBar = findViewById(R.id.nv_toolbar)
bottomBar = findViewById(R.id.nv_bottomBar)
bottomSheet = findViewById(R.id.nv_bottomSheet)
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
bottomSheetBehavior.state = STATE_HIDDEN
bottomSheetBehavior.peekHeight = displayHeight
bottomBar.drawer = drawer
bottomBar.bottomSheet = bottomSheet
bottomBar.fabView = floatingActionButton
bottomBar.fabExtendedView = extendedFloatingActionButton
nv_main.setPadding(
getLeftInset(nv_main).toInt(),
getTopInset(nv_main).toInt(),
getRightInset(nv_main).toInt(),
getBottomInset(nv_main).toInt()
)
nv_statusBarBackground.layoutParams.height = getTopInset(nv_main).toInt()
nv_navigationBarBackground.layoutParams.height = getBottomInset(nv_main).toInt()
bottomAppBar.setOnTouchListener { v, event ->
val location = IntArray(2)
bottomSheet.getLocationOnScreen(location)
event.setLocation(event.rawX - location[0], event.rawY - location[1])
bottomSheet.dispatchTouchEvent(event)
true
}
scrimView.setOnTouchListener { v, event ->
if (event.action == MotionEvent.ACTION_UP && bottomSheetBehavior.state != STATE_HIDDEN) {
bottomSheetBehavior.state = STATE_HIDDEN
}
true
}
bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(v: View, p1: Float) {}
override fun onStateChanged(v: View, newState: Int) {
if (newState == STATE_HIDDEN && bottomSheetVisible) {
bottomSheetVisible = false
Anim.fadeOut(scrimView, 300, null)
bottomSheet.scrollTo(0, 0)
}
else if (!bottomSheetVisible) {
bottomSheetVisible = true
Anim.fadeIn(scrimView, 300, null)
}
}
})
floatingActionButton.setOnClickListener {
if (bottomSheetBehavior.state == STATE_HIDDEN) {
bottomSheetBehavior.state = STATE_COLLAPSED
}
else {
bottomSheetBehavior.state = STATE_HIDDEN
}
}
//bottomSheetBehavior.peekHeight = displayHeight
nv_elevation.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
textView.text = "Set toolbar elevation ${progress}dp"
nv_toolbar.elevation = progress * displayMetrics.density
nv_toolbar.elevation = progress * context.resources.displayMetrics.density
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
}
fun configSystemBarsUtil(systemBarsUtil: SystemBarsUtil) {
systemBarsUtil.statusBarBgView = statusBarBackground
systemBarsUtil.navigationBarBgView = navigationBarBackground
systemBarsUtil.statusBarDarkView = nv_statusBarDarker
//systemBarsUtil.navigationBarDarkView = navigationBarBackground
systemBarsUtil.paddingBySystemBars = mainView
systemBarsUtil.paddingByNavigationBar = bottomSheet.getContentView()
}
var enableBottomSheet = true
var enableBottomSheetDrag = true
var bottomBarEnable = true
get() = bottomBar.enable
set(value) {
field = value
bottomBar.enable = value
setContentMargins() // TODO combine bottomBarEnable and bottomBar.enable
}
/**
* Shows the toolbar and sets the contentView's margin to be
* below the toolbar.
*/
var showToolbar = true; set(value) {
topBar.visibility = if (value) View.VISIBLE else View.GONE
field = value
setContentMargins()
}
/**
* Set the FAB's on click listener
*/
fun setFabOnClickListener(onClickListener: OnClickListener) {
floatingActionButton.setOnClickListener(onClickListener)
extendedFloatingActionButton.setOnClickListener(onClickListener)
}
@SuppressLint("ClickableViewAccessibility")
fun init(activity: Activity) {
}
private fun setContentMargins() {
val layoutParams = CoordinatorLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
val actionBarSize = 56 * context.resources.displayMetrics.density
layoutParams.topMargin = if (showToolbar) actionBarSize.toInt() else 0
layoutParams.bottomMargin = if (bottomBarEnable) actionBarSize.toInt() else 0
contentView?.layoutParams = layoutParams
}
fun addDrawer(activity: Activity) {
//if you want to update the items at a later time it is recommended to keep it in a variable
val item1 = PrimaryDrawerItem().withIdentifier(1).withName("Home")
val item2 = SecondaryDrawerItem().withIdentifier(2).withName("Settings")
drawer = DrawerBuilder(activity)
.withDrawerLayout(R.layout.material_drawer_fits_not)
.withRootView(R.id.nv_drawerContainer)
.withFullscreen(true)
.withTranslucentStatusBar(false)
.withTranslucentNavigationBar(false)
.withTranslucentNavigationBarProgrammatically(false)
.withToolbar(topBar)
.withDisplayBelowStatusBar(true)
.withActionBarDrawerToggleAnimated(true)
.addDrawerItems(
item1,
DividerDrawerItem(),
item2,
SecondaryDrawerItem().withName("Settings")
)
.withOnDrawerItemClickListener { view, position, drawerItem ->
true
}
.build()
bottomBar.drawer = drawer
}
override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
if (contentView == null) {
super.addView(child, index, params)

View File

@ -0,0 +1,369 @@
package pl.szczodrzynski.navlib
import android.app.Activity
import android.content.res.Configuration.ORIENTATION_PORTRAIT
import android.content.res.Resources
import android.graphics.Color
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES.*
import android.util.Log
import android.view.*
import android.view.View.*
import androidx.core.graphics.ColorUtils
import androidx.core.view.ViewCompat
import com.mikepenz.materialize.util.KeyboardUtil
class SystemBarsUtil(val activity: Activity) {
companion object {
private const val COLOR_TRANSPARENT = Color.TRANSPARENT
/**
* A fallback color.
* Tells to apply a #22000000 overlay over the status/nav bar color.
* This has the same effect as [statusBarDarker].
*/
const val COLOR_HALF_TRANSPARENT = -1
/**
* Use ?colorPrimaryDark as a fallback or status bar color.
*/
const val COLOR_PRIMARY_DARK = -2
/**
* A fallback color.
* Not recommended to use as [statusBarFallbackLight] because it will make status bar
* icons almost invisible.
*/
const val COLOR_DO_NOT_CHANGE = -3
private const val COLOR_DARK_OVERLAY = 0x22000000
private const val TARGET_MODE_NORMAL = 0
private const val TARGET_MODE_LIGHT = 1
private const val TARGET_MODE_GRADIENT = 2
}
val window: Window by lazy {
activity.window
}
val resources: Resources by lazy {
activity.resources
}
/**
* A view which will have the padding added when the soft input keyboard appears.
*/
var paddingByKeyboard: View? = null
/**
* Whether the app should be fullscreen.
*
* This means it will display under the system bars
* and you should probably provide [statusBarBgView],
* [navigationBarBgView] and [paddingBySystemBars].
*/
var appFullscreen = false
/**
* Define the color used to tint the status bar background.
*
* Valid values are [COLOR_PRIMARY_DARK] or a color integer.
*
* You cannot use neither [COLOR_HALF_TRANSPARENT] nor [COLOR_DO_NOT_CHANGE] here.
* See [statusBarDarker].
*/
var statusBarColor = COLOR_PRIMARY_DARK
/**
* Whether the status bar should have a dark overlay (#22000000).
*
* Useful if the [statusBarColor] is set to a bright color and is the same as an action bar.
* Not useful if [statusBarColor] is [COLOR_PRIMARY_DARK].
*/
var statusBarDarker = false
/**
* A fallback status bar color used on Android Lollipop
* when the [statusBarColor] combined with [statusBarDarker] is
* too bright not to blend with status bar icons (they cannot be
* set to dark).
*
* This will (most likely) not be used when [statusBarDarker] is true.
*
* Valid values are [COLOR_HALF_TRANSPARENT], [COLOR_PRIMARY_DARK], [COLOR_DO_NOT_CHANGE].
*/
var statusBarFallbackLight = COLOR_HALF_TRANSPARENT
/**
* A fallback status bar color used on Android KitKat and older.
* On these systems there is a black-to-transparent gradient as
* the status bar background.
*
* Valid values are [COLOR_HALF_TRANSPARENT], [COLOR_PRIMARY_DARK], [COLOR_DO_NOT_CHANGE].
*/
var statusBarFallbackGradient = COLOR_DO_NOT_CHANGE
// TODO remove - test for huawei
var statusBarTranslucent = false
/**
* If false, the nav bar is mostly translucent but not completely transparent.
*/
var navigationBarTransparent = true
/**
* A background view to be resized in order to fit under the status bar.
*/
var statusBarBgView: View? = null
/**
* A background view to be resized in order to fit under the nav bar.
*/
var navigationBarBgView: View? = null
/**
* A dark, half-transparent view to be resized in order to fit under the status bar.
*/
var statusBarDarkView: View? = null
/**
* A dark, half-transparent view to be resized in order to fit under the nav bar.
*/
var navigationBarDarkView: View? = null
/**
* A view which will have the padding added not to overlap with the status/nav bar.
*/
var paddingBySystemBars: View? = null
/**
* A view which will have the padding added not to overlap with the nav bar.
* Useful for persistent bottom sheets.
* Requires [paddingBySystemBars].
*/
var paddingByNavigationBar: View? = null
private var keyboardUtil: KeyboardUtil? = null
private var insetsApplied = false
fun commit() {
if (paddingByKeyboard != null) {
// thanks mikepenz for this life-saving class
keyboardUtil = KeyboardUtil(activity, paddingByKeyboard)
keyboardUtil?.enable()
}
// get the correct target SB color
var targetStatusBarColor = statusBarColor
if (targetStatusBarColor == COLOR_PRIMARY_DARK)
targetStatusBarColor = getColorFromAttr(activity, R.attr.colorPrimaryDark)
var targetStatusBarDarker = statusBarDarker
// fallback if the SB color is too light for the icons to be visible
// applicable on Lollipop 5.0 and TouchWiz 4.1-4.3
var targetStatusBarFallbackLight = statusBarFallbackLight
if (targetStatusBarFallbackLight == COLOR_PRIMARY_DARK)
targetStatusBarFallbackLight = getColorFromAttr(activity, R.attr.colorPrimaryDark)
// fallback if there is a gradient under the status bar
// applicable on AOSP/similar 4.4 and Huawei EMUI Lollipop
// TODO check huawei 6.0+ for gradient bars, check huawei 4.4
var targetStatusBarFallbackGradient = statusBarFallbackGradient
if (targetStatusBarFallbackGradient == COLOR_PRIMARY_DARK)
targetStatusBarFallbackGradient = getColorFromAttr(activity, R.attr.colorPrimaryDark)
// determines the target mode that will be applied
var targetStatusBarMode = TARGET_MODE_NORMAL
val targetStatusBarLight = ColorUtils.calculateLuminance(targetStatusBarColor) > 0.75 && !targetStatusBarDarker
if (appFullscreen) {
window.decorView.systemUiVisibility = 0
// API 19+ (KitKat 4.4+) - make the app fullscreen.
// On lower APIs this is useless because
// #1 the status/nav bar cannot be transparent (except Samsung TouchWiz)
// #2 tablets do not report status/nav bar height correctly
// #3 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the activity not resize when keyboard is open
// Samsung TouchWiz - app will go fullscreen. There is a problem though, see #3.
var targetAppFullscreen = false
if (SDK_INT >= KITKAT) {
targetAppFullscreen = true
}
if (SDK_INT in KITKAT until LOLLIPOP) {
// API 19-20 (KitKat 4.4) - set gradient status bar
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
// take FallbackGradient color
targetStatusBarMode = TARGET_MODE_GRADIENT
// disable darker even if [statusBarDarker] == true BUT gradient fallback is not COLOR_HALF_TRANSPARENT
//targetStatusBarDarker = targetStatusBarDarker && targetStatusBarFallbackGradient == COLOR_HALF_TRANSPARENT
}
else if (SDK_INT >= LOLLIPOP) {
// API 21+ (Lollipop 5.0+) - set transparent status bar
if (statusBarTranslucent) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
}
else {
window.statusBarColor = Color.TRANSPARENT
}
if (SDK_INT < M && targetStatusBarLight) {
// take FallbackLight color
targetStatusBarMode = TARGET_MODE_LIGHT
}
}
if (SDK_INT >= M && targetStatusBarLight) {
// API 23+ (Marshmallow 6.0+) - set the status bar icons to dark color if [statusBarLight] is true
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility or SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
}
// FOR SAMSUNG/SONY DEVICES (TouchWiz 4.1-4.3)
if (SDK_INT < KITKAT) {
val libs = activity.packageManager.systemSharedLibraryNames
var reflect: String? = null
// TODO galaxy s3 - opening keyboard does not resize activity if fullscreen
if (libs != null) {
for (lib in libs) {
Log.d("SBU", lib)
if (lib == "touchwiz")
// SYSTEM_UI_FLAG_TRANSPARENT_BACKGROUND = 0x00001000
reflect = "SYSTEM_UI_FLAG_TRANSPARENT_BACKGROUND"
else if (lib.startsWith("com.sonyericsson.navigationbar"))
reflect = "SYSTEM_UI_FLAG_TRANSPARENT"
}
if (reflect != null) {
try {
val field = View::class.java.getField(reflect)
var flag = 0
if (field.type === Integer.TYPE)
flag = field.getInt(null)
if (flag != 0) {
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility or flag
targetStatusBarMode = TARGET_MODE_LIGHT /* or TARGET_MODE_GRADIENT */
targetAppFullscreen = true
}
} catch (e: Exception) {
}
}
}
}
// TODO huawei detection for 5.0+
targetStatusBarColor = when (targetStatusBarMode) {
TARGET_MODE_LIGHT -> when (targetStatusBarFallbackLight) {
COLOR_DO_NOT_CHANGE -> targetStatusBarColor
COLOR_HALF_TRANSPARENT -> {
targetStatusBarDarker = true
targetStatusBarColor
}
else -> targetStatusBarFallbackLight
}
TARGET_MODE_GRADIENT -> when (targetStatusBarFallbackGradient) {
COLOR_DO_NOT_CHANGE -> {
targetStatusBarDarker = false
targetStatusBarColor
}
COLOR_HALF_TRANSPARENT -> {
targetStatusBarDarker = true
targetStatusBarColor
}
else -> {
targetStatusBarDarker = false
targetStatusBarFallbackGradient
}
}
else -> targetStatusBarColor
}
statusBarBgView?.setBackgroundColor(targetStatusBarColor)
statusBarDarkView?.visibility = if (targetStatusBarDarker) VISIBLE else GONE
if (targetAppFullscreen) {
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility or SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
}
// TODO navigation bar options like status bar
// NAVIGATION BAR
if (SDK_INT >= KITKAT && (SDK_INT < LOLLIPOP || !navigationBarTransparent)) {
// API 19-20 (KitKat 4.4) - set gradient navigation bar
// API 21+ (Lollipop 5.0+) - set half-transparent navigation bar if [navigationBarTransparent] is false
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
}
if (SDK_INT >= LOLLIPOP && navigationBarTransparent) {
// API 21+ (Lollipop 5.0+) - set fully transparent navigation bar if [navigationBarTransparent] is true
window.navigationBarColor = Color.TRANSPARENT
}
// PADDING
if (paddingBySystemBars != null) {
if (SDK_INT >= LOLLIPOP) {
ViewCompat.setOnApplyWindowInsetsListener(paddingBySystemBars!!) { _, insets ->
if (insetsApplied)
return@setOnApplyWindowInsetsListener insets.consumeSystemWindowInsets()
insetsApplied = true
applyPadding(
insets.systemWindowInsetLeft,
insets.systemWindowInsetTop,
insets.systemWindowInsetRight,
insets.systemWindowInsetBottom
)
insets.consumeSystemWindowInsets()
}
}
else {
var statusBarSize = 0
val statusBarRes = resources.getIdentifier("status_bar_height", "dimen", "android")
if (statusBarRes > 0 && targetAppFullscreen) {
statusBarSize = resources.getDimensionPixelSize(statusBarRes)
}
var navigationBarSize = 0
val hasMenuKey = ViewConfiguration.get(activity).hasPermanentMenuKey()
val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
if (!hasMenuKey && !hasBackKey && targetAppFullscreen) {
val orientation = resources.configuration.orientation
val navigationBarRes = when {
orientation == ORIENTATION_PORTRAIT ->
resources.getIdentifier("navigation_bar_height", "dimen", "android")
isTablet(activity) ->
resources.getIdentifier("navigation_bar_height_landscape", "dimen", "android")
else ->
resources.getIdentifier("navigation_bar_width", "dimen", "android")
}
if (navigationBarRes > 0) {
navigationBarSize = resources.getDimensionPixelSize(navigationBarRes)
}
}
applyPadding(
0,
statusBarSize,
0,
navigationBarSize
)
}
}
}
else {
// app not fullscreen
// TODO statusBarColor & navigationBarColor if not fullscreen (it's possible)
}
}
private fun applyPadding(left: Int, top: Int, right: Int, bottom: Int) {
paddingBySystemBars?.setPadding(left, top, right, bottom)
statusBarBgView?.layoutParams?.height = top
navigationBarBgView?.layoutParams?.height = bottom
statusBarDarkView?.layoutParams?.height = top
navigationBarDarkView?.layoutParams?.height = bottom
paddingByNavigationBar?.setPadding(
(8 * resources.displayMetrics.density).toInt(),
0,
(8 * resources.displayMetrics.density).toInt(),
bottom
)
}
fun destroy() {
if (paddingByKeyboard != null) {
keyboardUtil?.disable()
}
}
}

View File

@ -0,0 +1,81 @@
package pl.szczodrzynski.navlib
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.graphics.Color
import android.os.Build
import android.util.TypedValue
import android.view.View
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.core.graphics.ColorUtils
/*private val displayMetrics by lazy {
context.resources.displayMetrics
}*/
/*private val configuration by lazy { context.resources.configuration }
private val displayWidth: Int by lazy { configuration.screenWidthDp }
private val displayHeight: Int by lazy { configuration.screenHeightDp }*/
fun getTopInset(context: Context, view: View): Float {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
(view.rootWindowInsets?.systemWindowInsetTop ?: 24)
} else {
24
} * context.resources.displayMetrics.density
}
fun getLeftInset(context: Context, view: View): Float {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
(view.rootWindowInsets?.systemWindowInsetLeft ?: 0)
} else {
0
} * context.resources.displayMetrics.density
}
fun getRightInset(context: Context, view: View): Float {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
(view.rootWindowInsets?.systemWindowInsetRight ?: 0)
} else {
0
} * context.resources.displayMetrics.density
}
fun getBottomInset(context: Context, view: View): Float {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
(view.rootWindowInsets?.systemWindowInsetBottom ?: 48)
} else {
48
} * context.resources.displayMetrics.density
}
fun getColorFromAttr(context: Context, @AttrRes color: Int): Int {
val typedValue = TypedValue()
context.theme.resolveAttribute(color, typedValue, true)
return typedValue.data
}
fun View.getActivity(): Activity {
return findViewById<View>(android.R.id.content).context as Activity
}
fun blendColors(background: Int, foreground: Int): Int {
val r1 = (background shr 16 and 0xff)
val g1 = (background shr 8 and 0xff)
val b1 = (background and 0xff)
val r2 = (foreground shr 16 and 0xff)
val g2 = (foreground shr 8 and 0xff)
val b2 = (foreground and 0xff)
val a2 = (foreground shr 24 and 0xff)
//ColorUtils.compositeColors()
val factor = a2.toFloat() / 255f
val red = (r1 * (1 - factor) + r2 * factor)
val green = (g1 * (1 - factor) + g2 * factor)
val blue = (b1 * (1 - factor) + b2 * factor)
return (0xff000000 or (red.toLong() shl 16) or (green.toLong() shl 8) or (blue.toLong())).toInt()
}
fun isTablet(c: Context): Boolean {
return (c.resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE
}

View File

@ -0,0 +1,42 @@
package pl.szczodrzynski.navlib.bottomsheet
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import pl.szczodrzynski.navlib.R
import pl.szczodrzynski.navlib.bottomsheet.items.EditTextFilledItem
import pl.szczodrzynski.navlib.bottomsheet.items.IBottomSheetItem
import pl.szczodrzynski.navlib.bottomsheet.items.PrimaryItem
import pl.szczodrzynski.navlib.bottomsheet.items.SeparatorItem
class BottomSheetAdapter(val items: List<IBottomSheetItem<*>>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val viewHolderProvider = ViewHolderProvider()
init {
viewHolderProvider.registerViewHolderFactory(1, R.layout.nav_bs_item_primary) { itemView ->
PrimaryItem.ViewHolder(itemView)
}
viewHolderProvider.registerViewHolderFactory(2, R.layout.nav_bs_item_separator) { itemView ->
SeparatorItem.ViewHolder(itemView)
}
viewHolderProvider.registerViewHolderFactory(3, R.layout.nav_bs_item_edittext_filled) { itemView ->
EditTextFilledItem.ViewHolder(itemView)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return viewHolderProvider.provideViewHolder(viewGroup = parent, viewType = viewType)
}
override fun getItemViewType(position: Int): Int {
return items[position].viewType
}
override fun getItemCount(): Int {
return items.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
items[position].bindViewHolder(viewHolder = holder)
}
}

View File

@ -0,0 +1,207 @@
package pl.szczodrzynski.navlib.bottomsheet
import android.app.Activity
import android.content.Context
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.View.OnClickListener
import android.view.inputmethod.InputMethodManager
import android.widget.LinearLayout
import android.widget.Toast
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.widget.NestedScrollView
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import kotlinx.android.synthetic.main.nav_bottom_sheet.view.*
import pl.szczodrzynski.navlib.Anim
import pl.szczodrzynski.navlib.bottomsheet.items.EditTextFilledItem
import pl.szczodrzynski.navlib.bottomsheet.items.IBottomSheetItem
import pl.szczodrzynski.navlib.bottomsheet.items.PrimaryItem
import pl.szczodrzynski.navlib.bottomsheet.items.SeparatorItem
import pl.szczodrzynski.navlib.bottomsheet.listeners.OnItemInputListener
import pl.szczodrzynski.navlib.getColorFromAttr
class NavBottomSheet : CoordinatorLayout {
constructor(context: Context) : super(context) {
create(null, 0)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
create(attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
create(attrs, defStyle)
}
private lateinit var scrimView: View
private lateinit var bottomSheet: NestedScrollView
private lateinit var bottomSheetContent: LinearLayout
private lateinit var bottomSheetDragBar: View
private lateinit var bottomSheetBehavior: BottomSheetBehavior<View>
private var bottomSheetVisible = false
/**
* Enable the bottom sheet.
* This value is mostly relevant to the [pl.szczodrzynski.navlib.NavBottomBar].
*/
var enable = true
set(value) {
field = value
if (!value && bottomSheetVisible)
close()
}
/**
* Whether the [pl.szczodrzynski.navlib.NavBottomBar] should open this BottomSheet
* when the user drags the bottom bar.
*/
var enableDragToOpen = true
/**
* Control the scrim view visibility, shown when BottomSheet
* is expanded.
*/
var scrimViewEnabled = true
set(value) {
scrimView.visibility = if (value) View.INVISIBLE else View.GONE // INVISIBLE
field = value
}
/**
* Whether tapping the Scrim view should hide the BottomSheet.
*/
var scrimViewTapToClose = true
fun hideKeyboard() {
val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(rootView.windowToken, 0)
}
private fun create(attrs: AttributeSet?, defStyle: Int) {
val layoutInflater = LayoutInflater.from(context)
layoutInflater.inflate(pl.szczodrzynski.navlib.R.layout.nav_bottom_sheet, this)
scrimView = findViewById(pl.szczodrzynski.navlib.R.id.nv_scrim)
bottomSheet = findViewById(pl.szczodrzynski.navlib.R.id.nv_bottomSheetView)
bottomSheetContent = findViewById(pl.szczodrzynski.navlib.R.id.nv_bottomSheetContent)
bottomSheetDragBar = findViewById(pl.szczodrzynski.navlib.R.id.nv_bottomSheetDragBar)
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
scrimView.setOnTouchListener { _, event ->
if (!scrimViewTapToClose)
return@setOnTouchListener true
if (event.action == MotionEvent.ACTION_UP && bottomSheetBehavior.state != BottomSheetBehavior.STATE_HIDDEN) {
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
}
true
}
bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(v: View, p1: Float) {}
override fun onStateChanged(v: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_HIDDEN && bottomSheetVisible) {
bottomSheetVisible = false
bottomSheet.scrollTo(0, 0)
if (scrimViewEnabled)
Anim.fadeOut(scrimView, 300, null)
// steal the focus from any EditTexts
bottomSheetDragBar.requestFocus()
hideKeyboard()
}
else if (!bottomSheetVisible) {
bottomSheetVisible = true
if (scrimViewEnabled)
Anim.fadeIn(scrimView, 300, null)
}
}
})
bottomSheetContent.background.colorFilter = PorterDuffColorFilter(
getColorFromAttr(
context,
pl.szczodrzynski.navlib.R.attr.colorBackgroundFloating
), PorterDuff.Mode.SRC_ATOP)
// steal the focus from any EditTexts
bottomSheetDragBar.requestFocus()
val items = ArrayList<IBottomSheetItem<*>>()
items += EditTextFilledItem(true).apply {
id = 0
hint = "Search"
helperText = "0 results found"
onItemInputListener = object : OnItemInputListener {
override fun onItemInput(itemId: Int, item: EditTextFilledItem, text: CharSequence) {
item.helperText = "${text.length} results found"
bs_list.adapter?.notifyItemChanged(itemId)
}
}
}
items += PrimaryItem(true)
.withId(1)
.withTitle("Compose")
.withIcon(CommunityMaterial.Icon2.cmd_pencil)
.withOnClickListener(OnClickListener {
Toast.makeText(context, "Compose message", Toast.LENGTH_SHORT).show()
})
// TODO add separator item
items += SeparatorItem(true)
items += PrimaryItem(true)
.withId(3)
.withTitle("Synchronise")
.withIcon(CommunityMaterial.Icon2.cmd_sync)
.withOnClickListener(OnClickListener {
Toast.makeText(context, "Synchronising...", Toast.LENGTH_SHORT).show()
})
items += PrimaryItem(true)
.withId(4)
.withTitle("Help")
.withIcon(CommunityMaterial.Icon2.cmd_help)
.withOnClickListener(OnClickListener {
Toast.makeText(context, "Want some help?", Toast.LENGTH_SHORT).show()
})
bs_list.apply {
setHasFixedSize(true)
layoutManager = LinearLayoutManager(context)
adapter = BottomSheetAdapter(items)
}
}
fun dispatchBottomBarEvent(event: MotionEvent) {
val location = IntArray(2)
bottomSheet.getLocationOnScreen(location)
event.setLocation(event.rawX - location[0], event.rawY - location[1])
bottomSheet.dispatchTouchEvent(event)
}
fun setContentPadding(left: Int, top: Int, right: Int, bottom: Int) {
bottomSheetContent.setPadding(left, top, right, bottom)
}
fun getContentView() = bottomSheetContent
var isOpen
get() = bottomSheetBehavior.state != BottomSheetBehavior.STATE_HIDDEN
set(value) {
bottomSheetBehavior.state = if (value) BottomSheetBehavior.STATE_EXPANDED else BottomSheetBehavior.STATE_HIDDEN
}
fun open() { isOpen = true }
fun close() { isOpen = true }
fun toggle() {
if (!enable)
return
isOpen = !isOpen
}
}

View File

@ -0,0 +1,21 @@
package pl.szczodrzynski.navlib.bottomsheet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlin.reflect.KClass
class ViewHolderProvider {
private val viewHolderFactories = hashMapOf<Int, Pair<Int, (View) -> RecyclerView.ViewHolder>>()
fun provideViewHolder(viewGroup: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val (layoutId: Int, f: (View) -> RecyclerView.ViewHolder) = viewHolderFactories[viewType]!!
val view = LayoutInflater.from(viewGroup.getContext()).inflate(layoutId, viewGroup, false)
return f(view)
}
fun registerViewHolderFactory(viewType: Int, layoutId: Int, viewHolderFactory: (View) -> RecyclerView.ViewHolder) {
viewHolderFactories[viewType] = Pair(layoutId, viewHolderFactory)
}
}

View File

@ -0,0 +1,84 @@
package pl.szczodrzynski.navlib.bottomsheet.items
import android.graphics.drawable.Drawable
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.IIcon
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import com.mikepenz.iconics.utils.sizeDp
import com.mikepenz.materialize.holder.ImageHolder
import pl.szczodrzynski.navlib.R
import pl.szczodrzynski.navlib.bottomsheet.listeners.OnItemInputListener
class EditTextFilledItem(override val isContextual: Boolean = true) : IBottomSheetItem<EditTextFilledItem.ViewHolder> {
/*_ _
| | | |
| | __ _ _ _ ___ _ _| |_
| | / _` | | | |/ _ \| | | | __|
| |___| (_| | |_| | (_) | |_| | |_
|______\__,_|\__, |\___/ \__,_|\__|
__/ |
|__*/
override var id: Int = -1
override val viewType: Int
get() = 3
override val layoutId: Int
get() = R.layout.nav_bs_item_edittext_filled
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textInputLayout = itemView.findViewById<TextInputLayout>(R.id.item_text_input_layout)
val textInputEditText = itemView.findViewById<TextInputEditText>(R.id.item_text_input_edit_text)
}
override fun bindViewHolder(viewHolder: ViewHolder) {
viewHolder.textInputLayout.apply {
hint = this@EditTextFilledItem.hint
helperText = this@EditTextFilledItem.helperText
error = this@EditTextFilledItem.error
}
viewHolder.textInputEditText.apply {
setText(this@EditTextFilledItem.text)
removeTextChangedListener(textChangedListener)
addTextChangedListener(textChangedListener)
}
}
/*_____ _
| __ \ | |
| | | | __ _| |_ __ _
| | | |/ _` | __/ _` |
| |__| | (_| | || (_| |
|_____/ \__,_|\__\__,*/
var hint: CharSequence? = null
var helperText: CharSequence? = null
var error: CharSequence? = null
var text: CharSequence? = null
private var textChangedListener: TextWatcher? = null
var onItemInputListener: OnItemInputListener? = null
set(value) {
field = value
textChangedListener = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
onItemInputListener?.onItemInput(id, this@EditTextFilledItem, s?:"")
}
}
}
}

View File

@ -0,0 +1,19 @@
package pl.szczodrzynski.navlib.bottomsheet.items
import android.view.View
import androidx.annotation.LayoutRes
import androidx.recyclerview.widget.RecyclerView
import kotlin.reflect.KClass
interface IBottomSheetItem<T> {
val isContextual: Boolean
var id: Int
val viewType: Int
val layoutId: Int
fun bindViewHolder(viewHolder: T)
fun bindViewHolder(viewHolder: RecyclerView.ViewHolder) {
bindViewHolder(viewHolder as T)
}
}

View File

@ -0,0 +1,110 @@
package pl.szczodrzynski.navlib.bottomsheet.items
import android.graphics.drawable.Drawable
import android.view.View
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.recyclerview.widget.RecyclerView
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.IIcon
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import com.mikepenz.iconics.utils.sizeDp
import com.mikepenz.materialize.holder.ImageHolder
import pl.szczodrzynski.navlib.R
data class PrimaryItem(override val isContextual: Boolean = true) : IBottomSheetItem<PrimaryItem.ViewHolder> {
/*_ _
| | | |
| | __ _ _ _ ___ _ _| |_
| | / _` | | | |/ _ \| | | | __|
| |___| (_| | |_| | (_) | |_| | |_
|______\__,_|\__, |\___/ \__,_|\__|
__/ |
|__*/
override var id: Int = -1
override val viewType: Int
get() = 1
override val layoutId: Int
get() = R.layout.nav_bs_item_primary
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val root = itemView.findViewById<View>(R.id.item_root)
val text = itemView.findViewById<TextView>(R.id.item_text)
}
override fun bindViewHolder(viewHolder: ViewHolder) {
viewHolder.root.setOnClickListener(onClickListener)
viewHolder.text.text = title
viewHolder.text.setCompoundDrawables(
IconicsDrawable(viewHolder.text.context)
.icon(iconicsIcon?:CommunityMaterial.Icon.cmd_android)
.sizeDp(20),
null,
null,
null
)
}
/*_____ _
| __ \ | |
| | | | __ _| |_ __ _
| | | |/ _` | __/ _` |
| |__| | (_| | || (_| |
|_____/ \__,_|\__\__,*/
var title: CharSequence? = null
@StringRes
var titleRes: Int? = null
var description: CharSequence? = null
@StringRes
var descriptionRes: Int? = null
var icon: ImageHolder? = null
var iconicsIcon: IIcon? = null
var onClickListener: View.OnClickListener? = null
fun withId(id: Int): PrimaryItem {
this.id = id
return this
}
fun withTitle(title: CharSequence): PrimaryItem {
this.title = title
this.titleRes = null
return this
}
fun withTitle(@StringRes title: Int): PrimaryItem {
this.title = null
this.titleRes = title
return this
}
fun withDescription(description: CharSequence): PrimaryItem {
this.description = description
this.descriptionRes = null
return this
}
fun withDescription(@StringRes description: Int): PrimaryItem {
this.description = null
this.descriptionRes = description
return this
}
fun withIcon(icon: Drawable): PrimaryItem {
this.icon = ImageHolder(icon)
return this
}
fun withIcon(@DrawableRes icon: Int): PrimaryItem {
this.icon = ImageHolder(icon)
return this
}
fun withIcon(icon: IIcon): PrimaryItem {
this.iconicsIcon = icon
return this
}
fun withOnClickListener(onClickListener: View.OnClickListener): PrimaryItem {
this.onClickListener = onClickListener
return this
}
}

View File

@ -0,0 +1,28 @@
package pl.szczodrzynski.navlib.bottomsheet.items
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import pl.szczodrzynski.navlib.R
data class SeparatorItem(override val isContextual: Boolean = true) : IBottomSheetItem<SeparatorItem.ViewHolder> {
/*_ _
| | | |
| | __ _ _ _ ___ _ _| |_
| | / _` | | | |/ _ \| | | | __|
| |___| (_| | |_| | (_) | |_| | |_
|______\__,_|\__, |\___/ \__,_|\__|
__/ |
|__*/
override var id: Int = -1
override val viewType: Int
get() = 2
override val layoutId: Int
get() = R.layout.nav_bs_item_separator
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
override fun bindViewHolder(viewHolder: ViewHolder) {
}
}

View File

@ -0,0 +1,7 @@
package pl.szczodrzynski.navlib.bottomsheet.listeners
import pl.szczodrzynski.navlib.bottomsheet.items.EditTextFilledItem
interface OnItemInputListener {
fun onItemInput(itemId: Int, item: EditTextFilledItem, text: CharSequence)
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple android:color="#202196f3"
android:radius="5dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@android:id/mask"
android:top="3dp"
android:bottom="3dp"
android:drawable="@color/color" />
</ripple>

View File

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:shape="rectangle">
<corners
android:topLeftRadius="16dp"
android:topRightRadius="16dp" />
<solid android:color="?colorBackgroundFloating" />
<solid android:color="#ffffff" tools:color="?colorBackgroundFloating" />
</shape>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This will be the drawable used on API < 21 -->
<!-- Obviously you can specify here whatever you want -->
<!-- like activated states, animated states, shapes, pngs, whatever like any other drawable-->
<!-- I've just put 2 states (pressed,focused) using the same color than the v21 ripple -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bs_item_background_base" android:state_focused="true"/>
<item android:drawable="@drawable/bs_item_background_base" android:state_pressed="true"/>
<item android:drawable="@android:color/transparent"/>
</selector>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="3dp"
android:bottom="3dp">
<shape>
<solid android:color="#202196f3"/>
<corners android:radius="5dp"/>
</shape>
</item>
</layer-list>

View File

@ -1,90 +0,0 @@
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:background="@drawable/bottom_sheet_controll_bar" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<Button
android:id="@+id/button4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<CalendarView
android:id="@+id/calendarView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="48dp"
app:srcCompat="@android:drawable/checkbox_on_background" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RatingBar
android:id="@+id/ratingBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<SearchView
android:layout_width="match_parent"
android:layout_height="match_parent">
</SearchView>
<Switch
android:id="@+id/switch1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Switch" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/floatingActionButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
app:srcCompat="@drawable/ic_android" />
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/material_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false" />

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<com.mikepenz.materialize.view.ScrimInsetsRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/material_drawer_slider_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:layout_marginEnd="@dimen/material_drawer_margin"
android:layout_marginRight="@dimen/material_drawer_margin"
android:clickable="true"
android:elevation="8dp"
android:fitsSystemWindows="true"
android:focusable="true"
android:orientation="vertical">
<View
android:id="@+id/material_drawer_inner_shadow"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentStart="false"
android:layout_alignParentLeft="false"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:background="@drawable/material_drawer_shadow_left"
android:visibility="gone" />
</com.mikepenz.materialize.view.ScrimInsetsRelativeLayout>

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:translationZ="10dp"
tools:targetApi="lollipop">
<View
android:id="@+id/nv_scrim"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#99000000"
android:visibility="invisible"
tools:visibility="gone" />
<androidx.core.widget.NestedScrollView
android:id="@+id/nv_bottomSheetView"
style="@style/width_max_600dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:behavior_hideable="true"
app:behavior_peekHeight="auto"
app:layout_behavior="@string/bottom_sheet_behavior"
tools:visibility="visible">
<LinearLayout
android:id="@+id/nv_bottomSheetContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bottom_sheet_background"
android:paddingStart="8dp"
android:paddingEnd="8dp"
tools:paddingBottom="48dp"
android:orientation="vertical">
<ImageView
android:id="@+id/nv_bottomSheetDragBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:focusable="true"
android:focusableInTouchMode="true"
app:srcCompat="@drawable/bottom_sheet_control_bar"
tools:ignore="ContentDescription" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Sorting order" />
<com.google.android.material.button.MaterialButtonToggleGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleSelection="true">
<Button
android:id="@+id/button2"
style="?materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="By date"
app:icon="@drawable/ic_android"/>
<Button
android:id="@+id/button3"
style="?materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="By subject" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button4"
style="?materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="By sender" />
</com.google.android.material.button.MaterialButtonToggleGroup>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/bs_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dp"
tools:listitem="@layout/nav_bs_item_primary"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.textfield.TextInputLayout 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/item_text_input_layout"
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
tools:helperText="2 results found"
tools:hint="Search">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/item_text_input_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:singleLine="true"
tools:text="Kowalski" />
</com.google.android.material.textfield.TextInputLayout>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/item_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:orientation="vertical">
<TextView
android:id="@+id/item_text"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:drawablePadding="16dp"
android:fontFamily="sans-serif-medium"
android:gravity="start|center_vertical"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="14sp"
tools:text="Search activity" />
</LinearLayout>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="17dp"
android:gravity="center"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/material_drawer_divider" />
</LinearLayout>

View File

@ -10,25 +10,32 @@
<View
android:id="@+id/nv_statusBarBackground"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_height="0dp"
tools:layout_height="25dp"
android:background="?android:windowBackground" />
<View
android:id="@+id/nv_navigationBarBackground"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_height="0dp"
tools:layout_height="48dp"
android:layout_gravity="bottom"
android:background="?colorPrimaryDark"
android:background="?colorPrimaryVariant"
tools:background="?colorPrimaryVariant" />
<FrameLayout
android:id="@+id/nv_drawerContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/nv_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="24dp"
android:paddingBottom="48dp">
tools:paddingTop="24dp"
tools:paddingBottom="48dp">
<com.google.android.material.appbar.MaterialToolbar
<pl.szczodrzynski.navlib.NavToolbar
android:id="@+id/nv_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
@ -52,74 +59,67 @@
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:max="20"
android:progress="4" />
android:progress="4"
android:visibility="gone" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Set toolbar elevation" />
android:text="Set toolbar elevation"
android:visibility="gone" />
</LinearLayout>
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/nv_bottomAppBar"
<pl.szczodrzynski.navlib.NavBottomBar
android:id="@+id/nv_bottomBar"
style="@style/Widget.MaterialComponents.BottomAppBar.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:fabAlignmentMode="end" />
android:visibility="visible"
app:fabAlignmentMode="center"
app:fabAnimationMode="scale" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/nv_floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:focusable="true"
android:visibility="gone"
app:layout_anchor="@id/nv_bottomBar"
app:backgroundTint="?colorAccent"
app:layout_anchor="@id/nv_bottomAppBar"
tools:srcCompat="@android:drawable/ic_lock_lock" />
app:srcCompat="@android:drawable/ic_menu_edit"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:translationZ="10dp"
tools:targetApi="lollipop">
<View
android:id="@+id/nv_scrim"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#99000000"
android:visibility="invisible"
tools:visibility="gone" />
<androidx.core.widget.NestedScrollView
android:id="@+id/nv_bottomSheet"
style="@style/width_max_600dp"
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/nv_extendedFloatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:behavior_hideable="true"
app:behavior_peekHeight="auto"
app:layout_behavior="@string/bottom_sheet_behavior"
tools:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bottom_sheet_background"
android:paddingStart="8dp"
android:paddingEnd="8dp">
<include
layout="@layout/bottom_sheet_fragment_theme_info"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
android:layout_margin="16dp"
android:clickable="true"
android:focusable="true"
android:visibility="visible"
android:text=""
app:backgroundTint="?colorAccent"
app:icon="@android:drawable/ic_menu_edit"
app:layout_anchor="@+id/nv_bottomBar"
app:layout_anchorGravity="center|top"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout>
<pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
android:id="@+id/nv_bottomSheet"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<View
android:id="@+id/nv_statusBarDarker"
android:layout_width="match_parent"
android:layout_height="0dp"
tools:layout_height="25dp"
android:background="#22000000" />
</merge>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="color">#202196f3</color>
<color name="blue">#154FBC</color>
</resources>

View File

@ -1 +1 @@
include ':app', ':MaterialDrawer', ':navlib'
include ':app', ':navlib'