0

I have a framelayout in MainActivity and I've attached TabFragment fragment to the activity. The TabFragment has TabLayout as well as Navigation Drawer. I used this link's recommended answer to style toolbar in TabFragment. But when I use ((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); in a NewFragment(it opens on button click from one of the tab) the app crashes with NullPointerException. I want the back arrow without using any drawable icon. Thanks for any help in this regard.

FATAL EXCEPTION: main
                                                                    Process: com.sam.pagersliding, PID: 7652
                                                                    java.lang.NullPointerException
                                                                        at com.sam.pagersliding.NewFragment.onCreate(NewFragment.java:27)
                                                                        at android.support.v4.app.Fragment.performCreate(Fragment.java:1951)
                                                                        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1029)
                                                                        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
                                                                        at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742)
                                                                        at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
                                                                        at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
                                                                        at android.os.Handler.handleCallback(Handler.java:808)
                                                                        at android.os.Handler.dispatchMessage(Handler.java:103)
                                                                        at android.os.Looper.loop(Looper.java:193)
                                                                        at android.app.ActivityThread.main(ActivityThread.java:5388)
                                                                        at java.lang.reflect.Method.invokeNative(Native Method)
                                                                        at java.lang.reflect.Method.invoke(Method.java:515)
                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:655)
                                                                        at dalvik.system.NativeStart.main(Native Method)

public class NewFragment extends Fragment{

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        setHasOptionsMenu(true);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.newfrag, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

    }




    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id){
            case android.R.id.home:
                getActivity().onBackPressed();
                break;
        }
        return super.onOptionsItemSelected(item);
    }



}
public class TabFragment extends Fragment{

    Toolbar toolbar;
    private TabLayout tabLayout;
    private ViewPager viewPager;

    public static DrawerLayout mDrawerLayout;
    NavigationView navigationView;
    ActionBarDrawerToggle mDrawerToggle;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.tabfrag, container, false);


    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        toolbar = (Toolbar) view.findViewById(R.id.toolbar);
        tabLayout = (TabLayout) view.findViewById(R.id.tabs);
        viewPager = (ViewPager) view.findViewById(R.id.viewpager);
        mDrawerLayout = (DrawerLayout) view.findViewById(R.id.drawer_layout);
        navigationView = (NavigationView) view.findViewById(R.id.navigation_view);

        setupViewPager(viewPager);
        tabLayout.setupWithViewPager(viewPager);

        mDrawerToggle = new ActionBarDrawerToggle(getActivity(),mDrawerLayout, toolbar,R.string.app_name,R.string.app_name);
        mDrawerToggle.syncState();

        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {
                mDrawerLayout.closeDrawers();



                if (menuItem.getItemId() == R.id.nav_one) {
                    NavOne nav1 = new NavOne();
                    ((MainActivity)getActivity()).replaceFragment(nav1);
                    mDrawerLayout.closeDrawer(navigationView);

                }

                if (menuItem.getItemId() == R.id.nav_two) {
                    NavTwo nav2 = new NavTwo();
                    ((MainActivity)getActivity()).replaceFragment(nav2);
                    mDrawerLayout.closeDrawer(navigationView);

                }

                return false;
            }

        });
    }

    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> 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);
        }
    }
}
public class MainActivity extends AppCompatActivity {

