Skip to content

Instantly share code, notes, and snippets.

Avatar

Christophe Beyls cbeyls

View GitHub Profile
@cbeyls
cbeyls / FlowExt.kt
Created May 28, 2022
Synchronize Flow emissions with SharedFlow's subscriptionCount
View FlowExt.kt
package be.digitalia.flow
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@cbeyls
cbeyls / OptimizedDesugaring.groovy
Last active Jan 11, 2022
Automatically patch Android desugaring configuration to set "support_all_callbacks_from_library" flag to false
View OptimizedDesugaring.groovy
afterEvaluate {
// Update configuration of the R8 tasks to optimize desugaring shrinker
def originalSetting = "\"support_all_callbacks_from_library\": true"
def replacementSetting = "\"support_all_callbacks_from_library\": false"
tasks.forEach { task ->
def taskSimpleName = task.getClass().getSimpleName()
if (taskSimpleName.startsWith("R8Task")) {
task.configure {
def patchedDesugarConfig = coreLibDesugarConfig.getProvider().map {
it.replace(originalSetting, replacementSetting)
@cbeyls
cbeyls / LifecycleViewModel.kt
Last active Jan 1, 2022
Extension to add a CompositeLifecycleOwner property to a ViewModel
View LifecycleViewModel.kt
package androidx.lifecycle
import be.digitalia.utils.CompositeLifecycleOwner
private const val VIEW_LIFECYCLE_KEY = "androidx.lifecycle.VIEW_LIFECYCLE"
val ViewModel.lifecycleOwner: CompositeLifecycleOwner
get() {
return getTag(VIEW_LIFECYCLE_KEY)
?: setTagIfAbsent(VIEW_LIFECYCLE_KEY, CompositeLifecycleOwner())
@cbeyls
cbeyls / CompositeLifecycleOwner.kt
Last active Jan 1, 2022
A LifecycleOwner composed of children LifecycleOwners
View CompositeLifecycleOwner.kt
package be.digitalia.utils
import android.os.Handler
import android.os.Looper
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import java.io.Closeable
@cbeyls
cbeyls / ignore-jetified-proguard-rules.groovy
Created Oct 28, 2021
Ignore Proguard rules of jetified library dependencies
View ignore-jetified-proguard-rules.groovy
// Add the following to your Android app module build.gradle file, after the android section:
// Replace "proguard.txt" with the actual name of the proguard rules file in the library aar, if different
afterEvaluate {
// Update configuration of the minify tasks to exclude specific consumer Proguard rules files
tasks.findAll { task -> task.name.startsWith('minify') }.each { task ->
task.configure {
configurationFiles.from.collect().each { fileCollection ->
if (fileCollection instanceof FileCollection) {
configurationFiles.from.remove fileCollection
@cbeyls
cbeyls / StickyHeaderLinearLayoutManager.kt
Created Sep 27, 2021
Sticky headers LinearLayoutManager, adapted from Epoxy
View StickyHeaderLinearLayoutManager.kt
package be.digitalia.util.stickyheader
import android.content.Context
import android.graphics.PointF
import android.os.Parcel
import android.os.Parcelable
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.recyclerview.widget.LinearLayoutManager
@cbeyls
cbeyls / FlowLayout.kt
Created Sep 17, 2020
FlowLayout implementation for Jetpack Compose
View FlowLayout.kt
package be.digitalia.compose.layout
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Layout
import androidx.compose.ui.Modifier
@Composable
fun FlowLayout(
modifier: Modifier = Modifier,
@cbeyls
cbeyls / LayerCrossfadeTransition.kt
Last active Aug 1, 2020
A Transition for the Coil image loader that crossfades from the current drawable to a new one, and enables a hardware layer for the duration of the animation if the view is not opaque.
View LayerCrossfadeTransition.kt
package be.digitalia.bifff.coil
import android.view.View
import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
import coil.annotation.ExperimentalCoilApi
import coil.decode.DataSource
import coil.drawable.CrossfadeDrawable
import coil.request.ErrorResult
import coil.request.RequestResult
@cbeyls
cbeyls / TypedFragmentResults.kt
Created May 19, 2020
Example of type-safe Fragment result contract extensions
View TypedFragmentResults.kt
import android.os.Bundle
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentResultListener
import androidx.lifecycle.LifecycleOwner
interface FragmentResultContract<T> {
fun toBundle(result: T): Bundle
@cbeyls
cbeyls / RecyclerViewExt.kt
Last active Dec 30, 2020
Extension function to enforce a single scroll direction for a RecyclerView
View RecyclerViewExt.kt
package be.digitalia.samples.utils
import android.view.MotionEvent
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener
import kotlin.math.abs
fun RecyclerView.enforceSingleScrollDirection() {
val enforcer = SingleScrollDirectionEnforcer()
addOnItemTouchListener(enforcer)