Flame
Flame

Reputation: 33

Kotlin Android onClickListener in getView only works on edge

I'm new to Kotlin and Android development in general. I have created a custom adapter that extends BaseAdapter and it works as I want it to, but as soon as I was to add a click listener to the view that gets returned in the getView, it doesn't seem to work as expected.

I have looked everywhere for an answer. I have seen people talking about clickable, duplicateParentState, focusable,... But nothing seems to work

The click listener does react if I click on the left/right border of my layout RelativeLayout, but I want the entire RelativeLayout to react when I click.

Am I missing something in my XML? Or is there some kind of "hack" that works. I'm a little confused as to why my click listener is not working as expected

My TokenAdapter (extends BaseAdapter)

class TokenAdapter(private val ctx: Context) : BaseAdapter() {
    private val tokenPersistence: TokenPersistence = TokenPersistence(ctx)
    private val clipboardManager: ClipboardManager =
        ctx.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    var seconds: Int
    var percentage: Int = 100
    var shouldGenerateToken: Boolean = true

    init {
        seconds = getSecondsUntilRefresh()
    }

    fun getSecondsUntilRefresh() : Int{
        val secondsElapsedInMinute = LocalDateTime.now().second
        return if(secondsElapsedInMinute < 30) 30 - secondsElapsedInMinute else 60 - secondsElapsedInMinute
    }

    override fun getCount(): Int {
        return tokenPersistence.length()
    }

    override fun getItem(position: Int): Token? {
        return tokenPersistence.get(position)
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        val v: View = if (convertView == null) {
            val inflater: LayoutInflater =
                    ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            inflater.inflate(R.layout.list_item, parent, false)
        } else {
            convertView
        }

        val t: Token = getItem(position)!!

        val title: TextView = v.findViewById(R.id.list_item_title)
        val code: TextView = v.findViewById(R.id.list_item_subtitle)
        title.text = t.getLabel()
        if (shouldGenerateToken) {
            var generatedCode : String = t.generateCode()
            generatedCode = generatedCode.substring(0, 3) + " " + generatedCode.substring(3, generatedCode.length)
            code.text = generatedCode
            shouldGenerateToken = false
        }

        val countdown: ProgressBar = v.findViewById(R.id.progress_circular)
        val countdownText: TextView = v.findViewById(R.id.progress_circular_text)

        countdownText.text = seconds.toString()
        countdown.progress = percentage

        v.setOnClickListener {
            val copyText = code.text.split(' ').joinToString("")
            println("===================")
            println("Copied: $copyText")

            val clip: ClipData = ClipData.newPlainText("2FA Code", copyText)
            clipboardManager.setPrimaryClip(clip)

            Toast.makeText(ctx, "Copied: $copyText to clipboard", Toast.LENGTH_LONG).show()
        }

        return v
    }
}

The list_item XML layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/list_item_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/list_item_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="#000000"
        android:textSize="16sp"
        android:textStyle="bold"
        android:paddingHorizontal="8dp"
        android:paddingTop="16dp"
        android:paddingBottom="0dp"
        android:clickable="false"
        />


    <TextView
        android:id="@+id/list_item_subtitle"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_below="@id/list_item_title"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_toStartOf="@id/progress_circular_container"
        android:layout_toLeftOf="@id/progress_circular_container"
        android:paddingHorizontal="8dp"
        android:paddingTop="0dp"
        android:text="123456"
        android:textColor="@color/primary"
        android:textSize="32sp"
        android:textStyle="bold"
        android:clickable="false"/>

    <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/progress_circular_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_below="@id/list_item_title"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:clickable="false">
            <ProgressBar
                android:id="@+id/progress_circular"
                android:layout_width="48sp"
                android:layout_height="48sp"
                android:indeterminateOnly="false"
                android:progressDrawable="@drawable/pb_circular_determinative"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:progress="100"/>

            <TextView
                android:id="@+id/progress_circular_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@android:color/black"
                app:layout_constraintBottom_toBottomOf="@+id/progress_circular"
                app:layout_constraintEnd_toEndOf="@+id/progress_circular"
                app:layout_constraintStart_toStartOf="@+id/progress_circular"
                app:layout_constraintTop_toTopOf="@+id/progress_circular"
                tools:text="30" />
        </androidx.constraintlayout.widget.ConstraintLayout>

</RelativeLayout>

Upvotes: 0

Views: 277

Answers (1)

Flame
Flame

Reputation: 33

So I managed to fix my problem.

I did 2 "major" things after which my problem was resolved:

  1. I rewrote my list_item.xml making use of LinearLayout instead of RelativeLayout (although I doubt this did anything)

     <LinearLayout
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:orientation="vertical">
    
         <TextView
                 android:id="@+id/list_item_title"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:textColor="#000000"
                 android:textSize="16sp"
                 android:textStyle="bold"
                 android:paddingHorizontal="8dp"
                 android:paddingTop="16dp"
                 android:paddingBottom="0dp"
                 />
    
    
             <TextView
                 android:id="@+id/list_item_subtitle"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:paddingHorizontal="8dp"
                 android:paddingTop="0dp"
                 android:textColor="@color/primary"
                 android:textSize="32sp"
                 android:textStyle="bold"
                 />
     </LinearLayout>
    
    
     <androidx.constraintlayout.widget.ConstraintLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center">
                 <ProgressBar
                     android:id="@+id/progress_circular"
                     android:layout_width="48sp"
                     android:layout_height="48sp"
                     android:indeterminateOnly="false"
                     android:progressDrawable="@drawable/pb_circular_determinative"
                     app:layout_constraintBottom_toBottomOf="parent"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintStart_toStartOf="parent"
                     app:layout_constraintTop_toTopOf="parent"
                     tools:progress="100"/>
    
                 <TextView
                     android:id="@+id/progress_circular_text"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:textColor="@android:color/black"
                     app:layout_constraintBottom_toBottomOf="@+id/progress_circular"
                     app:layout_constraintEnd_toEndOf="@+id/progress_circular"
                     app:layout_constraintStart_toStartOf="@+id/progress_circular"
                     app:layout_constraintTop_toTopOf="@+id/progress_circular"
                     tools:text="30" />
             </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. I moved my ClickListener from my Adapter getView() to my MainActivity with an setOnItemClickListener on my ListView

         val listview = findViewById<ListView>(R.id.tokenList)
    
         listview.setOnItemClickListener { parent: AdapterView<*>, view: View, position: Int, id ->
             val token = tokenAdapter.getItem(position)
    
             if(token != null) {
                 val code = token.generateCode()
                 val clip: ClipData = ClipData.newPlainText("2FA Code", code)
                 clipboardManager.setPrimaryClip(clip)
                 Toast.makeText(this, "Copied: $code", Toast.LENGTH_LONG).show()
             }
         }
    

Using this method on my Listview I also didn't have to use clickable, or any of those kinds of properties on my XML layouts. If someone knows what exactly made it work, please tell me. Personally I think it is the Listener being an 'OnItemClick' and it being moved to the MainActivity, although don't take my word for it as it could just be something else random that I did.

Upvotes: 1

Related Questions