ViewPager and TabLayout in Fragment. setAdapter on a null object reference - java

I'm trying to add viewPager in Fragment. But when I start my application I receive this:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.view.ViewPager.setAdapter(android.support.v4.view.PagerAdapter)' on a null object reference
My MainFragment:
public class YourTasksFragment extends Fragment {
#Bind(R.id.viewpager)
ViewPager viewPager;
#Bind(R.id.tabs)
TabLayout tabLayout;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_your_tasks, container, false);
return v;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setupViewPager(viewPager);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFragment(new OneFragment(), "ONE");
adapter.addFragment(new TwoFragment(), "TWO");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragmentList = new ArrayList<>();
private final List<String> fragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager childFragmentManager) {
super(childFragmentManager);
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
return fragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
fragmentList.add(fragment);
fragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return fragmentTitleList.get(position);
}
}
}
Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />

You forgot to setup Butterknife in the onCreateView(), therefore the variable is never initialized.
Do this:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_your_tasks, container, false);
Butterknife.bind(this,v);
return v;
}
Hope it helps!

You forgot to add Butterknife.bind(this, v) on the method onCreateView.
It's required in order to bind the views.
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_your_tasks, container, false);
Butterknife.bind(this,v);
return v;
}

Related

Can't resolve layout in BottomNavigation Activity

So I have my main Bottom Navigation Activity, and there is three section one of which is dashboard. And I want to make a grid of categories in there. I've been trying to follow some guides on youtube about creation of GridView, but it seems to not work in this Bottom Navigation Activity. The main issue is that in my custom adapter in method getView it can't resolve R.layout.category_item but the file exists.
I would be grateful for some workaround or explanation of why it happens.
DashboardFragment class:
public class DashboardFragment extends Fragment {
private DashboardViewModel dashboardViewModel;
String[] category_names = {"one","two","three","four","five","six","seven","eight","nine","ten"};
int[] data ={1,2,3,4,5,6,7,8,9,10};
GridView gridView;
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
dashboardViewModel = ViewModelProviders.of(this).get(DashboardViewModel.class);
View root = inflater.inflate(R.layout.fragment_dashboard, container, false);
dashboardViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
}
});
gridView = root.findViewById(R.id.category_grid);
CustomAdapter customAdapter = new CustomAdapter();
gridView.setAdapter(customAdapter);
return root;
}
private class CustomAdapter extends BaseAdapter{
#Override
public int getCount() {
return category_names.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view1 = getLayoutInflater().inflate(R.layout.category_item,null);
return null;
}
}
}
category_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.dashboard.DashboardFragment">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</androidx.constraintlayout.widget.ConstraintLayout>
Hi i don't know if it's the solution of your problem but you don't use any context when you inflate your view
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// inflate the layout for each list row
if (convertView == null) {
convertView = LayoutInflater.from(context).
inflate(R.layout.layout_list_view_row_items, parent, false);
}
...
}

Fragment activity disappears after switching activities

I have 6 fragments fragments for my navigation drawer, one of which contains 2 other fragments which i use for a viewPager. My problem is that when i switch from the fragment containing the viewPager(HomeFragment) to another and switch back, the contents of both Fragments in HomeFragment disappears.
Here's my code
MainActivity.class
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new HomeFragment()).commit();
navigationView.setCheckedItem(R.id.nav_home);
...
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_home:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new HomeFragment()).commit();
toolbar.setTitle("mSeries");
toolbar.setTitleTextColor(getResources().getColor(R.color.colorPrimaryDark));
break;
...
HomeFragment.class
public class HomeFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_home, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewPager viewPager = view.findViewById(R.id.viewpager);
setupViewPager(viewPager);
TabLayout tabLayout = view.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getFragmentManager());
adapter.addFragment(new UpcomingShowsActivity(), "Upcoming episodes");
adapter.addFragment(new UnwatchedEpisodesActivity(), "Unwatched episodes");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#NonNull
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
UpcomingShowsActivity.class
public class UpcomingShowsActivity extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_upcoming_episodes, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
I am a newbie in android, if there's a better or more efficient way of achieving this please let me know.
Thanks for your time.
I fixed it myself and I'm posting this in case someone has a similar issue in the future
Because I'm making a fragment in another fragment, I am supposed to use getChildFragmentManager instead of get getFragmentManager in my HomeFragment.class
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFragment(new UpcomingShowsActivity(), "Upcoming episodes");
adapter.addFragment(new UnwatchedEpisodesActivity(), "Unwatched episodes");
viewPager.setAdapter(adapter);
}

