Fix navbar detection, again. Add text input to bottom sheet.

Add Drawer customization, drawer profiles, drawer badges, update Sample. Add text styles.
Completed BottomSheet & Drawer implementations.
This commit is contained in:
kubasz 2019-08-28 16:24:46 +02:00
parent 82fab7f934
commit ab7211e85c
35 changed files with 2262 additions and 417 deletions

View File

@ -35,7 +35,7 @@ dependencies {
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation "androidx.legacy:legacy-support-v4:1.0.0"
//implementation "com.mikepenz:materialdrawer:7.0.0-rc05"
implementation "com.mikepenz:materialdrawer:7.0.0-rc05"
//implementation "com.mikepenz:crossfader:1.6.0" // do not update
implementation "com.mikepenz:iconics-core:${iconics}" // do not update. >3.1.0 Breaks jelly bean
implementation "com.mikepenz:iconics-views:${iconics}" // do not update

View File

@ -3,6 +3,8 @@
package="pl.szczodrzynski.navigation">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
@ -10,9 +12,10 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme.Light"
android:windowSoftInputMode="adjustResize">
<activity android:name=".MainActivity">
android:theme="@style/AppTheme.Light"><!--
android:windowSoftInputMode="adjustResize"-->
<activity android:name=".MainActivity"
android:configChanges="screenSize|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@ -8,7 +8,16 @@ import android.view.Gravity
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.mikepenz.iconics.IconicsColor
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.IconicsSize
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import com.mikepenz.materialdrawer.Drawer
import com.mikepenz.materialdrawer.holder.StringHolder
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
import com.mikepenz.materialdrawer.model.ProfileDrawerItem
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem
import kotlinx.android.synthetic.main.sample_nav_view.*
import pl.szczodrzynski.navlib.SystemBarsUtil
import pl.szczodrzynski.navlib.SystemBarsUtil.Companion.COLOR_DO_NOT_CHANGE
@ -18,8 +27,10 @@ import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet.Companion.SORT_MODE_ASCENDING
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet.Companion.SORT_MODE_DESCENDING
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet.Companion.TOGGLE_GROUP_SORTING_ORDER
import pl.szczodrzynski.navlib.bottomsheet.items.PrimaryItem
import pl.szczodrzynski.navlib.bottomsheet.items.SeparatorItem
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
import pl.szczodrzynski.navlib.drawer.IDrawerProfile
import pl.szczodrzynski.navlib.drawer.items.DrawerPrimaryItem
import pl.szczodrzynski.navlib.getColorFromAttr
@ -38,6 +49,8 @@ class MainActivity : AppCompatActivity() {
Log.d("MainActivity", "Dark theme $darkTheme")
setTheme(if (darkTheme == true) R.style.AppTheme else R.style.AppTheme_Light)
Log.d("NavLib", "ACTIVITY created")
setContentView(R.layout.sample_nav_view)
appFullscreen.isChecked = getSharedPreferences("prefs", Context.MODE_PRIVATE).getBoolean("appFullscreen", true)
@ -65,18 +78,21 @@ class MainActivity : AppCompatActivity() {
else -> R.id.gradientDoNotChange
})
button.setOnClickListener {
themeButton.setOnClickListener {
// use commit instead of apply because of recreating the activity
darkTheme = (darkTheme == false)
getSharedPreferences("prefs", Context.MODE_PRIVATE).edit().putBoolean("darkTheme", darkTheme == true).commit()
recreate()
}
commitButton.setOnClickListener {
navView.systemBarsUtil?.commit()
}
//navView.init(this)
// init the drawer before SystemBarsUtil
navView.addDrawer(activity = this)
navView.drawer.init(this)
SystemBarsUtil(this).apply {
paddingByKeyboard = navView
@ -206,26 +222,150 @@ class MainActivity : AppCompatActivity() {
navView.bottomBar.fabExtended = false
navView.drawer.apply {
addUnreadCounterType(type = 10, drawerItem = 1)
addUnreadCounterType(type = 20, drawerItem = 2)
addUnreadCounterType(type = 30, drawerItem = 60)
addUnreadCounterType(type = 40, drawerItem = 62)
appendItems(
DrawerPrimaryItem()
.withAppTitle("Navigation")
.withName("Home")
.withSelected(true)
.withIdentifier(1)
.withBadgeStyle(badgeStyle)
.withIcon(CommunityMaterial.Icon.cmd_google_home),
DrawerPrimaryItem()
.withIdentifier(2)
.withName("Settings")
.withBadgeStyle(badgeStyle)
.withIcon(CommunityMaterial.Icon2.cmd_settings),
DrawerPrimaryItem().withName("iOS")
.withIdentifier(60)
.withBadgeStyle(badgeStyle)
.withIcon(CommunityMaterial.Icon.cmd_apple),
DrawerPrimaryItem().withName("School bell")
.withDescription("why not?")
.withIdentifier(61)
.withBadgeStyle(badgeStyle)
.withIcon(CommunityMaterial.Icon.cmd_alarm_bell),
DrawerPrimaryItem().withName("Lock screen")
.withIdentifier(62)
.withBadgeStyle(badgeStyle)
.withIcon(CommunityMaterial.Icon.cmd_fingerprint),
DrawerPrimaryItem().withName("HDR enable/disable")
.withTag(0)
.withIdentifier(63)
.withBadgeStyle(badgeStyle)
.withSelectable(false)
.withIcon(CommunityMaterial.Icon2.cmd_hdr),
DrawerPrimaryItem().withName("AdBlockPlus")
.withDescription("Because we all hate ads")
.withIdentifier(64)
.withBadgeStyle(badgeStyle)
.withIcon(CommunityMaterial.Icon.cmd_adchoices),
DrawerPrimaryItem().withName("Wonderful browsing experience and this is a long string")
.withIdentifier(65)
.withBadgeStyle(badgeStyle)
.withIcon(CommunityMaterial.Icon2.cmd_internet_explorer)
)
setUnreadCount(2, 20, 30) // phil swift has 30 unreads on "Settings item"
setUnreadCount(4, 40, 1000) // mark has 99+ unreads on "Lock screen item"
setAccountHeaderBackground("/sdcard/ban.gif")
appendProfiles(
IDrawerProfile(1, "Think Pad", "think with a pad", "/sdcard/thinkpad.gif"),
IDrawerProfile(2, "Phil Swift", "I sawed this boat in half!!!", "/sdcard/phil.jpg"),
IDrawerProfile(3, "The meme bay", "Visit my amazing website", "/sdcard/loader.gif"),
IDrawerProfile(4, "Mark Zuckerberg", "", null),
IDrawerProfile(5, "I love GDPR", "spotify:user:popjustice:playlist:5Pe51v0sHLybSEkX0m0JRf", "/sdcard/tenor2.gif"),
IDrawerProfile(6, "Gandalf", "http://sax.hol.es/", "/sdcard/facepalm.gif")
)
addProfileSettings(
ProfileSettingDrawerItem()
.withName("Add Account")
.withDescription("Add new GitHub Account")
.withIcon(
IconicsDrawable(context, CommunityMaterial.Icon2.cmd_plus)
.actionBar()
.padding(IconicsSize.dp(5))
.color(IconicsColor.colorRes(pl.szczodrzynski.navlib.R.color.material_drawer_dark_primary_text))
)
.withOnDrawerItemClickListener(object : Drawer.OnDrawerItemClickListener {
override fun onItemClick(view: View?, position: Int, drawerItem: IDrawerItem<*>): Boolean {
Toast.makeText(context, "Add account", Toast.LENGTH_SHORT).show()
return true
}
}),
ProfileSettingDrawerItem()
.withName("Manage Account")
.withIcon(CommunityMaterial.Icon2.cmd_settings)
)
drawerItemSelectedListener = { id, position, drawerItem ->
if (id == 1 || id == 2) {
getItemById(id) {
if (it is DrawerPrimaryItem) {
if (it.tag !is Int) {
it.tag = 0
}
it.tag = (it.tag as Int) + 1
// TODO 2019-08-27 allow string to be passed as name
it.name = StringHolder("Home ${it.tag as Int}")
// do not set item.badge unless you're not using Unread Counters
// because this *may* disappear/be overridden on profile change
// (if UnreadCounterList have at least one counter with matching
// drawer item ID)
// See with "Settings" when it.badge AND UnreadCounter is present.
//
// just do not do this.
it.badge = StringHolder("${it.tag as Int * 10}")
}
}
}
if (id == 63) {
getItemById(id) {
if (it is DrawerPrimaryItem) {
it.tag = if (it.tag as Int == 1) 0 else 1
it.withIcon(if (it.tag as Int == 1) CommunityMaterial.Icon2.cmd_hdr_off else CommunityMaterial.Icon2.cmd_hdr)
}
}
}
// you cannot select apple
id != 60
}
}
navView.bottomSheet.apply {
this += PrimaryItem(true)
this += BottomSheetPrimaryItem(true)
.withId(1)
.withTitle("Compose")
.withIcon(CommunityMaterial.Icon2.cmd_pencil)
.withOnClickListener(View.OnClickListener {
Toast.makeText(this@MainActivity, "Compose message", Toast.LENGTH_SHORT).show()
})
this += SeparatorItem(false)
this += PrimaryItem(false)
this += BottomSheetSeparatorItem(false)
this += BottomSheetPrimaryItem(false)
.withId(3)
.withTitle("Synchronise")
.withIcon(CommunityMaterial.Icon2.cmd_sync)
.withOnClickListener(View.OnClickListener {
Toast.makeText(this@MainActivity, "Synchronising...", Toast.LENGTH_SHORT).show()
})
this += PrimaryItem(false)
this += BottomSheetPrimaryItem(false)
.withId(4)
.withTitle("Help")
.withIcon(CommunityMaterial.Icon2.cmd_help)
@ -233,6 +373,7 @@ class MainActivity : AppCompatActivity() {
Toast.makeText(this@MainActivity, "Want some help?", Toast.LENGTH_SHORT).show()
})
toggleGroupEnabled = true
toggleGroupTitle = "Sort by"
toggleGroupRemoveItems()
toggleGroupSelectionMode = TOGGLE_GROUP_SORTING_ORDER
@ -240,16 +381,31 @@ class MainActivity : AppCompatActivity() {
toggleGroupAddItem(1, "By subject", null, SORT_MODE_ASCENDING)
toggleGroupAddItem(2, "By sender", null, SORT_MODE_ASCENDING)
toggleGroupAddItem(3, "By android", null, SORT_MODE_ASCENDING)
toggleGroupSortingOrderListener = object : NavBottomSheet.OnToggleGroupSortingListener {
override fun onSortingOrder(id: Int, sortMode: Int) {
Toast.makeText(
this@MainActivity,
"Sort mode $id ${if (sortMode == SORT_MODE_ASCENDING) "ascending" else "descending"}",
Toast.LENGTH_SHORT
).show()
}
toggleGroupSortingOrderListener = { id, sortMode ->
Toast.makeText(
this@MainActivity,
"Sort mode $id ${if (sortMode == SORT_MODE_ASCENDING) "ascending" else "descending"}",
Toast.LENGTH_SHORT
).show()
}
toggleGroupCheck(1)
textInputEnabled = true
textInputHint = "Search"
textInputHelperText = "0 messages found"
textInputIcon = CommunityMaterial.Icon2.cmd_magnify
textInputChangedListener = object : NavBottomSheet.OnTextInputChangedListener {
override fun onTextChanged(s: String, start: Int, before: Int, count: Int) {
navView.toolbar.subtitle = s
textInputError = if (s.length > 10) "Too many messages" else null
textInputHelperText = "${s.length} messages found"
}
}
}
}
override fun onBackPressed() {
if (!navView.onBackPressed())
super.onBackPressed()
}
}

View File

@ -8,6 +8,9 @@
android:id="@+id/navView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoTouch
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
@ -18,19 +21,25 @@
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:orientation="vertical">
android:orientation="vertical"
tools:ignore="HardcodedText">
<Button
android:id="@+id/button"
android:id="@+id/themeButton"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:text="Switch theme" />
<Button
android:id="@+id/commitButton"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:text="Commit SystemBarsUtil" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="NavView config"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
android:textAppearance="@style/NavView.TextView.Large" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchToolbar"
@ -71,7 +80,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="FAB config"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
android:textAppearance="@style/NavView.TextView.Large" />
<RadioGroup
android:id="@+id/fabPosition"
@ -99,7 +108,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="BottomSheet config"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
android:textAppearance="@style/NavView.TextView.Large" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/bsEnable"
@ -134,7 +143,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="System bars config"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
android:textAppearance="@style/NavView.TextView.Large" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/appFullscreen"
@ -147,12 +156,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Status bar color"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
android:textAppearance="@style/NavView.TextView.Medium" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="5.0+ with dark SB color, 6.0+" />
android:text="5.0+ with dark SB color, 6.0+"
android:textAppearance="@style/NavView.TextView.Small"/>
<RadioGroup
android:id="@+id/statusBarColor"
@ -205,12 +215,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Status bar fallback if light"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
android:textAppearance="@style/NavView.TextView.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" />
android:text="5.0 with SB color white, TouchWiz 4.1-4.3"
android:textAppearance="@style/NavView.TextView.Small"/>
<RadioGroup
android:id="@+id/statusBarFallbackLight"
@ -247,12 +258,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Status bar fallback if gradient"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
android:textAppearance="@style/NavView.TextView.Medium" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="4.4, 5.0 Huawei" />
android:text="4.4, 5.0 Huawei"
android:textAppearance="@style/NavView.TextView.Small"/>
<RadioGroup
android:id="@+id/statusBarFallbackGradient"
@ -290,12 +302,13 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"
android:text="SB color mode - translucent (not transparent)" />
android:text="SB color mode - translucent (not transparent)"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="(used for Huawei with EMUI Lollipop)"/>
android:text="(used for Huawei with EMUI Lollipop)"
android:textAppearance="@style/NavView.TextView.Small"/>
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/navigationBarTransparent"
@ -304,10 +317,255 @@
android:checked="false"
android:text="Nav bar fully transparent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NavView text appearances"
android:textAppearance="@style/NavView.TextView.Large"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Default text appearance"
android:ellipsize="end"
android:maxLines="1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="NavView.TextView.Title"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/NavView.TextView.Title"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="NavView.TextView.Subtitle"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/NavView.TextView.Subtitle"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="NavView.TextView.Large"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/NavView.TextView.Large"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="NavView.TextView.Medium"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/NavView.TextView.Medium"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="NavView.TextView.Small"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/NavView.TextView.Small"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is a list of predefined text appearances"
android:textAppearance="@style/TextAppearance.AppCompat.Large"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextAppearance.AppCompat:"
android:textAppearance="?textAppearanceHeadline6"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.AppCompat.Title"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.AppCompat.Title"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.AppCompat.Subhead"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.AppCompat.Large"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.AppCompat.Large"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.AppCompat.Medium"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.AppCompat.Small"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.AppCompat.Small"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents:"
android:textAppearance="?textAppearanceHeadline6"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Subtitle1"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Subtitle2"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Body1"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Body2"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Button"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Button" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Caption"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Headline1"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline1" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Headline2"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline2" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Headline3"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline3" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Headline4"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline4" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Headline5"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Headline6"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Overline"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Overline" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.Design.Error"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Design.Error" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.Design.Tab"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Design.Tab" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.Design.HelperText"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Design.HelperText" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.Design.Hint"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Design.Hint" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.Design.Counter"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Design.Counter" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.Design.Counter.Overflow"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Design.Counter.Overflow" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextAppearance.MaterialComponents.Badge"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Badge" />
</LinearLayout>
</ScrollView>
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoTouch>
</pl.szczodrzynski.navlib.NavView>

View File

@ -4,7 +4,6 @@
<item name="colorPrimary">#64b5f6</item>
<item name="colorPrimaryDark">#1976d2</item>
<item name="colorPrimaryVariant">#2196f3</item>
<!--<item name="colorAccent">#ffb300</item>-->
<item name="colorAccent">#2962ff</item>
<item name="colorSecondary">?colorAccent</item>
@ -20,7 +19,6 @@
<item name="colorPrimary">#2196f3</item>
<item name="colorPrimaryDark">#1976d2</item>
<item name="colorPrimaryVariant">#2196f3</item>
<!--<item name="colorAccent">#ffb300</item>-->
<item name="colorAccent">#2962ff</item>
<item name="colorSecondary">?colorAccent</item>

View File

@ -44,6 +44,7 @@ dependencies {
implementation "com.mikepenz:materialdrawer:7.0.0-rc05"
implementation "com.mikepenz:iconics-core:4.0.1-b01"
implementation 'com.mikepenz:community-material-typeface:3.5.95.1-kotlin@aar'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15'
implementation "androidx.appcompat:appcompat:${androidXAppCompat}"
implementation "androidx.recyclerview:recyclerview:${androidXRecyclerView}"

View File

@ -0,0 +1,208 @@
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package pl.szczodrzynski.edziennik.utils;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
/**
* The SwipeRefreshLayout should be used whenever the user can refresh the
* contents of a view via a vertical swipe gesture. The activity that
* instantiates this view should add an OnRefreshListener to be notified
* whenever the swipe to refresh gesture is completed. The SwipeRefreshLayout
* will notify the listener each and every time the gesture is completed again;
* the listener is responsible for correctly determining when to actually
* initiate a refresh of its content. If the listener determines there should
* not be a refresh, it must call setRefreshing(false) to cancel any visual
* indication of a refresh. If an activity wishes to show just the progress
* animation, it should call setRefreshing(true). To disable the gesture and
* progress animation, call setEnabled(false) on the view.
* <p>
* This layout should be made the parent of the view that will be refreshed as a
* result of the gesture and can only support one direct child. This view will
* also be made the target of the gesture and will be forced to match both the
* width and the height supplied in this layout. The SwipeRefreshLayout does not
* provide accessibility events; instead, a menu item must be provided to allow
* refresh of the content wherever this gesture is used.
* </p>
*/
public class SwipeRefreshLayoutNoIndicator extends SwipeRefreshLayout {
private SwipeRefreshLayoutNoTouch parent;
@Override
public void setEnabled(boolean enabled) {
if (parent == null)
return;
parent.setEnabled(enabled);
super.setEnabled(enabled);
}
public void setParent(SwipeRefreshLayoutNoTouch parent) {
this.parent = parent;
}
/**
* Simple constructor to use when creating a SwipeRefreshLayout from code.
*
* @param context
*/
public SwipeRefreshLayoutNoIndicator(@NonNull Context context) {
this(context, null);
}
/**
* Constructor that is called when inflating SwipeRefreshLayout from XML.
*
* @param context
* @param attrs
*/
public SwipeRefreshLayoutNoIndicator(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
ev.setSource(0x10000000);
boolean parentConsumed = parent.onInterceptTouchEvent(ev);
boolean superConsumed = super.onInterceptTouchEvent(ev);
return parentConsumed && superConsumed;
/*if (super.onInterceptTouchEvent(ev))
return parent.onInterceptTouchEvent(ev);
return false;*/
}
@Override
public void requestDisallowInterceptTouchEvent(boolean b) {
parent.requestDisallowInterceptTouchEvent(b);
}
// NestedScrollingParent
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
parent.onStartNestedScroll(child, target, nestedScrollAxes);
return !parent.isRefreshing() && super.onStartNestedScroll(child, target, nestedScrollAxes);
}
@Override
public void onNestedScrollAccepted(View child, View target, int axes) {
parent.onNestedScrollAccepted(child, target, axes);
}
@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
parent.onNestedPreScroll(target, dx, dy, consumed);
}
@Override
public int getNestedScrollAxes() {
return parent.getNestedScrollAxes();
}
@Override
public void onStopNestedScroll(View target) {
parent.onStopNestedScroll(target);
}
@Override
public void onNestedScroll(final View target, final int dxConsumed, final int dyConsumed,
final int dxUnconsumed, final int dyUnconsumed) {
parent.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
}
// NestedScrollingChild
@Override
public void setNestedScrollingEnabled(boolean enabled) {
if (parent == null)
return;
//parent.setNestedScrollingEnabled(enabled);
super.setNestedScrollingEnabled(enabled);
}
@Override
public boolean isNestedScrollingEnabled() {
return parent.isNestedScrollingEnabled();
}
@Override
public boolean startNestedScroll(int axes) {
return parent.startNestedScroll(axes);
}
@Override
public void stopNestedScroll() {
parent.stopNestedScroll();
}
@Override
public boolean hasNestedScrollingParent() {
return parent.hasNestedScrollingParent();
}
@Override
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
int dyUnconsumed, int[] offsetInWindow) {
return super.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
}
@Override
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
return super.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
}
@Override
public boolean onNestedPreFling(View target, float velocityX,
float velocityY) {
return parent.onNestedPreFling(target, velocityX, velocityY);
}
@Override
public boolean onNestedFling(View target, float velocityX, float velocityY,
boolean consumed) {
return parent.onNestedFling(target, velocityX, velocityY, consumed);
}
@Override
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
return parent.dispatchNestedFling(velocityX, velocityY, consumed);
}
@Override
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
return parent.dispatchNestedPreFling(velocityX, velocityY);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
ev.setSource(0x10000000);
/*boolean consumed = super.onTouchEvent(ev);
if (consumed) {
return false;
}*/
return parent.onTouchEvent(ev);
}
}

