0

I am trying to set a badge to a BottomNavigationView by following this straightforward approach.

However, when I initialize the BottomNavigationView I get:

java.lang.IllegalStateException: view.findViewById(R.id.bottom_navigation_view) must not be null

I am initializing the BottomNativigationView from a fragment. I am guessing that is the issue, but I cannot figure out the solution.

private lateinit var bottomNavigation: BottomNavigationView

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

    bottomNavigation = view.findViewById(R.id.bottom_navigation_view)
}

Here is the BottomNavigationView xml for the Activity that sets up navigation for the fragments.

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bottom_navigation_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorWhite"
    app:itemIconTint="@color/navigation_tint"
    app:itemTextColor="@color/navigation_tint"
    app:labelVisibilityMode="labeled"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:menu="@menu/bottom_navigation" />

It feels like I am missing something simple, but I cannot figure out what. Thanks!

Ben
  • 3,346
  • 6
  • 32
  • 51
  • if `fragment_home` doesnt contain `bottom_navigation_view` why you think that `findViewById` call on view inflated from this layout would return something other than null ? – Selvin Dec 19 '20 at 17:23
  • 1
    try this `bottomNavigation = (activity as MyActivityName).findViewById(R.id.bottom_navigation_view)` – Zain Dec 19 '20 at 17:31
  • Ben, Can you please review answers and decide which approach is more valuable to you. Thanks – Haris Dec 24 '20 at 21:28
  • @HarisDautović both are valuable. I will accept the one people vote higher over time. – Ben Dec 25 '20 at 22:35

2 Answers2

1

You have many options to communicate betwean fragments - activity and between fragment's itself..

You should not try access activity views from fragment.

Solution 1: Share data with the host activity

class ItemViewModel : ViewModel() {
    private val mutableSelectedItem = MutableLiveData<Item>()
    val selectedItem: LiveData<Item> get() = mutableSelectedItem

    fun selectItem(item: Item) {
        mutableSelectedItem.value = item
    }
}


class MainActivity : AppCompatActivity() {
    // Using the viewModels() Kotlin property delegate from the activity-ktx
    // artifact to retrieve the ViewModel in the activity scope
    private val viewModel: ItemViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel.selectedItem.observe(this, Observer { item ->
            // Perform an action with the latest item data
        })
    }
}

class ListFragment : Fragment() {
    // Using the activityViewModels() Kotlin property delegate from the
    // fragment-ktx artifact to retrieve the ViewModel in the activity scope
    private val viewModel: ItemViewModel by activityViewModels()

    // Called when the item is clicked
    fun onItemClicked(item: Item) {
        // Set a new item
        viewModel.selectItem(item)
    }
}

Solution 2: Receive results in the host activity

button.setOnClickListener {
    val result = "result"
    // Use the Kotlin extension in the fragment-ktx artifact
    setFragmentResult("requestKey", bundleOf("bundleKey" to result))
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportFragmentManager
                .setFragmentResultListener("requestKey", this) { requestKey, bundle ->
            // We use a String here, but any type that can be put in a Bundle is supported
            val result = bundle.getString("bundleKey")
            // Do something with the result
        }
    }
}

There is many more ways but these are latest approaches from Google.

Check this reference: https://developer.android.com/guide/fragments/communicate

Haris
  • 4,130
  • 3
  • 30
  • 47
1

You can access the activity from its fragment by casting activity to your activity class, and inflate the views then.

bottomNavigation = (activity as MyActivityName).findViewById(R.id.bottom_navigation_view)
Zain
  • 37,492
  • 7
  • 60
  • 84