Skip to content

Commit

Permalink
Merge pull request #67 from st235/feature/menu_item_refactoring
Browse files Browse the repository at this point in the history
Feature/menu item refactoring
  • Loading branch information
st235 authored Mar 28, 2021
2 parents bd582f3 + 591cfe1 commit 2964311
Show file tree
Hide file tree
Showing 24 changed files with 481 additions and 278 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Then you should add menu items to your navigation component
val bottomBar: ExpandableBottomBar = findViewById(R.id.expandable_bottom_bar)

bottomBar.addItems(
ExpandableBottomBarMenuItem.Builder(context = this)
MenuItemDescriptor.Builder(context = this)
.addItem(R.id.icon_home, R.drawable.ic_bug, R.string.text, Color.GRAY)
.addItem(R.id.icon_go, R.drawable.ic_gift, R.string.text2, 0xFFFF77A9)
.addItem(R.id.icon_left, R.drawable.ic_one, R.string.text3, 0xFF58A5F0)
Expand Down Expand Up @@ -126,7 +126,7 @@ Firstly, you should declare menu items in xml
android:id="@+id/bookmarks"
android:title="@string/text3"
android:icon="@drawable/ic_bookmarks"
app:exb_color="#fa2 />
app:exb_color="#fa2" />
</menu>
```

Expand Down Expand Up @@ -185,7 +185,7 @@ Then you should reference this xml file at the view attributes
/**
* Returns notification object
*/
val notification = bottomBar.getNotificationFor(i.itemId) // itemId is R.id.action_id
val notification = bottomBar.getMenuItemFor(i.itemId).notification() // itemId is R.id.action_id

notification.show() // shows simple dot-notification
notification.show("string literal") // shows notification with counter. Counter could not exceed the 4 symbols length
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,21 @@

import github.com.st235.expandablebottombar.R;
import github.com.st235.lib_expandablebottombar.ExpandableBottomBar;
import github.com.st235.lib_expandablebottombar.ExpandableBottomBarMenuItem;
import github.com.st235.lib_expandablebottombar.MenuItemDescriptor;

public class JavaActivity extends AppCompatActivity {

private static final String TAG = JavaActivity.class.getSimpleName();

private ExpandableBottomBar bottomBar;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_java);

bottomBar = findViewById(R.id.expandable_bottom_bar);
ExpandableBottomBar bottomBar = findViewById(R.id.expandable_bottom_bar);

bottomBar.addItems(
new ExpandableBottomBarMenuItem.Builder(this)
new MenuItemDescriptor.Builder(this)
.addItem(R.id.icon_home, R.drawable.ic_home, R.string.text, Color.GRAY)
.addItem(R.id.icon_likes, R.drawable.ic_likes, R.string.text2, 0xffff77a9)
.addItem(R.id.icon_bookmarks, R.drawable.ic_bookmarks, R.string.text3, 0xff58a5f0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.graphics.ColorUtils
import github.com.st235.expandablebottombar.R
import github.com.st235.lib_expandablebottombar.ExpandableBottomBar
import github.com.st235.lib_expandablebottombar.ExpandableBottomBarNotification
import github.com.st235.lib_expandablebottombar.Notification
import kotlinx.android.synthetic.main.activity_xml_declared.*

class NotificationBadgeActivity : AppCompatActivity() {

private lateinit var bottomBar: ExpandableBottomBar

private val notificationsLookup = mutableMapOf<Int, ExpandableBottomBarNotification>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_notification_badge)
Expand All @@ -40,10 +38,7 @@ class NotificationBadgeActivity : AppCompatActivity() {
}

bottomBar.onItemReselectedListener = { v, i ->
if (!notificationsLookup.containsKey(i.itemId)) {
notificationsLookup[i.itemId] = bottomBar.getNotificationFor(i.itemId)
}
val notification = notificationsLookup.getValue(i.itemId)
val notification = i.notification()

if (v.tag == null) {
notification.show()
Expand All @@ -64,8 +59,8 @@ class NotificationBadgeActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.clear -> {
for (notification in notificationsLookup.values) {
notification.clear()
for (menuItem in bottomBar.getMenuItems()) {
menuItem.notification().clear()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.graphics.ColorUtils
import github.com.st235.expandablebottombar.R
import github.com.st235.lib_expandablebottombar.ExpandableBottomBar
import github.com.st235.lib_expandablebottombar.ExpandableBottomBarMenuItem
import github.com.st235.lib_expandablebottombar.MenuItemDescriptor


class ProgrammaticallyCreatedDemoActivity : AppCompatActivity() {
Expand All @@ -24,7 +24,7 @@ class ProgrammaticallyCreatedDemoActivity : AppCompatActivity() {
color.setBackgroundColor(ColorUtils.setAlphaComponent(Color.GRAY, 60))

bottomBar.addItems(
ExpandableBottomBarMenuItem.Builder(this)
MenuItemDescriptor.Builder(this)
.addItem(
R.id.icon_home,
R.drawable.ic_home,
Expand Down Expand Up @@ -57,7 +57,7 @@ class ProgrammaticallyCreatedDemoActivity : AppCompatActivity() {
}

bottomBar.onItemReselectedListener = { _, i ->
Log.d("ExpandableBottomBar", "OnReselected: ${i.itemId}")
Log.d("ExpandableBottomBar", "OnReselected: ${i.id}")
}
}
}
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ android.useAndroidX=true

GROUP=com.github.st235

VERSION_CODE=39
VERSION_NAME=1.3.1
VERSION_CODE=42
VERSION_NAME=1.3.2

POM_DESCRIPTION=A new way to improve navigation in your app.
POM_URL=https://github.com/st235/ExpandableBottomBar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import android.graphics.Color
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import androidx.test.platform.app.InstrumentationRegistry
import github.com.st235.lib_expandablebottombar.ExpandableBottomBarMenuItem
import github.com.st235.lib_expandablebottombar.MenuItemDescriptor
import github.com.st235.lib_expandablebottombar.parsers.ExpandableBottomBarParser
import org.junit.Before
import org.junit.runner.RunWith
Expand Down Expand Up @@ -45,7 +45,7 @@ class ExpandableBottomBarParserTest {
val items = expandableBottomBarParser.inflate(R.menu.valid_menu)
val iconText = appContext.getString(R.string.icon_text)
val actualItem =
ExpandableBottomBarMenuItem(R.id.icon_id, R.drawable.item_icon, iconText, Color.WHITE, null, null)
MenuItemDescriptor(R.id.icon_id, R.drawable.item_icon, iconText, Color.WHITE, null, null)
assertThat(items, contains(actualItem))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import github.com.st235.lib_expandablebottombar.ExpandableBottomBar.ItemStyle.Co
import github.com.st235.lib_expandablebottombar.behavior.ExpandableBottomBarBehavior
import github.com.st235.lib_expandablebottombar.parsers.ExpandableBottomBarParser
import github.com.st235.lib_expandablebottombar.state.BottomBarSavedState
import github.com.st235.lib_expandablebottombar.utils.AnimationHelper
import github.com.st235.lib_expandablebottombar.utils.*
import github.com.st235.lib_expandablebottombar.utils.DrawableHelper
import github.com.st235.lib_expandablebottombar.utils.StyleController
import github.com.st235.lib_expandablebottombar.utils.applyForApiLAndHigher
Expand All @@ -41,7 +41,7 @@ import github.com.st235.lib_expandablebottombar.utils.toPx

internal const val ITEM_NOT_SELECTED = -1

typealias OnItemClickListener = (v: View, menuItem: ExpandableBottomBarMenuItem) -> Unit
typealias OnItemClickListener = (v: View, menuItem: MenuItem) -> Unit

/**
* Widget, which implements bottom bar navigation pattern
Expand Down Expand Up @@ -88,8 +88,7 @@ class ExpandableBottomBar @JvmOverloads constructor(

@IdRes private var selectedItemId: Int = ITEM_NOT_SELECTED

private val menuItems = mutableListOf<ExpandableBottomBarMenuItem>()
private val viewControllers: MutableMap<Int, ExpandableItemViewController> = mutableMapOf()
private val menuItems: MutableMap<Int, MenuItemImpl> = mutableMapOf()
private val stateController = ExpandableBottomBarStateController(this)
private lateinit var styleController: StyleController

Expand Down Expand Up @@ -201,7 +200,7 @@ class ExpandableBottomBar @JvmOverloads constructor(
}
}

override fun onSaveInstanceState(): Parcelable? {
override fun onSaveInstanceState(): Parcelable {
val superState = super.onSaveInstanceState()
return stateController.store(superState)
}
Expand All @@ -220,33 +219,47 @@ class ExpandableBottomBar @JvmOverloads constructor(
bounds.set(0, 0, w, h)
}

/**
* Returns menu item for the given id value
*
* @throws NullPointerException when id doesn't exists
*/
fun getMenuItemFor(@IdRes id: Int): MenuItem {
return menuItems.getValue(id)
}

/**
* Returns notification for passed menu item
*
* @throws NullPointerException when id doesn't exists
*/
fun getNotificationFor(@IdRes id: Int): ExpandableBottomBarNotification {
return viewControllers.getValue(id).notification()
@Deprecated(
message = "This method was replaced with MenuItem#notification",
replaceWith = ReplaceWith(expression = "this.getMenuItemFor(id = id).notification()"),
level = DeprecationLevel.ERROR
)
fun getNotificationFor(@IdRes id: Int): Notification {
return menuItems.getValue(id).notification()
}

/**
* Adds passed items to widget
*
* @param items - bottom bar menu items
* @param itemDescriptors - bottom bar menu items
*/
fun addItems(items: List<ExpandableBottomBarMenuItem>) {
fun addItems(itemDescriptors: List<MenuItemDescriptor>) {
menuItems.clear()

val firstItemId = items.first().itemId
val lastItemId = items.last().itemId
val firstItemId = itemDescriptors.first().itemId
val lastItemId = itemDescriptors.last().itemId
selectedItemId = firstItemId

for ((i, item) in items.withIndex()) {
for ((i, item) in itemDescriptors.withIndex()) {
val viewController = createItem(item)
viewControllers[item.itemId] = viewController
menuItems[item.itemId] = viewController

val prevIconId = if (i - 1 < 0) firstItemId else items[i - 1].itemId
val nextIconId = if (i + 1 >= items.size) lastItemId else items[i + 1].itemId
val prevIconId = if (i - 1 < 0) firstItemId else itemDescriptors[i - 1].itemId
val nextIconId = if (i + 1 >= itemDescriptors.size) lastItemId else itemDescriptors[i + 1].itemId

viewController.attachTo(
this,
Expand All @@ -255,26 +268,28 @@ class ExpandableBottomBar @JvmOverloads constructor(
)
}

menuItems.addAll(items)
madeMenuItemsAccessible(items)
madeMenuItemsAccessible(itemDescriptors)
}

internal fun getMenuItems(): List<ExpandableBottomBarMenuItem> = menuItems
/**
* Returns all menu items
*/
fun getMenuItems(): List<MenuItem> = menuItems.values.toList()

/**
* Programmatically select item
*
* @param id - identifier of menu item, which should be selected
*/
fun select(@IdRes id: Int) {
val itemToSelect = viewControllers.getValue(id)
onItemSelected(itemToSelect.menuItem)
val itemToSelect = menuItems.getValue(id)
onItemSelected(itemToSelect)
}

/**
* Returns currently selected item
*/
fun getSelected(): ExpandableBottomBarMenuItem = viewControllers.getValue(selectedItemId).menuItem
fun getSelected(): MenuItem = menuItems.getValue(selectedItemId)

/**
* Shows the bottom bar
Expand Down Expand Up @@ -308,64 +323,58 @@ class ExpandableBottomBar @JvmOverloads constructor(
}
}

private fun madeMenuItemsAccessible(items: List<ExpandableBottomBarMenuItem>) {
for ((i, item) in items.withIndex()) {
val prev = viewControllers[items.getOrNull(i - 1)?.itemId]
val next = viewControllers[items.getOrNull(i + 1)?.itemId]
private fun madeMenuItemsAccessible(itemDescriptors: List<MenuItemDescriptor>) {
for ((i, item) in itemDescriptors.withIndex()) {
val prev = menuItems[itemDescriptors.getOrNull(i - 1)?.itemId]
val next = menuItems[itemDescriptors.getOrNull(i + 1)?.itemId]

viewControllers[item.itemId]?.setAccessibleWith(prev = prev, next = next)
menuItems[item.itemId]?.setAccessibleWith(prev = prev, next = next)
}
}

private fun createItem(menuItem: ExpandableBottomBarMenuItem): ExpandableItemViewController {
val viewController =
ExpandableItemViewController.Builder(menuItem)
private fun createItem(menuItemDescriptor: MenuItemDescriptor): MenuItemImpl {
val menuItem =
MenuItemImpl.Builder(menuItemDescriptor)
.styleController(styleController)
.itemMargins(menuHorizontalPadding, menuVerticalPadding)
.itemBackground(itemBackgroundCornerRadius, itemBackgroundOpacity)
.itemInactiveColor(itemInactiveColor)
.notificationBadgeColor(globalBadgeColor)
.notificationBadgeTextColor(globalBadgeTextColor)
.onItemClickListener { v: View ->
.onItemClickListener { menuItem: MenuItem, v: View ->
if (!v.isSelected) {
onItemSelected(menuItem)
onItemSelectedListener?.invoke(v, menuItem)
} else {
onItemReselectedListener?.invoke(v, menuItem)
}
}
.build(context)
.build(this)

if (selectedItemId == menuItem.itemId) {
viewController.select()
if (selectedItemId == menuItemDescriptor.itemId) {
menuItem.select()
}

return viewController
return menuItem
}

private fun onItemSelected(activeMenuItem: ExpandableBottomBarMenuItem) {
if (selectedItemId == activeMenuItem.itemId) {
private fun onItemSelected(activeMenuItem: MenuItem) {
if (selectedItemId == activeMenuItem.id) {
return
}

applyTransition()
delayTransition(duration = transitionDuration.toLong())

val set = ConstraintSet()
set.clone(this)

viewControllers.getValue(activeMenuItem.itemId).select()
viewControllers.getValue(selectedItemId).unselect()
selectedItemId = activeMenuItem.itemId
menuItems.getValue(activeMenuItem.id).select()
menuItems.getValue(selectedItemId).deselect()
selectedItemId = activeMenuItem.id

set.applyTo(this)
}

private fun applyTransition() {
val autoTransition = AutoTransition()
autoTransition.duration = transitionDuration.toLong()
TransitionManager.beginDelayedTransition(this, autoTransition)
}

internal class ExpandableBottomBarStateController(
private val expandableBottomBar: ExpandableBottomBar
) {
Expand All @@ -374,8 +383,8 @@ class ExpandableBottomBar @JvmOverloads constructor(

fun restore(stateBottomBar: BottomBarSavedState) {
val selectedItemId = stateBottomBar.selectedItem
val viewController = expandableBottomBar.viewControllers.getValue(selectedItemId)
expandableBottomBar.onItemSelected(viewController.menuItem)
val menuItem = expandableBottomBar.menuItems.getValue(selectedItemId)
expandableBottomBar.onItemSelected(menuItem)
}
}

Expand Down
Loading

0 comments on commit 2964311

Please sign in to comment.