View File

@ -7,7 +7,6 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

View File

@ -0,0 +1,279 @@
package pl.szczodrzynski.navlib
import android.annotation.TargetApi
import android.content.Context
import android.graphics.*
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewOutlineProvider
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.view.ViewCompat
import com.mikepenz.materialdrawer.R
import com.mikepenz.materialdrawer.util.DrawerImageLoader
import pl.droidsonroids.gif.GifImageView
/**
* An [android.widget.ImageView] that draws its contents inside a mask and draws a border
* drawable on top. This is useful for applying a beveled look to image contents, but is also
* flexible enough for use with other desired aesthetics.
*/
open class BezelGifImageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : GifImageView(context, attrs, defStyle) {
private val mBlackPaint: Paint
private val mMaskedPaint: Paint
private var mBounds: Rect? = null
private var mBoundsF: RectF? = null
private val mMaskDrawable: Drawable?
private var mDrawCircularShadow = true
private var mDesaturateColorFilter: ColorMatrixColorFilter? = null
private val mSelectorAlpha = 150
private var mSelectorColor: Int = 0
private var mSelectorFilter: ColorFilter? = null
private var mCacheValid = false
private var mCacheBitmap: Bitmap
private var mCachedWidth: Int = 0
private var mCachedHeight: Int = 0
private var mIsPressed = false
private var mIsSelected: Boolean = false
private var mTempDesaturateColorFilter: ColorMatrixColorFilter? = null
private var mTempSelectorFilter: ColorFilter? = null
init {
// Attribute initialization
val a = context.obtainStyledAttributes(attrs, R.styleable.BezelImageView, defStyle, R.style.BezelImageView)
mMaskDrawable = a.getDrawable(R.styleable.BezelImageView_biv_maskDrawable)
if (mMaskDrawable != null) {
mMaskDrawable.callback = this
}
mDrawCircularShadow = a.getBoolean(R.styleable.BezelImageView_biv_drawCircularShadow, true)
mSelectorColor = a.getColor(R.styleable.BezelImageView_biv_selectorOnPress, 0)
a.recycle()
// Other initialization
mBlackPaint = Paint()
mBlackPaint.color = -0x1000000
mMaskedPaint = Paint()
mMaskedPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
// Always want a cache allocated.
mCacheBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
// Create a desaturate color filter for pressed state.
val cm = ColorMatrix()
cm.setSaturation(0f)
mDesaturateColorFilter = ColorMatrixColorFilter(cm)
//create a selectorFilter if we already have a color
if (mSelectorColor != 0) {
this.mSelectorFilter = PorterDuffColorFilter(Color.argb(mSelectorAlpha, Color.red(mSelectorColor), Color.green(mSelectorColor), Color.blue(mSelectorColor)), PorterDuff.Mode.SRC_ATOP)
}
}
override fun onSizeChanged(w: Int, h: Int, old_w: Int, old_h: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mDrawCircularShadow) {
outlineProvider = CustomOutline(w, h)
}
}
}
@TargetApi(21)
private inner class CustomOutline internal constructor(internal var width: Int, internal var height: Int) : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
outline.setOval(0, 0, width, height)
}
}
override fun setFrame(l: Int, t: Int, r: Int, b: Int): Boolean {
val changed = super.setFrame(l, t, r, b)
mBounds = Rect(0, 0, r - l, b - t).also {
mBoundsF = RectF(it)
if (mMaskDrawable != null) {
mMaskDrawable.bounds = it
}
}
if (changed) {
mCacheValid = false
}
return changed
}
override fun onDraw(canvas: Canvas) {
val bounds = mBounds ?: return
val width = bounds.width()
val height = bounds.height()
if (width == 0 || height == 0) {
return
}
if (!mCacheValid || width != mCachedWidth || height != mCachedHeight || mIsSelected != mIsPressed) {
// Need to redraw the cache
if (width == mCachedWidth && height == mCachedHeight) {
// Have a correct-sized bitmap cache already allocated. Just erase it.
mCacheBitmap.eraseColor(0)
} else {
// Allocate a new bitmap with the correct dimensions.
mCacheBitmap.recycle()
mCacheBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
mCachedWidth = width
mCachedHeight = height
}
val cacheCanvas = Canvas(mCacheBitmap)
when {
mMaskDrawable != null -> {
val sc = cacheCanvas.save()
mMaskDrawable.draw(cacheCanvas)
if (mIsSelected) {
if (mSelectorFilter != null) {
mMaskedPaint.colorFilter = mSelectorFilter
} else {
mMaskedPaint.colorFilter = mDesaturateColorFilter
}
} else {
mMaskedPaint.colorFilter = null
}
cacheCanvas.saveLayer(mBoundsF, mMaskedPaint, Canvas.ALL_SAVE_FLAG)
super.onDraw(cacheCanvas)
cacheCanvas.restoreToCount(sc)
}
mIsSelected -> {
val sc = cacheCanvas.save()
cacheCanvas.drawRect(0f, 0f, mCachedWidth.toFloat(), mCachedHeight.toFloat(), mBlackPaint)
if (mSelectorFilter != null) {
mMaskedPaint.colorFilter = mSelectorFilter
} else {
mMaskedPaint.colorFilter = mDesaturateColorFilter
}
cacheCanvas.saveLayer(mBoundsF, mMaskedPaint, Canvas.ALL_SAVE_FLAG)
super.onDraw(cacheCanvas)
cacheCanvas.restoreToCount(sc)
}
else -> super.onDraw(cacheCanvas)
}
}
// Draw from cache
canvas.drawBitmap(mCacheBitmap, bounds.left.toFloat(), bounds.top.toFloat(), null)
//remember the previous press state
mIsPressed = isPressed
}
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
// Check for clickable state and do nothing if disabled
if (!this.isClickable) {
this.mIsSelected = false
return super.onTouchEvent(event)
}
// Set selected state based on Motion Event
when (event.action) {
MotionEvent.ACTION_DOWN -> this.mIsSelected = true
MotionEvent.ACTION_UP, MotionEvent.ACTION_SCROLL, MotionEvent.ACTION_OUTSIDE, MotionEvent.ACTION_CANCEL -> this.mIsSelected = false
}
// Redraw image and return super type
this.invalidate()
return super.dispatchTouchEvent(event)
}
override fun drawableStateChanged() {
super.drawableStateChanged()
if (mMaskDrawable != null && mMaskDrawable.isStateful) {
mMaskDrawable.state = drawableState
}
if (isDuplicateParentStateEnabled) {
ViewCompat.postInvalidateOnAnimation(this)
}
}
override fun invalidateDrawable(who: Drawable) {
if (who === mMaskDrawable) {
invalidate()
} else {
super.invalidateDrawable(who)
}
}
override fun verifyDrawable(who: Drawable): Boolean {
return who === mMaskDrawable || super.verifyDrawable(who)
}
/**
* Sets the color of the selector to be draw over the
* CircularImageView. Be sure to provide some opacity.
*
* @param selectorColor The color (including alpha) to set for the selector overlay.
*/
fun setSelectorColor(selectorColor: Int) {
this.mSelectorColor = selectorColor
this.mSelectorFilter = PorterDuffColorFilter(Color.argb(mSelectorAlpha, Color.red(mSelectorColor), Color.green(mSelectorColor), Color.blue(mSelectorColor)), PorterDuff.Mode.SRC_ATOP)
this.invalidate()
}
override fun setImageDrawable(drawable: Drawable?) {
super.setImageDrawable(drawable)
}
override fun setImageResource(resId: Int) {
super.setImageResource(resId)
}
override fun setImageBitmap(bm: Bitmap) {
super.setImageBitmap(bm)
}
override fun setImageURI(uri: Uri?) {
if ("http" == uri?.scheme || "https" == uri?.scheme) {
DrawerImageLoader.instance.setImage(this, uri, null)
} else {
super.setImageURI(uri)
}
}
fun disableTouchFeedback(disable: Boolean) {
if (disable) {
mTempDesaturateColorFilter = this.mDesaturateColorFilter
mTempSelectorFilter = this.mSelectorFilter
this.mSelectorFilter = null
this.mDesaturateColorFilter = null
} else {
if (mTempDesaturateColorFilter != null) {
this.mDesaturateColorFilter = mTempDesaturateColorFilter
}
if (mTempSelectorFilter != null) {
this.mSelectorFilter = mTempSelectorFilter
}
}
}
}

