Reputation: 3
I include a layout in the xml for a fragment. In the Kotlin code for the fragment, I want to access a button within the layout so I can set its onClick listener. Attempting to find the button by id, however, causes the app to close. (I navigate to the fragment using my bottom navigation, and the app just closes. No error message.) Finding the layout itself by id is successful because logging it as a string gives "androidx.constraintlayout.widget.ConstraintLayout. . ." which is the parent tag of the layout I include.
Here is my code, simplified:
The layout being included, noteView.xml:
...
<androidx.constraintlayout.widget.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:id="@+id/noteViewCont">
<ImageButton
android:id="@+id/button"/>
...
The fragment.xml layout:
...
<androidx.constraintlayout.widget.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:id="@+id/frameLayout">
<FrameLayout
...>
<include
android:id="@+id/noteViewCont"
layout="@layout/noteview"
.../>
<FrameLayout/>
...
(Though I did not write them there, there are constraints for the FrameLayout and ImageButton)
My Fragment.kt:
...
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment, container, false)
val noteVw: View = root.findViewById(R.id.noteViewCont)
Log.v("test", noteVw.toString())
...
val btn: Button = noteVw.findViewById(R.id.button)
...
return root
}
I have referred to this question and tried various solutions suggested there: findViewById not working for an include? None have worked. -As you can see, the id of the included XML file is the same as the id of include (noteViewCont). -I tried setting up noteVw in onViewCreated() and that changed nothing.
Thank you!
UPDATE
-I tried a suggestion to basically bypass noteVw entirely and do root.findViewById(R.id.button)
but this changed nothing.```
Also, here is the onViewCreated I tried:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val noteVw: View = view.findViewById(R.id.noteViewCont)
val makeBtn: Button = noteVw.findViewById(R.id.button)
}
2ND UPDATE
I figured it out, thanks to @CôngHải. Once he asked for crash log, I realized I probably should check that I was getting a crash log before I kept saying the app left "no error message". So, I found this article https://www.loginworks.com/blogs/get-crash-logs-android-applications/ and found this in my crash log:
05-04 01:17:43.758 551 551 E AndroidRuntime: java.lang.ClassCastException: androidx.appcompat.widget.AppCompatImageButton cannot be cast to android.widget.Button
A detail I did not include in this post was that I was actually using an ImageButton for the view I was trying to store in val button: Button
. I changed Button to ImageButton and everything worked fine.
Also, the first change @CôngHải suggested is a good way to simplify the code. You can access the child of an included layout directly from the layout that is including it. I removed noteVw and just used root.findViewById to get the button.
Sorry to bring up something that was actually an obvious issue, but I hope this is a useful example.
Upvotes: 0
Views: 269
Reputation: 5241
In your XML you define ImageButton
but in your code you cast it to Button, It not instance of Button, change to
val makeBtn: ImageButton = noteVw.findViewById(R.id.button)
Upvotes: 1