Hide Bottom Navigation View in fragment - android

I want to hide bottomNavigationView in some fragments.
I have tried the below code, but it has a flicker effect. (bottomNavigationView hide before the nextFragment becomes visible.
val navController = this.findNavController(R.id.nav_host_home)
navController.addOnDestinationChangedListener { _, destination, _ ->
when (destination.id) {
R.id.searchArticlesFragment -> bnvMain.visibility = View.GONE
R.id.articleFragment -> bnvMain.visibility = View.GONE
else -> bnvMain.visibility = View.VISIBLE
}
}
I have also tried another code. But it resizes the fragment. And giving OutOfMemoryException in Destination Fragment.
supportFragmentManager.registerFragmentLifecycleCallbacks(object :
FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentViewCreated(
fm: FragmentManager,
f: Fragment,
v: View,
savedInstanceState: Bundle?
) {
when (f) {
is SearchArticlesFragment -> bnvMain.visibility = View.GONE
is ArticleDetailsFragment -> bnvMain.visibility = View.GONE
else -> bnvMain.visibility = View.VISIBLE
}
}
}, true)
Please help me how can I hide the bottomNavigationView in the proper and best possible way? Is this the only way I can hide the bottomNavigationView? How youtube and Instagram achieve this behavior?

If your code follows single activity design pattern then the following solution suites you.
Create a method inside the parent activity to hide/show bottomNavigationView.
Create a BaseFragment class(create your fragments by extending this BaseFragment Class)
In the BaseFragment create a variable to hold the bottomNavigationViewVisibility (hide/show)
In onActivityCreated method of the BaseFragment, get the activity reference and set the bottomNavigationViewVisibility by calling the method which we created in STEP1.
In each fragment you create, just set the bottomNavigationViewVisibility variable.
Example:
In parentAcitivty layout, file add bottomNavigationView
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/main_bottom_navigation_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:labelVisibilityMode="labeled"
app:menu="#menu/main_nav" />
Step 1: In parent activity, create a method to change the visibility.
fun setBottomNavigationVisibility(visibility: Int) {
// get the reference of the bottomNavigationView and set the visibility.
activityMainBinding.mainBottomNavigationView.visibility = visibility
}
Step 2 & 3 & 4:
abstract class BaseFragment : Fragment() {
protected open var bottomNavigationViewVisibility = View.VISIBLE
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
// get the reference of the parent activity and call the setBottomNavigationVisibility method.
if (activity is MainActivity) {
var mainActivity = activity as MainActivity
mainActivity.setBottomNavigationVisibility(bottomNavigationViewVisibility)
}
}
override fun onResume() {
super.onResume()
if (activity is MainActivity) {
mainActivity.setBottomNavigationVisibility(bottomNavigationViewVisibility)
}
}
}
Step 5:
class SampleFragment1 : BaseFragment() {
// set the visibility here, it takes care of setting the bottomNavigationView.
override var navigationVisibility = View.VISIBLE
// override var navigationVisibility = View.GONE
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_sampleFragment1, container, false)
}
}

Related

Bottom Navigation View Null

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!
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
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)

Kotlin: spinner onItemSelectedListener from another fragment