View File

@ -0,0 +1,68 @@
package pl.szczodrzynski.navlib
import android.view.View
import com.mikepenz.materialdrawer.*
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.IProfile
fun DrawerBuilder.withOnDrawerItemClickListener(listener: (view: View?, position: Int, drawerItem: IDrawerItem<*>) -> Boolean): DrawerBuilder {
return this.withOnDrawerItemClickListener(object : Drawer.OnDrawerItemClickListener {
override fun onItemClick(view: View?, position: Int, drawerItem: IDrawerItem<*>): Boolean {
return listener(view, position, drawerItem)
}
})
}
fun DrawerBuilder.withOnDrawerItemLongClickListener(listener: (view: View, position: Int, drawerItem: IDrawerItem<*>) -> Boolean): DrawerBuilder {
return this.withOnDrawerItemLongClickListener(object : Drawer.OnDrawerItemLongClickListener {
override fun onItemLongClick(view: View, position: Int, drawerItem: IDrawerItem<*>): Boolean {
return listener(view, position, drawerItem)
}
})
}
fun AccountHeaderBuilder.withOnAccountHeaderListener(listener: (view: View?, profile: IProfile<*>, current: Boolean) -> Boolean): AccountHeaderBuilder {
return this.withOnAccountHeaderListener(object : AccountHeader.OnAccountHeaderListener {
override fun onProfileChanged(view: View?, profile: IProfile<*>, current: Boolean): Boolean {
return listener(view, profile, current)
}
})
}
fun AccountHeaderBuilder.withOnAccountHeaderItemLongClickListener(listener: (view: View, profile: IProfile<*>, current: Boolean) -> Boolean): AccountHeaderBuilder {
return this.withOnAccountHeaderItemLongClickListener(object : AccountHeader.OnAccountHeaderItemLongClickListener {
override fun onProfileLongClick(view: View, profile: IProfile<*>, current: Boolean): Boolean {
return listener(view, profile, current)
}
})
}
fun AccountHeaderBuilder.withOnAccountHeaderProfileImageListener(
onClick: (
view: View,
profile: IProfile<*>,
current: Boolean
) -> Boolean,
onLongClick: (
view: View,
profile: IProfile<*>,
current: Boolean
) -> Boolean
): AccountHeaderBuilder {
return this.withOnAccountHeaderProfileImageListener(object : AccountHeader.OnAccountHeaderProfileImageListener {
override fun onProfileImageClick(view: View, profile: IProfile<*>, current: Boolean): Boolean {
return onClick(view, profile, current)
}
override fun onProfileImageLongClick(view: View, profile: IProfile<*>, current: Boolean): Boolean {
return onLongClick(view, profile, current)
}
})
}
fun MiniDrawer.withOnMiniDrawerItemClickListener(listener: (view: View?, position: Int, drawerItem: IDrawerItem<*>, type: Int) -> Boolean): MiniDrawer {
return this.withOnMiniDrawerItemClickListener(object : MiniDrawer.OnMiniDrawerItemClickListener {
override fun onItemClick(view: View?, position: Int, drawerItem: IDrawerItem<*>, type: Int): Boolean {
return listener(view, position, drawerItem, type)
}
})
}

View File

@ -0,0 +1,74 @@
package pl.szczodrzynski.navlib
import android.content.Context
import android.graphics.Bitmap
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.net.Uri
import android.view.View
import android.widget.ImageView
import androidx.annotation.DrawableRes
import androidx.appcompat.content.res.AppCompatResources
import com.mikepenz.iconics.IconicsColor
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.IconicsSize
import com.mikepenz.iconics.typeface.IIcon
import com.mikepenz.materialdrawer.util.DrawerImageLoader
import pl.droidsonroids.gif.GifDrawable
import java.io.FileNotFoundException
/**
* Created by mikepenz on 13.07.15.
*/
open class ImageHolder : com.mikepenz.materialdrawer.holder.ImageHolder {
constructor(url: String) : super(url) {}
constructor(uri: Uri) : super(uri) {}
constructor(icon: Drawable?) : super(icon) {}
constructor(bitmap: Bitmap?) : super(bitmap) {}
constructor(@DrawableRes iconRes: Int) : super(iconRes) {}
constructor(iicon: IIcon) : super(null as Bitmap?) {
this.iIcon = iicon
}
/**
* sets an existing image to the imageView
*
* @param imageView
* @param tag used to identify imageViews and define different placeholders
* @return true if an image was set
*/
override fun applyTo(imageView: ImageView, tag: String?): Boolean {
val ii = iIcon
if (uri != null) {
if (uri.toString().endsWith(".gif", true)) {
imageView.setImageDrawable(GifDrawable(uri.toString()))
}
else {
val consumed = DrawerImageLoader.instance.setImage(imageView, uri, tag)
if (!consumed) {
imageView.setImageURI(uri)
}
}
} else if (icon != null) {
imageView.setImageDrawable(icon)
} else if (bitmap != null) {
imageView.setImageBitmap(bitmap)
} else if (iconRes != -1) {
imageView.setImageResource(iconRes)
} else if (ii != null) {
imageView.setImageDrawable(IconicsDrawable(imageView.context, ii).actionBar())
} else {
imageView.setImageBitmap(null)
return false
}
return true
}
}

View File

