Make fast scroll bar and popup use the theme color

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
This commit is contained in:
Álvaro Brey 2022-06-15 12:33:27 +02:00
parent 31c84d57e9
commit a7877ceb41
No known key found for this signature in database
GPG key ID: 2585783189A62105
4 changed files with 208 additions and 4 deletions

View file

@ -27,23 +27,59 @@
package com.nextcloud.utils.view package com.nextcloud.utils.view
import android.content.Context
import android.graphics.drawable.Drawable
import android.view.ViewGroup import android.view.ViewGroup
import androidx.annotation.ColorInt
import androidx.core.content.res.ResourcesCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout
import com.owncloud.android.utils.theme.ThemeColorUtils
import com.owncloud.android.utils.theme.ThemeDrawableUtils
import me.zhanghai.android.fastscroll.FastScroller import me.zhanghai.android.fastscroll.FastScroller
import me.zhanghai.android.fastscroll.FastScrollerBuilder import me.zhanghai.android.fastscroll.FastScrollerBuilder
import me.zhanghai.android.fastscroll.PopupStyles
object FastScroll { object FastScroll {
@JvmStatic @JvmStatic
@JvmOverloads @JvmOverloads
fun applyFastScroll(recyclerView: RecyclerView, viewHelper: FastScroller.ViewHelper? = null) { fun applyFastScroll(
val builder = FastScrollerBuilder(recyclerView).useMd2Style() context: Context,
themeColorUtils: ThemeColorUtils,
themeDrawableUtils: ThemeDrawableUtils,
recyclerView: RecyclerView,
viewHelper: FastScroller.ViewHelper? = null
) {
val primaryColor = themeColorUtils.primaryColor(context)
val builder = FastScrollerBuilder(recyclerView)
.useMd2Style()
.setThumbDrawable(getThumbDrawable(context, themeDrawableUtils, primaryColor))
.setPopupStyle {
PopupStyles.MD2.accept(it)
it.background = FastScrollPopupBackground(context, primaryColor)
}
if (viewHelper != null) { if (viewHelper != null) {
builder.setViewHelper(viewHelper) builder.setViewHelper(viewHelper)
} }
builder.build() builder.build()
} }
private fun getThumbDrawable(
context: Context,
themeDrawableUtils: ThemeDrawableUtils,
@ColorInt color: Int
): Drawable {
val thumbDrawable =
ResourcesCompat.getDrawable(
context.resources,
me.zhanghai.android.fastscroll.R.drawable.afs_md2_thumb,
null
)
themeDrawableUtils.tintDrawable(thumbDrawable, color)
return thumbDrawable!!
}
@JvmStatic @JvmStatic
fun fixAppBarForFastScroll(appBarLayout: AppBarLayout, content: ViewGroup) { fun fixAppBarForFastScroll(appBarLayout: AppBarLayout, content: ViewGroup) {
val contentLayoutInitialPaddingBottom = content.paddingBottom val contentLayoutInitialPaddingBottom = content.paddingBottom

View file

@ -0,0 +1,164 @@
/*
* Nextcloud Android Library is available under MIT license
*
* @author Álvaro Brey Vilas
* Copyright (C) 2022 Álvaro Brey Vilas
* Copyright (C) 2022 Nextcloud GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.nextcloud.utils.view
import android.content.Context
import android.graphics.Canvas
import android.graphics.ColorFilter
import android.graphics.Matrix
import android.graphics.Outline
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PixelFormat
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.os.Build
import android.view.View
import androidx.annotation.ColorInt
import androidx.core.graphics.drawable.DrawableCompat
import kotlin.math.sqrt
/**
* Copied over from [me.zhanghai.android.fastscroll.Md2PopupBackground] on 2022/06/15
* and adapted for color changing
*/
class FastScrollPopupBackground(context: Context, @ColorInt color: Int) : Drawable() {
private val mPaint: Paint = Paint()
private val mPaddingStart: Int
private val mPaddingEnd: Int
private val mPath = Path()
private val mTempMatrix = Matrix()
init {
mPaint.isAntiAlias = true
mPaint.color = color
mPaint.style = Paint.Style.FILL
val resources = context.resources
mPaddingStart =
resources.getDimensionPixelOffset(me.zhanghai.android.fastscroll.R.dimen.afs_md2_popup_padding_start)
mPaddingEnd =
resources.getDimensionPixelOffset(me.zhanghai.android.fastscroll.R.dimen.afs_md2_popup_padding_end)
}
override fun draw(canvas: Canvas) {
canvas.drawPath(mPath, mPaint)
}
override fun setAlpha(alpha: Int) {
// noop
}
override fun setColorFilter(colorFilter: ColorFilter?) {
// noop
}
override fun isAutoMirrored(): Boolean {
return true
}
override fun getOpacity(): Int {
return PixelFormat.TRANSPARENT
}
private fun shouldMirrorPath(): Boolean {
return DrawableCompat.getLayoutDirection(this) == View.LAYOUT_DIRECTION_RTL
}
override fun onLayoutDirectionChanged(layoutDirection: Int): Boolean {
updatePath()
return true
}
override fun onBoundsChange(bounds: Rect) {
updatePath()
}
@Suppress("MagicNumber")
private fun updatePath() {
mPath.reset()
val bounds = bounds
var width = bounds.width().toFloat()
val height = bounds.height().toFloat()
val r = height / 2
val sqrt2 = sqrt(2.0).toFloat()
// Ensure we are convex.
width = (r + sqrt2 * r).coerceAtLeast(width)
pathArcTo(mPath, r, r, r, startAngle = 90f, sweepAngle = 180f)
val o1X = width - sqrt2 * r
pathArcTo(mPath, o1X, r, r, startAngle = -90f, sweepAngle = 45f)
val r2 = r / 5
val o2X = width - sqrt2 * r2
pathArcTo(mPath, o2X, r, r2, startAngle = -45f, sweepAngle = 90f)
pathArcTo(mPath, o1X, r, r, startAngle = 45f, sweepAngle = 45f)
mPath.close()
if (shouldMirrorPath()) {
mTempMatrix.setScale(-1f, 1f, width / 2, 0f)
} else {
mTempMatrix.reset()
}
mTempMatrix.postTranslate(bounds.left.toFloat(), bounds.top.toFloat())
mPath.transform(mTempMatrix)
}
override fun getPadding(padding: Rect): Boolean {
if (shouldMirrorPath()) {
padding[mPaddingEnd, 0, mPaddingStart] = 0
} else {
padding[mPaddingStart, 0, mPaddingEnd] = 0
}
return true
}
override fun getOutline(outline: Outline) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && !mPath.isConvex) {
// The outline path must be convex before Q, but we may run into floating point error
// caused by calculation involving sqrt(2) or OEM implementation difference, so in this
// case we just omit the shadow instead of crashing.
super.getOutline(outline)
return
}
outline.setConvexPath(mPath)
}
companion object {
@Suppress("LongParameterList")
private fun pathArcTo(
path: Path,
centerX: Float,
centerY: Float,
radius: Float,
startAngle: Float,
sweepAngle: Float
) {
path.arcTo(
centerX - radius, centerY - radius, centerX + radius, centerY + radius,
startAngle, sweepAngle, false
)
}
}
}

View file

@ -118,7 +118,11 @@ public class GalleryFragment extends OCFileListFragment {
mAdapter.setLayoutManager(layoutManager); mAdapter.setLayoutManager(layoutManager);
getRecyclerView().setLayoutManager(layoutManager); getRecyclerView().setLayoutManager(layoutManager);
FastScroll.applyFastScroll(getRecyclerView(), new GalleryFastScrollViewHelper(getRecyclerView(), mAdapter)); FastScroll.applyFastScroll(requireContext(),
themeColorUtils,
themeDrawableUtils,
getRecyclerView(),
new GalleryFastScrollViewHelper(getRecyclerView(), mAdapter));
} }
@Override @Override

View file

@ -432,7 +432,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
setRecyclerViewAdapter(mAdapter); setRecyclerViewAdapter(mAdapter);
FastScroll.applyFastScroll(getRecyclerView()); FastScroll.applyFastScroll(requireContext(), themeColorUtils, themeDrawableUtils, getRecyclerView());
} }
protected void prepareCurrentSearch(SearchEvent event) { protected void prepareCurrentSearch(SearchEvent event) {