i have a fragment with a BottomNavigationView, a Spinner and a FrameLayout, in the FrameLayout appears a a new fragment with the BottomNavigationView.setOnNavigationItemSelectedListener, this is my code:
Fragment ValcuotaEvolFragment
class ValcuotaEvolFragment: Fragment() {
lateinit var fragment : Fragment
override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?, savedInstanceState: Bundle?): View? {
val root = inflater.inflate(R.layout.fragment_valcuota_evol, container, false)
val menuBottom: BottomNavigationView = root.findViewById(R.id.nav_view_valcuota_evol)
val spn : Spinner = root.findViewById(R.id.spnAFP)
val db = DataBaseHandler(activity!!.applicationContext)
val afpListName : ArrayList<String> = db.getAFPNames()
fragment= ValcuotaChartFragment()
val bundle = Bundle()
spn.adapter= ArrayAdapter<String>(activity!!.applicationContext,android.R.layout.simple_spinner_dropdown_item,afpListName)
spn.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
bundle.putString("afp",spn.selectedItem.toString())
}
override fun onNothingSelected(parent: AdapterView<*>) { }
}
menuBottom.setOnNavigationItemSelectedListener {
menuItem ->
when(menuItem.itemId){
R.id.nav_evolcuota_chart -> {
fragment = ValcuotaChartFragment()
}
R.id.nav_evolcuota_data -> {
fragment = ValcuotaDataFragment()
}
}
fragment.setArguments(bundle);
val transaction = childFragmentManager.beginTransaction()
transaction.replace(R.id.frame_valcuota_evol, fragment)
transaction.addToBackStack(null)
transaction.commit()
true
}
fragment.setArguments(bundle);
val transaction = childFragmentManager.beginTransaction()
transaction.replace(R.id.frame_valcuota_evol, fragment)
transaction.addToBackStack(null)
transaction.commit()
return root
}
}
I pass to the new fragment the value "afp" through a Bundle, now i need the new fragment to do something different depending on what I select in the spinner of ValcuotaEvolFragment
this is what i need:
class ValcuotaDataFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val root = inflater.inflate(R.layout.fragment_valcuota_data, container, false)
val afp = arguments!!.getString("afp")
if(afp == "something"){
doSomething()
else {
doSomethingElse
}
return root
}
}
this actually works, but only when i change the item in the BottomNavigationView i need this works when change the item in the Spinner, thx
EDIT
The EventBus solution works fine , but now i have a new problem in ValcuotaDataFragment i have a RecyclerView, so now i need fill the RecyclerView after change the item in the Spinner, this is how i do it now:
val rcViewValcuota = root. findViewById(R.id.rc_valcuota_data) as RecyclerView
var valcuota : MutableList<ValcuotaModel>
val db = DataBaseHandler(activity!!.applicationContext)
valcuota = db.getCompleteValCuota(spinnerData.selectedItem,"desc")
rcViewValcuota.adapter= ContentValcuotaMonthlyAdapter(valcuota)
i can't access the "root" from the function listenItemChange
Okay, so when you're selecting a different item from the spinner, your fragment is not aware of it unless you pass data to fragment. So for informing the fragment, you can implement the interface if you'd like. Or my favorite you can use EventBus library to pass the data.
I'll show you how you can implement EventBus.
First, add EventBus Dependency is the Gradle file:
implementation 'org.greenrobot:eventbus:3.1.1'
Okay now create a data class for passing data say SpinnerData:
data class SpinnerData(val selectedItem:String)
Then inside your itemSelected listener, pass the data using EventBus:
spn.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
// bundle.putString("afp",spn.selectedItem.toString())
//insted add following line
EventBus.getDefault().post(SpinnerData(spn.selectedItem.toString()))
}
override fun onNothingSelected(parent: AdapterView<*>) { }
}
Then inside your ValcuotaDataFragment add the following:
#Subscribe
fun listenItemChange(spinnerData: SpinnerData){
if (spinnerData.selectedItem == "something") {
doSomething()
} else {
doSomethingElse()
}
}
override fun onStart() {
super.onStart()
EventBus.getDefault().register(this)
}
override fun onStop() {
EventBus.getDefault().unregister(this)
super.onStop()
}
Now, whenever you change the spinner item Evenbus will be triggered and pass the data to the Subscribed method inside your fragment.
Hope this helps, let me know if you get stuck somewhere.
Edit:
This won't work if your fragment isn't initialized already.
SO keep your line inside your itemSelected listener for first time use:
bundle.putString("afp",spn.selectedItem.toString())

KOTLIN - How to set TextViews and buttons setting from Activity to fragment