I want to show 3 different fragments for 3 different tabs in view-pager ,Tabbed activity Android

I am very new to android , this time i created a view-pager tabbed activity by looking a video tutorial. the problem or the need is to show 3 different fragments if the user slides the position like tab1(shows first fragment),tab2 (shows second fragment) tab3 (shows third fragment)
Now it is showing one and only fragment for all tabs
this is my adapter class named datafragment
package com.example.jaison.news;
public class datafragment extends Fragment {
View view;
ViewPager viewPager;
TabLayout tabLayout;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view= inflater.inflate(R.layout.sample,container,false);
viewPager = (ViewPager) view.findViewById(R.id.viewpager);
viewPager.setAdapter(new sliderAdapter(getChildFragmentManager()));
tabLayout = (TabLayout) view.findViewById(R.id.sliding_tabs);
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return view;
}
private class sliderAdapter extends FragmentPagerAdapter{
final String tabs[]={"tab1", "tab2","tab3"};
public sliderAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
return fragment;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
return tabs[position];
}
}
}
for those who did not get my point , all i need is implement the code something just like this, but i am not sure about this..
switch (position) {
case 0:
//showing first fragment
case 1:
//showing second fragment
case 2:
//showing third fragment
default:
return new Fragment();
}
change your getItem method like this
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position){
case 0:
fragment = new Tab1Fragment();
break;
case 1:
fragment = new Tab2Fragment();
break;
case 2:
fragment = new Tab3Fragment();
break;
}
return fragment;
}
You need to create an instance of your viewPagerAdapter and then add items to it.
Something like this:
ViewPagerAdapter viewpagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
viewPager.setAdapter(viewpagerAdapter);
// then add items to it as you add items to a recyclerview adapter or to any list
viewpagerAdapter.addFragment(new Fragment1(), "title1");
And the custom code for the viewpager Adapter is:
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
Also since you are new to programming, would advice you to use proper nomenclature, for eg. names of classes always begin with initial letter Uppercase
class ClassName
void methodName
MainActivity
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new OneFragment(), "ONE");
adapter.addFragment(new TwoFragment(), "TWO");
adapter.addFragment(new ThreeFragment(), "THREE");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
OneFragment.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class OneFragment extends Fragment{
public OneFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_one, container, false);
}
}
fragment_one.xml
<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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/one"
android:textSize="40dp"
android:textStyle="bold"
android:layout_centerInParent="true"/>
</RelativeLayout>
Likewise create few more fragment activities with same code we used for OneFragment.java.
See this simple complete example:
Here I used TabLayout also which is often used with ViewPager, so will be useful for you on next.
It requires API:
compile 'com.android.support:design:25.3.1'
You can ignore and remove all parts of TabLayout from xml and java files if want to go simpler at this instance.
1. activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/viewPager"/>
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
app:tabIndicatorColor="#color/colorPrimaryDark"
app:layout_scrollFlags="scroll|enterAlways"
android:id="#+id/tabLayout"/>
</RelativeLayout>
2. Fragment Tab1.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="TAB 1"
android:id="#+id/textTab1"/>
</RelativeLayout>
3. Fragment Tab2.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="TAB 2"
android:id="#+id/textTab2"/>
</RelativeLayout>
4. Fragment Tab3.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="TAB 3"
android:id="#+id/textSpacerNoTitleab3"/>
</RelativeLayout>
5. MainActivity.java
public class MainActivity extends AppCompatActivity
implements TabLayout.OnTabSelectedListener, ViewPager.OnPageChangeListener{
ViewPager viewPager;
TabLayout tabLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText("Page 1"));
tabLayout.addTab(tabLayout.newTab().setText("Page 2"));
tabLayout.addTab(tabLayout.newTab().setText("Page 3"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.addOnTabSelectedListener(this);
viewPager.setAdapter(new VPAdapter(getSupportFragmentManager()));
viewPager.addOnPageChangeListener(this);
}
#Override
public void onTabSelected(TabLayout.Tab tab) {
w("onTabSelected(): "+tab.getPosition());
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
w("onPageSelected(): "+position);
TabLayout.Tab tab = tabLayout.getTabAt(position);
if(tab!=null)tab.select();
}
#Override
public void onPageScrollStateChanged(int state) {
}
void w(String string){
Log.w("MKN",getClass().getSimpleName()+" "+string);
}
}
6. Fragment class Tab1.java
public class Tab1 extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.tab1,container,false);
}
}
7. Fragment class Tab2.java
public class Tab2 extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.tab2,container,false);
}
}
8. Fragment class Tab3.java
public class Tab3 extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
return inflater.inflate(R.layout.tab3,container,false);
}
}
9. Adapter class VPAdapter.java
public class VPAdapter extends FragmentPagerAdapter {
public VPAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if(position == 0) return new Tab1();
if(position == 1) return new Tab2();
if(position == 2) return new Tab3();
throw new IllegalStateException("Unexpected position " + position);
}
#Override
public int getCount() {
return 3;
}
}
Use this :
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
// adding the fragments here with titles
adapter.addFragment(new OneFragment(), "ONE");
adapter.addFragment(new TwoFragment(), "TWO");
adapter.addFragment(new ThreeFragment(), "THREE");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
//return null;
}
}
then set it like this:
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) view.findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
hope it helps!!!

