Skip to content

Commit

Permalink
improve breadcrumbs
Browse files Browse the repository at this point in the history
  • Loading branch information
connyduck committed May 1, 2024
1 parent 88a349f commit e6358ca
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 132 deletions.
141 changes: 30 additions & 111 deletions commons/src/main/kotlin/org/fossify/commons/views/Breadcrumbs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,38 @@ package org.fossify.commons.views

import android.content.Context
import android.content.res.ColorStateList
import android.graphics.drawable.ColorDrawable
import android.util.AttributeSet
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.widget.HorizontalScrollView
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.widget.TextViewCompat
import org.fossify.commons.R
import org.fossify.commons.databinding.ItemBreadcrumbBinding
import org.fossify.commons.databinding.ItemBreadcrumbFirstBinding
import org.fossify.commons.extensions.*
import org.fossify.commons.extensions.getBasePath
import org.fossify.commons.extensions.getProperPrimaryColor
import org.fossify.commons.extensions.getProperTextColor
import org.fossify.commons.extensions.humanizePath
import org.fossify.commons.models.FileDirItem

class Breadcrumbs(context: Context, attrs: AttributeSet) : HorizontalScrollView(context, attrs) {
private val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
private val itemsLayout: LinearLayout
private var textColor = context.getProperTextColor()
private var accentColor = context.getProperPrimaryColor()
private var fontSize = resources.getDimension(R.dimen.bigger_text_size)
private var lastPath = ""
private var isLayoutDirty = true
private var isScrollToSelectedItemPending = false
private var isFirstScroll = true
private var stickyRootInitialLeft = 0
private var rootStartPadding = 0

private val textColorStateList: ColorStateList
get() = ColorStateList(
arrayOf(intArrayOf(android.R.attr.state_activated), intArrayOf()),
intArrayOf(
textColor,
textColor.adjustAlpha(0.6f)
accentColor,
textColor
)
)

Expand All @@ -45,49 +44,9 @@ class Breadcrumbs(context: Context, attrs: AttributeSet) : HorizontalScrollView(
isHorizontalScrollBarEnabled = false
itemsLayout = LinearLayout(context)
itemsLayout.orientation = LinearLayout.HORIZONTAL
rootStartPadding = paddingStart
itemsLayout.setPaddingRelative(0, paddingTop, paddingEnd, paddingBottom)
itemsLayout.setPaddingRelative(paddingStart, paddingTop, paddingEnd, paddingBottom)
setPaddingRelative(0, 0, 0, 0)
addView(itemsLayout, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT))
onGlobalLayout {
stickyRootInitialLeft = if (itemsLayout.childCount > 0) {
itemsLayout.getChildAt(0).left
} else {
0
}
}
}

private fun recomputeStickyRootLocation(left: Int) {
stickyRootInitialLeft = left
handleRootStickiness(scrollX)
}

private fun handleRootStickiness(scrollX: Int) {
if (scrollX > stickyRootInitialLeft) {
stickRoot(scrollX - stickyRootInitialLeft)
} else {
freeRoot()
}
}

private fun freeRoot() {
if (itemsLayout.childCount > 0) {
itemsLayout.getChildAt(0).translationX = 0f
}
}

private fun stickRoot(translationX: Int) {
if (itemsLayout.childCount > 0) {
val root = itemsLayout.getChildAt(0)
root.translationX = translationX.toFloat()
ViewCompat.setTranslationZ(root, translationZ)
}
}

override fun onScrollChanged(scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int) {
super.onScrollChanged(scrollX, scrollY, oldScrollX, oldScrollY)
handleRootStickiness(scrollX)
}

override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
Expand All @@ -98,8 +57,6 @@ class Breadcrumbs(context: Context, attrs: AttributeSet) : HorizontalScrollView(
scrollToSelectedItem()
isScrollToSelectedItemPending = false
}

recomputeStickyRootLocation(left)
}