I'm new on Android, in particular on Kotlin development.
How from title, i'm trying to understand how to achieve this:
I have an Activity with some buttons and textviews. I would to implement an hidden fragment opened after 5 clicks on UI. That fragment work look like the activity. I'm able to open the fragment properly and set the layout properly. I don't know how to replace buttons activity settings from activity to fragment. I have same problem with the textview. How could I achieve it?
Thanks in Advance.
Here Activity Kotlin part that open fragment:
override fun onTouchEvent(event: MotionEvent): Boolean {
var eventaction = event.getAction()
if (eventaction == MotionEvent.ACTION_UP) {
//get system current milliseconds
var time = System.currentTimeMillis()
//if it is the first time, or if it has been more than 3 seconds since the first tap ( so it is like a new try), we reset everything
if (startMillis == 0L || (time-startMillis> 3000) ) {
startMillis=time
count=1
}
//it is not the first, and it has been less than 3 seconds since the first
else{ // time-startMillis< 3000
count++
}
if (count==5) {
// Log.d("tag","start hidden layout")
// Get the text fragment instance
val textFragment = MyFragment()
val mytostring =board_status_tv.toString()
val mArgs = Bundle()
mArgs.putString(BOARDSTATE, mytostring)
textFragment.setArguments(mArgs)
// Get the support fragment manager instance
val manager = supportFragmentManager
// Begin the fragment transition using support fragment manager
val transaction = manager.beginTransaction()
// Replace the fragment on container
transaction.replace(R.id.fragment_container,textFragment)
transaction.addToBackStack(null)
// Finishing the transition
transaction.commit()
}
return true
}
return false
}
Fragment Kotlin class:
class MyFragment : Fragment(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val parentViewGroup = linearLayout
parentViewGroup?.removeAllViews()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Get the custom view for this fragment layout
val view = inflater!!.inflate(R.layout.my_own_fragment,container,false)
// Get the text view widget reference from custom layout
val tv = view.findViewById<TextView>(R.id.text_view)
// val tv1 = view.findViewById<TextView>(R.id.board_status_tv1)
// Set a click listener for text view object
tv.setOnClickListener{
// Change the text color
tv.setTextColor(Color.RED)
// Show click confirmation
Toast.makeText(view.context,"TextView clicked.",Toast.LENGTH_SHORT).show()
}
// Return the fragment view/layout
return view
}
override fun onPause() {
super.onPause()
}
override fun onAttach(context: Context?) {
super.onAttach(context)
}
override fun onDestroy() {
super.onDestroy()
}
override fun onDetach() {
super.onDetach()
}
override fun onStart() {
super.onStart()
}
override fun onStop() {
super.onStop()
}
}
Please note that you will need to get Text before converting it to string, like that in second line.
board_status_tv .getText(). toString()
val textFragment = MyFragment()
val mytostring = board_status_tv.getText().toString()
val mArgs = Bundle()
mArgs.putString(BOARDSTATE, mytostring)
textFragment.setArguments(mArgs)
Hope this will resolve your problem

Hide android bottom navigation view for child screens/ fragments