swipe tablayout is not working correctly

i am using "compile 'com.android.support:design:25.1.0'" to implement swipe tablayout. My code has no syntax error but due to some logical error it is not working correctly
Problems: 1) when i slide a page it should move on next tab but it slide or move very slowly and go between two tabs
2) when i come back on privious tabs sometime it does not show even any page and sometime it show wrong page e.g on second tabs it shows third page(fragment)
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabLayout tabLayout;
String[] tabs={"SCORES","NEWS","SERIES"};
tabLayout=(TabLayout) findViewById(R.id.cricTabLayout);
tabLayout.addTab(tabLayout.newTab().setText(tabs[0]));
tabLayout.addTab(tabLayout.newTab().setText(tabs[1]));
tabLayout.addTab(tabLayout.newTab().setText(tabs[2]));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabTextColors(Color.parseColor("#627179"), Color.parseColor("#BF4A32"));
final ViewPager viewPager=(ViewPager)findViewById(R.id.cricPagerView);
final PageAdapter pageAdapter=new PageAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(pageAdapter);
// new line
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
// viewPager.clearOnPageChangeListeners();
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
// Toast.makeText(MainActivity.this,"Tab changed",Toast.LENGTH_LONG).show();
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
PageAdapter.java
public class PageAdapter extends FragmentStatePagerAdapter {
int numOfTabs;
public PageAdapter(FragmentManager fm, int numOfTabs) {
super(fm);
this.numOfTabs=numOfTabs;
}
public PageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
return new ScoreFragment();
case 1:
return new NewsFragment();
case 2:
return new SeriesFragment();
default: return null;
}
}
#Override
public int getCount() {
return numOfTabs;
}
}
ScoreFragment.java
public class ScoreFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view=null;
Toast.makeText(getContext(),"Score",Toast.LENGTH_LONG).show();
return view;
}
}
SeriesFragment.java
public class ScoreFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view=null;
Toast.makeText(getContext(),"Score",Toast.LENGTH_LONG).show();
return view;
}
}
NewsFragment.java
public class NewsFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view=null;
Toast.makeText(getContext(),"News",Toast.LENGTH_LONG).show();
return view;
}
}
MainActivity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_news"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.apple.crickapp.MainActivity"
android:layout_marginLeft="0dp">
<android.support.design.widget.TabLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:elevation="8dp"
android:background="#color/colorBlack"
android:minHeight="?attr/actionBarSize"
android:id="#+id/cricTabLayout"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
>
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="#+id/cricPagerView"
android:layout_below="#id/cricTabLayout"
>
</android.support.v4.view.ViewPager>
</RelativeLayout>

java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference

