Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
95 views
in Technique[技术] by (71.8m points)

How do I (continue to, post-Kotlin Android Extensions) access widgets as array elements (which are doubly-included)?

I am "modernizing" some 15-month-old code to take advantage of Kotlin Extension View Binding (migrating away from the deprecated Kotlin Android Extensions compiler plugin).

The issue I'm having is related to the practice of using vars of type Array<ConstraintLayout> throughout my code. This is exemplified by charKeys throughout this posting.

I'm using nested includes within the XML.

I am struggling to figure the correct new syntax or approach. I cannot get this code to compile yet.

NOTE: All Kotlin & XML has been reduced to relevant sections only.

First, the "old" way - which is working perfectly.

PuzzleFragment.kt

import kotlinx.android.synthetic.main.fragment_puzzle.*
import kotlinx.android.synthetic.main.item_keyboard.*
import kotlinx.android.synthetic.main.item_keyboard.view.*
import kotlinx.android.synthetic.main.item_kkey.view.*
 :
 
class PuzzleFragment : Fragment() {

    lateinit var charKeys: Array<ConstraintLayout>
    
    charKeys = arrayOf(
        kbd_char_0, 
        kbd_char_1
         :
        )

fragment_puzzle.xml

<androidx.constraintlayout.widget.ConstraintLayout 
    android:id="@+id/puzzle_fragment"
    >
    <include layout="@layout/item_keyboard" />
</androidx.constraintlayout.widget.ConstraintLayout>

item_keyboard.xml

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/keyboard"
    >
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/kbd_char_0"
        >
        <include layout="@layout/item_kkey" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/kbd_char_1"
        >
        <include layout="@layout/item_kkey" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

item_kkey.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <TextView
        android:id="@+id/kkey"
        />
</merge>

Again, all of that is (was) working (using Kotlin Android Extensions). And this code allows (allowed) me to do things like:

PuzzleFragment.kt

    for (x in 0 until someNumber) {
        val shape = charKeys[x].background as GradientDrawable
        shape.setStroke(...)
        charKeys[x].kkey.setTextColor(...)


    for (key in charKeys)
        key.isEnabled = false


    for ((kx, key) in charKeys.withIndex())
        key.elevation = ... //using kx 


    for (cx in 0 until maxGuessLength)
        makeKeyRed(charKeys[cx], true)


    private fun makeKeyRed(key: ConstraintLayout, doRed: Boolean) {
        when {
            doRed -> key.kkey.setTextColor(...)
            key.kkey.text != "#" -> key.kkey.setTextColor(...)
            else -> key.kkey.setTextColor(...)
        }
    }

@@@@@@@@@@@@@@@@@@@@@@

So - that's the old way. Everything's cool. Now I'm converting this code. I have:

PuzzleFragment.kt

import com.zazzem.thats.databinding.FragmentPuzzleBinding

class PuzzleFragment : Fragment(R.layout.fragment_puzzle) {

    private var _binding: FragmentPuzzleBinding? = null
    private val binding get() = _binding!!

The following code seems ok (no "highlighted" errors in the IDE):

    lateinit var charKeys: Array<ConstraintLayout>

    charKeys = arrayOf(
        binding.item_keyboard.kbd_char_0, 
        binding.item_keyboard.kbd_char_1,
         :
    )    
    

    for (x in 0 until someNumber) {
        val shape = charKeys[x].background as GradientDrawable
        shape.setStroke(...)

But it "falls apart" with the next line of code:

        charKeys[x].kkey.setTextColor(...)

It doesn't like "kkey" here ("Unresolved reference"). And, in fact, Basic code completion (Ctrl + Space) shows none of the widgets which are part of item_kkey.

I don't know if I'm simply missing something obvious? Or if this whole "array of 'vaguely-typed' ConstraintLayouts" approach isn't valid (any longer)? Or if it's something in between?

As always, any help, suggestions, thoughts are greatly appreciated.

question from:https://stackoverflow.com/questions/65891847/how-do-i-continue-to-post-kotlin-android-extensions-access-widgets-as-array-e

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your .kkey is another use of a synthetic property, so you can't do that without Kotlin Android Extensions. The synthetic property is under the hood using findViewById on whatever ConstraintLayout you call it on to find the child view.

With view binding, no such properties of Views exist. But the generated class does have properties for include blocks. These properties return the generated binding classes of the layout files that you're including. However, you have not used android:id elements on your include elements, so they won't be accessible via your binding class.

Even if you did, that wouldn't be compatible with your ConstraintLayout Array strategy here.

I suggest for ease of converting your code, you create a direct replacement for the synthetic property, like this:

val ConstraintLayout.kkey: TextView get() = findViewById(R.id.kkey)

One downside to this compared to the synthetic property is that it has to find the view every time you use it, which is slightly slower than synthetic properties when they are repeatedly used. But I don't think it will be very significant here, since this particular view is always the sole child of the layout you are searching in.

Note, this strategy has the same weakness that they deprecated Android Extensions for. It's not safe to call this on any arbitrary ConstraintLayout.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...