1

EDIT Ok guys, I was literally trying to call the FAB which is inside the fragment_home, in another fragment, my mistake, I should've called inside the Homefragment, I just changed it and it works now, thank you to everyone that help.

TO ANYONE THAT GETS THE SAME ERROR -Check if you declared the ID of the view well -Check if you are inside that activity class (activity_main.xml -> MainActivity.kt) -Call the view correctly. IF that doesn't solve it, you will find great answers down below, good luck.

I have this fab, declared here:


<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".BaseFragment"
    android:background="@color/darkBlack">

    <TextView
        android:id="@+id/my_notes"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="sans-serif-black"
        android:text="@string/notes"
        android:textColor="@color/white"
        android:textSize="@dimen/_20sdp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <androidx.appcompat.widget.SearchView
        android:id="@+id/search_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:searchIcon="@drawable/ic_search"
        android:background="@drawable/background"
        app:queryHint="Search..."
        app:defaultQueryHint="Search..."
        android:theme="@style/ThemeOverlay.search"
        android:iconifiedByDefault="false"
        app:layout_constraintTop_toBottomOf="@+id/my_notes"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_margin="10dp"
        />


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/_10sdp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/search_view" />

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/darkBlack"
        android:orientation="horizontal"
        android:padding="@dimen/_10sdp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_baseline_check_24"
            app:tint="@color/white" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/_10sdp"
            android:src="@drawable/ic_image"
            app:tint="@color/white" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/_10sdp"
            android:src="@drawable/ic_baseline_insert_link_24"
            app:tint="@color/white" />

    </LinearLayout>


    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/yellow"
        android:id="@+id/fabBtnCreateNote"
        android:tint="@color/yellow"
        android:layout_marginEnd="@dimen/_20sdp"
        android:layout_marginBottom="@dimen/_20sdp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:src="@drawable/ic_add"
        android:contentDescription="Fab" />

</androidx.constraintlayout.widget.ConstraintLayout>

I am calling it here:


import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.google.android.material.floatingactionbutton.FloatingActionButton
import kotlinx.android.synthetic.main.fragment_home.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlin.coroutines.CoroutineContext

abstract class BaseFragment() : Fragment(), CoroutineScope {

    private lateinit var job: Job
    override val coroutineContext: CoroutineContext
        get() = job +Dispatchers.Main

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_home, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        var fab = view.findViewById<FloatingActionButton>(R.id.fabBtnCreateNote)

        //Line throwing the error ->
        fab.setOnClickListener{
            replaceFragment(CreateNoteFragment.newInstance(), true)
        }
    }


    open fun replaceFragment(fragment: Fragment, istransition:Boolean) {
        val fragmentTransition = activity!!.supportFragmentManager.beginTransaction()

        if(istransition) {
            fragmentTransition.setCustomAnimations(android.R.anim.slide_out_right, android.R.anim.slide_in_left)
        }

        fragmentTransition.add(R.id.frame_layout, fragment).addToBackStack(fragment.javaClass.simpleName).commit()
    }
}

I have declared it and am know calling it (I have android-kotlin-extensions) but it is throwing me a null object error:

java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.material.floatingactionbutton.FloatingActionButton.setOnClickListener(android.view.View$OnClickListener)' on a null object reference

It is pointing to the fabBtnCreateNote.setOnClickListener{} line.

I am not understanding what this means, could anyone help me out?

Tomas Mota
  • 672
  • 5
  • 27
  • @a_local_nobody could you elaborate please, what am I doing wrong? – Tomas Mota Apr 26 '21 at 21:28
  • @a_local_nobody I have seen that answer, but I haven't understood much and I can't get my head around what I am doing wrong, can I get some help? – Tomas Mota Apr 26 '21 at 21:29
  • what are you doing in onCreateView ? – a_local_nobody Apr 26 '21 at 21:31
  • @a_local_nobody I have this fab, I am calling that fab which is replacing the home fragment with another one (similar to when you are creating a new tweet), that fab is supposed to open that new fragment but it just throws that error – Tomas Mota Apr 26 '21 at 21:32
  • that doesn't answer my question - `what are you doing in onCreateView?` – a_local_nobody Apr 26 '21 at 21:33
  • @a_local_nobody From my little understanding here, I think that I am calling the fab and defining what happens when I click it – Tomas Mota Apr 26 '21 at 21:35
  • 1
    "Is there a way of knowing how a view is null, even though it was declared and called?" This is not enough. You also need to **initialize** the variable. For a view, this is usually done with `view.findViewById()`. – Code-Apprentice Apr 26 '21 at 21:35
  • 1
    no, you have to look at what i'm asking carefully :) i'm not asking what are you doing inside `onViewCreated`, i'm asking what are you doing `onCreateView` - they are different – a_local_nobody Apr 26 '21 at 21:35
  • @TomasMota You are not "calling" the fab. You can only call methods, but here `fabBtnCreateNote` is a variable. You are calling `setOnClickListener()` with that variable to define what happens when the user clicks on it. But you did not intialize `fabBtnCreateNote`. – Code-Apprentice Apr 26 '21 at 21:37
  • @a_local_nobody I have tried that, I have edited it to show what I have done there – Tomas Mota Apr 26 '21 at 21:37
  • i wrote an answer, maybe it helps you out – a_local_nobody Apr 26 '21 at 21:43
  • Check your imported file. Sometimes it happens when you import wrong xml file in your fragment. And that view which you want to access ( in ur case fabBtnCreateNote) happened to be present in that xml file too. Then this kind of scenario can be created . – rafi Apr 26 '21 at 21:46
  • @rafi I just added more information, I believe that could have caused it... – Tomas Mota Apr 26 '21 at 21:57
  • Your `BaseFragment` is `abstract`. What are the concrete classes doing, returning another layout from `onCreateView()` without the FAB in the layout? – laalto Apr 26 '21 at 22:00
  • Why not trying to use the recomanded way which is ViewBindig https://developer.android.com/topic/libraries/view-binding – Anis MARZOUK Apr 26 '21 at 22:08

