Skip to content

Instantly share code, notes, and snippets.

View yongjhih's full-sized avatar
🏠
Working from home

Andrew Chen yongjhih

🏠
Working from home
View GitHub Profile
inline fun <reified T : View> ViewGroup.childrenByType(): Sequence<T> = descendantsBreadth.filterIsInstance<T>()
val ViewGroup.descendantsBreadth: Sequence<View>
get() = sequence {
val queue: Queue<View> = LinkedList()
this@descendantsBreadth.forEach { child -> queue.offer(child) }
var child = queue.poll()
while (child != null) {
yield(child)
inline fun <reified T> Any.getDeclaredFieldValue(fieldName: String): T =
javaClass.findDeclaredField(fieldName).run {
if (!isAccessible) isAccessible = true
get(this@getDeclaredFieldValue) as T
}
inline fun <reified T> Any.getDeclaredFieldValueOrNull(fieldName: String): T? =
try { getDeclaredFieldValue(fieldName) }
catch (e: NoSuchFieldException) { null }
catch (e: SecurityException) { null }
private val childHelper by lazy { NestedScrollingChildHelper(this).apply {
//isNestedScrollingEnabled = false
} }
init {
isNestedScrollingEnabled = true
}
override fun setNestedScrollingEnabled(enabled: Boolean) {
return childHelper.setNestedScrollingEnabled(enabled) // Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object kotlin.Lazy.getValue()' on a null object reference
class NestedScrollingChildImpl(val view: View) : NestedScrollingChild3 {
private val childHelper by lazy { NestedScrollingChildHelper(view) }
override fun setNestedScrollingEnabled(enabled: Boolean) {
return childHelper.setNestedScrollingEnabled(enabled)
}
override fun isNestedScrollingEnabled(): Boolean {
return childHelper.isNestedScrollingEnabled
}
fun <I> ActivityResultCaller.registerForActivityResult(
onCreateIntent: Context.(input: I) -> Intent,
callback: ActivityResultCallback<Pair<Int, Intent?>>,
) = registerForActivityResult(
activityResultContract(onCreateIntent),
callback,
)
/**
* ```
@yongjhih
yongjhih / DashedBorder.kt
Created September 27, 2023 12:17 — forked from DavidIbrahim/DashedBorder.kt
dashedBorder modifier for android compose
import androidx.compose.foundation.BorderStroke
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
const Duration _sideSheetEnterDuration = Duration(milliseconds: 250);
const Duration _sideSheetExitDuration = Duration(milliseconds: 200);
const Curve _modalSideSheetCurve = decelerateEasing;
const double _minFlingVelocity = 700.0;
const double _closeProgressThreshold = 0.5;
@RequiresApi(Build.VERSION_CODES.M)
fun View.scrollChanges() = callbackFlow {
val listener = View.OnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
trySendBlocking(Quintuple(v, scrollX, scrollY, oldScrollX, oldScrollY))
}
setOnScrollChangeListener(listener)
awaitClose { setOnScrollChangeListener(null) }
}
fun ViewTreeObserver.scrollChanges() = callbackFlow {
fun <T : Any> Class<T>.getDeclaredFieldOrNull(name: String): Field? =
tryOrNull { getDeclaredField(name) }
@Suppress("SpreadOperator")
fun <T : Any> Class<T>.getDeclaredMethodOrNull(name: String, vararg parameterTypes: Class<*>): Method? =
tryOrNull { getDeclaredMethod(name, *parameterTypes) }
@Suppress("SpreadOperator")
fun <T : Any> Class<T>.getDeclaredConstructorOrNull(vararg parameterTypes: Class<*>): Constructor<T>? =
tryOrNull { getDeclaredConstructor(*parameterTypes) }
@yongjhih
yongjhih / MemoizedInterceptor.kt
Last active August 17, 2023 15:16
Memoized Cache Interceptor
/**
* Intercepts and caches memoized responses based on the provided LruCache.
*
* @property cache an instance of LruCache to store the responses.
*/
class MemoizedInterceptor(private val cache: LruCache<String, Response>) : Interceptor {
/**
* Callback that will be invoked when a cached response is found.
* @param request the request being executed.
* @param isFresh `true` if the cached response is still fresh, `false` otherwise.