[UI] Upgrade to Material 3 design, refactor some core elements (#201)

* Material 3 theme and color support, filled cards

* Change drawer header, dark bottombar color

* Replace MaterialComponents with Material3

* wielki powrót pr m3 do szkolnego (nie czytajcie tego kodu)

* fix M3 UI code & upgrade kotlin

* update dependencies

* fix missing Intent receiver flags for Tiramisu+

* fix kapt errors related to SelectiveDAO + migrate BuildConfig

* adapt code to updated dependencies + align lessons (based by szkolny-eu/szkolny-android#196)

* fix: no query filtering

* fix: duplicated items in about card

* fix: "Back button opens drawer" (redundant super call)

* fix: too small heading in agenda dialog

* adapt notes fragment to MD3

* add lock layout function (szkolny-eu/szkolny-android#199)

* hide classroom heading when no classroom is specified

* add support for grade column codes

* grades: join code and category together

* add cosmetic ui changes + fix build issues

* fix proguard rules (attempt 1)

* add new Retrofit2 rules

* add new ProGuard rules + fix QR scanning

* fix agenda view crash when building release variant

* improve LessonDetailsDialog

* remove duplicated string extension

* set separate app ID & icon for debug version

* remove unneeded import statement

* fix collapsing toolbar title when doing back gesture

* remove useless dependencies

* fix UI issues on old Android versions

* fix missing color resources + cleanup dependencies

* fix release building issue

* fix release building issue & remove ripple from NavView

* move version badge to the top bar

* Revert changes introduced by rebase

* Update NavLib from sadorowo/NavLib

* Revert "add lock layout function (szkolny-eu/szkolny-android#199)"

This reverts commit 2fd7038d0c.

* Revert "add support for grade column codes"

* Revert unnecessary code changes, part 1

* Lower minSdk to 19

* Revert unnecessary code changes, part 2

* Add new application logo

* Restore bottom bar support in NavLib, revert unnecessary changes

* Use new IconicsMaterialButton in MessageFragment

* Migrate NavView to view binding

* Support IconButton in IconicsMaterialButton

* Cleanup NavLib w600dp styles

* Remove NavLib text styles

* Refactor all application themes, update styles in layouts

* Move enums and config entry to .data, fix app crashing

* Rename non-theme styles to AppStyle

* Restructure app config classes, move config to .data

* Add Theme enum and UiManager, support basic theme changing

* Actually support basic theme changing

* Serialize enum as string, fix config migration, bring back DebugDb

* Fix changing themes, apply night mode in App

* Fix resolving ColorStateList attributes, add LabPlaygroundFragment

* add Iconics methods into ProGuard rules

* Replace home card icon buttons, remove unused icons

* Update gradle properties

* Update build.gradle

* Remove unnecessary dependencies

* Remove playstore icon

* Apply fixes after review

---------

Co-authored-by: Adam Kasprzycki <66315787+santoni0@users.noreply.github.com>
Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
This commit is contained in:
2024-06-30 16:12:07 +02:00
committed by GitHub
parent fadf1d7754
commit 0823e72328
595 changed files with 5725 additions and 3910 deletions

View File

@ -1,7 +1,6 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion setup.compileSdk
@ -9,12 +8,14 @@ android {
defaultConfig {
minSdkVersion setup.minSdk
targetSdkVersion setup.targetSdk
versionCode release.versionCode
versionName release.versionName
consumerProguardFiles 'consumer-rules.pro'
vectorDrawables.useSupportLibrary = true
multiDexEnabled true
}
kotlinOptions {
jvmTarget = "1.8"
}
buildTypes {
@ -26,30 +27,33 @@ android {
buildFeatures {
dataBinding = true
viewBinding = true
}
packagingOptions {
exclude 'META-INF/library-core_release.kotlin_module'
resources {
excludes += ['META-INF/library-core_release.kotlin_module']
}
}
}
namespace 'pl.szczodrzynski.navlib'
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.core:core-ktx:1.3.2"
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "com.google.android.material:material:1.3.0"
implementation "androidx.appcompat:appcompat:1.7.0"
implementation "androidx.core:core-ktx:1.13.1"
implementation "androidx.recyclerview:recyclerview:1.3.2"
implementation "com.google.android.material:material:1.12.0"
api "com.mikepenz:materialize:1.2.1"
api "com.mikepenz:materialdrawer:8.3.3"
api "com.mikepenz:iconics-core:5.3.0-b01"
api "com.mikepenz:materialdrawer:9.0.1"
api "com.mikepenz:iconics-core:5.3.2"
api "com.mikepenz:itemanimators:1.1.0"
compileOnly "pl.droidsonroids.gif:android-gif-drawable:1.2.15"
implementation "com.balysv:material-ripple:1.0.2"
implementation project(":navlib-font")
}

View File

@ -1,2 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pl.szczodrzynski.navlib" />
xmlns:tools="http://schemas.android.com/tools">
<uses-sdk tools:overrideLibrary="com.mikepenz.materialdrawer"/>
</manifest>

View File

@ -9,6 +9,7 @@ import android.view.MenuItem
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import com.google.android.material.bottomappbar.BottomAppBar
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.floatingactionbutton.FloatingActionButton
@ -19,33 +20,27 @@ import com.mikepenz.iconics.utils.sizeDp
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
import pl.szczodrzynski.navlib.drawer.NavDrawer
class NavBottomBar : BottomAppBar {
constructor(context: Context) : super(context) {
create(null, 0)
}
class NavBottomBar @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
) : BottomAppBar(context, attrs, defStyle), NavMenuBarBase {
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
create(attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
create(attrs, defStyle)
}
var drawer: NavDrawer? = null
var bottomSheet: NavBottomSheet? = null
var fabView: FloatingActionButton? = null
var fabExtendedView: ExtendedFloatingActionButton? = null
internal lateinit var navView: NavView
override lateinit var bottomSheet: NavBottomSheet
internal lateinit var fabView: FloatingActionButton
internal lateinit var fabExtendedView: ExtendedFloatingActionButton
/**
* Shows the BottomAppBar and sets the contentView's margin to be
* above the BottomAppBar.
*/
var enable = true
var enable
get() = isVisible
set(value) {
field = value
visibility = if (value) View.VISIBLE else View.GONE
isVisible = value
setFabParams()
navView.setContentMargins()
}
/**
* Whether the FAB should be visible.
@ -82,9 +77,9 @@ class NavBottomBar : BottomAppBar {
set(value) {
field = value
if (fabExtended)
fabExtendedView?.extend()
fabExtendedView.extend()
else
fabExtendedView?.shrink()
fabExtendedView.shrink()
}
/**
* Set the FAB's icon.
@ -92,14 +87,14 @@ class NavBottomBar : BottomAppBar {
var fabIcon: IIcon? = null
set(value) {
field = value
fabView?.setImageDrawable(IconicsDrawable(context).apply {
fabView.setImageDrawable(IconicsDrawable(context).apply {
icon = value
colorAttr(context, R.attr.colorFabIcon)
colorAttr(context, R.attr.colorOnPrimaryContainer)
sizeDp = 24
})
fabExtendedView?.icon = IconicsDrawable(context).apply {
fabExtendedView.icon = IconicsDrawable(context).apply {
icon = value
colorAttr(context, R.attr.colorFabIcon)
colorAttr(context, R.attr.colorOnPrimaryContainer)
sizeDp = 24
}
}
@ -107,21 +102,23 @@ class NavBottomBar : BottomAppBar {
* Set the ExtendedFAB's text.
*/
var fabExtendedText
get() = fabExtendedView?.text
get() = fabExtendedView.text
set(value) {
fabExtendedView?.text = value
fabExtendedView.text = value
}
/**
* Set the FAB's on click listener
*/
fun setFabOnClickListener(onClickListener: OnClickListener?) {
fabView?.setOnClickListener(onClickListener)
fabExtendedView?.setOnClickListener(onClickListener)
fabView.setOnClickListener(onClickListener)
fabExtendedView.setOnClickListener(onClickListener)
}
@SuppressLint("ClickableViewAccessibility")
private fun create(attrs: AttributeSet?, defStyle: Int) {
override var drawerClickListener: (() -> Unit)? = null
override var menuClickListener: (() -> Unit)? = null
init {
setOnTouchListener { _, event ->
if (bottomSheet?.enable != true || bottomSheet?.enableDragToOpen != true)
return@setOnTouchListener false
@ -130,45 +127,11 @@ class NavBottomBar : BottomAppBar {
}
elevation = 0f
val icon = ContextCompat.getDrawable(context, R.drawable.ic_menu_badge) as LayerDrawable?
icon?.apply {
mutate()
setDrawableByLayerId(R.id.ic_menu, IconicsDrawable(context).apply {
this.icon = NavLibFont.Icon.nav_menu
sizeDp = 24
colorAttr(context, R.attr.colorOnPrimary)
})
setDrawableByLayerId(R.id.ic_badge, BadgeDrawable(context))
}
navigationIcon = icon
menu.add(0, -1, 0, "Menu")
.setIcon(IconicsDrawable(context).apply {
this.icon = NavLibFont.Icon.nav_dots_vertical
sizeDp = 24
colorAttr(context, R.attr.colorOnPrimary)
})
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
setNavigationOnClickListener {
drawer?.toggle()
}
super.setOnMenuItemClickListener {
if (it.itemId == -1 && bottomSheet?.enable == true) {
bottomSheet?.toggle()
}
else {
onMenuItemClickListener?.onMenuItemClick(it)
}
true
}
}
private fun setFabParams() {
val layoutParams =
((if (fabExtendable) fabExtendedView?.layoutParams else fabView?.layoutParams) ?: return) as CoordinatorLayout.LayoutParams
((if (fabExtendable) fabExtendedView.layoutParams else fabView.layoutParams) ?: return) as CoordinatorLayout.LayoutParams
if (enable) {
layoutParams.anchorId = this.id
@ -184,28 +147,23 @@ class NavBottomBar : BottomAppBar {
}
fabAlignmentMode = if (fabGravity == Gravity.END) FAB_ALIGNMENT_MODE_END else FAB_ALIGNMENT_MODE_CENTER
if (fabExtendable)
fabExtendedView?.layoutParams = layoutParams
fabExtendedView.layoutParams = layoutParams
else
fabView?.layoutParams = layoutParams
fabView.layoutParams = layoutParams
setFabVisibility()
}
private fun setFabVisibility() {
if (fabEnable && fabExtendable) {
fabView?.hide()
fabExtendedView?.show()
fabView.hide()
fabExtendedView.show()
}
else if (fabEnable) {
fabView?.show()
fabExtendedView?.hide()
fabView.show()
fabExtendedView.hide()
}
else {
fabView?.hide()
fabExtendedView?.hide()
fabView.hide()
fabExtendedView.hide()
}
}
private var onMenuItemClickListener: OnMenuItemClickListener? = null
override fun setOnMenuItemClickListener(listener: OnMenuItemClickListener?) {
onMenuItemClickListener = listener
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) Kuba Szczodrzyński 2024-6-20.
*/
package pl.szczodrzynski.navlib
import android.graphics.drawable.LayerDrawable
import android.view.MenuItem
import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.navlibfont.NavLibFont
import com.mikepenz.iconics.utils.sizeDp
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
interface NavMenuBarBase {
var bottomSheet: NavBottomSheet
var drawerClickListener: (() -> Unit)?
var menuClickListener: (() -> Unit)?
var Toolbar.enableMenuControls: Boolean
get() = navigationIcon != null
set(value) {
if (value)
this.attach()
else
this.detach()
}
private fun Toolbar.attach() {
val navIcon = ContextCompat.getDrawable(context, R.drawable.ic_menu_badge) as LayerDrawable?
navIcon?.apply {
mutate()
setDrawableByLayerId(R.id.ic_menu, IconicsDrawable(context).apply {
this.icon = NavLibFont.Icon.nav_menu
sizeDp = 24
colorAttr(context, R.attr.colorOnSurface)
})
setDrawableByLayerId(R.id.ic_badge, BadgeDrawable(context))
}
navigationIcon = navIcon
setNavigationOnClickListener {
drawerClickListener?.invoke()
}
menu.add(0, -1, 0, "Menu")
.setIcon(IconicsDrawable(context).apply {
this.icon = NavLibFont.Icon.nav_dots_vertical
sizeDp = 24
colorAttr(context, R.attr.colorOnSurface)
})
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
setOnMenuItemClickListener {
if (it.itemId == -1 && bottomSheet.enable) {
bottomSheet.toggle()
} else {
menuClickListener?.invoke()
}
true
}
}
private fun Toolbar.detach() {
navigationIcon = null
setNavigationOnClickListener(null)
menu.clear()
setOnMenuItemClickListener(null)
}
}

View File

@ -2,22 +2,31 @@ package pl.szczodrzynski.navlib
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.ImageView
import androidx.core.view.isVisible
import com.google.android.material.appbar.MaterialToolbar
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
class NavToolbar : MaterialToolbar {
class NavToolbar @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
) : MaterialToolbar(context, attrs, defStyle), NavMenuBarBase {
constructor(context: Context) : super(context) {
create(null, 0)
}
internal lateinit var navView: NavView
override lateinit var bottomSheet: NavBottomSheet
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
create(attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
create(attrs, defStyle)
}
/**
* Shows the toolbar and sets the contentView's margin to be
* below the toolbar.
*/
var enable
get() = isVisible
set(value) {
isVisible = value
navView.setContentMargins()
}
var toolbarImage: ImageView? = null
set(value) {
@ -27,8 +36,12 @@ class NavToolbar : MaterialToolbar {
}
}
override var drawerClickListener: (() -> Unit)? = null
override var menuClickListener: (() -> Unit)? = null
var profileImageClickListener: (() -> Unit)? = null
override fun setSubtitle(subtitle: CharSequence?) {
if(subtitle.isNullOrEmpty()) {
if (subtitle.isNullOrEmpty()) {
setPadding(0, 0, 0, 0)
toolbarImage?.translationY = 0f
} else {
@ -38,18 +51,9 @@ class NavToolbar : MaterialToolbar {
super.setSubtitle(subtitle)
}
private fun create(attrs: AttributeSet?, defStyle: Int) {
}
var subtitleFormat: Int? = null
var subtitleFormatWithUnread: Int? = null
var profileImageClickListener: (() -> Unit)? = null
var profileImage
get() = toolbarImage?.drawable
set(value) {
toolbarImage?.setImageDrawable(value)
}
}
}

View File

@ -3,155 +3,78 @@ package pl.szczodrzynski.navlib
import android.content.Context
import android.content.res.Configuration
import android.content.res.Configuration.ORIENTATION_PORTRAIT
import android.graphics.Point
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.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.TextView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.children
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.floatingactionbutton.FloatingActionButton
import kotlinx.android.synthetic.main.nav_view.view.*
import androidx.core.view.updateLayoutParams
import pl.szczodrzynski.navlib.bottomsheet.NavBottomSheet
import pl.szczodrzynski.navlib.databinding.NavViewBinding
import pl.szczodrzynski.navlib.drawer.NavDrawer
class NavView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
) : FrameLayout(context, attrs, defStyle) {
class NavView : FrameLayout {
companion object {
const val SOURCE_OTHER = 0
const val SOURCE_DRAWER = 1
const val SOURCE_BOTTOM_SHEET = 1
}
private val b = NavViewBinding.inflate(LayoutInflater.from(context), this)
private var contentView: LinearLayout? = null
val drawer: NavDrawer
private lateinit var statusBarBackground: View
private lateinit var navigationBarBackground: View
private lateinit var mainView: LinearLayout
private lateinit var floatingActionButton: FloatingActionButton
private lateinit var extendedFloatingActionButton: ExtendedFloatingActionButton
val coordinator
get() = b.nvCoordinator
val toolbar
get() = b.nvToolbar
val bottomBar: NavBottomBar
get() = b.nvBottomBar
val nightlyText: TextView
get() = b.nvNightlyText
val bottomSheet: NavBottomSheet
get() = b.nvBottomSheet
lateinit var drawer: NavDrawer
lateinit var toolbar: NavToolbar
lateinit var bottomBar: NavBottomBar
lateinit var bottomSheet: NavBottomSheet
val coordinator by lazy {
findViewById<CoordinatorLayout>(R.id.nv_coordinator)
}
var navigationLoader: NavigationLoader? = null
constructor(context: Context) : super(context) {
create(null, 0)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
create(attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
create(attrs, defStyle)
}
private fun create(attrs: AttributeSet?, defStyle: Int) {
// Load attributes
val a = context.obtainStyledAttributes(attrs, R.styleable.NavView, defStyle, 0)
/*_exampleString = a.getString(
R.styleable.NavView_exampleString
)*/
a.recycle()
val layoutInflater = LayoutInflater.from(context)
layoutInflater.inflate(R.layout.nav_view, this)
contentView = findViewById<LinearLayout>(R.id.nv_content)
statusBarBackground = findViewById(R.id.nv_statusBarBackground)
navigationBarBackground = findViewById(R.id.nv_navigationBarBackground)
mainView = findViewById(R.id.nv_main)
floatingActionButton = findViewById(R.id.nv_floatingActionButton)
extendedFloatingActionButton = findViewById(R.id.nv_extendedFloatingActionButton)
init {
contentView = b.nvContent
drawer = NavDrawer(
context,
findViewById(R.id.nv_drawerLayout),
findViewById(R.id.nv_drawerContainerLandscape),
findViewById(R.id.nv_miniDrawerContainerPortrait),
findViewById(R.id.nv_miniDrawerElevation)
b.nvDrawerLayout,
b.nvDrawerContainerLandscape,
b.nvMiniDrawerContainerPortrait,
b.nvMiniDrawerElevation,
)
toolbar = findViewById(R.id.nv_toolbar)
bottomBar = findViewById(R.id.nv_bottomBar)
bottomSheet = findViewById(R.id.nv_bottomSheet)
drawer.toolbar = toolbar
drawer.bottomBar = bottomBar
drawer.toolbar = b.nvToolbar
drawer.bottomBar = b.nvBottomBar
toolbar.toolbarImage = findViewById(R.id.nv_toolbar_image)
b.nvToolbar.navView = this
b.nvToolbar.bottomSheet = b.nvBottomSheet
b.nvToolbar.toolbarImage = b.nvToolbarImage
bottomBar.drawer = drawer
bottomBar.bottomSheet = bottomSheet
bottomBar.fabView = floatingActionButton
bottomBar.fabExtendedView = extendedFloatingActionButton
ripple.isEnabled = false
ripple.children.forEach { it.isEnabled = false }
//bottomSheetBehavior.peekHeight = displayHeight
}
private fun convertDpToPixel(dp: Float): Float {
val resources = context.resources
val metrics = resources.displayMetrics
return dp * (metrics.densityDpi / 160f)
}
fun gainAttentionOnBottomBar() {
var x = ripple.width.toFloat()
var y = ripple.height.toFloat()
x -= convertDpToPixel(56f) / 2
y -= convertDpToPixel(56f) / 2
ripple.performRipple(Point(x.toInt(), y.toInt()))
b.nvBottomBar.navView = this
b.nvBottomBar.bottomSheet = b.nvBottomSheet
b.nvBottomBar.fabView = b.nvFloatingActionButton
b.nvBottomBar.fabExtendedView = b.nvExtendedFloatingActionButton
}
fun configSystemBarsUtil(systemBarsUtil: SystemBarsUtil) {
this.systemBarsUtil = systemBarsUtil.apply {
this.statusBarBgView = statusBarBackground
this.navigationBarBgView = navigationBarBackground
this.statusBarDarkView = nv_statusBarDarker
//this.navigationBarDarkView = navigationBarBackground
this.insetsListener = nv_drawerLayout
this.marginBySystemBars = mainView
this.paddingByNavigationBar = bottomSheet.getContentView()
this.statusBarBgView = b.nvStatusBarBackground
this.navigationBarBgView = b.nvNavigationBarBackground
this.statusBarDarkView = b.nvStatusBarDarker
this.navigationBarDarkView = b.nvNavigationBarBackground
this.insetsListener = b.nvDrawerLayout
this.marginBySystemBars = b.nvMain
}
}
var enableBottomSheet = true
var enableBottomSheetDrag = true
var bottomBarEnable = true
get() = bottomBar.enable
set(value) {
field = value
bottomBar.enable = value
setContentMargins() // TODO combine bottomBarEnable and bottomBar.enable
}
/**
* Shows the toolbar and sets the contentView's margin to be
* below the toolbar.
*/
var showToolbar = true; set(value) {
toolbar.visibility = if (value) View.VISIBLE else View.GONE
field = value
setContentMargins()
}
/**
* Set the FAB's on click listener
*/
@ -161,12 +84,17 @@ class NavView : FrameLayout {
internal var systemBarsUtil: SystemBarsUtil? = null
private fun setContentMargins() {
val layoutParams = CoordinatorLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
val actionBarSize = 56 * context.resources.displayMetrics.density
layoutParams.topMargin = if (showToolbar) actionBarSize.toInt() else 0
layoutParams.bottomMargin = if (bottomBarEnable) actionBarSize.toInt() else 0
contentView?.layoutParams = layoutParams
internal fun setContentMargins() {
contentView?.updateLayoutParams<CoordinatorLayout.LayoutParams> {
topMargin = if (toolbar.enable) {
toolbar.measure(MATCH_PARENT, WRAP_CONTENT)
toolbar.measuredHeight
} else 0
bottomMargin = if (bottomBar.enable) {
bottomBar.measure(MATCH_PARENT, WRAP_CONTENT)
bottomBar.measuredHeight
} else 0
}
}
override fun onConfigurationChanged(newConfig: Configuration?) {
@ -174,7 +102,7 @@ class NavView : FrameLayout {
Log.d(
"NavLib",
"CONFIGURATION CHANGED: ${newConfig?.screenWidthDp}x${newConfig?.screenHeightDp} "+if (newConfig?.orientation == ORIENTATION_PORTRAIT) "portrait" else "landscape"
"CONFIGURATION CHANGED: ${newConfig?.screenWidthDp}x${newConfig?.screenHeightDp} " + if (newConfig?.orientation == ORIENTATION_PORTRAIT) "portrait" else "landscape"
)
systemBarsUtil?.commit()
@ -202,12 +130,6 @@ class NavView : FrameLayout {
return false
}
override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
if (contentView == null) {
super.addView(child, index, params)
}
else {
contentView!!.addView(child, index, params)
}
}
override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) =
contentView?.addView(child, index, params) ?: super.addView(child, index, params)
}

View File

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

View File

@ -4,6 +4,7 @@ import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.os.Build
import android.util.DisplayMetrics
import android.util.TypedValue
@ -13,6 +14,7 @@ import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import com.google.android.material.elevation.ElevationOverlayProvider
import com.mikepenz.iconics.IconicsColor
import com.mikepenz.iconics.IconicsDrawable
@ -127,6 +129,9 @@ fun IconicsDrawable.colorAttr(context: Context, @AttrRes attrRes: Int) {
fun getColorFromAttr(context: Context, @AttrRes color: Int): Int {
val typedValue = TypedValue()
context.theme.resolveAttribute(color, typedValue, true)
if (typedValue.resourceId != 0) {
return ContextCompat.getColor(context, typedValue.resourceId)
}
return typedValue.data
}
@ -149,6 +154,20 @@ fun Context.getColorFromRes(@ColorRes id: Int): Int {
}
}
fun Drawable.setBadgeCount(count: Int) {
if (this is LayerDrawable) {
(this as LayerDrawable?)?.apply {
findDrawableByLayerId(R.id.ic_badge)
.takeIf { it is BadgeDrawable }
?.also { badge ->
(badge as BadgeDrawable).setCount(count.toString())
mutate()
setDrawableByLayerId(R.id.ic_badge, badge)
}
}
}
}
fun crc16(buffer: String): Int {
/* Note the change here */
var crc = 0x1D0F

View File

@ -17,6 +17,8 @@ import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.widget.NestedScrollView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@ -130,6 +132,18 @@ class NavBottomSheet : CoordinatorLayout {
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
ViewCompat.setOnApplyWindowInsetsListener(list) { view, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
// Apply the insets as a margin to the view. Here the system is setting
// only the bottom, left, and right dimensions, but apply whichever insets are
// appropriate to your layout. You can also update the view padding
// if that's more appropriate.
view.setPadding(insets.left, 0, insets.right, insets.bottom)
// Return CONSUMED if you don't want want the window insets to keep being
// passed down to descendant views.
WindowInsetsCompat.CONSUMED
}
scrimView.setOnTouchListener { _, event ->
if (!scrimViewTapToClose)
return@setOnTouchListener true

View File

@ -6,23 +6,31 @@ import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Color
import android.graphics.Outline
import android.graphics.PorterDuff
import android.graphics.drawable.LayerDrawable
import android.os.Build
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.ViewGroup.MarginLayoutParams
import android.view.ViewOutlineProvider
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.ViewCompat.setOnApplyWindowInsetsListener
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams
import androidx.customview.widget.ViewDragHelper
import androidx.drawerlayout.widget.DrawerLayout
import com.mikepenz.fastadapter.IAdapter
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.appbar.CollapsingToolbarLayout
import com.mikepenz.itemanimators.AlphaCrossFadeAnimator
import com.mikepenz.materialdrawer.*
import com.mikepenz.materialdrawer.holder.BadgeStyle
import com.mikepenz.materialdrawer.holder.ColorHolder
import com.mikepenz.materialdrawer.holder.StringHolder
@ -37,7 +45,6 @@ import com.mikepenz.materialdrawer.widget.MaterialDrawerSliderView
import com.mikepenz.materialdrawer.widget.MiniDrawerSliderView
import com.mikepenz.materialize.util.UIUtils
import pl.szczodrzynski.navlib.*
import pl.szczodrzynski.navlib.R
import pl.szczodrzynski.navlib.drawer.items.DrawerPrimaryItem
class NavDrawer(
@ -98,6 +105,7 @@ class NavDrawer(
})
accountHeader = AccountHeaderView(context).apply {
dividerBelowHeader = false
headerBackground = ImageHolder(R.drawable.header)
displayBadgesOnSmallProfileImages = true
@ -168,6 +176,19 @@ class NavDrawer(
}
}
setOnApplyWindowInsetsListener(drawer) { view, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
// Apply the insets as a margin to the view. Here the system is setting
// only the bottom, left, and right dimensions, but apply whichever insets are
// appropriate to your layout. You can also update the view padding
// if that's more appropriate.
view.setPadding(insets.left, insets.top, insets.right, insets.bottom)
// Return CONSUMED if you don't want want the window insets to keep being
// passed down to descendant views.
WindowInsetsCompat.CONSUMED
}
miniDrawer = MiniDrawerSliderView(context).apply {
drawer = this@NavDrawer.drawer
includeSecondaryDrawerItems = false
@ -191,6 +212,12 @@ class NavDrawer(
profileSelectionOpen()
open()
}
toolbar.drawerClickListener = {
open()
}
bottomBar.drawerClickListener = {
open()
}
val configuration = context.resources.configuration
decideDrawerMode(
@ -671,32 +698,8 @@ class NavDrawer(
}
updateMiniDrawer()
if (bottomBar.navigationIcon is LayerDrawable) {
(bottomBar.navigationIcon as LayerDrawable?)?.apply {
findDrawableByLayerId(R.id.ic_badge)
.takeIf { it is BadgeDrawable }
?.also { badge ->
(badge as BadgeDrawable).setCount(totalCount.toString())
mutate()
setDrawableByLayerId(R.id.ic_badge, badge)
}
}
}
if (totalCount == 0) {
toolbar.subtitle = resources.getString(
toolbar.subtitleFormat ?: return,
currentProfileObj?.name ?: ""
)
}
else {
toolbar.subtitle = resources.getQuantityString(
toolbar.subtitleFormatWithUnread ?: toolbar.subtitleFormat ?: return,
totalCount,
currentProfileObj?.name ?: "",
totalCount
)
}
toolbar.navigationIcon?.setBadgeCount(totalCount)
bottomBar.navigationIcon?.setBadgeCount(totalCount)
}
fun setUnreadCounterList(unreadCounterList: MutableList<out IUnreadCounter>) {

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="#ffffff" />
</shape>

View File

@ -19,7 +19,8 @@
<androidx.core.widget.NestedScrollView
android:id="@+id/bs_view"
style="@style/width_max_600dp"
android:layout_width="match_parent"
android:maxWidth="600dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:behavior_hideable="true"
@ -50,11 +51,10 @@
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/bs_textInputLayout"
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
style="?textInputFilledDenseStyle"
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"

View File

@ -28,10 +28,7 @@
android:id="@+id/item_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:gravity="start|center_vertical"
android:textAppearance="@style/NavView.TextView"
android:textSize="14sp"
tools:text="Search activity" />
<TextView
@ -42,8 +39,8 @@
android:gravity="center_vertical|start"
android:lines="1"
android:singleLine="true"
android:textAppearance="@style/NavView.TextView.Small"
android:textAppearance="?textAppearanceBodySmall"
android:textSize="12sp"
tools:text="Some drawer text" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -25,7 +25,7 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="top"
android:background="?android:windowBackground"
android:background="?nvStatusBarBackground"
tools:layout_height="25dp" />
<LinearLayout
@ -50,17 +50,31 @@
<pl.szczodrzynski.navlib.NavToolbar
android:id="@+id/nv_toolbar"
style="@style/Widget.MaterialComponents.Toolbar.Surface"
style="?toolbarSurfaceStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?actionBarBackground"
android:background="?nvActionBarBackground"
android:clipToPadding="false"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
app:title="@string/app_name"
app:titleMargin="0dp"
tools:targetApi="lollipop">
<TextView
android:id="@+id/nv_nightlyText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_gravity="center_vertical|end"
android:background="@drawable/nightly_text_rounded"
android:fontFamily="sans-serif-light"
android:padding="4dp"
android:textAllCaps="true"
android:textSize="12sp"
android:textStyle="bold"
tools:backgroundTint="#a0ff0000"
tools:text="Nightly\n20200503" />
<com.mikepenz.materialdrawer.view.BezelImageView
android:id="@+id/nv_toolbar_image"
android:layout_width="30dp"
@ -108,49 +122,25 @@
<pl.szczodrzynski.navlib.NavBottomBar
android:id="@+id/nv_bottomBar"
style="@style/Widget.MaterialComponents.BottomAppBar.Colored"
style="?bottomAppBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?nvBottomBarBackground"
android:gravity="start"
android:visibility="visible"
app:fabAlignmentMode="center"
app:fabAnimationMode="scale" />
<com.balysv.materialripple.MaterialRippleLayout
android:id="@+id/ripple"
android:layout_width="100dp"
android:layout_height="?actionBarSize"
android:layout_gravity="bottom|end"
android:enabled="false"
android:focusableInTouchMode="false"
android:focusable="false"
app:mrl_rippleFadeDuration="200"
app:mrl_rippleDuration="350"
app:mrl_rippleColor="?colorOnBackground"
app:mrl_rippleAlpha="0.3">
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:enabled="false"
android:focusableInTouchMode="false"
android:focusable="false"
android:visibility="invisible"/>
</com.balysv.materialripple.MaterialRippleLayout>
<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_anchor="@id/nv_bottomBar"
app:layout_anchorGravity="center|top"
tools:icon="@android:drawable/ic_menu_edit" />
@ -158,11 +148,9 @@
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" />
@ -175,7 +163,7 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="bottom"
android:background="?navigationBarBackground"
android:background="?nvNavigationBarBackground"
tools:layout_height="48dp" />
</FrameLayout>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="width_max_600dp">
<item name="android:layout_width">600dp</item>
</style>
</resources>

View File

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<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" />
</resources>
<attr name="nvStatusBarBackground" format="color" />
<attr name="nvActionBarBackground" format="color" />
<attr name="nvBottomBarBackground" format="color" />
<attr name="nvNavigationBarBackground" format="color" />
</resources>

View File

@ -1,8 +0,0 @@
<resources>
<declare-styleable name="NavView">
<attr name="exampleString" format="string" />
<attr name="exampleDimension" format="dimension" />
<attr name="exampleColor" format="color" />
<attr name="exampleDrawable" format="color|reference" />
</declare-styleable>
</resources>

View File

@ -1,11 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="color">#202196f3</color>
<color name="blue">#154FBC</color>
<color name="background_light">#ffffff</color>
<color name="background_dark">#242424</color>
<color name="background_black">#000000</color>
<color name="colorSurface_1dp">#0dffffff</color>
<color name="colorSurface_2dp">#12ffffff</color>
@ -16,4 +11,4 @@
<color name="colorSurface_12dp">#24ffffff</color>
<color name="colorSurface_16dp">#26ffffff</color>
<color name="colorSurface_24dp">#29ffffff</color>
</resources>
</resources>

View File

@ -1,4 +0,0 @@
<resources>
<string name="app_name">NavLib</string>
<string name="toolbar_subtitle">%1$s</string>
</resources>

View File

@ -1,159 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="NavView" />
<style name="NavView.Widget" />
<style name="NavView.Widget.FloatingActionButton" parent="Widget.MaterialComponents.FloatingActionButton">
<item name="backgroundTint">?colorFab</item>
<item name="android:textColor">?colorOnFab</item>
</style>
<style name="NavView.Widget.ExtendedFloatingActionButton" parent="Widget.MaterialComponents.ExtendedFloatingActionButton">
<item name="backgroundTint">?colorFab</item>
<item name="android:textColor">?colorOnFab</item>
</style>
<style name="NavView.TextView">
<item name="android:textAppearance">@style/NavView.TextView.Normal</item>
</style>
<!-- title text 20sp, primary, medium -->
<!-- subtitle text 16sp, primary, medium -->
<!-- large body text 22sp, primary, regular -->
<!-- medium body text 18sp, primary, regular -->
<!-- normal(default) body text 14sp, primary, regular -->
<!-- small body text 14sp, secondary, medium -->
<!-- helper body text 14sp, secondary, regular -->
<style name="NavView.TextView.Normal" parent="Widget.MaterialComponents.TextView">
<item name="android:textAppearance">?attr/textAppearanceBody2</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">?android:textColorPrimary</item>
</style>
<style name="NavView.TextView.Title" parent="TextAppearance.AppCompat.Title">
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="NavView.TextView.Subtitle" parent="TextAppearance.AppCompat.Subhead">
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textSize">16sp</item>
<item name="android:fontFamily">sans-serif-medium</item>
</style>
<style name="NavView.TextView.Large" parent="TextAppearance.AppCompat.Large">
</style>
<style name="NavView.TextView.Medium" parent="TextAppearance.AppCompat.Medium">
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="NavView.TextView.Small" parent="TextAppearance.AppCompat.Small">
<item name="android:textSize">14sp</item>
<item name="android:fontFamily">sans-serif-medium</item>
</style>
<style name="NavView.TextView.Helper" parent="TextAppearance.AppCompat.Small">
<item name="android:textSize">14sp</item>
</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:windowBackground">?android:colorBackground</item>
<!-- a descendant theme should specify those two as background colors -->
<item name="android:colorBackground">@color/background_light</item>
<item name="colorSurface">#ffffff</item>
<!-- FAB styling -->
<item name="colorFab">?colorAccent</item>
<item name="colorFabIcon">?colorOnSecondary</item>
<item name="colorOnFab">?colorOnSecondary</item>
<!-- text colors -->
<item name="android:textColorPrimary">#db000000</item>
<item name="android:textColorSecondary">#99000000</item>
<item name="colorOnPrimary">#ffffff</item>
<item name="colorOnSecondary">#ffffff</item>
<item name="colorOnBackground">?android:textColorPrimary</item>
<item name="colorOnSurface">?android:textColorPrimary</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="materialDrawerStyle">@style/Widget.MaterialDrawerStyle</item>
<item name="materialDrawerHeaderStyle">@style/Widget.MaterialDrawerHeaderStyle</item>
<!--<item name="materialDrawerPrimaryIcon">#5F6368</item>-->
</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:windowBackground">?android:colorBackground</item>
<!-- a descendant theme should specify those two as background colors -->
<item name="android:colorBackground">@color/background_dark</item>
<item name="colorSurface">#333333</item>
<!-- FAB styling -->
<item name="colorFab">?colorAccent</item>
<item name="colorFabIcon">?colorOnSecondary</item>
<item name="colorOnFab">?colorOnSecondary</item>
<!-- text colors -->
<item name="android:textColorPrimary">#ffffffff</item>
<item name="android:textColorSecondary">#99ffffff</item>
<item name="colorOnPrimary">#ffffff</item>
<item name="colorOnSecondary">#ffffff</item>
<item name="colorOnBackground">?android:textColorPrimary</item>
<item name="colorOnSurface">?android:textColorPrimary</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="materialDrawerStyle">@style/Widget.MaterialDrawerStyle</item>
<item name="materialDrawerHeaderStyle">@style/Widget.MaterialDrawerHeaderStyle</item>
<!--<item name="material_drawer_primary_icon">#9AA0A6</item>-->
</style>
<style name="NavView.Black" parent="NavView.Dark">
<item name="android:colorBackground">@color/background_black</item>
<item name="colorSurface">#121212</item>
</style>
<style name="width_max_600dp">
<item name="android:layout_width">match_parent</item>
</style>
</resources>