I'm trying to create a single activity Android application.
I have MainActivity (only activity) with BottomNavigationView, three top level fragments and some child fragments. My requirement is whenever the screen is showing top level fragments, bottom navigation should be visible such that switching is possible. But when I'm viewing any of the child fragments, bottom navigation should be hidden.
Is there any out-of-box way using the Navigation component or need to change the visibility manually ?
Update (Navigation component 1.0)
As of Navigation component 1.0.0-alpha08, method addOnNavigatedListener(controller: NavController, destination: NavDestination) was changed to addOnDestinationChangedListener(controller: NavController, destination: NavDestination, arguments: Bundle). Its behavior was also slightly changed (it is also called if the destinations arguments change).
Old Answer
You can use NavController.OnNavigatedListener to achieve this behavior (set it in Activity onCreate):
findNavController(R.id.container).addOnNavigatedListener { _, destination ->
when (destination.id) {
R.id.dashboardFragment -> showBottomNavigation()
else -> hideBottomNavigation()
}
}
private fun hideBottomNavigation() {
// bottom_navigation is BottomNavigationView
with(bottom_navigation) {
if (visibility == View.VISIBLE && alpha == 1f) {
animate()
.alpha(0f)
.withEndAction { visibility = View.GONE }
.duration = EXIT_DURATION
}
}
}
private fun showBottomNavigation() {
// bottom_navigation is BottomNavigationView
with(bottom_navigation) {
visibility = View.VISIBLE
animate()
.alpha(1f)
.duration = ENTER_DURATION
}
}
Using addOnDestinationChangedListener works, and it's the solution recommended in the official documentation, but it does cause some flickering, as the callback is executed before the fragment is attached.
I find the below answer more flexible, and handles animations better:
supportFragmentManager.registerFragmentLifecycleCallbacks(object : FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentViewCreated(fm: FragmentManager, f: Fragment, v: View, savedInstanceState: Bundle?) {
TransitionManager.beginDelayedTransition(binding.root, Slide(Gravity.BOTTOM).excludeTarget(R.id.nav_host_fragment, true))
when (f) {
is ModalFragment -> {
binding.bottomNavigation.visibility = View.GONE
}
else -> {
binding.bottomNavigation.visibility = View.VISIBLE
}
}
}
}, true)
You can customize it depending on the transitions between your fragments, by choosing different animation (on my example it's a Slide), or by making the call at another lifecycle callback.
You have to make a method in MainActivity for visibility. Do call that method from fragments where you want to show or hide.
One thing I faced with such scenario is, bottom navigation visibility is not being properly gone. So I put bottom navigation view in Relative layout and hide that parent view.
you just need to write this code in MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Getting the Navigation Controller
navController = Navigation.findNavController(this, R.id.fragment)
//Setting the navigation controller to Bottom Nav
bottomNav.setupWithNavController(navController)
//Setting up the action bar
NavigationUI.setupActionBarWithNavController(this, navController)
//setting the Bottom navigation visibiliy
navController.addOnDestinationChangedListener { _, destination, _ ->
if(destination.id == R.id.full_screen_destination ){
bottomNav.visibility = View.GONE
}else{
bottomNav.visibility = View.VISIBLE
}
}
}
get more details from the android developer documentation:
Update UI components with NavigationUI
So even tho this question was already answered and the accepted answer is one that works, here is the code to actually achieve this behaviour:
MainActivity
fun hideBottomNav() {
bottomNavigationView.visibility = View.GONE
}
fun showBottomNav() {
bottomNavigationView.visibility = View.VISIBLE
}
Then you call the functions in your fragment onViewCreated(), onDetach() function, like:
Fragment
class FragmentWithOutBottomNav() : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as MainActivity).hideBottomNav()
}
override fun onDetach() {
super.onDetach()
(activity as MainActivity).showBottomNav()
}
}
Hope I could help some people. Happy coding!
navController.addOnDestinationChangedListener { _, destination, _ ->
val isMainPage = bottomNavigationView.selectedItemId == destination.id
bottomNavigationView.isVisible = isMainPage
}

is it possible to get `RecyclerView` from Fragment?

