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 /build
/captures /captures
.externalNativeBuild .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"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/MaterialDrawer" />
<option value="$PROJECT_DIR$/app" /> <option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/navlib" /> <option value="$PROJECT_DIR$/navlib" />
</set> </set>

View File

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

View File

@ -31,10 +31,11 @@ dependencies {
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.appcompat:appcompat:1.0.2'
implementation "androidx.legacy:legacy-support-v4:1.0.0" 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: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-core:${iconics}" // do not update. >3.1.0 Breaks jelly bean
implementation "com.mikepenz:iconics-views:${iconics}" // do not update 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.core:core-ktx:1.0.1'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation "com.google.android.material:material:$material_version" implementation "com.google.android.material:material:$material_version"

View File

@ -1,6 +1,6 @@
# Add project specific ProGuard rules here. # Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the # 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 # For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html # 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" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pl.szczodrzynski.navigation"> package="pl.szczodrzynski.navigation">
<uses-permission android:name="android.permission.INTERNET" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme.Light"> android:theme="@style/AppTheme.Light"
android:windowSoftInputMode="adjustResize">
<activity android:name=".MainActivity"> <activity android:name=".MainActivity">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

View File

@ -1,21 +1,20 @@
package pl.szczodrzynski.navigation package pl.szczodrzynski.navigation
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.MotionEvent
import android.view.View 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 android.widget.Toast
import androidx.core.widget.NestedScrollView import android.view.Gravity
import com.google.android.material.bottomappbar.BottomAppBar
import android.view.WindowManager
import android.os.Build
import kotlinx.android.synthetic.main.sample_nav_view.* 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() { class MainActivity : AppCompatActivity() {
@ -23,8 +22,7 @@ class MainActivity : AppCompatActivity() {
var darkTheme: Boolean? = null var darkTheme: Boolean? = null
} }
var showing = false @SuppressLint("ApplySharedPref")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -36,19 +34,30 @@ class MainActivity : AppCompatActivity() {
setContentView(R.layout.sample_nav_view) setContentView(R.layout.sample_nav_view)
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or (when { appFullscreen.isChecked = getSharedPreferences("prefs", Context.MODE_PRIVATE).getBoolean("appFullscreen", false)
darkTheme == true -> 0 statusBarDarker.isChecked = getSharedPreferences("prefs", Context.MODE_PRIVATE).getBoolean("statusBarDarker", false)
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR statusBarTranslucent.isChecked = getSharedPreferences("prefs", Context.MODE_PRIVATE).getBoolean("statusBarTranslucent", false)
else -> 0 navigationBarTransparent.isChecked = getSharedPreferences("prefs", Context.MODE_PRIVATE).getBoolean("navigationBarTransparent", true)
})
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { statusBarColor.check(when (getSharedPreferences("prefs", Context.MODE_PRIVATE).getString("statusBarColor", "colorBackground")) {
val w = window // in Activity's onCreate() for instance "colorPrimaryDark" -> R.id.colorPrimaryDark
w.setFlags( "colorPrimary" -> R.id.colorPrimary
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, "colorAccent" -> R.id.colorAccent
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS "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 { button.setOnClickListener {
// use commit instead of apply because of recreating the activity // use commit instead of apply because of recreating the activity
@ -57,62 +66,136 @@ class MainActivity : AppCompatActivity() {
recreate() recreate()
} }
/*val dim = findViewById<View>(R.id.view)
val nestedScrollView = findViewById<View>(R.id.nestedScrollView) //navView.init(this)
val bottomSheetBehavior = BottomSheetBehavior.from(nestedScrollView)
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN // init the drawer before SystemBarsUtil
navView.addDrawer(activity = this)
val fab = findViewById<FloatingActionButton>(R.id.floatingActionButton) SystemBarsUtil(this).apply {
fab.setOnClickListener { paddingByKeyboard = navView
if (bottomSheetBehavior.state == BottomSheetBehavior.STATE_HIDDEN) { appFullscreen = this@MainActivity.appFullscreen.isChecked
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED 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 { statusBarDarker = this@MainActivity.statusBarDarker.isChecked
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN 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 -> statusBarDarker.setOnCheckedChangeListener { _, isChecked ->
if (event.action == MotionEvent.ACTION_UP) { getSharedPreferences("prefs", Context.MODE_PRIVATE).edit().putBoolean("statusBarDarker", isChecked).commit()
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN recreate()
} }
true 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) statusBarColor.setOnCheckedChangeListener { _, checkedId ->
bottomAppBar.setOnTouchListener { v, event -> getSharedPreferences("prefs", Context.MODE_PRIVATE).edit().putString("statusBarColor",
Log.d("Main", "Y: ${event.y}, Raw Y: ${event.rawY}") when (checkedId) {
event.setLocation(event.rawX, event.rawY) R.id.colorPrimaryDark -> "colorPrimaryDark"
nestedScrollView.dispatchTouchEvent(event) 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() { navView.enableBottomSheetDrag = true
override fun onSlide(bottomSheet: View, slideOffset: Float) { 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) { navView.setFabOnClickListener(View.OnClickListener {
when (newState) { Toast.makeText(this, "FAB clicked", Toast.LENGTH_SHORT).show()
BottomSheetBehavior.STATE_HIDDEN -> { })
if (showing) {
showing = false scrimClose.setOnCheckedChangeListener { _, isChecked ->
Anim.fadeOut(dim, 300, null) navView.bottomSheet.scrimViewTapToClose = isChecked
} }
}
else -> { scrimEnable.setOnCheckedChangeListener {_, isChecked ->
if (!showing) { navView.bottomSheet.scrimViewEnabled = isChecked
showing = true }
Anim.fadeIn(dim, 300, null)
} fabPosition.setOnCheckedChangeListener { _, checkedId ->
} navView.bottomBar.fabGravity = if (checkedId == R.id.fabCenter) Gravity.CENTER else Gravity.END
} }
//Toast.makeText(this@MainActivity, "Bottom Sheet State Changed to: $state", Toast.LENGTH_SHORT).show()
} 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"> xmlns:tools="http://schemas.android.com/tools">
<pl.szczodrzynski.navlib.NavView <pl.szczodrzynski.navlib.NavView
android:id="@+id/navView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:orientation="vertical">
<Button <Button
android:id="@+id/button" android:id="@+id/button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="48dp" android:layout_height="48dp"
android:text="booton" /> android:text="Switch theme" />
<Switch <TextView
android:id="@+id/switch1" android:layout_width="match_parent"
android:layout_height="wrap_content"
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_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Switch" /> android:checked="true"
android:text="Toolbar" />
<ProgressBar <com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/progressBar2" android:id="@+id/switchBottomAppBar"
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_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="8dp"> android:checked="true"
android:text="Bottom app bar" />
<LinearLayout <com.google.android.material.switchmaterial.SwitchMaterial
android:layout_width="match_parent" android:id="@+id/switchFab"
android:layout_height="match_parent" android:layout_width="wrap_content"
android:orientation="vertical" android:layout_height="wrap_content"
android:padding="16dp"> android:checked="true"
android:text="FAB" />
<androidx.appcompat.widget.AppCompatImageView <com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/iconImageView" 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_width="match_parent"
android:layout_height="0dp" 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:layout_weight="1"
android:contentDescription="Card Icon" android:checked="true"
app:tint="?attr/colorOnSurface" /> android:text="FAB center" />
<androidx.appcompat.widget.AppCompatTextView <RadioButton
android:id="@+id/titleTextView" 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_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:text="BottomSheet config"
android:textAppearance="?attr/textAppearanceHeadline6" android:textAppearance="@style/TextAppearance.AppCompat.Large" />
android:textColor="?attr/colorOnSurface"
tools:text="Title" /> <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> </LinearLayout>
</com.google.android.material.card.MaterialCardView>
</ScrollView>
</pl.szczodrzynski.navlib.NavView> </pl.szczodrzynski.navlib.NavView>

View File

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

View File

@ -6,11 +6,11 @@ buildscript {
repositories { repositories {
google() google()
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.0-rc03' classpath 'com.android.tools.build:gradle:3.5.0-rc03'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 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 // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }
@ -20,7 +20,7 @@ allprojects {
repositories { repositories {
google() google()
jcenter() jcenter()
maven { url 'https://jitpack.io' }
} }
} }
@ -36,9 +36,9 @@ ext {
androidXCardView = '1.0.0' androidXCardView = '1.0.0'
androidXGridLayout = '1.0.0' androidXGridLayout = '1.0.0'
androidXConstraintLayout = '1.1.3' 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) { task clean(type: Delete) {

View File

@ -1,5 +1,6 @@
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android-extensions'
android { android {
compileSdkVersion 28 compileSdkVersion 28
@ -23,6 +24,13 @@ android {
} }
} }
dataBinding {
enabled = true
}
packagingOptions {
exclude 'META-INF/library-core_release.kotlin_module'
}
} }
dependencies { dependencies {
@ -32,4 +40,14 @@ dependencies {
implementation 'androidx.core:core-ktx:1.0.2' implementation 'androidx.core:core-ktx:1.0.2'
implementation 'com.google.android.material:material:1.1.0-alpha09' implementation 'com.google.android.material:material:1.1.0-alpha09'
implementation "androidx.legacy:legacy-support-v4:1.0.0" 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. # Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the # 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 # For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html # 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 package pl.szczodrzynski.navlib
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log import android.view.*
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.widget.FrameLayout import android.widget.*
import android.widget.LinearLayout
import android.widget.SeekBar
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.* import androidx.core.view.ViewCompat
import androidx.core.widget.NestedScrollView import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
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 com.google.android.material.floatingactionbutton.FloatingActionButton 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 kotlinx.android.synthetic.main.nav_view.view.*
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
class NavView : FrameLayout { class NavView : FrameLayout {
private var contentView: LinearLayout? = null 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 floatingActionButton: FloatingActionButton
private lateinit var scrimView: View private lateinit var extendedFloatingActionButton: ExtendedFloatingActionButton
private lateinit var bottomSheet: NestedScrollView
private lateinit var bottomSheetBehavior: BottomSheetBehavior<View> var drawer: Drawer? = null
private var bottomSheetVisible = false 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) { constructor(context: Context) : super(context) {
init(null, 0) create(null, 0)
} }
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { 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) { 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 // Load attributes
val a = context.obtainStyledAttributes(attrs, R.styleable.NavView, defStyle, 0) val a = context.obtainStyledAttributes(attrs, R.styleable.NavView, defStyle, 0)
/*_exampleString = a.getString( /*_exampleString = a.getString(
@ -93,78 +62,117 @@ class NavView : FrameLayout {
contentView = findViewById<LinearLayout>(R.id.nv_content) contentView = findViewById<LinearLayout>(R.id.nv_content)
//findViewById<TextView>(R.id.textView).text = "${displayWidth}dp x ${displayHeight}dp" statusBarBackground = findViewById(R.id.nv_statusBarBackground)
navigationBarBackground = findViewById(R.id.nv_navigationBarBackground)
// TODO add vars for status/navigation bar background mainView = findViewById(R.id.nv_main)
bottomAppBar = findViewById(R.id.nv_bottomAppBar)
floatingActionButton = findViewById(R.id.nv_floatingActionButton) 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) bottomSheet = findViewById(R.id.nv_bottomSheet)
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
bottomSheetBehavior.state = STATE_HIDDEN bottomBar.drawer = drawer
bottomSheetBehavior.peekHeight = displayHeight bottomBar.bottomSheet = bottomSheet
bottomBar.fabView = floatingActionButton
bottomBar.fabExtendedView = extendedFloatingActionButton
nv_main.setPadding( //bottomSheetBehavior.peekHeight = displayHeight
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
}
}
nv_elevation.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { nv_elevation.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
textView.text = "Set toolbar elevation ${progress}dp" 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 onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(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?) { override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
if (contentView == null) { if (contentView == null) {
super.addView(child, index, params) 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"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:shape="rectangle"> android:shape="rectangle">
<corners <corners
android:topLeftRadius="16dp" android:topLeftRadius="16dp"
android:topRightRadius="16dp" /> android:topRightRadius="16dp" />
<solid android:color="?colorBackgroundFloating" /> <solid android:color="#ffffff" tools:color="?colorBackgroundFloating" />
</shape> </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 <View
android:id="@+id/nv_statusBarBackground" android:id="@+id/nv_statusBarBackground"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="25dp" android:layout_height="0dp"
tools:layout_height="25dp"
android:background="?android:windowBackground" /> android:background="?android:windowBackground" />
<View <View
android:id="@+id/nv_navigationBarBackground" android:id="@+id/nv_navigationBarBackground"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="0dp"
tools:layout_height="48dp"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:background="?colorPrimaryDark" android:background="?colorPrimaryVariant"
tools: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 <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/nv_main" android:id="@+id/nv_main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:paddingTop="24dp" tools:paddingTop="24dp"
android:paddingBottom="48dp"> tools:paddingBottom="48dp">
<com.google.android.material.appbar.MaterialToolbar <pl.szczodrzynski.navlib.NavToolbar
android:id="@+id/nv_toolbar" android:id="@+id/nv_toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
@ -52,74 +59,67 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:max="20" android:max="20"
android:progress="4" /> android:progress="4"
android:visibility="gone" />
<TextView <TextView
android:id="@+id/textView" android:id="@+id/textView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Set toolbar elevation" /> android:text="Set toolbar elevation"
android:visibility="gone" />
</LinearLayout> </LinearLayout>
<com.google.android.material.bottomappbar.BottomAppBar <pl.szczodrzynski.navlib.NavBottomBar
android:id="@+id/nv_bottomAppBar" android:id="@+id/nv_bottomBar"
style="@style/Widget.MaterialComponents.BottomAppBar.Colored" style="@style/Widget.MaterialComponents.BottomAppBar.Colored"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
app:fabAlignmentMode="end" /> android:visibility="visible"
app:fabAlignmentMode="center"
app:fabAnimationMode="scale" />
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/nv_floatingActionButton" android:id="@+id/nv_floatingActionButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:visibility="gone"
app:layout_anchor="@id/nv_bottomBar"
app:backgroundTint="?colorAccent" app:backgroundTint="?colorAccent"
app:layout_anchor="@id/nv_bottomAppBar" app:srcCompat="@android:drawable/ic_menu_edit"/>
tools:srcCompat="@android:drawable/ic_lock_lock" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/nv_extendedFloatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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> </androidx.coordinatorlayout.widget.CoordinatorLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout </FrameLayout>
<pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
android:id="@+id/nv_bottomSheet"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent" />
android:translationZ="10dp"
tools:targetApi="lollipop">
<View <View
android:id="@+id/nv_scrim" android:id="@+id/nv_statusBarDarker"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="0dp"
android:background="#99000000" tools:layout_height="25dp"
android:visibility="invisible" android:background="#22000000" />
tools:visibility="gone" />
<androidx.core.widget.NestedScrollView
android:id="@+id/nv_bottomSheet"
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="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>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</merge> </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'