Background
I am populating the textview and imageview dynamically for standarized fragments.
Instead of creating 6 Fragment Layouts and activities, I created 3 and I am setting text/images as needed. This way I would be able to save time and memory instead of creating one fragment per activity when the only thing that changes is the text in the textView and imageView.
Problem
When it reaches the Fragment 3, I get a nullpointer when the implementation is the same as FragmenFirst,FragmentSecond and I do not why.
Code
Page adapter which populates the tablayout
package com.company.app
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentPagerAdapter
class CustomPageAdapter(FragManager:FragmentManager): FragmentPagerAdapter(FragManager) {
var fragManagerItems:ArrayList<Fragment> = ArrayList()
var fragManagerTitles:ArrayList<String> = ArrayList()
fun removeFragments()
{
fragManagerItems.clear()
}
fun addFragments(fragmentItem:Fragment,fragmentTitle:String)
{
fragManagerItems.add(fragmentItem)
fragManagerTitles.add(fragmentTitle)
override fun getItem(position: Int): Fragment {
return fragManagerItems[position]
}
override fun getCount(): Int {
return fragManagerItems.size
}
override fun getPageTitle(position: Int): CharSequence {
return fragManagerTitles[position]
}
Fragments are standard, nothing have changed
class FragmentFirst : Fragment() {
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment "
return inflater!!.inflate(R.layout.fragment_fragment_first, container, false)
}
Second
class FragmentSecond : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater!!.inflate(R.layout.fragment_fragment_second, container, false)
}
}
Third
class FragmentThird : Fragment() {
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater!!.inflate(R.layout.fragment_fragment_third, container, false)
}
}
Portion where Main Activity change the textViews of each
import android.os.Bundle import android.support.design.widget.NavigationView import android.support.design.widget.TabLayout import android.support.v4.view.GravityCompat import android.support.v7.app.ActionBarDrawerToggle import android.support.v7.app.AppCompatActivity import android.view.Menu import android.view.MenuItem import com.company.app.fragments.* import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.app_bar_main.* import kotlinx.android.synthetic.main.content_appbar_main.* import kotlinx.android.synthetic.main.fragment_fragment_first.* import kotlinx.android.synthetic.main.fragment_fragment_second.* import kotlinx.android.synthetic.main.fragment_fragment_third.*
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
var objPageAdapter:CustomPageAdapter?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
...
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
objPageAdapter = CustomPageAdapter(supportFragmentManager)
when (item.itemId) {
R.id.nav_fruits -> {
objPageAdapter!!.removeFragments()
objPageAdapter!!.addFragments(FragmentFirst(),getString(R.string.txt_tab_fruits_Element_1))
objPageAdapter!!.addFragments(FragmentSecond(),getString(R.string.txt_tab_fruits_Element_2))
objPageAdapter!!.addFragments(FragmentThird(),getString(R.string.txt_tab_fruits_Element_3))
ViewPagerMain.adapter = objPageAdapter
TabLayoutMain.setupWithViewPager(ViewPagerMain)
this.textViewFragment_1.text = getString(R.string.txt_txtView_fruits_Element_1)
this.textViewFragment_2.text = getString(R.string.txt_txtView_fruits_Element_2)
this.textViewFragment_3.text = getString(R.string.txt_txtView_fruits_Element_3)
...
Error
Xml Fragment 2 and 3 as sample
Fragment 2
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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=".fragments.FragmentSecond">
<ImageView
android:id="@+id/imageViewFragment_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_banana" />
<TextView
android:id="@+id/textViewFragment_2"
android:layout_width="match_parent"
android:layout_height="261dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
Fragment 3
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".fragments.FragmentThird">
<ImageView
android:id="@+id/imageViewFragment_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_banana" />
<TextView
android:id="@+id/textViewFragment_3"
android:layout_width="match_parent"
android:layout_height="261dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
Approaches used
1. Clear/Rebuild Project
2. Shutdown/Restart PC
EDIT:Per request, I paste the stacktrace that I am getting
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.company.app, PID: 6790
java.lang.IllegalStateException: this.textViewFragment_3 must not be null
at com.company.app.MainActivity.onNavigationItemSelected(MainActivity.kt:111)
at android.support.design.widget.NavigationView$1.onMenuItemSelected(NavigationView.java:154)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:171)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:973)
at android.support.design.internal.NavigationMenuPresenter$1.onClick(NavigationMenuPresenter.java:342)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Edit2: To Address Rahul answer
Embedded code in the Main Activity
...
ViewPagerMain.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
private lateinit var fr: Fragment
private lateinit var viewPager: ViewPager
private lateinit var textView1:TextView
private lateinit var textView2:TextView
private lateinit var textView3:TextView
override fun onPageSelected(position: Int) {
when (position) {
0 ->{
fr = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.ViewPagerMain + ":" + ViewPagerMain.getCurrentItem())
textView1 = fr.textViewFragment_1
textView1.text= "test1"
}
1 ->{
fr = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.ViewPagerMain + ":" + ViewPagerMain.getCurrentItem())
textView2 = fr.textViewFragment_2
textView2.text= "test2"
}
2 ->{
fr = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.ViewPagerMain + ":" + ViewPagerMain.getCurrentItem())
textView3.text= "test3"
}
Instead of accessing textView in onCreate use onPageChangeListener event
private lateinit var fr: Fragment;
private lateinit var viewPager: ViewPager
private lateinit var textView1:TextView
private lateinit var textView2:TextView
private lateinit var textView3:TextView
override fun onPageSelected(position: Int) {
when (position) {
0 ->{
fr = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + viewPager.getCurrentItem())
textView1 = fr.textViewFragment_1
}
1-> {
fr = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + viewPager.getCurrentItem())
textView2 = fr.textViewFragment_2
textView2.text = "rr"
}
2-> {
fr = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + viewPager.getCurrentItem())
textView3= fr.textViewFragment_3
textView3.text = "tt"
}
}
}
override fun onPageScrollStateChanged(state: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setContentView(R.layout.test_layout)
}
use these lines in onPageselected to get instance of current visible fragment
Fragment fr = getSupportFragmentManager().findFragmentByTag(“android:switcher:” + R.id.pager + “:” + mViewPager.getCurrentItem());
now you can access textview but check if fr instancOf Fragment1 textView1=fr.findViewById(textview1Id) and so os..........