Kotlin OnClick Listener

12,178

Solution 1

I think the problem here is that you're calling val buttonClick= findViewById<Button>(R.id.button) in BaseActivity.onCreate, which is called in MainActivity.onCreate before you call setContentView... So the view isn't initialized yet, and you aren't subscribed for click events.

You can attach onClickListener in MainActivity, or if you still want to do it from your BaseActivity you can make additional initViews method and call it after setContentView:

class MainActivity : BaseActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initViews()
    }
}



open class BaseActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    } 

    protected fun initViews() {
        val buttonClick= findViewById<Button>(R.id.button)
        buttonClick?.setOnClickListener {
            Toast.makeText(this@BaseActivity, "Click...", Toast.LENGTH_LONG).show()
        }
    }    
}

Solution 2

You need to move the code of your listener in your MainActivity.

MainActivity.kt

    override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)

            val buttonClick= findViewById<Button>(R.id.button)
            buttonClick?.setOnClickListener {
                Toast.makeText(this@MainActivity, "Click...", Toast.LENGTH_LONG).show()
            }

    }

Because you are defining your listener in your BaseActivity's onCreate your findViewById<Button>(R.id.button) is effectively null due to the fact that setContentView(R.layout.activity_main) is called after.

Share:
12,178

Related videos on Youtube

Ankit Tale
Author by

Ankit Tale

An Mobile Developer by Profession on the way to become Full Stack Developer, an tech enthusiast who love to explore technology read magazine. I am here to answer the question and help the budding developer with an experience and helpful knowledge

Updated on June 04, 2022

Comments

  • Ankit Tale
    Ankit Tale almost 2 years

    I am trying to get Toast from UI defined in MainActivity and writing a code in Base Activity for onClick Listener. As per requirement I had define my base class as open but still I am not getting Toast

    Here is code

    BaseActivity

        open class BaseActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            val buttonClick= findViewById<Button>(R.id.button)
            buttonClick?.setOnClickListener {
                Toast.makeText(this@BaseActivity, "Click...", Toast.LENGTH_LONG).show()
            }
    
        }
    }
    

    MainActivity

        class MainActivity : BaseActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
        }
    }
    

    activity_main.xml

     <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        tools:layout_editor_absoluteY="81dp">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="18dp"
            android:layout_marginBottom="16dp"
            android:layout_marginEnd="16dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="16dp"
            android:text="Hello World!"
            app:layout_constraintBottom_toTopOf="@+id/button"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.409" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="190dp"
            android:text="Button"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    
    
    </android.support.constraint.ConstraintLayout>
    

    Can you tell what wrong with code how can I get a click from it

    • Sweeper
      Sweeper almost 6 years
      Did you forget to call setContentView?
  • egorikem
    egorikem almost 6 years
    Personally, i think this is a bad approach. There is quite a possibility that you will forget to call initViews at some point that nothing will work, leading you to hours of investigation. Furthermore, if you want to fix that and define initViews as abstract, there is no point in having this in separate method in first place: just make variable abstract. See my answer for more details
  • egorikem
    egorikem almost 6 years
    It does solve the issue, however it does not suit logic he wanted to maintain: all activities inherited from base one should behave in the same way
  • Enzokie
    Enzokie almost 6 years
    @GeorgySavatkov yes that's correct although you have it answered already I'll just leave the credit to yours :)
  • Demigod
    Demigod almost 6 years
    While this is not the best approach, it doesn't force you to use initViews, while having abstract val button will force every activity that will extend BaseActivity to implement it. Furthermore, your question doesn't solve the core problem.
  • egorikem
    egorikem almost 6 years
    Hold on, the question itself intended, that he wants to have a base activity, which incapsulates some logic (every activity extended from that one should have the same logic), therefore "force every activity" is exactly what he wants
  • Enzokie
    Enzokie almost 6 years
    Wait I notice a slight problem here > BaseActivity.onCreate() will be called first before MainActivity.onCreate() which stills make buttonClick null.