4 Answers4

2

Try using the "findViewById" function like in this answer:

Android setOnClickListener method - How does it work?

I haven't done this stuff in a while, but I think the @id attribute only creates a string id which you have to access through R. and use to return the actual view.

EDIT: responding to your edit: You have to do:

var fabBtnCreateNote = view.findViewById<FloatingActionButton>(R.id.fabBtnCreateNote)
Grifball
  • 756
  • 1
  • 5
  • 14
  • Thank you very much for your answer, I have just edited the post to show just that, I did it but still get the same error. – Tomas Mota Apr 26 '21 at 21:38
  • I tried it, replacing the fabs id with "view", but I still get that error – Tomas Mota Apr 26 '21 at 21:39
  • @TomasMota If you are still getting an NPE, please tell us which line causes it. Right now we are only guessing where the problem is. If you tell us exactly which line causes the problem, we can better help you. Also be sure to read the link under your question that explains what a NPE is so you can start learning how to figure out these kinds of problems on your own in the future. – Code-Apprentice Apr 26 '21 at 21:42
  • Thank you very much man, I just added a comment on the line that is throwing the error. – Tomas Mota Apr 26 '21 at 21:43
  • @TomasMota I'm assuming its an error with the same line. At this point, I suspect this subview is not in the "View" object passed to ```onViewCreated``` and I would try logging all the subviews to double check like in this answer: https://stackoverflow.com/questions/7749824/android-get-all-subviews-of-a-view – Grifball Apr 26 '21 at 21:44
  • Thank you very much for your reply, I am going to read it and try it, I'll give you a feedback. – Tomas Mota Apr 26 '21 at 21:49
  • Thank you, I was declaring this function inside the wrong file... Thank you for your time. Have a nice day. – Tomas Mota Apr 26 '21 at 22:04
2
var fab = fabBtnCreateNote.findViewById<FloatingActionButton>(R.id.fabBtnCreateNote)

This is getting closer. However, you probably still get a NPE because fabBtnCreateNote is null. Instead, try this:

var fabBtnCreateNote = view.findViewById<FloatingActionButton>(R.id.fabBtnCreateNote)

Note that you need to call findViewById() with view because this is the parent which contains the FAB.

Now that fabBtnCreateNote has a valid reference to the FAB view object, you can call methods on it, such as setOnClickListener().

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • Thank you very much for your answer, I have made an edit. I have tried that, but it still throws the error :( – Tomas Mota Apr 26 '21 at 21:41
  • @TomasMota Which line causes the NPE now? – Code-Apprentice Apr 26 '21 at 21:43
  • It is still the same line, I have added the whole class so you may get a better view on what I am trying to do. Thank you – Tomas Mota Apr 26 '21 at 21:45
  • @TomasMota This sounds like the id you pass into `findViewById()` doesn't exist in the current `view`. Double check that the id `fabBtnCreateNote` exists in the XML file for your fragment. Double check the spelling. Double check that you are looking at the correct XML file (is the FAB in the XML file for the parent activity instead?). – Code-Apprentice Apr 26 '21 at 21:51
  • 1
    I think we just made a small step. I have the fab inside the fragment_home, but I am calling it inside the BaseFragment, could that have anything to do with it? – Tomas Mota Apr 26 '21 at 21:54
  • Thank you, I was declaring this function inside the wrong file... Thank you for your time. Have a nice day. – Tomas Mota Apr 26 '21 at 22:04
2

If you specifically want to use synthetics, you can consider this:

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    return inflater.inflate(R.layout.your_fragment, container, false)
}

then use

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        yourButton.whatever
    }

because onCreateView occurs before onViewCreated, so inside onViewCreated you can access your button

a_local_nobody
  • 7,947
  • 5
  • 29
  • 51
1

ANSWER

Ok guys, I was literally trying to call the FAB which is inside the fragment_home, in another fragment, my mistake, I should've called inside the Homefragment, I just changed it and it works now, thank you to everyone that help.

TO ANYONE THAT GETS THE SAME ERROR

  • Check if you declared the ID of the view well
  • Check if you are inside that activity class (activity_main.xml -> MainActivity.kt)
  • Call the view correctly.

IF that doesn't solve it, you will find great answers down below, good luck.

Consider reading:

Android setOnClickListener method - How does it work?

Tomas Mota
  • 672
  • 5
  • 27
  • 1
    I'm glad to hear that you solve the problem! To clarify terminology here, you are not calling the fab. Rather you are calling the method `setOnClickListener()` on a reference to an instance of `FloatingActionButton`. I think it is critical to have the correct terminology to describe what you are doing so that you can communicate clearly with others and think about it clearly. – Code-Apprentice Apr 27 '21 at 02:33
  • Thank you very much, my man! I appreciate it. Have a nice one. – Tomas Mota Apr 29 '21 at 16:56