mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-27 20:15:29 +00:00
Use libs instead of copy code
This commit is contained in:
parent
a8640f52ef
commit
11600fc116
@ -74,6 +74,9 @@ dependencies {
|
|||||||
implementation("com.github.topjohnwu:lz4-java:1.7.1")
|
implementation("com.github.topjohnwu:lz4-java:1.7.1")
|
||||||
implementation("com.jakewharton.timber:timber:4.7.1")
|
implementation("com.jakewharton.timber:timber:4.7.1")
|
||||||
implementation("org.bouncycastle:bcpkix-jdk15on:1.70")
|
implementation("org.bouncycastle:bcpkix-jdk15on:1.70")
|
||||||
|
implementation("dev.rikka.rikkax.layoutinflater:layoutinflater:1.2.0")
|
||||||
|
implementation("dev.rikka.rikkax.insets:insets:1.1.1")
|
||||||
|
implementation("dev.rikka.rikkax.recyclerview:recyclerview-ktx:1.3.1")
|
||||||
|
|
||||||
val vBAdapt = "4.0.0"
|
val vBAdapt = "4.0.0"
|
||||||
val bindingAdapter = "me.tatarka.bindingcollectionadapter2:bindingcollectionadapter"
|
val bindingAdapter = "me.tatarka.bindingcollectionadapter2:bindingcollectionadapter"
|
||||||
|
@ -14,9 +14,10 @@ import androidx.navigation.NavController
|
|||||||
import androidx.navigation.NavDirections
|
import androidx.navigation.NavDirections
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.arch.inflater.LayoutInflaterFactory
|
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||||
|
import rikka.insets.WindowInsetsHelper
|
||||||
|
import rikka.layoutinflater.view.LayoutInflaterFactory
|
||||||
|
|
||||||
abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
|
abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
|
||||||
BaseActivity(), BaseUIComponent<VM> {
|
BaseActivity(), BaseUIComponent<VM> {
|
||||||
@ -44,6 +45,7 @@ abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
layoutInflater.factory2 = LayoutInflaterFactory(delegate)
|
layoutInflater.factory2 = LayoutInflaterFactory(delegate)
|
||||||
|
.addOnViewCreatedListener(WindowInsetsHelper.LISTENER)
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.arch.inflater
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.InflateException
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
|
||||||
import androidx.collection.SimpleArrayMap
|
|
||||||
import java.lang.reflect.Constructor
|
|
||||||
|
|
||||||
open class LayoutInflaterFactory(private val delegate: AppCompatDelegate) : LayoutInflater.Factory2 {
|
|
||||||
|
|
||||||
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
|
|
||||||
return onCreateView(null, name, context, attrs)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(parent: View?, name: String, context: Context, attrs: AttributeSet): View? {
|
|
||||||
val view = delegate.createView(parent, name, context, attrs)
|
|
||||||
?: LayoutInflaterFactoryDefaultImpl.createViewFromTag(context, name, attrs)
|
|
||||||
onViewCreated(view, parent, name, context, attrs)
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun onViewCreated(view: View?, parent: View?, name: String, context: Context, attrs: AttributeSet) {
|
|
||||||
if (view == null) return
|
|
||||||
|
|
||||||
WindowInsetsHelper.attach(view, attrs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private object LayoutInflaterFactoryDefaultImpl {
|
|
||||||
|
|
||||||
private val constructorSignature = arrayOf(
|
|
||||||
Context::class.java, AttributeSet::class.java)
|
|
||||||
|
|
||||||
private val classPrefixList = arrayOf(
|
|
||||||
"android.widget.",
|
|
||||||
"android.view.",
|
|
||||||
"android.webkit."
|
|
||||||
)
|
|
||||||
|
|
||||||
private val constructorMap = SimpleArrayMap<String, Constructor<out View?>>()
|
|
||||||
|
|
||||||
fun createViewFromTag(context: Context, name: String, attrs: AttributeSet): View? {
|
|
||||||
var name = name
|
|
||||||
if (name == "view") {
|
|
||||||
name = attrs.getAttributeValue(null, "class")
|
|
||||||
}
|
|
||||||
return try {
|
|
||||||
if (-1 == name.indexOf('.')) {
|
|
||||||
for (prefix in classPrefixList) {
|
|
||||||
val view: View? = createViewByPrefix(context, name, attrs, prefix)
|
|
||||||
if (view != null) {
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
}
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
createViewByPrefix(context, name, attrs, null)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(ClassNotFoundException::class, InflateException::class)
|
|
||||||
private fun createViewByPrefix(context: Context, name: String, attrs: AttributeSet, prefix: String?): View? {
|
|
||||||
var constructor = constructorMap[name]
|
|
||||||
return try {
|
|
||||||
if (constructor == null) { // Class not found in the cache, see if it's real, and try to add it
|
|
||||||
val clazz = Class.forName(
|
|
||||||
if (prefix != null) prefix + name else name,
|
|
||||||
false,
|
|
||||||
context.classLoader).asSubclass(View::class.java)
|
|
||||||
constructor = clazz.getConstructor(*constructorSignature)
|
|
||||||
constructorMap.put(name, constructor)
|
|
||||||
}
|
|
||||||
constructor!!.isAccessible = true
|
|
||||||
constructor.newInstance(context, attrs)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,284 +0,0 @@
|
|||||||
@file:Suppress("unused")
|
|
||||||
|
|
||||||
package com.topjohnwu.magisk.arch.inflater
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.annotation.TargetApi
|
|
||||||
import android.graphics.Rect
|
|
||||||
import android.os.Build
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.Gravity.*
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.core.graphics.Insets
|
|
||||||
import androidx.core.view.OnApplyWindowInsetsListener
|
|
||||||
import androidx.core.view.ViewCompat
|
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
|
|
||||||
private typealias ApplyInsetsCallback<T> = (insets: Insets, left: Boolean, top: Boolean, right: Boolean, bottom: Boolean) -> T
|
|
||||||
|
|
||||||
private class ApplyInsets(private val out: Rect) : ApplyInsetsCallback<Unit> {
|
|
||||||
|
|
||||||
override fun invoke(insets: Insets, left: Boolean, top: Boolean, right: Boolean, bottom: Boolean) {
|
|
||||||
out.left += if (left) insets.left else 0
|
|
||||||
out.top += if (top) insets.top else 0
|
|
||||||
out.right += if (right) insets.right else 0
|
|
||||||
out.bottom += if (bottom) insets.bottom else 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ConsumeInsets : ApplyInsetsCallback<Insets> {
|
|
||||||
|
|
||||||
override fun invoke(insets: Insets, left: Boolean, top: Boolean, right: Boolean, bottom: Boolean): Insets {
|
|
||||||
val insetsLeft = if (left) 0 else insets.left
|
|
||||||
val insetsTop = if (top) 0 else insets.top
|
|
||||||
val insetsRight = if (right) 0 else insets.right
|
|
||||||
val insetsBottom = if (bottom) 0 else insets.bottom
|
|
||||||
return Insets.of(insetsLeft, insetsTop, insetsRight, insetsBottom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
open class WindowInsetsHelper private constructor(
|
|
||||||
private val view: View,
|
|
||||||
private val fitSystemWindows: Int,
|
|
||||||
private val layout_fitsSystemWindowsInsets: Int,
|
|
||||||
private val consumeSystemWindows: Int) : OnApplyWindowInsetsListener {
|
|
||||||
|
|
||||||
internal var initialPaddingLeft: Int = view.paddingLeft
|
|
||||||
internal var initialPaddingTop: Int = view.paddingTop
|
|
||||||
internal var initialPaddingRight: Int = view.paddingRight
|
|
||||||
internal var initialPaddingBottom: Int = view.paddingBottom
|
|
||||||
|
|
||||||
private var initialMargin = false
|
|
||||||
internal var initialMarginLeft: Int = 0
|
|
||||||
internal var initialMarginTop: Int = 0
|
|
||||||
internal var initialMarginRight: Int = 0
|
|
||||||
internal var initialMarginBottom: Int = 0
|
|
||||||
internal var initialMarginStart: Int = 0
|
|
||||||
internal var initialMarginEnd: Int = 0
|
|
||||||
|
|
||||||
private var lastInsets: WindowInsetsCompat? = null
|
|
||||||
|
|
||||||
open fun setInitialPadding(left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
initialPaddingLeft = left
|
|
||||||
initialPaddingTop = top
|
|
||||||
initialPaddingRight = right
|
|
||||||
initialPaddingBottom = bottom
|
|
||||||
|
|
||||||
lastInsets?.let { applyWindowInsets(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun setInitialPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) {
|
|
||||||
val isRTL = view.layoutDirection == View.LAYOUT_DIRECTION_RTL
|
|
||||||
if (isRTL) {
|
|
||||||
setInitialPadding(start, top, end, bottom)
|
|
||||||
} else {
|
|
||||||
setInitialPadding(start, top, end, bottom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun setInitialMargin(left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
initialPaddingLeft = left
|
|
||||||
initialPaddingTop = top
|
|
||||||
initialPaddingRight = right
|
|
||||||
initialPaddingBottom = bottom
|
|
||||||
|
|
||||||
lastInsets?.let { applyWindowInsets(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun setInitialMarginRelative(start: Int, top: Int, end: Int, bottom: Int) {
|
|
||||||
initialMarginStart = start
|
|
||||||
initialMarginTop = top
|
|
||||||
initialMarginEnd = end
|
|
||||||
initialMarginBottom = bottom
|
|
||||||
|
|
||||||
lastInsets?.let { applyWindowInsets(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("RtlHardcoded")
|
|
||||||
private fun <T> applyInsets(insets: Insets, fit: Int, callback: ApplyInsetsCallback<T>): T {
|
|
||||||
val relativeMode = (fit and RELATIVE_LAYOUT_DIRECTION) == RELATIVE_LAYOUT_DIRECTION
|
|
||||||
|
|
||||||
val isRTL = view.layoutDirection == View.LAYOUT_DIRECTION_RTL
|
|
||||||
|
|
||||||
val left: Boolean
|
|
||||||
val top = fit and TOP == TOP
|
|
||||||
val right: Boolean
|
|
||||||
val bottom = fit and BOTTOM == BOTTOM
|
|
||||||
|
|
||||||
if (relativeMode) {
|
|
||||||
val start = fit and START == START
|
|
||||||
val end = fit and END == END
|
|
||||||
left = (!isRTL && start) || (isRTL && end)
|
|
||||||
right = (!isRTL && end) || (isRTL && start)
|
|
||||||
} else {
|
|
||||||
left = fit and LEFT == LEFT
|
|
||||||
right = fit and RIGHT == RIGHT
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback.invoke(insets, left, top, right, bottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun applyWindowInsets(windowInsets: WindowInsetsCompat): WindowInsetsCompat {
|
|
||||||
if (fitSystemWindows != 0) {
|
|
||||||
val padding = Rect(initialPaddingLeft, initialPaddingTop, initialPaddingRight, initialPaddingBottom)
|
|
||||||
applyInsets(windowInsets.systemWindowInsets, fitSystemWindows, ApplyInsets(padding))
|
|
||||||
view.setPadding(padding.left, padding.top, padding.right, padding.bottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (layout_fitsSystemWindowsInsets != 0) {
|
|
||||||
if (!initialMargin) {
|
|
||||||
initialMarginLeft = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.leftMargin ?: 0
|
|
||||||
initialMarginTop = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.topMargin ?: 0
|
|
||||||
initialMarginRight = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.rightMargin ?: 0
|
|
||||||
initialMarginBottom = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.bottomMargin ?: 0
|
|
||||||
initialMarginStart = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.marginStart ?: 0
|
|
||||||
initialMarginEnd = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.marginEnd ?: 0
|
|
||||||
initialMargin = true
|
|
||||||
}
|
|
||||||
|
|
||||||
val margin = if ((layout_fitsSystemWindowsInsets and RELATIVE_LAYOUT_DIRECTION) == RELATIVE_LAYOUT_DIRECTION)
|
|
||||||
Rect(initialMarginLeft, initialMarginTop, initialMarginRight, initialMarginBottom)
|
|
||||||
else
|
|
||||||
Rect(initialMarginStart, initialMarginTop, initialMarginEnd, initialMarginBottom)
|
|
||||||
|
|
||||||
applyInsets(windowInsets.systemWindowInsets, layout_fitsSystemWindowsInsets, ApplyInsets(margin))
|
|
||||||
|
|
||||||
val lp = view.layoutParams
|
|
||||||
if (lp is ViewGroup.MarginLayoutParams) {
|
|
||||||
lp.topMargin = margin.top
|
|
||||||
lp.bottomMargin = margin.bottom
|
|
||||||
|
|
||||||
if ((layout_fitsSystemWindowsInsets and RELATIVE_LAYOUT_DIRECTION) == RELATIVE_LAYOUT_DIRECTION) {
|
|
||||||
lp.marginStart = margin.left
|
|
||||||
lp.marginEnd = margin.right
|
|
||||||
} else {
|
|
||||||
lp.leftMargin = margin.left
|
|
||||||
lp.rightMargin = margin.right
|
|
||||||
}
|
|
||||||
|
|
||||||
view.layoutParams = lp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val systemWindowInsets = if (consumeSystemWindows != 0) applyInsets(windowInsets.systemWindowInsets, consumeSystemWindows, ConsumeInsets()) else windowInsets.systemWindowInsets
|
|
||||||
|
|
||||||
return WindowInsetsCompat.Builder(windowInsets)
|
|
||||||
.setSystemWindowInsets(systemWindowInsets)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onApplyWindowInsets(view: View, insets: WindowInsetsCompat): WindowInsetsCompat {
|
|
||||||
if (lastInsets == insets) {
|
|
||||||
return insets
|
|
||||||
}
|
|
||||||
|
|
||||||
lastInsets = insets
|
|
||||||
|
|
||||||
return applyWindowInsets(insets)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun attach(view: View, attrs: AttributeSet) {
|
|
||||||
val a = view.context.obtainStyledAttributes(attrs, R.styleable.WindowInsetsHelper, 0, 0)
|
|
||||||
val edgeToEdge = a.getBoolean(R.styleable.WindowInsetsHelper_edgeToEdge, false)
|
|
||||||
val fitsSystemWindowsInsets = a.getInt(R.styleable.WindowInsetsHelper_fitsSystemWindowsInsets, 0)
|
|
||||||
val layout_fitsSystemWindowsInsets = a.getInt(R.styleable.WindowInsetsHelper_layout_fitsSystemWindowsInsets, 0)
|
|
||||||
val consumeSystemWindowsInsets = a.getInt(R.styleable.WindowInsetsHelper_consumeSystemWindowsInsets, 0)
|
|
||||||
a.recycle()
|
|
||||||
|
|
||||||
attach(view, edgeToEdge, fitsSystemWindowsInsets, layout_fitsSystemWindowsInsets, consumeSystemWindowsInsets)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun attach(view: View, edgeToEdge: Boolean, fitsSystemWindowsInsets: Int, layout_fitsSystemWindowsInsets: Int, consumeSystemWindowsInsets: Int) {
|
|
||||||
if (edgeToEdge) {
|
|
||||||
view.systemUiVisibility = (view.systemUiVisibility
|
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fitsSystemWindowsInsets == 0 && layout_fitsSystemWindowsInsets == 0 && consumeSystemWindowsInsets == 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val listener = WindowInsetsHelper(view, fitsSystemWindowsInsets, layout_fitsSystemWindowsInsets, consumeSystemWindowsInsets)
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(view, listener)
|
|
||||||
view.setTag(R.id.tag_rikka_material_WindowInsetsHelper, listener)
|
|
||||||
|
|
||||||
if (!view.isAttachedToWindow) {
|
|
||||||
view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
|
|
||||||
override fun onViewAttachedToWindow(v: View) {
|
|
||||||
v.removeOnAttachStateChangeListener(this)
|
|
||||||
v.requestApplyInsets()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewDetachedFromWindow(v: View) = Unit
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val View.windowInsetsHelper: WindowInsetsHelper?
|
|
||||||
get() {
|
|
||||||
val value = getTag(R.id.tag_rikka_material_WindowInsetsHelper)
|
|
||||||
return if (value is WindowInsetsHelper) value else null
|
|
||||||
}
|
|
||||||
|
|
||||||
val View.initialPaddingLeft: Int
|
|
||||||
get() = windowInsetsHelper?.initialPaddingLeft ?: 0
|
|
||||||
|
|
||||||
val View.initialPaddingTop: Int
|
|
||||||
get() = windowInsetsHelper?.initialPaddingTop ?: 0
|
|
||||||
|
|
||||||
val View.initialPaddingRight: Int
|
|
||||||
get() = windowInsetsHelper?.initialPaddingRight ?: 0
|
|
||||||
|
|
||||||
val View.initialPaddingBottom: Int
|
|
||||||
get() = windowInsetsHelper?.initialPaddingBottom ?: 0
|
|
||||||
|
|
||||||
val View.initialPaddingStart: Int
|
|
||||||
get() = if (layoutDirection == View.LAYOUT_DIRECTION_RTL) initialPaddingRight else initialPaddingLeft
|
|
||||||
|
|
||||||
val View.initialPaddingEnd: Int
|
|
||||||
get() = if (layoutDirection == View.LAYOUT_DIRECTION_RTL) initialPaddingLeft else initialPaddingRight
|
|
||||||
|
|
||||||
fun View.setInitialPadding(left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
windowInsetsHelper?.setInitialPadding(left, top, right, bottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun View.setInitialPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) {
|
|
||||||
windowInsetsHelper?.setInitialPaddingRelative(start, top, end, bottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
val View.initialMarginLeft: Int
|
|
||||||
get() = windowInsetsHelper?.initialMarginLeft ?: 0
|
|
||||||
|
|
||||||
val View.initialMarginTop: Int
|
|
||||||
get() = windowInsetsHelper?.initialMarginTop ?: 0
|
|
||||||
|
|
||||||
val View.initialMarginRight: Int
|
|
||||||
get() = windowInsetsHelper?.initialMarginRight ?: 0
|
|
||||||
|
|
||||||
val View.initialMarginBottom: Int
|
|
||||||
get() = windowInsetsHelper?.initialMarginBottom ?: 0
|
|
||||||
|
|
||||||
val View.initialMarginStart: Int
|
|
||||||
get() = windowInsetsHelper?.initialMarginStart ?: 0
|
|
||||||
|
|
||||||
val View.initialMarginEnd: Int
|
|
||||||
get() = windowInsetsHelper?.initialMarginEnd ?: 0
|
|
||||||
|
|
||||||
fun View.setInitialMargin(left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
windowInsetsHelper?.setInitialMargin(left, top, right, bottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun View.setInitialMarginRelative(start: Int, top: Int, end: Int, bottom: Int) {
|
|
||||||
windowInsetsHelper?.setInitialMarginRelative(start, top, end, bottom)
|
|
||||||
}
|
|
@ -1,193 +0,0 @@
|
|||||||
@file:Suppress("unused")
|
|
||||||
|
|
||||||
package com.topjohnwu.magisk.ktx
|
|
||||||
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.Rect
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.EdgeEffect
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
|
|
||||||
fun RecyclerView.addInvalidateItemDecorationsObserver() {
|
|
||||||
|
|
||||||
adapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
|
||||||
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
|
|
||||||
invalidateItemDecorations()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
|
||||||
invalidateItemDecorations()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
|
|
||||||
invalidateItemDecorations()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun RecyclerView.addVerticalPadding(paddingTop: Int = 0, paddingBottom: Int = 0) {
|
|
||||||
addItemDecoration(VerticalPaddingDecoration(paddingTop, paddingBottom))
|
|
||||||
}
|
|
||||||
|
|
||||||
private class VerticalPaddingDecoration(private val paddingTop: Int = 0, private val paddingBottom: Int = 0) : RecyclerView.ItemDecoration() {
|
|
||||||
|
|
||||||
private var allowTop: Boolean = true
|
|
||||||
private var allowBottom: Boolean = true
|
|
||||||
|
|
||||||
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
|
|
||||||
val adapter = parent.adapter ?: return
|
|
||||||
val position = parent.getChildAdapterPosition(view)
|
|
||||||
val count = adapter.itemCount
|
|
||||||
if (position == 0 && allowTop) {
|
|
||||||
outRect.top = paddingTop
|
|
||||||
} else if (position == count - 1 && allowBottom) {
|
|
||||||
outRect.bottom = paddingBottom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun RecyclerView.addSimpleItemDecoration(
|
|
||||||
left: Int = 0,
|
|
||||||
top: Int = 0,
|
|
||||||
right: Int = 0,
|
|
||||||
bottom: Int = 0,
|
|
||||||
) {
|
|
||||||
addItemDecoration(SimpleItemDecoration(left, top, right, bottom))
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SimpleItemDecoration(
|
|
||||||
private val left: Int = 0,
|
|
||||||
private val top: Int = 0,
|
|
||||||
private val right: Int = 0,
|
|
||||||
private val bottom: Int = 0
|
|
||||||
) : RecyclerView.ItemDecoration() {
|
|
||||||
|
|
||||||
private var allowLeft: Boolean = true
|
|
||||||
private var allowTop: Boolean = true
|
|
||||||
private var allowRight: Boolean = true
|
|
||||||
private var allowBottom: Boolean = true
|
|
||||||
|
|
||||||
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
|
|
||||||
if (parent.adapter == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (allowLeft) {
|
|
||||||
outRect.left = left
|
|
||||||
}
|
|
||||||
if (allowTop) {
|
|
||||||
outRect.top = top
|
|
||||||
}
|
|
||||||
if (allowRight) {
|
|
||||||
outRect.right = right
|
|
||||||
}
|
|
||||||
if (allowBottom) {
|
|
||||||
outRect.top = bottom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun RecyclerView.fixEdgeEffect(overScrollIfContentScrolls: Boolean = true, alwaysClipToPadding: Boolean = true) {
|
|
||||||
if (overScrollIfContentScrolls) {
|
|
||||||
val listener = OverScrollIfContentScrollsListener()
|
|
||||||
addOnLayoutChangeListener(listener)
|
|
||||||
setTag(R.id.tag_rikka_recyclerView_OverScrollIfContentScrollsListener, listener)
|
|
||||||
} else {
|
|
||||||
val listener = getTag(R.id.tag_rikka_recyclerView_OverScrollIfContentScrollsListener) as? OverScrollIfContentScrollsListener
|
|
||||||
if (listener != null) {
|
|
||||||
removeOnLayoutChangeListener(listener)
|
|
||||||
setTag(R.id.tag_rikka_recyclerView_OverScrollIfContentScrollsListener, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
edgeEffectFactory = if (alwaysClipToPadding && !clipToPadding) {
|
|
||||||
AlwaysClipToPaddingEdgeEffectFactory()
|
|
||||||
} else {
|
|
||||||
RecyclerView.EdgeEffectFactory()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class OverScrollIfContentScrollsListener : View.OnLayoutChangeListener {
|
|
||||||
private var show = true
|
|
||||||
override fun onLayoutChange(v: View, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {
|
|
||||||
if (shouldDrawOverScroll(v as RecyclerView) != show) {
|
|
||||||
show = !show
|
|
||||||
if (show) {
|
|
||||||
v.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS)
|
|
||||||
} else {
|
|
||||||
v.setOverScrollMode(View.OVER_SCROLL_NEVER)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun shouldDrawOverScroll(recyclerView: RecyclerView): Boolean {
|
|
||||||
if (recyclerView.layoutManager == null || recyclerView.adapter == null || recyclerView.adapter!!.itemCount == 0) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (recyclerView.layoutManager is LinearLayoutManager) {
|
|
||||||
val itemCount = recyclerView.layoutManager!!.itemCount
|
|
||||||
val firstPosition: Int = (recyclerView.layoutManager as LinearLayoutManager?)!!.findFirstCompletelyVisibleItemPosition()
|
|
||||||
val lastPosition: Int = (recyclerView.layoutManager as LinearLayoutManager?)!!.findLastCompletelyVisibleItemPosition()
|
|
||||||
return firstPosition != 0 || lastPosition != itemCount - 1
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AlwaysClipToPaddingEdgeEffectFactory : RecyclerView.EdgeEffectFactory() {
|
|
||||||
|
|
||||||
override fun createEdgeEffect(view: RecyclerView, direction: Int): EdgeEffect {
|
|
||||||
|
|
||||||
return object : EdgeEffect(view.context) {
|
|
||||||
private var ensureSize = false
|
|
||||||
|
|
||||||
private fun ensureSize() {
|
|
||||||
if (ensureSize) return
|
|
||||||
ensureSize = true
|
|
||||||
|
|
||||||
when (direction) {
|
|
||||||
DIRECTION_LEFT -> {
|
|
||||||
setSize(view.measuredHeight - view.paddingTop - view.paddingBottom,
|
|
||||||
view.measuredWidth - view.paddingLeft - view.paddingRight)
|
|
||||||
}
|
|
||||||
DIRECTION_TOP -> {
|
|
||||||
setSize(view.measuredWidth - view.paddingLeft - view.paddingRight,
|
|
||||||
view.measuredHeight - view.paddingTop - view.paddingBottom)
|
|
||||||
}
|
|
||||||
DIRECTION_RIGHT -> {
|
|
||||||
setSize(view.measuredHeight - view.paddingTop - view.paddingBottom,
|
|
||||||
view.measuredWidth - view.paddingLeft - view.paddingRight)
|
|
||||||
}
|
|
||||||
DIRECTION_BOTTOM -> {
|
|
||||||
setSize(view.measuredWidth - view.paddingLeft - view.paddingRight,
|
|
||||||
view.measuredHeight - view.paddingTop - view.paddingBottom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun draw(c: Canvas): Boolean {
|
|
||||||
ensureSize()
|
|
||||||
|
|
||||||
val restore = c.save()
|
|
||||||
when (direction) {
|
|
||||||
DIRECTION_LEFT -> {
|
|
||||||
c.translate(view.paddingBottom.toFloat(), 0f)
|
|
||||||
}
|
|
||||||
DIRECTION_TOP -> {
|
|
||||||
c.translate(view.paddingLeft.toFloat(), view.paddingTop.toFloat())
|
|
||||||
}
|
|
||||||
DIRECTION_RIGHT -> {
|
|
||||||
c.translate(-view.paddingTop.toFloat(), 0f)
|
|
||||||
}
|
|
||||||
DIRECTION_BOTTOM -> {
|
|
||||||
c.translate(view.paddingRight.toFloat(), view.paddingBottom.toFloat())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val res = super.draw(c)
|
|
||||||
c.restoreToCount(restore)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,10 +12,10 @@ import com.topjohnwu.magisk.R
|
|||||||
import com.topjohnwu.magisk.arch.BaseUIFragment
|
import com.topjohnwu.magisk.arch.BaseUIFragment
|
||||||
import com.topjohnwu.magisk.databinding.FragmentDenyMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentDenyMd2Binding
|
||||||
import com.topjohnwu.magisk.di.viewModel
|
import com.topjohnwu.magisk.di.viewModel
|
||||||
import com.topjohnwu.magisk.ktx.addSimpleItemDecoration
|
|
||||||
import com.topjohnwu.magisk.ktx.addVerticalPadding
|
|
||||||
import com.topjohnwu.magisk.ktx.fixEdgeEffect
|
|
||||||
import com.topjohnwu.magisk.ktx.hideKeyboard
|
import com.topjohnwu.magisk.ktx.hideKeyboard
|
||||||
|
import rikka.recyclerview.addEdgeSpacing
|
||||||
|
import rikka.recyclerview.addItemSpacing
|
||||||
|
import rikka.recyclerview.fixEdgeEffect
|
||||||
|
|
||||||
class DenyListFragment : BaseUIFragment<DenyListViewModel, FragmentDenyMd2Binding>() {
|
class DenyListFragment : BaseUIFragment<DenyListViewModel, FragmentDenyMd2Binding>() {
|
||||||
|
|
||||||
@ -39,20 +39,11 @@ class DenyListFragment : BaseUIFragment<DenyListViewModel, FragmentDenyMd2Bindin
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
val resource = requireContext().resources
|
binding.appList.apply {
|
||||||
val l_50 = resource.getDimensionPixelSize(R.dimen.l_50)
|
addEdgeSpacing(top = R.dimen.l_50, bottom = R.dimen.l1)
|
||||||
val l1 = resource.getDimensionPixelSize(R.dimen.l1)
|
addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
|
||||||
binding.appList.addVerticalPadding(
|
fixEdgeEffect()
|
||||||
l_50,
|
}
|
||||||
l1 + resource.getDimensionPixelSize(R.dimen.internal_action_bar_size)
|
|
||||||
)
|
|
||||||
binding.appList.addSimpleItemDecoration(
|
|
||||||
left = l1,
|
|
||||||
top = l_50,
|
|
||||||
right = l1,
|
|
||||||
bottom = l_50,
|
|
||||||
)
|
|
||||||
binding.appList.fixEdgeEffect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPreBind(binding: FragmentDenyMd2Binding) = Unit
|
override fun onPreBind(binding: FragmentDenyMd2Binding) = Unit
|
||||||
|
@ -10,11 +10,11 @@ import com.topjohnwu.magisk.R
|
|||||||
import com.topjohnwu.magisk.arch.BaseUIFragment
|
import com.topjohnwu.magisk.arch.BaseUIFragment
|
||||||
import com.topjohnwu.magisk.databinding.FragmentLogMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentLogMd2Binding
|
||||||
import com.topjohnwu.magisk.di.viewModel
|
import com.topjohnwu.magisk.di.viewModel
|
||||||
import com.topjohnwu.magisk.ktx.addSimpleItemDecoration
|
|
||||||
import com.topjohnwu.magisk.ktx.addVerticalPadding
|
|
||||||
import com.topjohnwu.magisk.ktx.fixEdgeEffect
|
|
||||||
import com.topjohnwu.magisk.ui.MainActivity
|
import com.topjohnwu.magisk.ui.MainActivity
|
||||||
import com.topjohnwu.magisk.utils.MotionRevealHelper
|
import com.topjohnwu.magisk.utils.MotionRevealHelper
|
||||||
|
import rikka.recyclerview.addEdgeSpacing
|
||||||
|
import rikka.recyclerview.addItemSpacing
|
||||||
|
import rikka.recyclerview.fixEdgeEffect
|
||||||
|
|
||||||
class LogFragment : BaseUIFragment<LogViewModel, FragmentLogMd2Binding>() {
|
class LogFragment : BaseUIFragment<LogViewModel, FragmentLogMd2Binding>() {
|
||||||
|
|
||||||
@ -47,20 +47,11 @@ class LogFragment : BaseUIFragment<LogViewModel, FragmentLogMd2Binding>() {
|
|||||||
isMagiskLogVisible = true
|
isMagiskLogVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
val resource = requireContext().resources
|
binding.logFilterSuperuser.logSuperuser.apply {
|
||||||
val l_50 = resource.getDimensionPixelSize(R.dimen.l_50)
|
addEdgeSpacing(bottom = R.dimen.l1)
|
||||||
val l1 = resource.getDimensionPixelSize(R.dimen.l1)
|
addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
|
||||||
binding.logFilterSuperuser.logSuperuser.addVerticalPadding(
|
fixEdgeEffect()
|
||||||
0,
|
}
|
||||||
l1
|
|
||||||
)
|
|
||||||
binding.logFilterSuperuser.logSuperuser.addSimpleItemDecoration(
|
|
||||||
left = l1,
|
|
||||||
top = l_50,
|
|
||||||
right = l1,
|
|
||||||
bottom = l_50,
|
|
||||||
)
|
|
||||||
binding.logFilterSuperuser.logSuperuser.fixEdgeEffect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,48 +1,20 @@
|
|||||||
package com.topjohnwu.magisk.ui.module
|
package com.topjohnwu.magisk.ui.module
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuInflater
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.arch.BaseUIFragment
|
import com.topjohnwu.magisk.arch.BaseUIFragment
|
||||||
import com.topjohnwu.magisk.arch.ReselectionTarget
|
|
||||||
import com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding
|
||||||
import com.topjohnwu.magisk.di.viewModel
|
import com.topjohnwu.magisk.di.viewModel
|
||||||
import com.topjohnwu.magisk.ktx.*
|
import rikka.recyclerview.addEdgeSpacing
|
||||||
import com.topjohnwu.magisk.ui.MainActivity
|
import rikka.recyclerview.addInvalidateItemDecorationsObserver
|
||||||
import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener
|
import rikka.recyclerview.addItemSpacing
|
||||||
import com.topjohnwu.magisk.utils.MotionRevealHelper
|
import rikka.recyclerview.fixEdgeEffect
|
||||||
|
|
||||||
class ModuleFragment : BaseUIFragment<ModuleViewModel, FragmentModuleMd2Binding>(),
|
class ModuleFragment : BaseUIFragment<ModuleViewModel, FragmentModuleMd2Binding>() {
|
||||||
ReselectionTarget {
|
|
||||||
|
|
||||||
override val layoutRes = R.layout.fragment_module_md2
|
override val layoutRes = R.layout.fragment_module_md2
|
||||||
override val viewModel by viewModel<ModuleViewModel>()
|
override val viewModel by viewModel<ModuleViewModel>()
|
||||||
override val snackbarAnchorView: View
|
|
||||||
get() {
|
|
||||||
return if (isFilterVisible) {
|
|
||||||
binding.moduleFilterInclude.moduleFilterTitleSearch
|
|
||||||
} else {
|
|
||||||
binding.moduleFilterToggle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val listeners = hashSetOf<EndlessRecyclerScrollListener>()
|
|
||||||
|
|
||||||
private var isFilterVisible
|
|
||||||
get() = binding.moduleFilter.isVisible
|
|
||||||
set(value) {
|
|
||||||
if (!value) hideKeyboard()
|
|
||||||
MotionRevealHelper.withViews(binding.moduleFilter, binding.moduleFilterToggle, value)
|
|
||||||
with(activity as MainActivity) {
|
|
||||||
requestNavigationHidden(value)
|
|
||||||
setDisplayHomeAsUpEnabled(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
@ -53,92 +25,14 @@ class ModuleFragment : BaseUIFragment<ModuleViewModel, FragmentModuleMd2Binding>
|
|||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
binding.moduleFilterToggle.setOnClickListener {
|
|
||||||
isFilterVisible = true
|
|
||||||
}
|
|
||||||
binding.moduleFilterInclude.moduleFilterDone.setOnClickListener {
|
|
||||||
isFilterVisible = false
|
|
||||||
}
|
|
||||||
binding.moduleFilterInclude.moduleFilterList.addOnScrollListener(object :
|
|
||||||
RecyclerView.OnScrollListener() {
|
|
||||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
|
||||||
if (newState != RecyclerView.SCROLL_STATE_IDLE) hideKeyboard()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
val resource = requireContext().resources
|
|
||||||
val l_50 = resource.getDimensionPixelSize(R.dimen.l_50)
|
|
||||||
val l1 = resource.getDimensionPixelSize(R.dimen.l1)
|
|
||||||
binding.moduleList.apply {
|
binding.moduleList.apply {
|
||||||
addVerticalPadding(
|
addEdgeSpacing(top = R.dimen.l_50, bottom = R.dimen.l1)
|
||||||
l_50,
|
addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
|
||||||
l1 + l_50 + resource.getDimensionPixelSize(R.dimen.internal_action_bar_size)
|
|
||||||
)
|
|
||||||
addSimpleItemDecoration(
|
|
||||||
left = l1,
|
|
||||||
top = l_50,
|
|
||||||
right = l1,
|
|
||||||
bottom = l_50,
|
|
||||||
)
|
|
||||||
fixEdgeEffect()
|
fixEdgeEffect()
|
||||||
post {
|
post { addInvalidateItemDecorationsObserver() }
|
||||||
addInvalidateItemDecorationsObserver()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.moduleFilterInclude.moduleFilterList.apply {
|
|
||||||
addVerticalPadding(
|
|
||||||
l_50,
|
|
||||||
l_50
|
|
||||||
)
|
|
||||||
addSimpleItemDecoration(
|
|
||||||
left = l1,
|
|
||||||
top = l_50,
|
|
||||||
right = l1,
|
|
||||||
bottom = l_50,
|
|
||||||
)
|
|
||||||
fixEdgeEffect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
|
||||||
listeners.forEach {
|
|
||||||
binding.moduleList.removeOnScrollListener(it)
|
|
||||||
binding.moduleFilterInclude.moduleFilterList.removeOnScrollListener(it)
|
|
||||||
}
|
|
||||||
super.onDestroyView()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
|
||||||
if (isFilterVisible) {
|
|
||||||
isFilterVisible = false
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return super.onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
|
||||||
inflater.inflate(R.menu.menu_module_md2, menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
when (item.itemId) {
|
|
||||||
R.id.action_refresh -> viewModel.forceRefresh()
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---
|
|
||||||
|
|
||||||
override fun onReselected() {
|
|
||||||
binding.moduleList.scrollToPosition(10)
|
|
||||||
binding.moduleList.also { it.post { it.smoothScrollToPosition(0) } }
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---
|
|
||||||
|
|
||||||
override fun onPreBind(binding: FragmentModuleMd2Binding) = Unit
|
override fun onPreBind(binding: FragmentModuleMd2Binding) = Unit
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,9 @@ import com.topjohnwu.magisk.R
|
|||||||
import com.topjohnwu.magisk.arch.BaseUIFragment
|
import com.topjohnwu.magisk.arch.BaseUIFragment
|
||||||
import com.topjohnwu.magisk.databinding.FragmentSettingsMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentSettingsMd2Binding
|
||||||
import com.topjohnwu.magisk.di.viewModel
|
import com.topjohnwu.magisk.di.viewModel
|
||||||
import com.topjohnwu.magisk.ktx.addSimpleItemDecoration
|
import rikka.recyclerview.addEdgeSpacing
|
||||||
import com.topjohnwu.magisk.ktx.addVerticalPadding
|
import rikka.recyclerview.addItemSpacing
|
||||||
import com.topjohnwu.magisk.ktx.fixEdgeEffect
|
import rikka.recyclerview.fixEdgeEffect
|
||||||
import com.topjohnwu.magisk.ktx.setOnViewReadyListener
|
|
||||||
|
|
||||||
class SettingsFragment : BaseUIFragment<SettingsViewModel, FragmentSettingsMd2Binding>() {
|
class SettingsFragment : BaseUIFragment<SettingsViewModel, FragmentSettingsMd2Binding>() {
|
||||||
|
|
||||||
@ -24,24 +23,11 @@ class SettingsFragment : BaseUIFragment<SettingsViewModel, FragmentSettingsMd2Bi
|
|||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
binding.settingsList.setOnViewReadyListener {
|
binding.settingsList.apply {
|
||||||
binding.settingsList.scrollToPosition(0)
|
addEdgeSpacing(bottom = R.dimen.l1)
|
||||||
|
addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
|
||||||
|
fixEdgeEffect()
|
||||||
}
|
}
|
||||||
|
|
||||||
val resource = requireContext().resources
|
|
||||||
val l_50 = resource.getDimensionPixelSize(R.dimen.l_50)
|
|
||||||
val l1 = resource.getDimensionPixelSize(R.dimen.l1)
|
|
||||||
binding.settingsList.addVerticalPadding(
|
|
||||||
0,
|
|
||||||
l1
|
|
||||||
)
|
|
||||||
binding.settingsList.addSimpleItemDecoration(
|
|
||||||
left = l1,
|
|
||||||
top = l_50,
|
|
||||||
right = l1,
|
|
||||||
bottom = l_50,
|
|
||||||
)
|
|
||||||
binding.settingsList.fixEdgeEffect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
@ -6,9 +6,9 @@ import com.topjohnwu.magisk.R
|
|||||||
import com.topjohnwu.magisk.arch.BaseUIFragment
|
import com.topjohnwu.magisk.arch.BaseUIFragment
|
||||||
import com.topjohnwu.magisk.databinding.FragmentSuperuserMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentSuperuserMd2Binding
|
||||||
import com.topjohnwu.magisk.di.viewModel
|
import com.topjohnwu.magisk.di.viewModel
|
||||||
import com.topjohnwu.magisk.ktx.addSimpleItemDecoration
|
import rikka.recyclerview.addEdgeSpacing
|
||||||
import com.topjohnwu.magisk.ktx.addVerticalPadding
|
import rikka.recyclerview.addItemSpacing
|
||||||
import com.topjohnwu.magisk.ktx.fixEdgeEffect
|
import rikka.recyclerview.fixEdgeEffect
|
||||||
|
|
||||||
class SuperuserFragment : BaseUIFragment<SuperuserViewModel, FragmentSuperuserMd2Binding>() {
|
class SuperuserFragment : BaseUIFragment<SuperuserViewModel, FragmentSuperuserMd2Binding>() {
|
||||||
|
|
||||||
@ -23,20 +23,11 @@ class SuperuserFragment : BaseUIFragment<SuperuserViewModel, FragmentSuperuserMd
|
|||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
val resource = requireContext().resources
|
binding.superuserList.apply {
|
||||||
val l_50 = resource.getDimensionPixelSize(R.dimen.l_50)
|
addEdgeSpacing(top = R.dimen.l_50, bottom = R.dimen.l1)
|
||||||
val l1 = resource.getDimensionPixelSize(R.dimen.l1)
|
addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1)
|
||||||
binding.superuserList.addVerticalPadding(
|
fixEdgeEffect()
|
||||||
l_50,
|
}
|
||||||
l1
|
|
||||||
)
|
|
||||||
binding.superuserList.addSimpleItemDecoration(
|
|
||||||
left = l1,
|
|
||||||
top = l_50,
|
|
||||||
right = l1,
|
|
||||||
bottom = l_50,
|
|
||||||
)
|
|
||||||
binding.superuserList.fixEdgeEffect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPreBind(binding: FragmentSuperuserMd2Binding) {}
|
override fun onPreBind(binding: FragmentSuperuserMd2Binding) {}
|
||||||
|
@ -19,34 +19,6 @@
|
|||||||
|
|
||||||
<!--endregion-->
|
<!--endregion-->
|
||||||
|
|
||||||
<declare-styleable name="WindowInsetsHelper">
|
|
||||||
<attr name="edgeToEdge" format="boolean"/>
|
|
||||||
<attr name="fitsSystemWindowsInsets" format="flags">
|
|
||||||
<flag name="top" value="0x30" />
|
|
||||||
<flag name="bottom" value="0x50" />
|
|
||||||
<flag name="left" value="0x03" />
|
|
||||||
<flag name="right" value="0x05" />
|
|
||||||
<flag name="start" value="0x00800003" />
|
|
||||||
<flag name="end" value="0x00800005" />
|
|
||||||
</attr>
|
|
||||||
<attr name="consumeSystemWindowsInsets" format="flags">
|
|
||||||
<flag name="top" value="0x30" />
|
|
||||||
<flag name="bottom" value="0x50" />
|
|
||||||
<flag name="left" value="0x03" />
|
|
||||||
<flag name="right" value="0x05" />
|
|
||||||
<flag name="start" value="0x00800003" />
|
|
||||||
<flag name="end" value="0x00800005" />
|
|
||||||
</attr>
|
|
||||||
<attr name="layout_fitsSystemWindowsInsets" format="flags">
|
|
||||||
<flag name="top" value="0x30" />
|
|
||||||
<flag name="bottom" value="0x50" />
|
|
||||||
<flag name="left" value="0x03" />
|
|
||||||
<flag name="right" value="0x05" />
|
|
||||||
<flag name="start" value="0x00800003" />
|
|
||||||
<flag name="end" value="0x00800005" />
|
|
||||||
</attr>
|
|
||||||
</declare-styleable>
|
|
||||||
|
|
||||||
<declare-styleable name="ConcealableView">
|
<declare-styleable name="ConcealableView">
|
||||||
<attr name="state_hidden" format="boolean" />
|
<attr name="state_hidden" format="boolean" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
@ -2,7 +2,4 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<item name="recyclerScrollListener" type="id" />
|
<item name="recyclerScrollListener" type="id" />
|
||||||
<item name="coroutineScope" type="id" />
|
<item name="coroutineScope" type="id" />
|
||||||
|
|
||||||
<item name="tag_rikka_material_WindowInsetsHelper" type="id"/>
|
|
||||||
<item name="tag_rikka_recyclerView_OverScrollIfContentScrollsListener" type="id"/>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user