private fun scrollToSelectedItem() {
Expand Down Expand Up @@ -146,73 +103,36 @@ class Breadcrumbs(context: Context, attrs: AttributeSet) : HorizontalScrollView(
val tempPath = context.humanizePath(fullPath)

itemsLayout.removeAllViews()
val dirs = tempPath.split("/").dropLastWhile(String::isEmpty)
for (i in dirs.indices) {
val dir = dirs[i]
if (i > 0) {
currPath += dir + "/"
}

if (dir.isEmpty()) {
continue
}

currPath = "${currPath.trimEnd('/')}/"
val item = FileDirItem(currPath, dir, true, 0, 0, 0)
addBreadcrumb(item, i, i > 0)
scrollToSelectedItem()
}
}

private fun addBreadcrumb(item: FileDirItem, index: Int, addPrefix: Boolean) {
if (itemsLayout.childCount == 0) {
val firstItemBgColor = if (isShownInDialog && context.baseConfig.isUsingSystemTheme) {
resources.getColor(R.color.you_dialog_background_color, context.theme)
} else {
context.getProperBackgroundColor()
}


ItemBreadcrumbFirstBinding.inflate(inflater, itemsLayout, false).apply {
resources.apply {
breadcrumbText.background = ContextCompat.getDrawable(context, R.drawable.button_background)
breadcrumbText.background.applyColorFilter(textColor)
elevation = 1f
background = ColorDrawable(firstItemBgColor)
val medium = getDimension(R.dimen.medium_margin).toInt()
breadcrumbText.setPadding(medium, medium, medium, medium)
setPadding(rootStartPadding, 0, 0, 0)
tempPath.split("/")
.dropLastWhile(String::isEmpty)
.forEachIndexed { i, dir ->
if (i > 0) {
currPath += "$dir/"
}

isActivated = item.path.trimEnd('/') == lastPath.trimEnd('/')
breadcrumbText.text = item.name
breadcrumbText.setTextColor(textColorStateList)
breadcrumbText.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)

itemsLayout.addView(this.root)

breadcrumbText.setOnClickListener {
if (itemsLayout.getChildAt(index) != null) {
listener?.breadcrumbClicked(index)
}
if (dir.isEmpty()) {
return@forEachIndexed
}

root.tag = item
currPath = "${currPath.trimEnd('/')}/"
val item = FileDirItem(currPath, dir, true, 0, 0, 0)
addBreadcrumb(item, i, i > 0)
scrollToSelectedItem()
}
} else {
ItemBreadcrumbBinding.inflate(inflater, itemsLayout, false).apply {
var textToAdd = item.name
if (addPrefix) {
textToAdd = "> $textToAdd"
}
}

isActivated = item.path.trimEnd('/') == lastPath.trimEnd('/')
private fun addBreadcrumb(item: FileDirItem, index: Int, isLast: Boolean) {
ItemBreadcrumbBinding.inflate(inflater, itemsLayout, false).apply {
breadcrumbText.isActivated = isLast

breadcrumbText.text = textToAdd
breadcrumbText.text = item.name
breadcrumbText.setTextColor(textColorStateList)
breadcrumbText.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
breadcrumbText.text

itemsLayout.addView(root)
if (index > 0) {
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(breadcrumbText, R.drawable.ic_chevron_right_vector, 0, 0, 0)
TextViewCompat.setCompoundDrawableTintList(breadcrumbText, textColorStateList)
}

breadcrumbText.setOnClickListener { v ->
if (itemsLayout.getChildAt(index) != null && itemsLayout.getChildAt(index) == v) {
Expand All @@ -226,7 +146,6 @@ class Breadcrumbs(context: Context, attrs: AttributeSet) : HorizontalScrollView(

root.tag = item
}
}
}

fun updateColor(color: Int) {
Expand Down
3 changes: 1 addition & 2 deletions commons/src/main/res/layout/item_breadcrumb.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
android:id="@+id/breadcrumb_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/selector_clickable"
android:gravity="center_vertical"
android:minHeight="@dimen/breadcrumbs_layout_height"
android:paddingLeft="@dimen/small_margin"
android:paddingTop="@dimen/medium_margin"
android:paddingRight="@dimen/small_margin"
android:paddingBottom="@dimen/medium_margin"
android:textSize="@dimen/normal_text_size" />
19 changes: 0 additions & 19 deletions commons/src/main/res/layout/item_breadcrumb_first.xml

This file was deleted.

0 comments on commit e6358ca

Please sign in to comment.