trying to get RecyclerView from this layout :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".listFragment">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recyclee">
</android.support.v7.widget.RecyclerView>
into main activity class :
private var mBlogList = findViewById<RecyclerView>(R.id.recyclee)
getting error :
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window$Callback android.view.Window.getCallback()' on a null object reference
any help please :)
edit 1
i use kotlin extension now
import kotlinx.android.synthetic.main.fragment_list.*
class MainActivity : AppCompatActivity() {
private lateinit var mBlogList : RecyclerView
in onCreate method :
mBlogList = recyclee
but the same error still exist
edit 2
listFragment code :
class listFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_list, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclee != null
}
companion object {
fun newInstance(): listFragment = listFragment()
}
}
edit 3
whole MainActivity code:
//this app supposed to read from FirebaseDatabase
//into Recycler view
//the RecyclerView is into Fragment layout
//i use Fragments into FrameLayout in the activity_main.xml
// the RecyclerView should be shown when navigatoinBar is clicked
//or on start of MainActivity
class MainActivity : AppCompatActivity() {
private var mDatabase:DatabaseReference? = null
private lateinit var mBlogList : RecyclerView
private var query:Query?=null
private var options:FirebaseRecyclerOptions<Blog>?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//start listFragment , RecyclerView is there
val mFragment = listFragment.newInstance()
//openFragment method is below
openFragment(mFragment)
//navigation bottom onclicklistener
navBar.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
//get data from database
mDatabase=FirebaseDatabase.getInstance().getReference().child("mall")
mDatabase?.keepSynced(true)
//here i should have recyclee but it is null i don't know why
mBlogList = recyclee
mBlogList.setHasFixedSize(true)
mBlogList.layoutManager = LinearLayoutManager(this)
//query of database
query = mDatabase?.orderByKey()
}
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
//there are 4 icons in the navigation_bottom_bar
//now we are talking about listNav icon only because it is realted
// with listFragment
when (item.itemId) {
R.id.listNav -> {
val mFragment = listFragment.newInstance()
openFragment(mFragment)
return#OnNavigationItemSelectedListener true
}
R.id.cartNav -> {
val mFragment = cartFragment.newInstance()
openFragment(mFragment)
return#OnNavigationItemSelectedListener true
}
R.id.supportNav -> {
val mFragment = supportFragment.newInstance()
openFragment(mFragment)
return#OnNavigationItemSelectedListener true
}
R.id.accountNav -> {
val mFragment = accountFragment.newInstance()
openFragment(mFragment)
return#OnNavigationItemSelectedListener true
}
}
false
}
private fun openFragment(fragment: Fragment) {
//open Fragment into FrameLayout in the main_activity.xml
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.mainFrame, fragment)
transaction.addToBackStack(null)
transaction.commit()
}
override fun onStart() {
super.onStart()
//set options for FirebaseRecyclerAdapter
options = FirebaseRecyclerOptions.Builder<Blog>()
.setQuery(query!!, Blog::class.java)
.build()
//set custom adapter
val mAdapter = object : FirebaseRecyclerAdapter<Blog, BlogViewHolder>(
options!!) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BlogViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.cardview, parent, false)
return BlogViewHolder(view)}
override fun onBindViewHolder(holder: BlogViewHolder, position: Int, model: Blog) {
holder.setTitle(model.title)
holder.setDes(model.des)
holder.setImage(applicationContext, model.image)
}
}
mBlogList.adapter = mAdapter
}
inner class BlogViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var mView:View= itemView
//set title, des amd image with data we got from database
fun setTitle(title:String){
var postTitle = mView.findViewById<TextView>(R.id.post_title)
postTitle?.text = title
}
fun setDes(des:String){
var postDes = mView.findViewById<TextView>(R.id.post_des)
postDes?.text = des
}
fun setImage(image:String){
var postImage = mView.findViewById<ImageView>(R.id.post_title)
Picasso.get().load(image).into(postImage)
}
}
}
If you apply kotlin-android-extensions plugin then you don't need to use findViewById anymore because you can access views in the layout as if they're properties (by name). So, your onCreate could look as follows:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
assert recyclee != null
}
Edit
Since you're trying to do this in Fragment and your layout file is called
fragment_List.xml then in your Fragment you must inflate the layout first and then you can access your RecyclerView as in the example above for Activity:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_List, container, false)
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
assert recyclee != null
}
If you try to access your RecyclerView in Activity before fragment_List is inflated in the Fragment then it will obviously be null (it hasn't been created yet). That's actually what you're trying to do in onCreate - it's too early as the Fragment's layout hasn't been built yet.
Edit 2
As it's seen from your code, mBlogList = recyclee is set in onCreate. Even though it's done after the ListFragment is created, it's still too early as its onCreateView hasn't been called yet and so no layout is in place.
A quick fix would be to do it in onStart as at that point ListFragment is definitely there. However, a better approach is to do the logic inside ListFragment itself and communicate with MainActivity via callbacks as described here
Try to use the findViewById on onCreate or onCreateView (if you are in a Fragment). It is happening because before this methods your layout wasn't inflated yet so Android cannot find your RecyclerView
class MainActivity : AppCompatActivity() {
private lateinit var mBlogList : RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mBlogList = findViewById<RecyclerView>(R.id.recyclee)
}
}
I would recommend you to read this: https://kotlinlang.org/docs/tutorials/android-plugin.html
Kotlin has a better way to get the reference os your views, you don't need to use findViewById =)
You cannot call findViewById from the global scope. But, you can declare it as:
private val mBlogList by lazy { findViewById<RecyclerView>(R.id.recyclee) }
...then use the variable the usual.
In this way you could access RecyclerView attributes once adapter has been loaded at onCreate() function
var recyclerView : RecyclerViewAdapterYourClass = adapter as RecyclerViewAdapterYourClass
recyclerView.yourRecyclerAttribute

Categories

Resources