    FragmentManager myFragmentManager;
    FragmentTransaction myFragmentTransaction;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Attach main fragment to activity
        if (findViewById(R.id.containerView) != null) {
            if (savedInstanceState != null) {
                return;
            }

            myFragmentManager = getSupportFragmentManager();
            myFragmentTransaction = myFragmentManager.beginTransaction();
            myFragmentTransaction.replace(R.id.containerView, new TabFragment()).commit();
        }



    }

    public void replaceFragment(Fragment fragment){
        FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        t.replace(R.id.containerView, fragment).addToBackStack(null);
        t.commit();
    }



}
CodeAssasins
  • 237
  • 5
  • 17
  • 2
    "The app crashes" -- Please [edit] your question with the logcat, then – OneCricketeer Jun 10 '16 at 07:09
  • Added Logcat. Its in the same line ` ((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);` @cricket_007 – CodeAssasins Jun 10 '16 at 07:13
  • Why are you trying to set the Activity's Toolbar from the Fragment? That seems like a poor design. You can toggle the Up arrow whenever you use the FragmentTransaction in the Activity code. – OneCricketeer Jun 10 '16 at 07:14
  • Can you show me how to toggle it ? Please note that I've: `false` and `true` in styles.xml @cricket_007 – CodeAssasins Jun 10 '16 at 07:21
  • XML doesn't matter. `getSupportActionBar().setDisplayHomeAsUpEnabled(true)` in the **Activity** instead of the **Fragment** is all I said – OneCricketeer Jun 10 '16 at 07:22
  • I added `getSupportActionBar().setDisplayHomeAsUpEnabled(true);` in onCreate of MainActivity but now the app crashes on opening. @cricket_007 – CodeAssasins Jun 10 '16 at 07:32
  • I can't count the line numbers of your code, but I assume you now have a different error or it is on a different line. You are welcome to read about [reading the Logcat](http://stackoverflow.com/questions/23353173/unfortunately-myapp-has-stopped-how-can-i-solve-this) to fix your errors, or more generally, [using the stacktrace](http://stackoverflow.com/questions/3988788/what-is-a-stack-trace-and-how-can-i-use-it-to-debug-my-application-errors). Both are valuable tools that you can use to debug and solve most simple errors such as a NullPointerException – OneCricketeer Jun 10 '16 at 07:36
  • Its in the same line `getSupportActionBar().setDisplayHomeAsUpEnabled(true);` but now its in activity. Logically when windowActionBar is false in styles then it should not support Actionbar at all in activity. @cricket_007 – CodeAssasins Jun 10 '16 at 07:40
  • Ah! I think you are missing `setSupportActionBar(toolbar)` in the onCreate of the Activity. Yeah, your Toolbar is null otherwise if you use the NoActionBar themes – OneCricketeer Jun 10 '16 at 07:44
  • And your Toolbar (and the following views) should ideally be in the Activity's layout file, not the Fragment – OneCricketeer Jun 10 '16 at 07:45
  • Thanks a lot. Your last suggestion `setSupportActionBar(toolbar)` worked for me. I removed the `getSupportActionBar().setDisplayHomeAsUpEnabled(true);` and included the toolbar from activity. @cricket_007 – CodeAssasins Jun 10 '16 at 08:07

3 Answers3

4

Instead of getting the toolbar in your fragment from layout, try to reference it from your MainActivity:

toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

and then use in the fragment:

     ((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
gymni f
  • 398
  • 2
  • 14
  • 1
    "try to reference it from your MainActivity" seems to conflict with "then in the Fragment" – OneCricketeer Jun 10 '16 at 08:10
  • There is a different problem with this solution. If I want menu icon in the Navigation fragments then how to do it? Bcuz if I use above code, I'm getting same `back arrow` icon and text in each fragment. I can change the text but how to show menu icon ? – CodeAssasins Jun 10 '16 at 08:24
  • You can add a reference to the toolbar in each fragment through Toolbar toolbar = (Toolbar)((AppCompatActivity)getActivity()).getSupportActionBar().getCustomView(); so then you can change the icon with setIcon method – gymni f Jun 10 '16 at 08:26
  • Add what? I've 2 fragments in Navigation Drawer and I want menu icon in both fragments but its showing back arrow icon in both. – CodeAssasins Jun 10 '16 at 08:31
  • Not looking to use icon drawables. Any other idea to get menu icon in fragment? – CodeAssasins Jun 10 '16 at 08:53
  • I'm sorry I think I have misunderstood your problem. As you have used setDisplayHomeAsUpEnabled in one fragment, to show again the menu icon in other fragments you can use the same method with false parameter – gymni f Jun 10 '16 at 08:59
3

The below two feature should be enabled

getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);

along with setting the back button

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                this.finish();
                return true;
            default:
                return false;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return false;
    }
Sreehari
  • 5,621
  • 2
  • 25
  • 59
  • I added your recommendation. Its showing error when adding `onCreateOptionsMenu` in fragment so didn't used it. And the app still crashes on clicking the button in one of the tabs of TabLayout. @Stallion – CodeAssasins Jun 10 '16 at 07:17
-1

remove this line

((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);

from onActivityCreated

try to use it on resume

((AppCompatActivity)getView().getContext())getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Sush
  • 3,864
  • 2
  • 17
  • 35