I have a BlankFragment
package com.hfad.addingafragmenttoframelayout;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.w3c.dom.Text;
/**
* A simple {#link Fragment} subclass.
*/
public class BlankFragment extends Fragment {
public BlankFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message","onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
public void setText(String textToBeSet){
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
tv.setText(textToBeSet);
}
}
and it's layout is:
<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="com.hfad.addingafragmenttoframelayout.BlankFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_blank_fragment"
android:id="#+id/fragmentText"/>
</FrameLayout>
Here is the MainActivity
package com.hfad.addingafragmenttoframelayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//BlankFragment bf = new BlankFragment();
//getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, bf).commit();
BlankFragment bf = new BlankFragment();
bf.setText("hello world");
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, bf).commit();
}
}
and here is the layout of MainActivity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.hfad.addingafragmenttoframelayout.MainActivity"
android:orientation="vertical">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/fragment_container"
/>
</LinearLayout>
In the onCreate method of activity I am adding fragment to layout. This works fine unless I try to change the Text using setText method.
And I get this error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
at com.hfad.addingafragmenttoframelayout.BlankFragment.setText(BlankFragment.java:35)
at com.hfad.addingafragmenttoframelayout.MainActivity.onStart(MainActivity.java:29)
referring to this line
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
Can somebody explain what's causing this exception?
Don't
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message","onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
public void setText(String textToBeSet){
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
tv.setText(textToBeSet);
}
Do
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View RootView = inflater.inflate(R.layout.fragment_blank, container, false);
TextView tv = (TextView)RootView.findViewById(R.id.fragmentText);
tv.setText("HI");
return RootView;
}
Here:
bf.setText("hello world");
line causing issue, becuase calling setText method of Fragment before adding Fragment in FragmentManager.
Call setText method after adding bf Fragment:
getSupportFragmentManager().beginTransaction().
add(R.id.fragment_container, bf).commit();
bf.setText("hello world"); // call here
The problem is FragmentTransaction is async by default
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_container, BlankFragment.newInstance);
ft.disallowBackStack();
ft.commitNowAllowingStateLoss();
Then you still can't get the Fragment yet, you have to get it from the FragmentTransaction
BlankFragment bf = (BlankFragment) getSupportFragmentManager().getFragmentById(R.id.fragment_container);
bf.setText("hello world");
This article helped me to understand this problem better
TextView tv = (TextView)this.getView().findViewById(R.id.fragmentText);
do it in onCreateView();
You can use a temporary variable that can hold the String while the View is not yet created.
private TextView tv;
private String holder = "";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_blank, container,false);
tv = (TextView)v.findViewById(R.id.fragmentText);
return v;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
tv.setText(holder);
}
public void setText(String textToBeSet){
if(tv != null){
tv.setText(textToBeSet);
}else{
holder = textToBeSet;
}
}
My assumption is that you want to instantiate your BlankFragment with some initial text as well as allowing the text to be set later on from your MainActivity.
In that case I would first change the the Fragment to accept an initial text like so:
public class BlankFragment extends Fragment {
private static final String ARG_INITIAL_TEXT = "arg_initial_text";
public static BlankFragment newInstance(CharSequence initialText) {
final BlankFragment fragment = new BlankFragment();
final Bundle args = new Bundle();
args.putCharSequence(ARG_INITIAL_TEXT, initialText);
fragment.setArguments(args);
return fragment;
}
public BlankFragment() {
// Required empty public constructor
}
private CharSequence mInitialText;
private TextView mText;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mInitialText = getArguments().getCharSequence(ARG_INITIAL_TEXT);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("message", "onCreateView() of BlankFragment");
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mText = view.findViewById(R.id.fragmentText);
mText.setText(mInitialText);
}
public void setText(CharSequence textToBeSet) {
mText.setText(textToBeSet);
}
}
The Activity code would then look like the following:
public class MainActivity extends AppCompatActivity {
private BlankFragment mBlankFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
final Fragment bf = BlankFragment.newInstance("hello world");
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, bf, BlankFragment.class.getName())
.commit();
}
mBlankFragment = (BlankFragment) getSupportFragmentManager()
.findFragmentByTag(BlankFragment.class.getName());
}
private void someTimeLaterWhenWantingToSetNewTextToFragmentFromActivity(CharSequence newText) {
if (mBlankFragment != null) {
mBlankFragment.setText(newText);
}
}
}
Note that the null-check of savedInstanceState is to guard for Activity-recreation for instance due to configuration changes.

Categories