Search code examples
kotlinaccessibilityandroid-jetpack-compose

Create a list of Reference for FocusRequester in Jetpack compose


I have something like

            promotions.forEachIndexed { index, item ->
                key(item.hashCode()) {
                    PromotionItem(
                        promotionItem = item,
                        onRemove = { onRemove(index) }
                    )
                }
            }

I want to focus to one of them. I know I can create focusrequester like

val (item1, item2, item3, item4) = remember { FocusRequester.createRefs() }

How can I create the list of reference for the list in the code above. Or is there other way to handle the list?

Thanks in advance


Solution

  • First of all

    val (item1, item2, item3, item4) = remember { FocusRequester.createRefs() }
    

    This line returns only 16 FocusRequester objects most as

      @ExperimentalComposeUiApi
            object FocusRequesterFactory {
                operator fun component1() = FocusRequester()
                operator fun component2() = FocusRequester()
                operator fun component3() = FocusRequester()
                operator fun component4() = FocusRequester()
                operator fun component5() = FocusRequester()
                operator fun component6() = FocusRequester()
                operator fun component7() = FocusRequester()
                operator fun component8() = FocusRequester()
                operator fun component9() = FocusRequester()
                operator fun component10() = FocusRequester()
                operator fun component11() = FocusRequester()
                operator fun component12() = FocusRequester()
                operator fun component13() = FocusRequester()
                operator fun component14() = FocusRequester()
                operator fun component15() = FocusRequester()
                operator fun component16() = FocusRequester()
            }
    

    First and complicated way is to use kotlin-reflection to get these components and put them inside a map or list of wrapper class instance

    I add first alternative since it's part of the question but you can simply call put(promotion, FocusRequester())

    @OptIn(ExperimentalComposeUiApi::class)
    @Preview
    @Composable
    private fun FocusTest() {
        
        val focusRequesterFactory = remember { FocusRequester.createRefs() }
    
        val promotions = List(5) {
            Promotion(it)
        }
    
        val promotionMap = remember {
            linkedMapOf<Promotion, FocusRequester>().apply {
    
                val kCallables = focusRequesterFactory::class.members.toList()
    
                promotions.forEachIndexed { index, promotion ->
    
                    (kCallables.getOrNull(index)
                        ?.call(focusRequesterFactory) as? FocusRequester)
                        ?.let { focusRequester ->
                            put(promotion, focusRequester)
                        }
    
    
                    // Alternative 2
    //                put(promotion, FocusRequester())
    
                }
            }
        }
        
        Column {
            promotionMap.forEach { (promotion, focusRequester) ->  
                
                // Do something
            }
        }
    }
    
    data class Promotion(val code: Int, val tag: String = "Promotion #$code")
    

    Reflection api also requires you to add

    implementation "org.jetbrains.kotlin:kotlin-reflect:1.8.21"
    

    dependency