@ -1,7 +1,6 @@
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
@ -15,8 +14,8 @@ import com.mikepenz.iconics.typeface.IIcon
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
import pl.szczodrzynski.navlib.drawer.NavDrawer
class NavBottomBar : BottomAppBar {
constructor(context: Context) : super(context) {
@ -31,7 +30,7 @@ class NavBottomBar : BottomAppBar {
create(attrs, defStyle)
}
var drawer: Drawer? = null
var drawer: NavDrawer? = null
var bottomSheet: NavBottomSheet? = null
var fabView: FloatingActionButton? = null
var fabExtendedView: ExtendedFloatingActionButton? = null
@ -127,10 +126,7 @@ class NavBottomBar : BottomAppBar {
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
setNavigationOnClickListener {
if (drawer?.isDrawerOpen == true)
drawer?.closeDrawer()
else
drawer?.openDrawer()
drawer?.toggle()
}
super.setOnMenuItemClickListener {

View File

@ -1,44 +1,46 @@
package pl.szczodrzynski.navlib
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.content.res.Configuration.ORIENTATION_PORTRAIT
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.SeekBar
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import com.mikepenz.materialdrawer.Drawer
import com.mikepenz.materialdrawer.DrawerBuilder
import com.mikepenz.materialdrawer.model.DividerDrawerItem
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem
import kotlinx.android.synthetic.main.nav_view.view.*
import pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoTouch
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
import pl.szczodrzynski.navlib.drawer.NavDrawer
class NavView : FrameLayout {
companion object {
const val SOURCE_OTHER = 0
const val SOURCE_DRAWER = 1
const val SOURCE_BOTTOM_SHEET = 1
}
private var contentView: LinearLayout? = null
private lateinit var statusBarBackground: View
private lateinit var navigationBarBackground: View
private lateinit var mainView: CoordinatorLayout
private lateinit var mainView: LinearLayout
private lateinit var floatingActionButton: FloatingActionButton
private lateinit var extendedFloatingActionButton: ExtendedFloatingActionButton
var drawer: Drawer? = null
lateinit var topBar: NavToolbar
lateinit var drawer: NavDrawer
lateinit var toolbar: NavToolbar
lateinit var bottomBar: NavBottomBar
lateinit var bottomSheet: NavBottomSheet
var navigationLoader: NavigationLoader? = null
constructor(context: Context) : super(context) {
create(null, 0)
@ -71,33 +73,36 @@ class NavView : FrameLayout {
floatingActionButton = findViewById(R.id.nv_floatingActionButton)
extendedFloatingActionButton = findViewById(R.id.nv_extendedFloatingActionButton)
topBar = findViewById(R.id.nv_toolbar)
drawer = NavDrawer(
context,
findViewById(R.id.nv_drawerContainer),
findViewById(R.id.nv_fixedDrawerContainer),
findViewById(R.id.nv_miniDrawerContainerLandscape),
findViewById(R.id.nv_miniDrawerContainerPortrait)
)
toolbar = findViewById(R.id.nv_toolbar)
bottomBar = findViewById(R.id.nv_bottomBar)
bottomSheet = findViewById(R.id.nv_bottomSheet)
drawer.toolbar = toolbar
drawer.bottomBar = bottomBar
bottomBar.drawer = drawer
bottomBar.bottomSheet = bottomSheet
bottomBar.fabView = floatingActionButton
bottomBar.fabExtendedView = extendedFloatingActionButton
//bottomSheetBehavior.peekHeight = displayHeight
nv_elevation.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
textView.text = "Set toolbar elevation ${progress}dp"
nv_toolbar.elevation = progress * context.resources.displayMetrics.density
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
}
fun configSystemBarsUtil(systemBarsUtil: SystemBarsUtil) {
this.systemBarsUtil = systemBarsUtil
systemBarsUtil.statusBarBgView = statusBarBackground
systemBarsUtil.navigationBarBgView = navigationBarBackground
systemBarsUtil.statusBarDarkView = nv_statusBarDarker
//systemBarsUtil.navigationBarDarkView = navigationBarBackground
systemBarsUtil.paddingBySystemBars = mainView
systemBarsUtil.insetsListener = nv_drawerContainer
systemBarsUtil.marginBySystemBars = mainView
systemBarsUtil.paddingByNavigationBar = bottomSheet.getContentView()
}
@ -118,7 +123,7 @@ class NavView : FrameLayout {
* below the toolbar.
*/
var showToolbar = true; set(value) {
topBar.visibility = if (value) View.VISIBLE else View.GONE
toolbar.visibility = if (value) View.VISIBLE else View.GONE
field = value
setContentMargins()
}
@ -131,13 +136,7 @@ class NavView : FrameLayout {
extendedFloatingActionButton.setOnClickListener(onClickListener)
}
@SuppressLint("ClickableViewAccessibility")
fun init(activity: Activity) {
}
var systemBarsUtil: SystemBarsUtil? = null
private fun setContentMargins() {
val layoutParams = CoordinatorLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
@ -147,33 +146,37 @@ class NavView : FrameLayout {
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").withIcon(CommunityMaterial.Icon.cmd_google_home)
val item2 = SecondaryDrawerItem().withIdentifier(2).withName("Settings").withIcon(CommunityMaterial.Icon2.cmd_settings)
override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
drawer = DrawerBuilder(activity)
.withDrawerLayout(R.layout.material_drawer_fits_not)
.withRootView(R.id.nv_drawerContainer)
.withFullscreen(true)
.withTranslucentStatusBar(false)
.withTranslucentNavigationBar(false)
.withTranslucentNavigationBarProgrammatically(false)
.withToolbar(bottomBar)
.withDisplayBelowStatusBar(true)
.withActionBarDrawerToggleAnimated(true)
.addDrawerItems(
item1,
DividerDrawerItem(),
item2,
SecondaryDrawerItem().withName("Settings")
)
/*.withOnDrawerItemClickListener { view, position, drawerItem ->
true
}*/
.build()
Log.d(
"NavLib",
"CONFIGURATION CHANGED: ${newConfig?.screenWidthDp}x${newConfig?.screenHeightDp} "+if (newConfig?.orientation == ORIENTATION_PORTRAIT) "portrait" else "landscape"
)
bottomBar.drawer = drawer
systemBarsUtil?.commit()
drawer.decideDrawerMode(
newConfig?.orientation ?: ORIENTATION_PORTRAIT,
newConfig?.screenWidthDp ?: 0,
newConfig?.screenHeightDp ?: 0
)
}
fun onBackPressed(): Boolean {
if (drawer.isOpen) {
if (drawer.profileSelectionIsOpen) {
drawer.profileSelectionClose()
return true
}
drawer.close()
return true
}
if (bottomSheet.isOpen) {
bottomSheet.close()
return true
}
return false
}
override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {

View File

@ -0,0 +1,5 @@
package pl.szczodrzynski.navlib
interface NavigationLoader {
fun load(itemId: Int, callerId: Int, source: Int, args: Map<String, Any?>)
}

View File

@ -11,6 +11,7 @@ import android.view.View
import android.view.View.*
import android.view.Window
import android.view.WindowManager
import android.widget.Toast
import androidx.core.graphics.ColorUtils
import androidx.core.view.ViewCompat
import com.mikepenz.materialize.util.KeyboardUtil
@ -36,8 +37,6 @@ class SystemBarsUtil(private val activity: Activity) {
*/
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
@ -59,7 +58,7 @@ class SystemBarsUtil(private val activity: Activity) {
*
* This means it will display under the system bars
* and you should probably provide [statusBarBgView],
* [navigationBarBgView] and [paddingBySystemBars].
* [navigationBarBgView] and [marginBySystemBars].
*/
var appFullscreen = false
@ -126,13 +125,17 @@ class SystemBarsUtil(private val activity: Activity) {
var navigationBarDarkView: View? = null
/**
* A view which will have the padding added not to overlap with the status/nav bar.
* A view which will have the margin added not to overlap with the status/nav bar.
*/
var paddingBySystemBars: View? = null
var marginBySystemBars: View? = null
/**
* A view which will listen to the inset applying.
*/
var insetsListener: View? = null
/**
* A view which will have the padding added not to overlap with the nav bar.
* Useful for persistent bottom sheets.
* Requires [paddingBySystemBars].
* Requires [marginBySystemBars].
*/
var paddingByNavigationBar: View? = null
@ -140,6 +143,8 @@ class SystemBarsUtil(private val activity: Activity) {
private var insetsApplied = false
fun commit() {
Log.d("NavLib", "SystemBarsUtil applying")
insetsApplied = false
if (paddingByKeyboard != null) {
// thanks mikepenz for this life-saving class
keyboardUtil = KeyboardUtil(activity, paddingByKeyboard)
@ -289,11 +294,14 @@ class SystemBarsUtil(private val activity: Activity) {
}
// PADDING
if (paddingBySystemBars != null) {
if (insetsListener != null) {
if (SDK_INT >= LOLLIPOP) {
ViewCompat.setOnApplyWindowInsetsListener(paddingBySystemBars!!) { _, insets ->
ViewCompat.setOnApplyWindowInsetsListener(insetsListener!!) { _, insets ->
Toast.makeText(activity, "Insets applied ", Toast.LENGTH_SHORT).show()
Log.d("NavLib", "Got insets left = ${insets.systemWindowInsetLeft}, top = ${insets.systemWindowInsetTop}, right = ${insets.systemWindowInsetRight}, bottom = ${insets.systemWindowInsetBottom}")
if (insetsApplied)
return@setOnApplyWindowInsetsListener insets.consumeSystemWindowInsets()
Log.d("NavLib", "Applied insets left = ${insets.systemWindowInsetLeft}, top = ${insets.systemWindowInsetTop}, right = ${insets.systemWindowInsetRight}, bottom = ${insets.systemWindowInsetBottom}")
insetsApplied = true
applyPadding(
insets.systemWindowInsetLeft,
@ -313,7 +321,7 @@ class SystemBarsUtil(private val activity: Activity) {
var navigationBarSize = 0
if (hasNavigationBar(resources) && targetAppFullscreen) {
if (hasNavigationBar(activity) && targetAppFullscreen) {
val orientation = resources.configuration.orientation
val navigationBarRes = when {
@ -346,7 +354,7 @@ class SystemBarsUtil(private val activity: Activity) {
}
private fun applyPadding(left: Int, top: Int, right: Int, bottom: Int) {
paddingBySystemBars?.setPadding(left, top, right, bottom)
marginBySystemBars?.setPadding(left, top, right, bottom)
statusBarBgView?.layoutParams?.height = top
navigationBarBgView?.layoutParams?.height = bottom

View File

@ -13,6 +13,18 @@ import androidx.annotation.DrawableRes
import com.google.android.material.elevation.ElevationOverlayProvider
import com.mikepenz.iconics.IconicsColor
import com.mikepenz.iconics.IconicsDrawable
import android.util.DisplayMetrics
import android.view.Display
import android.view.WindowManager
import android.R.attr.y
import android.R.attr.x
import android.graphics.Point
import com.mikepenz.materialdrawer.Drawer
import com.mikepenz.materialdrawer.holder.StringHolder
import com.mikepenz.materialdrawer.model.BaseDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.Badgeable
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem
import pl.szczodrzynski.navlib.drawer.items.DrawerPrimaryItem
/*private val displayMetrics by lazy {
@ -90,9 +102,27 @@ fun isTablet(c: Context): Boolean {
return (c.resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE
}
fun hasNavigationBar(resources: Resources): Boolean {
val id = resources.getIdentifier("config_showNavigationBar", "bool", "android")
var hasNavigationBar = id > 0 && resources.getBoolean(id)
fun hasNavigationBar(context: Context): Boolean {
val id = context.resources.getIdentifier("config_showNavigationBar", "bool", "android")
var hasNavigationBar = id > 0 && context.resources.getBoolean(id)
if (!hasNavigationBar && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
val d = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
val realDisplayMetrics = DisplayMetrics()
d.getRealMetrics(realDisplayMetrics)
val realHeight = realDisplayMetrics.heightPixels
val realWidth = realDisplayMetrics.widthPixels
val displayMetrics = DisplayMetrics()
d.getMetrics(displayMetrics)
val displayHeight = displayMetrics.heightPixels
val displayWidth = displayMetrics.widthPixels
hasNavigationBar = realWidth - displayWidth > 0 || realHeight - displayHeight > 0
}
// Allow a system property to override this. Used by the emulator.
// See also hasNavigationBar().
@ -113,4 +143,12 @@ fun Context.getDrawableFromRes(@DrawableRes id: Int): Drawable {
else {
resources.getDrawable(id)
}
}
fun Drawer.updateBadge(identifier: Long, badge: StringHolder?) {
val drawerItem = getDrawerItem(identifier)
if (drawerItem is Badgeable<*>) {
drawerItem.withBadge(badge)
updateItem(drawerItem)
}
}

View File

@ -3,10 +3,9 @@ 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
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
class BottomSheetAdapter(val items: List<IBottomSheetItem<*>>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
@ -14,13 +13,10 @@ class BottomSheetAdapter(val items: List<IBottomSheetItem<*>>) : RecyclerView.Ad
init {
viewHolderProvider.registerViewHolderFactory(1, R.layout.nav_bs_item_primary) { itemView ->
PrimaryItem.ViewHolder(itemView)
BottomSheetPrimaryItem.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)
BottomSheetSeparatorItem.ViewHolder(itemView)
}
}

View File

@ -5,6 +5,9 @@ import android.content.Context
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.drawable.Drawable
import android.system.Os.close
import android.text.Editable
import android.text.TextWatcher
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.MotionEvent
@ -21,17 +24,17 @@ import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.button.MaterialButton
import com.google.android.material.button.MaterialButtonToggleGroup
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.paddingDp
import com.mikepenz.iconics.utils.sizeDp
import pl.szczodrzynski.navlib.Anim
import pl.szczodrzynski.navlib.R
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem
import pl.szczodrzynski.navlib.*
import pl.szczodrzynski.navlib.bottomsheet.items.IBottomSheetItem
import pl.szczodrzynski.navlib.bottomsheet.items.SeparatorItem
import pl.szczodrzynski.navlib.elevateSurface
import pl.szczodrzynski.navlib.getDrawableFromRes
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
class NavBottomSheet : CoordinatorLayout {
@ -60,6 +63,8 @@ class NavBottomSheet : CoordinatorLayout {
private lateinit var bottomSheet: NestedScrollView
private lateinit var content: LinearLayout
private lateinit var dragBar: View
private lateinit var textInputLayout: TextInputLayout
private lateinit var textInputEditText: TextInputEditText
private lateinit var toggleGroupContainer: LinearLayout
private lateinit var toggleGroup: MaterialButtonToggleGroup
private lateinit var toggleGroupTitleView: TextView
@ -68,7 +73,7 @@ class NavBottomSheet : CoordinatorLayout {
private lateinit var bottomSheetBehavior: BottomSheetBehavior<View>
private var bottomSheetVisible = false
val items = ArrayList<IBottomSheetItem<*>>()
private val items = ArrayList<IBottomSheetItem<*>>()
private val adapter = BottomSheetAdapter(items)
/**
@ -116,6 +121,8 @@ class NavBottomSheet : CoordinatorLayout {
bottomSheet = findViewById(R.id.bs_view)
content = findViewById(R.id.bs_content)
dragBar = findViewById(R.id.bs_dragBar)
textInputLayout = findViewById(R.id.bs_textInputLayout)
textInputEditText = findViewById(R.id.bs_textInputEditText)
toggleGroupContainer = findViewById(R.id.bs_toggleGroupContainer)
toggleGroup = findViewById(R.id.bs_toggleGroup)
toggleGroupTitleView = findViewById(R.id.bs_toggleGroupTitle)
@ -169,15 +176,15 @@ class NavBottomSheet : CoordinatorLayout {
}
toggleGroup.addOnButtonCheckedListener(toggleGroupCheckedListener)
textInputEditText.addTextChangedListener(textInputWatcher)
}
/* _____ _ _ _
|_ _| | ___ | | | |
| | | |_ ___ _ __ ___ ___ ( _ ) __| | __ _| |_ __ _
| | | __/ _ \ '_ ` _ \/ __| / _ \/\ / _` |/ _` | __/ _` |
_| |_| || __/ | | | | \__ \ | (_> < | (_| | (_| | || (_| |
|_____|\__\___|_| |_| |_|___/ \___/\/ \__,_|\__,_|\__\__,*/
/* _____ _
|_ _| |
| | | |_ ___ _ __ ___ ___
| | | __/ _ \ '_ ` _ \/ __|
_| |_| || __/ | | | | \__ \
|_____|\__\___|_| |_| |_|__*/
operator fun plusAssign(item: IBottomSheetItem<*>) {
appendItem(item)
}
@ -193,6 +200,9 @@ class NavBottomSheet : CoordinatorLayout {
items.add(index, item)
adapter.notifyItemInserted(index)
}
fun removeItemById(id: Int) {
items.filterNot { it.id == id }
}
fun removeItemAt(index: Int) {
items.removeAt(index)
adapter.notifyItemRemoved(index)
@ -210,10 +220,37 @@ class NavBottomSheet : CoordinatorLayout {
adapter.notifyDataSetChanged()
}
fun removeSeparators() {
items.filterNot { it is SeparatorItem }
items.filterNot { it is BottomSheetSeparatorItem }
adapter.notifyDataSetChanged()
}
fun getItemById(id: Int, run: (it: IBottomSheetItem<*>?) -> Unit) {
items.singleOrNull { it.id == id }.also {
run(it)
if (it != null)
adapter.notifyItemChanged(items.indexOf(it))
}
}
fun getItemByIndex(index: Int, run: (it: IBottomSheetItem<*>?) -> Unit) {
items.getOrNull(index).also {
run(it)
if (it != null)
adapter.notifyItemChanged(index)
}
}
/* _______ _
|__ __| | |
| | ___ __ _ __ _| | ___ __ _ _ __ ___ _ _ _ __
| |/ _ \ / _` |/ _` | |/ _ \ / _` | '__/ _ \| | | | '_ \
| | (_) | (_| | (_| | | __/ | (_| | | | (_) | |_| | |_) |
|_|\___/ \__, |\__, |_|\___| \__, |_| \___/ \__,_| .__/
__/ | __/ | __/ | | |
|___/ |___/ |___/ |*/
var toggleGroupEnabled
get() = toggleGroupContainer.visibility == View.VISIBLE
set(value) { toggleGroupContainer.visibility = if (value) View.VISIBLE else View.GONE }
var toggleGroupTitle
get() = toggleGroupTitleView.text.toString()
set(value) { toggleGroupTitleView.text = value }
@ -288,33 +325,68 @@ class NavBottomSheet : CoordinatorLayout {
else -> null
})
if (sortingMode != null) {
toggleGroupSortingOrderListener?.onSortingOrder(checkedId, sortingMode)
toggleGroupSortingOrderListener?.invoke(checkedId, sortingMode)
}
}
else if (toggleGroup.isSingleSelection && isChecked) {
toggleGroupSingleSelectionListener?.onSingleSelection(checkedId - 1)
toggleGroupSingleSelectionListener?.invoke(checkedId - 1)
}
else {
toggleGroupMultipleSelectionListener?.onMultipleSelection(checkedId - 1, isChecked)
toggleGroupMultipleSelectionListener?.invoke(checkedId - 1, isChecked)
}
}
interface OnToggleGroupChangeListener {
fun onSingleSelection(id: Int)
var toggleGroupSingleSelectionListener: ((id: Int) -> Unit)? = null
var toggleGroupMultipleSelectionListener: ((id: Int, checked: Boolean) -> Unit)? = null
var toggleGroupSortingOrderListener: ((id: Int, sortMode: Int) -> Unit)? = null
/* _______ _ _ _
|__ __| | | (_) | |
| | _____ _| |_ _ _ __ _ __ _ _| |_
| |/ _ \ \/ / __| | | '_ \| '_ \| | | | __|
| | __/> <| |_ | | | | | |_) | |_| | |_
|_|\___/_/\_\\__| |_|_| |_| .__/ \__,_|\__|
| |
|*/
var textInputEnabled
get() = textInputLayout.visibility == View.VISIBLE
set(value) { textInputLayout.visibility = if (value) View.VISIBLE else View.GONE }
var textInputText
get() = textInputEditText.text.toString()
set(value) { textInputEditText.setText(value) }
var textInputHint
get() = textInputLayout.hint.toString()
set(value) { textInputLayout.hint = value }
var textInputHelperText
get() = textInputLayout.helperText.toString()
set(value) { textInputLayout.helperText = value }
var textInputError
get() = textInputLayout.error
set(value) { textInputLayout.error = value }
var textInputIcon: Any?
get() = textInputLayout.startIconDrawable
set(value) {
textInputLayout.startIconDrawable = when (value) {
is Drawable -> value
is IIcon -> IconicsDrawable(context, value).sizeDp(24)/*.colorInt(Color.BLACK)*/
is Int -> context.getDrawableFromRes(value)
else -> null
}
}
private var textInputWatcher = 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) {
textInputChangedListener?.onTextChanged(s?.toString() ?: "", start, before, count)
}
}
var toggleGroupSingleSelectionListener: OnToggleGroupChangeListener? = null
interface OnToggleGroupCheckedListener {
fun onMultipleSelection(id: Int, checked: Boolean)
interface OnTextInputChangedListener {
fun onTextChanged(s: String, start: Int, before: Int, count: Int)
}
var toggleGroupMultipleSelectionListener: OnToggleGroupCheckedListener? = null
interface OnToggleGroupSortingListener {
fun onSortingOrder(id: Int, sortMode: Int)
}
var toggleGroupSortingOrderListener: OnToggleGroupSortingListener? = null
var textInputChangedListener: OnTextInputChangedListener? = null
@ -336,7 +408,7 @@ class NavBottomSheet : CoordinatorLayout {
bottomSheetBehavior.state = if (value) BottomSheetBehavior.STATE_EXPANDED else BottomSheetBehavior.STATE_HIDDEN
}
fun open() { isOpen = true }
fun close() { isOpen = true }
fun close() { isOpen = false }
fun toggle() {
if (!enable)
return

View File

@ -15,7 +15,7 @@ import pl.szczodrzynski.navlib.R
import pl.szczodrzynski.navlib.colorAttr
import pl.szczodrzynski.navlib.getColorFromAttr
data class PrimaryItem(override val isContextual: Boolean = true) : IBottomSheetItem<PrimaryItem.ViewHolder> {
data class BottomSheetPrimaryItem(override val isContextual: Boolean = true) : IBottomSheetItem<BottomSheetPrimaryItem.ViewHolder> {
/*_ _
| | | |
@ -67,47 +67,47 @@ data class PrimaryItem(override val isContextual: Boolean = true) : IBottomSheet
var iconicsIcon: IIcon? = null
var onClickListener: View.OnClickListener? = null
fun withId(id: Int): PrimaryItem {
fun withId(id: Int): BottomSheetPrimaryItem {
this.id = id
return this
}
fun withTitle(title: CharSequence): PrimaryItem {
fun withTitle(title: CharSequence): BottomSheetPrimaryItem {
this.title = title
this.titleRes = null
return this
}
fun withTitle(@StringRes title: Int): PrimaryItem {
fun withTitle(@StringRes title: Int): BottomSheetPrimaryItem {
this.title = null
this.titleRes = title
return this
}
fun withDescription(description: CharSequence): PrimaryItem {
fun withDescription(description: CharSequence): BottomSheetPrimaryItem {
this.description = description
this.descriptionRes = null
return this
}
fun withDescription(@StringRes description: Int): PrimaryItem {
fun withDescription(@StringRes description: Int): BottomSheetPrimaryItem {
this.description = null
this.descriptionRes = description
return this
}
fun withIcon(icon: Drawable): PrimaryItem {
fun withIcon(icon: Drawable): BottomSheetPrimaryItem {
this.icon = ImageHolder(icon)
return this
}
fun withIcon(@DrawableRes icon: Int): PrimaryItem {
fun withIcon(@DrawableRes icon: Int): BottomSheetPrimaryItem {
this.icon = ImageHolder(icon)
return this
}
fun withIcon(icon: IIcon): PrimaryItem {
fun withIcon(icon: IIcon): BottomSheetPrimaryItem {
this.iconicsIcon = icon
return this
}
fun withOnClickListener(onClickListener: View.OnClickListener): PrimaryItem {
fun withOnClickListener(onClickListener: View.OnClickListener): BottomSheetPrimaryItem {
this.onClickListener = onClickListener
return this
}

View File

@ -4,7 +4,7 @@ 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> {
data class BottomSheetSeparatorItem(override val isContextual: Boolean = true) : IBottomSheetItem<BottomSheetSeparatorItem.ViewHolder> {
/*_ _
| | | |

View File

@ -1,84 +0,0 @@
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

@ -1,7 +0,0 @@
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,6 @@
package pl.szczodrzynski.navlib.drawer
data class IDrawerProfile(var id: Int,
var name: String,
var subname: String?,
var image: String?)

View File

@ -0,0 +1,6 @@
package pl.szczodrzynski.navlib.drawer
data class IUnreadCounter(val profileId: Int,
val type: Int,
var drawerItemId: Int? = null,
var count: Int)

View File

@ -0,0 +1,616 @@
package pl.szczodrzynski.navlib.drawer
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.net.Uri
import android.util.Log
import android.view.View
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.customview.widget.ViewDragHelper
import androidx.drawerlayout.widget.DrawerLayout
import com.mikepenz.iconics.IconicsColor
import com.mikepenz.iconics.IconicsColor.Companion.colorRes
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.IconicsSize
import com.mikepenz.iconics.IconicsSize.Companion.dp
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import com.mikepenz.materialdrawer.*
import com.mikepenz.materialdrawer.holder.BadgeStyle
import com.mikepenz.materialdrawer.holder.StringHolder
import com.mikepenz.materialdrawer.model.BaseDrawerItem
import com.mikepenz.materialdrawer.model.ProfileDrawerItem
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem
import com.mikepenz.materialdrawer.model.interfaces.IProfile
import pl.droidsonroids.gif.GifDrawable
import pl.droidsonroids.gif.MultiCallback
import pl.szczodrzynski.navlib.*
import pl.szczodrzynski.navlib.R
import pl.szczodrzynski.navlib.drawer.items.DrawerPrimaryItem
class NavDrawer(
val context: Context,
val drawerContainer: LinearLayout,
val fixedDrawerContainer: FrameLayout,
val miniDrawerContainerLandscape: FrameLayout,
val miniDrawerContainerPortrait: FrameLayout
) {
companion object {
private const val DRAWER_MODE_NORMAL = 0
private const val DRAWER_MODE_MINI = 1
private const val DRAWER_MODE_FIXED = 2
}
private lateinit var activity: Activity
private val resources: Resources
get() = context.resources
internal lateinit var toolbar: NavToolbar
internal lateinit var bottomBar: NavBottomBar
private var drawer: Drawer? = null
private var drawerView: View? = null
private var accountHeader: AccountHeader? = null
private var miniDrawer: MiniDrawer? = null
private var miniDrawerView: View? = null
private var drawerMode: Int = DRAWER_MODE_NORMAL
private var selection: Int = -1
lateinit var badgeStyle: BadgeStyle
@SuppressLint("ClickableViewAccessibility")
fun init(activity: Activity) {
this.activity = activity
/*badgeStyle = BadgeStyle(
R.drawable.material_drawer_badge,
getColorFromAttr(context, R.attr.colorError),
getColorFromAttr(context, R.attr.colorError),
getColorFromAttr(context, R.attr.colorOnError)
)*/
badgeStyle = BadgeStyle()
.withTextColor(Color.WHITE)
.withColorRes(R.color.md_red_700)
val drawerBuilder = DrawerBuilder()
.withActivity(activity)
.withDrawerLayout(R.layout.material_drawer_fits_not)
.withRootView(drawerContainer)
.withFullscreen(true)
.withTranslucentStatusBar(false)
.withTranslucentNavigationBar(true)
.withTranslucentNavigationBarProgrammatically(false)
.withToolbar(bottomBar)
.withDisplayBelowStatusBar(true)
.withActionBarDrawerToggleAnimated(true)
.withGenerateMiniDrawer(true /* if it is not showing on screen, clicking items throws an exception */)
.withOnDrawerListener(object : Drawer.OnDrawerListener {
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {}
override fun onDrawerOpened(drawerView: View) {
drawerOpenedListener?.invoke()
}
override fun onDrawerClosed(drawerView: View) {
drawerClosedListener?.invoke()
profileSelectionClose()
}
})
.withOnDrawerItemClickListener { _, position, drawerItem ->
if (drawerItem.identifier.toInt() == selection) {
return@withOnDrawerItemClickListener false
}
when (drawerItemSelectedListener?.invoke(drawerItem.identifier.toInt(), position, drawerItem)) {
true -> {
when {
!drawerItem.isSelectable -> {
setSelection(selection, false)
return@withOnDrawerItemClickListener false
}
drawerItem is DrawerPrimaryItem -> toolbar.title = drawerItem.appTitle ?: drawerItem.name?.text ?: ""
drawerItem is BaseDrawerItem<*, *> -> toolbar.title = drawerItem.name?.text ?: ""
}
setSelection(drawerItem.identifier.toInt(), false)
return@withOnDrawerItemClickListener false
}
false -> {
setSelection(selection, false)
return@withOnDrawerItemClickListener true
}
else -> {
return@withOnDrawerItemClickListener false
}
}
}
.withOnDrawerItemLongClickListener { _, position, drawerItem ->
drawerItemLongClickListener?.invoke(drawerItem.identifier.toInt(), position, drawerItem) ?: true
}
val accountHeaderBuilder = AccountHeaderBuilder()
.withActivity(activity)
.withTranslucentStatusBar(true)
.withOnAccountHeaderListener { view, profile, current ->
if (profile is ProfileSettingDrawerItem) {
return@withOnAccountHeaderListener drawerProfileSettingClickListener?.invoke(profile.identifier.toInt(), view) ?: false
}
updateBadges()
if (current) {
profileSelectionClose()
close()
return@withOnAccountHeaderListener true
}
drawerProfileSelectedListener?.invoke(profile.identifier.toInt(), profile, current, view) ?: false
}
.withOnAccountHeaderItemLongClickListener { view, profile, current ->
if (profile is ProfileSettingDrawerItem) {
return@withOnAccountHeaderItemLongClickListener drawerProfileSettingLongClickListener?.invoke(profile.identifier.toInt(), view) ?: true
}
drawerProfileLongClickListener?.invoke(profile.identifier.toInt(), profile, current, view) ?: false
}
.withOnAccountHeaderProfileImageListener(
onClick = { view, profile, current ->
drawerProfileImageClickListener?.invoke(profile.identifier.toInt(), profile, current, view) ?: false
},
onLongClick = { view, profile, current ->
drawerProfileImageLongClickListener?.invoke(profile.identifier.toInt(), profile, current, view) ?: false
}
)
.withHeaderBackground(R.drawable.header)
.withTextColor(ContextCompat.getColor(context, R.color.material_drawer_dark_primary_text))
accountHeader = accountHeaderBuilder.build()
drawerBuilder.withAccountHeader(accountHeader!!)
drawer = drawerBuilder.build()
drawerView = drawer?.slider
miniDrawer = drawer?.miniDrawer
miniDrawer?.withOnMiniDrawerItemClickListener { _, _, _, type ->
if (type == MiniDrawer.PROFILE) {
profileSelectionOpen()
open()
return@withOnMiniDrawerItemClickListener true
}
return@withOnMiniDrawerItemClickListener false
}
// TODO 2019-08-27 build miniDrawerView only if needed
// building in decideDrawerMode causes an exception when clicking drawer items
// also update method updateMiniDrawer...
miniDrawerView = miniDrawer?.build(context)
updateMiniDrawer()
val configuration = context.resources.configuration
decideDrawerMode(
configuration.orientation,
configuration.screenWidthDp,
configuration.screenHeightDp
)
}
/* _____ _
|_ _| |
| | | |_ ___ _ __ ___ ___
| | | __/ _ \ '_ ` _ \/ __|
_| |_| || __/ | | | | \__ \
|_____|\__\___|_| |_| |_|__*/
operator fun plusAssign(item: IDrawerItem<*>) {
appendItem(item)
}
fun appendItem(item: IDrawerItem<*>) {
drawer?.addItem(item)
updateMiniDrawer()
}
fun appendItems(vararg items: IDrawerItem<*>) {
drawer?.addItems(*items)
updateMiniDrawer()
}
fun prependItem(item: IDrawerItem<*>) {
drawer?.addItemAtPosition(item, 0)
updateMiniDrawer()
}
fun prependItems(vararg items: IDrawerItem<*>) {
drawer?.addItemsAtPosition(0, *items)
updateMiniDrawer()
}
fun addItemAt(index: Int, item: IDrawerItem<*>) {
drawer?.addItemAtPosition(item, index)
updateMiniDrawer()
}
fun addItemsAt(index: Int, vararg items: IDrawerItem<*>) {
drawer?.addItemsAtPosition(index, *items)
updateMiniDrawer()
}
fun removeItemById(id: Int) {
drawer?.removeItem(id.toLong())
updateMiniDrawer()
}
fun removeItemAt(index: Int) {
drawer?.removeItemByPosition(index)
updateMiniDrawer()
}
fun removeAllItems() {
drawer?.removeAllItems()
updateMiniDrawer()
}
fun getItemById(id: Int, run: (it: IDrawerItem<*>?) -> Unit) {
drawer?.getDrawerItem(id.toLong()).also {
run(it)
if (it != null)
drawer?.updateItem(it)
updateMiniDrawer()
}
}
fun getItemByIndex(index: Int, run: (it: IDrawerItem<*>?) -> Unit) {
drawer?.drawerItems?.getOrNull(index).also {
run(it)
if (it != null)
drawer?.updateItem(it)
updateMiniDrawer()
}
}
/* _____ _ _ _ _ _
| __ \ (_) | | | | | | | |
| |__) | __ ___ ____ _| |_ ___ _ __ ___ ___| |_| |__ ___ __| |___
| ___/ '__| \ \ / / _` | __/ _ \ | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
| | | | | |\ V / (_| | || __/ | | | | | | __/ |_| | | | (_) | (_| \__ \
|_| |_| |_| \_/ \__,_|\__\___| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|__*/
private fun drawerSetDragMargin(size: Float) {
val mDrawerLayout = drawer?.drawerLayout
val mDragger = mDrawerLayout?.javaClass?.getDeclaredField(
"mLeftDragger"
)//mRightDragger for right obviously
mDragger?.isAccessible = true
val draggerObj = mDragger?.get(mDrawerLayout) as ViewDragHelper?
val mEdgeSize = draggerObj?.javaClass?.getDeclaredField(
"mEdgeSize"
)
mEdgeSize?.isAccessible = true
mEdgeSize?.setInt(
draggerObj,
size.toInt()
) //optimal value as for me, you may set any constant in dp
}
internal fun decideDrawerMode(orientation: Int, widthDp: Int, heightDp: Int) {
Log.d("NavLib", "Deciding drawer mode:")
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
if (fixedDrawerContainer.childCount > 0) {
fixedDrawerContainer.removeAllViews()
}
Log.d("NavLib", "- fixed container disabled")
drawer?.drawerLayout?.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
if (drawer?.drawerLayout?.indexOfChild(drawerView) == -1) {
drawer?.drawerLayout?.addView(drawerView)
}
Log.d("NavLib", "- slider enabled")
if (miniDrawerContainerLandscape.childCount > 0) {
miniDrawerContainerLandscape.removeAllViews()
}
Log.d("NavLib", "- mini drawer land disabled")
if (widthDp >= 480) {
if (miniDrawerView == null)
miniDrawerView = miniDrawer?.build(context)
if (miniDrawerContainerPortrait.indexOfChild(miniDrawerView) == -1)
miniDrawerContainerPortrait.addView(miniDrawerView)
Log.d("NavLib", "- mini drawer port enabled")
drawerSetDragMargin(72 * resources.displayMetrics.density)
drawerMode = DRAWER_MODE_MINI
updateMiniDrawer()
}
else {
if (miniDrawerContainerPortrait.childCount > 0) {
miniDrawerContainerPortrait.removeAllViews()
}
Log.d("NavLib", "- mini drawer port disabled")
drawerSetDragMargin(20 * resources.displayMetrics.density)
drawerMode = DRAWER_MODE_NORMAL
}
}
else {
if (miniDrawerContainerPortrait.childCount > 0) {
miniDrawerContainerPortrait.removeAllViews()
}
Log.d("NavLib", "- mini drawer port disabled")
if (widthDp in 480 until 9000) {
if (miniDrawerView == null)
miniDrawerView = miniDrawer?.build(context)
if (miniDrawerContainerLandscape.indexOfChild(miniDrawerView) == -1)
miniDrawerContainerLandscape.addView(miniDrawerView)
Log.d("NavLib", "- mini drawer land enabled")
drawerSetDragMargin(72 * resources.displayMetrics.density)
drawerMode = DRAWER_MODE_MINI
updateMiniDrawer()
}
else {
if (miniDrawerContainerLandscape.childCount > 0) {
miniDrawerContainerLandscape.removeAllViews()
}
Log.d("NavLib", "- mini drawer land disabled")
drawerSetDragMargin(20 * resources.displayMetrics.density)
drawerMode = DRAWER_MODE_NORMAL
}
if (widthDp >= 9000) {
// screen is big enough to show fixed drawer
if (drawer?.drawerLayout?.indexOfChild(drawerView) != -1) {
// remove from slider
drawer?.drawerLayout?.removeView(drawerView)
}
// lock the slider
drawer?.drawerLayout?.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
Log.d("NavLib", "- slider disabled")
// add to fixed container
if (fixedDrawerContainer.indexOfChild(drawerView) == -1)
fixedDrawerContainer.addView(drawerView)
Log.d("NavLib", "- fixed container enabled")
drawerMode = DRAWER_MODE_FIXED
}
else {
// screen is too small for the fixed drawer
if (fixedDrawerContainer.childCount > 0) {
// remove from fixed container
fixedDrawerContainer.removeAllViews()
}
Log.d("NavLib", "- fixed container disabled")
// unlock the slider
drawer?.drawerLayout?.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
if (drawer?.drawerLayout?.indexOfChild(drawerView) == -1) {
// add to slider
drawer?.drawerLayout?.addView(drawerView)
}
Log.d("NavLib", "- slider enabled")
}
}
}
private fun updateMiniDrawer() {
selection = drawer?.currentSelection?.toInt() ?: -1
//if (drawerMode == DRAWER_MODE_MINI)
miniDrawer?.createItems()
}
/* _____ _ _ _ _ _ _
| __ \ | | | (_) | | | | | |
| |__) | _| |__ | |_ ___ _ __ ___ ___| |_| |__ ___ __| |___
| ___/ | | | '_ \| | |/ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
| | | |_| | |_) | | | (__ | | | | | | __/ |_| | | | (_) | (_| \__ \
|_| \__,_|_.__/|_|_|\___| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|__*/
var isOpen
get() = drawer?.isDrawerOpen ?: false || drawerMode == DRAWER_MODE_FIXED
set(value) {
if (drawerMode == DRAWER_MODE_FIXED)
return
if (value && !isOpen) drawer?.openDrawer() else if (!value && isOpen) drawer?.closeDrawer()
}
fun open() { isOpen = true }
fun close() { isOpen = false }
fun toggle() {
if (drawer == null)
return
isOpen = !isOpen
}
var profileSelectionIsOpen
get() = accountHeader?.isSelectionListShown == true
set(value) {
if (value != profileSelectionIsOpen)
profileSelectionToggle()
}
fun profileSelectionOpen() { profileSelectionIsOpen = true }
fun profileSelectionClose() { profileSelectionIsOpen = false }
fun profileSelectionToggle() {
accountHeader?.let {
it.toggleSelectionList(it.view.context)
}
}
var drawerOpenedListener: (() -> Unit)? = null
var drawerClosedListener: (() -> Unit)? = null
var drawerItemSelectedListener: ((id: Int, position: Int, drawerItem: IDrawerItem<*>) -> Boolean)? = null
var drawerItemLongClickListener: ((id: Int, position: Int, drawerItem: IDrawerItem<*>) -> Boolean)? = null
var drawerProfileSelectedListener: ((id: Int, profile: IProfile<*>, current: Boolean, view: View?) -> Boolean)? = null
var drawerProfileLongClickListener: ((id: Int, profile: IProfile<*>, current: Boolean, view: View) -> Boolean)? = null
var drawerProfileImageClickListener: ((id: Int, profile: IProfile<*>, current: Boolean, view: View) -> Boolean)? = null
var drawerProfileImageLongClickListener: ((id: Int, profile: IProfile<*>, current: Boolean, view: View) -> Boolean)? = null
var drawerProfileListEmptyListener: (() -> Unit)? = null
var drawerProfileSettingClickListener: ((id: Int, view: View?) -> Boolean)? = null
var drawerProfileSettingLongClickListener: ((id: Int, view: View) -> Boolean)? = null
fun miniDrawerEnabled(): Boolean = drawerMode == DRAWER_MODE_MINI
fun fixedDrawerEnabled(): Boolean = drawerMode == DRAWER_MODE_FIXED
fun setSelection(id: Int, fireOnClick: Boolean = true) {
selection = id
if (drawer?.currentSelection != id.toLong())
drawer?.setSelection(id.toLong(), fireOnClick)
if (drawerMode == DRAWER_MODE_MINI)
miniDrawer?.setSelection(id.toLong())
}
// TODO 2019-08-27 add methods for Drawable, @DrawableRes
fun setAccountHeaderBackground(path: String?) {
if (path == null) {
accountHeader?.setBackgroundRes(R.drawable.header)
return
}
accountHeader?.setHeaderBackground(ImageHolder(path))
}
/* _____ __ _ _
| __ \ / _(_) |
| |__) | __ ___ | |_ _| | ___ ___
| ___/ '__/ _ \| _| | |/ _ \/ __|
| | | | | (_) | | | | | __/\__ \
|_| |_| \___/|_| |_|_|\___||__*/
private var profileList = arrayListOf<IDrawerProfile>()
fun addProfileSettings(vararg items: ProfileSettingDrawerItem) {
accountHeader?.profiles?.addAll(items)
}
private fun updateProfileList() {
// remove all profile items
accountHeader?.profiles?.filterNot { it is ProfileDrawerItem }
if (profileList.isEmpty())
drawerProfileListEmptyListener?.invoke()
profileList.forEachIndexed { index, profile ->
val image = if (profile.image != null) {
try {
ImageHolder(profile.image ?: "")
}
catch (_: Exception) {
ImageHolder(R.drawable.profile4)
}
}
else {
ImageHolder(R.drawable.profile4)
}
ProfileDrawerItem()
.withIdentifier(profile.id.toLong())
.withName(profile.name)
.withEmail(profile.subname)
.also { it.icon = image }
.withNameShown(true)
.also { accountHeader?.profiles?.add(index, it) }
}
accountHeader?.profiles = accountHeader?.profiles
updateMiniDrawer()
}
fun setProfileList(profiles: ArrayList<IDrawerProfile>) {
profileList = profiles
updateProfileList()
/*profileList.clear()
profileList.addAll(profiles)*/
}
var currentProfile: Int
get() = accountHeader?.activeProfile?.identifier?.toInt() ?: -1
set(value) {
accountHeader?.setActiveProfile(value.toLong(), true)
}
fun appendProfile(profile: IDrawerProfile) {
profileList.add(profile)
updateProfileList()
}
fun appendProfiles(vararg profiles: IDrawerProfile) {
profileList.addAll(profiles)
updateProfileList()
}
fun prependProfile(profile: IDrawerProfile) {
profileList.add(0, profile)
updateProfileList()
}
fun prependProfiles(vararg profiles: IDrawerProfile) {
profileList.addAll(0, profiles.asList())
updateProfileList()
}
fun addProfileAt(index: Int, profile: IDrawerProfile) {
profileList.add(index, profile)
updateProfileList()
}
fun addProfilesAt(index: Int, vararg profiles: IDrawerProfile) {
profileList.addAll(index, profiles.asList())
updateProfileList()
}
fun removeProfileById(id: Int) {
profileList.filterNot { it.id == id }
updateProfileList()
}
fun removeProfileAt(index: Int) {
profileList.removeAt(index)
updateProfileList()
}
fun removeAllProfile() {
profileList.clear()
updateProfileList()
}
fun getProfileById(id: Int, run: (it: IDrawerProfile?) -> Unit) {
profileList.singleOrNull { it.id == id }.also {
run(it)
updateProfileList()
}
}
fun getProfileByIndex(index: Int, run: (it: IDrawerProfile?) -> Unit) {
profileList.getOrNull(index).also {
run(it)
updateProfileList()
}
}
/* ____ _
| _ \ | |
| |_) | __ _ __| | __ _ ___ ___
| _ < / _` |/ _` |/ _` |/ _ \/ __|
| |_) | (_| | (_| | (_| | __/\__ \
|____/ \__,_|\__,_|\__, |\___||___/
__/ |
|__*/
private var unreadCounterList = arrayListOf<IUnreadCounter>()
private val unreadCounterTypeMap = mutableMapOf<Int, Int>()
fun updateBadges() {
unreadCounterList.map {
it.drawerItemId = unreadCounterTypeMap[it.type]
}
unreadCounterList.forEach {
if (it.drawerItemId == null)
return@forEach
if (it.profileId != currentProfile) {
drawer?.updateBadge(it.drawerItemId?.toLong() ?: 0, null)
return@forEach
}
drawer?.updateBadge(
it.drawerItemId?.toLong() ?: 0,
when {
it.count == 0 -> null
it.count >= 99 -> StringHolder("99+")
else -> StringHolder(it.count.toString())
}
)
}
updateMiniDrawer()
}
fun setUnreadCounterList(unreadCounterList: ArrayList<IUnreadCounter>) {
this.unreadCounterList = unreadCounterList
updateBadges()
}
fun addUnreadCounterType(type: Int, drawerItem: Int) {
unreadCounterTypeMap[type] = drawerItem
}
fun setUnreadCount(profileId: Int, type: Int, count: Int) {
val item = unreadCounterList.singleOrNull {
it.type == type && it.profileId == profileId
}
if (item != null) {
item.count = count
updateBadges()
}
else {
unreadCounterList.add(IUnreadCounter(profileId, type, null, count))
}
}
}

View File

@ -0,0 +1,11 @@
package pl.szczodrzynski.navlib.drawer.items
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
class DrawerPrimaryItem : PrimaryDrawerItem() {
var appTitle: String? = null
fun withAppTitle(appTitle: String?): PrimaryDrawerItem {
this.appTitle = appTitle
return this
}
}

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="0.16" android:color="?attr/colorOnSurface" android:state_hovered="true"/>
<item android:alpha="0.04" android:color="?attr/colorOnSurface" android:state_enabled="false"/>
<item android:alpha="0.12" android:color="?attr/colorOnSurface"/>
</selector>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- increased alpha by 1/2 -->
<item android:alpha="0.24" android:color="?attr/colorOnSurface" android:state_hovered="true"/>
<item android:alpha="0.06" android:color="?attr/colorOnSurface" android:state_enabled="false"/>
<item android:alpha="0.18" android:color="?attr/colorOnSurface"/>
</selector>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="270"
android:endColor="#00000000"
android:startColor="#40000000"
android:type="linear" />
</shape>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="0"
android:endColor="#00000000"
android:startColor="#40000000"
android:type="linear" />
</shape>

View File

@ -43,19 +43,41 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_marginBottom="16dp"
android:focusable="true"
android:focusableInTouchMode="true"
app:srcCompat="@drawable/bottom_sheet_control_bar"
tools:ignore="ContentDescription" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/bs_textInputLayout"
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:boxBackgroundColor="?boxBackgroundColor"
app:endIconMode="clear_text"
tools:startIconDrawable="@drawable/ic_android"
tools:helperText="0 messages found"
tools:hint="Search">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/bs_textInputEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
tools:text="John" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:id="@+id/bs_toggleGroupContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
android:layout_marginBottom="16dp"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:id="@+id/bs_toggleGroupTitle"
@ -64,56 +86,11 @@
android:layout_marginTop="8dp"
android:text="Sorting order" />
<androidx.gridlayout.widget.GridLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone">
<com.google.android.material.button.MaterialButton
style="?materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="By date"
app:icon="@drawable/ic_android" />
<com.google.android.material.button.MaterialButton
style="?materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="By subject" />
<com.google.android.material.button.MaterialButton
style="?materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="By sender" />
<com.google.android.material.button.MaterialButton
style="?materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="By date"
app:icon="@drawable/ic_android" />
<com.google.android.material.button.MaterialButton
style="?materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="By subject" />
<com.google.android.material.button.MaterialButton
style="?materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="By sender" />
</androidx.gridlayout.widget.GridLayout>
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/bs_toggleGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleSelection="true"/>
app:singleSelection="true" />
</LinearLayout>

View File

@ -1,21 +0,0 @@
<?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

@ -4,122 +4,170 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:orientation="horizontal"
tools:parentTag="FrameLayout">
<View
android:id="@+id/nv_statusBarBackground"
android:layout_width="match_parent"
android:layout_height="0dp"
tools:layout_height="25dp"
android:background="?android:windowBackground" />
<View
android:id="@+id/nv_navigationBarBackground"
android:layout_width="match_parent"
android:layout_height="0dp"
tools:layout_height="48dp"
android:layout_gravity="bottom"
android:background="?colorPrimaryVariant"
tools:background="?colorPrimaryVariant" />
<FrameLayout
<LinearLayout
android:id="@+id/nv_drawerContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="horizontal"
android:baselineAligned="false">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/nv_main"
android:layout_width="match_parent"
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
tools:paddingTop="24dp"
tools:paddingBottom="48dp">
android:layout_weight="1"
android:orientation="vertical">
<pl.szczodrzynski.navlib.NavToolbar
android:id="@+id/nv_toolbar"
<View
android:id="@+id/nv_statusBarBackground"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?nv_actionBarBackground"
android:elevation="4dp"
app:title="@string/app_name"
tools:targetApi="lollipop" />
android:layout_height="0dp"
android:layout_gravity="top"
android:background="?android:windowBackground"
tools:layout_height="25dp" />
<LinearLayout
android:id="@+id/nv_content"
android:id="@+id/nv_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginTop="?actionBarSize"
android:layout_marginBottom="?actionBarSize"
android:orientation="vertical">
android:orientation="horizontal"
tools:paddingTop="24dp"
tools:paddingBottom="48dp">
<SeekBar
android:id="@+id/nv_elevation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:max="20"
android:progress="4"
android:visibility="gone" />
<FrameLayout
android:id="@+id/nv_miniDrawerContainerLandscape"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:background="#2196f3" /><!--tools:layout_width="72dp"-->
<TextView
android:id="@+id/textView"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Set toolbar elevation"
android:visibility="gone" />
android:layout_height="match_parent">
<pl.szczodrzynski.navlib.NavToolbar
android:id="@+id/nv_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?actionBarBackground"
android:elevation="4dp"
app:title="@string/app_name"
tools:targetApi="lollipop" />
<View
android:id="@+id/nv_toolbarElevation"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_marginTop="?actionBarSize"
android:layout_weight="1"
android:background="@drawable/shadow_bottom" />
<LinearLayout
android:id="@+id/nv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginTop="?actionBarSize"
android:layout_marginBottom="?actionBarSize"
android:orientation="horizontal" >
<FrameLayout
android:id="@+id/nv_miniDrawerContainerPortrait"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:background="#ffb300" /><!--tools:layout_width="72dp"-->
<View
android:id="@+id/nv_miniDrawerElevation"
android:layout_width="4dp"
android:layout_height="match_parent"
android:background="@drawable/shadow_right" />
</LinearLayout>
<pl.szczodrzynski.navlib.NavBottomBar
android:id="@+id/nv_bottomBar"
style="@style/Widget.MaterialComponents.BottomAppBar.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:visibility="visible"
app:fabAlignmentMode="center"
app:fabAnimationMode="scale" />
<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:text=""
android:visibility="visible"
app:backgroundTint="?colorFab"
app:layout_anchor="@+id/nv_bottomBar"
app:layout_anchorGravity="center|top"
tools:icon="@android:drawable/ic_menu_edit" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/nv_floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:focusable="true"
android:visibility="gone"
app:backgroundTint="?colorFab"
app:layout_anchor="@id/nv_bottomBar"
tools:srcCompat="@android:drawable/ic_menu_edit" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>
<pl.szczodrzynski.navlib.NavBottomBar
android:id="@+id/nv_bottomBar"
style="@style/Widget.MaterialComponents.BottomAppBar.Colored"
<View
android:id="@+id/nv_navigationBarBackground"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:layout_gravity="bottom"
android:visibility="visible"
app:fabAlignmentMode="center"
app:fabAnimationMode="scale" />
android:background="?navigationBarBackground"
tools:layout_height="48dp" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/nv_floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:focusable="true"
android:visibility="gone"
app:layout_anchor="@id/nv_bottomBar"
app:backgroundTint="?colorFab"
tools:srcCompat="@android:drawable/ic_menu_edit"/>
</FrameLayout>
<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="?colorFab"
tools:icon="@android:drawable/ic_menu_edit"
app:layout_anchor="@+id/nv_bottomBar"
app:layout_anchorGravity="center|top"/>
<FrameLayout
android:id="@+id/nv_fixedDrawerContainer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:background="#4caf50"/><!--tools:layout_width="300dp"-->
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>
</FrameLayout>
<View
android:id="@+id/nv_statusBarDarker"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="top"
android:background="#44000000"
android:visibility="gone"
tools:layout_height="25dp"
tools:visibility="visible" />
<View
android:id="@+id/nv_navigationBarDarker"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="bottom"
android:background="#44000000"
android:visibility="gone"
tools:layout_height="48dp"
tools:visibility="visible" />
<pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
android:id="@+id/nv_bottomSheet"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<View
android:id="@+id/nv_statusBarDarker"
android:layout_width="match_parent"
android:layout_height="0dp"
tools:layout_height="25dp"
android:background="#22000000" />
</merge>

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="nv_actionBarBackground" format="color" />
<attr name="actionBarBackground" format="color" />
<attr name="navigationBarBackground" format="color" />
<attr name="colorFab" format="color" />
<attr name="colorFabIcon" format="color" />
<attr name="colorOnFab" format="color" />

View File

@ -12,26 +12,72 @@
<item name="backgroundTint">?colorFab</item>
<item name="android:textColor">?colorOnFab</item>
</style>
<!-- default body text -->
<style name="NavView.TextView" parent="Widget.MaterialComponents.TextView">
<item name="android:textAppearance">?attr/textAppearanceBody2</item>
</style>
<!-- title text -->
<style name="NavView.TextView.Title" parent="TextAppearance.AppCompat.Title">
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<!-- subtitle text, smaller than medium -->
<style name="NavView.TextView.Subtitle" parent="TextAppearance.AppCompat.Subhead">
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<!-- large body text -->
<style name="NavView.TextView.Large" parent="TextAppearance.AppCompat.Large">
</style>
<!-- medium body text -->
<style name="NavView.TextView.Medium" parent="TextAppearance.AppCompat.Medium">
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<!-- small (helper) body text -->
<style name="NavView.TextView.Small" parent="TextAppearance.AppCompat.Small">
</style>
<!--<item name="colorAccent">#ffb300</item>-->
<style name="NavView.Light" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- primary styling -->
<item name="colorPrimary">#6200EE</item>
<item name="colorPrimaryDark">#3700B3</item>
<item name="colorPrimaryVariant">#6200EE</item>
<item name="colorAccent">#03DAC6</item>
<item name="colorSecondary">?colorAccent</item>
<item name="colorSecondaryVariant">#018786</item>
<!-- window colors -->
<item name="android:colorBackground">@color/background_light</item>
<item name="android:windowBackground">?android:colorBackground</item>
<item name="colorSurface">#ffffff</item>
<item name="elevationOverlayColor">#ffffff</item>
<!-- FAB styling -->
<item name="colorFab">?colorAccent</item>
<item name="colorFabIcon">?colorOnSecondary</item>
<item name="colorOnFab">?colorOnSecondary</item>
<!-- text colors -->
<item name="colorOnPrimary">#ffffff</item>
<item name="colorOnSecondary">#ffffff</item>
<item name="colorOnBackground">#000000</item>
<item name="colorOnSurface">#000000</item>
<item name="nv_actionBarBackground">?colorSurface</item>
<item name="elevationOverlayColor">#ffffff</item>
<!-- system bars config -->
<item name="actionBarBackground">?colorSurface</item>
<item name="navigationBarBackground">?colorPrimaryVariant</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<!-- component styling -->
<item name="floatingActionButtonStyle">@style/NavView.Widget.FloatingActionButton</item>
<item name="extendedFloatingActionButtonStyle">@style/NavView.Widget.ExtendedFloatingActionButton</item>
<item name="boxBackgroundColor" tools:ignore="PrivateResource">@color/mtrl_filled_background_color</item>
<item name="android:textViewStyle">@style/NavView.TextView</item>
<!-- drawer & bottom sheet styling -->
<item name="material_drawer_background">?android:colorBackground</item>
<item name="material_drawer_primary_text">#242424</item>
<item name="material_drawer_primary_icon">#5F6368</item>
@ -45,20 +91,43 @@
</style>
<style name="NavView.Dark" parent="Theme.MaterialComponents.NoActionBar">
<!-- primary styling -->
<item name="colorPrimary">#BB86FC</item>
<item name="colorPrimaryDark">#3700B3</item>
<item name="colorPrimaryVariant">#6200EE</item>
<item name="colorAccent">#03DAC6</item>
<item name="colorSecondary">?colorAccent</item>
<item name="colorSecondaryVariant">?colorAccent</item>
<!-- window colors -->
<item name="android:colorBackground">@color/background_dark</item>
<item name="android:windowBackground">?android:colorBackground</item>
<item name="colorSurface">#303030</item>
<!-- FAB styling -->
<item name="colorFab">?colorAccent</item>
<item name="colorFabIcon">?colorOnSecondary</item>
<item name="colorOnFab">?colorOnSecondary</item>
<!-- text colors -->
<item name="colorOnPrimary">#ffffff</item>
<item name="colorOnSecondary">#ffffff</item>
<item name="colorOnBackground">#ffffff</item>
<item name="colorOnSurface">#ffffff</item>
<item name="nv_actionBarBackground">?colorSurface</item>
<!-- system bars config -->
<item name="actionBarBackground">?colorSurface</item>
<item name="navigationBarBackground">?colorPrimaryVariant</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<!-- component styling -->
<item name="floatingActionButtonStyle">@style/NavView.Widget.FloatingActionButton</item>
<item name="extendedFloatingActionButtonStyle">@style/NavView.Widget.ExtendedFloatingActionButton</item>
<item name="boxBackgroundColor">@color/text_input_layout_background</item>
<item name="android:textViewStyle">@style/NavView.TextView</item>
<!-- drawer & bottom sheet styling -->
<item name="material_drawer_background">?android:colorBackground</item>
<item name="material_drawer_primary_text">#FFFFFF</item>
<item name="material_drawer_primary_icon">#9AA0A6</item>
@ -75,6 +144,8 @@
<item name="android:colorBackground">@color/background_black</item>
<item name="android:windowBackground">?android:colorBackground</item>
<item name="colorSurface">#121212</item>
<item name="colorBackgroundFloating">#2D2D2D</item>
</style>