1

I am trying to realize communication between fragments and cannot understand how to realize one thing. I have tabs + swipe(viewpager), I can swipe between tabs and see fragmntscontent which are binded by default but I cannot call another fragment, for instance, by button click in one of the tabs content that new fragment will appear in current tab and will not get nullpointer exception if you try to swipe after that. Right now I have half working fragment calling. I mean that new fragment is called and I see it in log file but nothing from content is displayed and when I try to swipe after it I got crashes - nullpointer exception.

MyTabsActivity:

package com.example.tabstest;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.util.Log;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.ActionBar.TabListener;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

public class TabsActivity extends SherlockFragmentActivity implements TabListener {

    private static final String TAG = "TabsActivity";
    AppSectionsPagerAdapter mAppSectionsPagerAdapter;

    private ViewPager mViewPager;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mViewPager = (ViewPager) findViewById(R.id.pager);

        mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager(), mViewPager);

        final ActionBar actionBar = getSupportActionBar();

        actionBar.setHomeButtonEnabled(false);
        actionBar.setDisplayUseLogoEnabled(true);
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        mViewPager.setAdapter(mAppSectionsPagerAdapter);
        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                actionBar.setSelectedNavigationItem(position);
            }
        });

        actionBar.addTab(actionBar.newTab().setTag("home").setText("Home").setTabListener(this));
        actionBar.addTab(actionBar.newTab().setTag("calculator").setText("Calculator").setTabListener(this));
        actionBar.addTab(actionBar.newTab().setTag("login").setText("Log in").setTabListener(this));

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getSupportMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        return super.onOptionsItemSelected(item);

    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {

    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        mViewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {

    }

    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the primary sections of the app.
     */
    public static class AppSectionsPagerAdapter extends FragmentPagerAdapter {

        private FragmentManager mFm;
        private ViewPager mVp;

        public AppSectionsPagerAdapter(FragmentManager fm, ViewPager viewPager) {
            super(fm);
            mFm = fm;
            mVp = viewPager;
        }

        @Override
        public Fragment getItem(int i) {
            switch (i) {
            case 1:
                return new CalculatorFragment();
            case 2:
                Fragment LogInFragment = new LogInFragment();
                Bundle userProfile = new Bundle();
                userProfile.putString("USER", "Test");
                LogInFragment.setArguments(userProfile);
                return LogInFragment;
            default:
                return new HomeFragment();
            }
        }

        @Override
        public int getCount() {
            return 3;
        }

        public void selectPage(int page) {
            mVp.setCurrentItem(page);
        }

        public void replaceFragment(int FragmentContatiner, Fragment newFragment) {
            Log.w(TAG, "Replace Fragment!");
            FragmentTransaction transaction = mFm.beginTransaction();
            transaction.replace(FragmentContatiner, newFragment).addToBackStack(null).commit();
            notifyDataSetChanged();

        }
     }
}

EDITED: One of the fragments where I try replace current fragment by a new one:

package com.example.tabstest;

import com.actionbarsherlock.app.SherlockFragment;
import com.example.tabstest.TabsActivity.AppSectionsPagerAdapter;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class HomeFragment extends SherlockFragment {

    private static final String TAG = "HomeFragment";
    private View rootView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_home, container, false);

        rootView.findViewById(R.id.bCalculate).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                AppSectionsPagerAdapter aspa = new AppSectionsPagerAdapter(getFragmentManager(), (ViewPager) getActivity().findViewById(R.id.pager));
//              aspa.selectPage(1);

                Fragment LogInFragment = new LogInFragment();
                Bundle userProfile = new Bundle();
                userProfile.putString("USER", "Test");
                LogInFragment.setArguments(userProfile);
                aspa.replaceFragment(rootView.findViewById(R.id.HomePage).getId(), LogInFragment);

            }
        });

        return rootView;
    }
    }

That is my fragment_home layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/HomePage"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/ivGetLoan"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight=".1"
        android:src="@android:color/darker_gray" />

    <Button
        android:id="@+id/bCalculate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Calculate your loan" />

</LinearLayout>

It replaced and I see the content of LogInFragment however when it replaced I see not only all LogInFragment content but the button which was used to replace fragment from old fragment content.

NullPointer exception if you use ViewPager as a container:

12-09 20:37:52.416: E/AndroidRuntime(24660): FATAL EXCEPTION: main
12-09 20:37:52.416: E/AndroidRuntime(24660): java.lang.NullPointerException
12-09 20:37:52.416: E/AndroidRuntime(24660):    at com.example.tabstest.HomeFragment$1.onClick(HomeFragment.java:30)
12-09 20:37:52.416: E/AndroidRuntime(24660):    at android.view.View.performClick(View.java:2461)
12-09 20:37:52.416: E/AndroidRuntime(24660):    at android.view.View$PerformClick.run(View.java:8890)
12-09 20:37:52.416: E/AndroidRuntime(24660):    at android.os.Handler.handleCallback(Handler.java:587)
12-09 20:37:52.416: E/AndroidRuntime(24660):    at android.os.Handler.dispatchMessage(Handler.java:92)
12-09 20:37:52.416: E/AndroidRuntime(24660):    at android.os.Looper.loop(Looper.java:123)
12-09 20:37:52.416: E/AndroidRuntime(24660):    at android.app.ActivityThread.main(ActivityThread.java:4627)
12-09 20:37:52.416: E/AndroidRuntime(24660):    at java.lang.reflect.Method.invokeNative(Native Method)
12-09 20:37:52.416: E/AndroidRuntime(24660):    at java.lang.reflect.Method.invoke(Method.java:521)
12-09 20:37:52.416: E/AndroidRuntime(24660):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
12-09 20:37:52.416: E/AndroidRuntime(24660):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
12-09 20:37:52.416: E/AndroidRuntime(24660):    at dalvik.system.NativeStart.main(Native Method)

New thoughts

Unfortunately, it doesnt help me. Than more I deal with fragments than a bit more I understand about them. I mark that I cannot replace fragment which is used to jump on another fragment. That is to say if I use fragment with container android.R.id.container where is a button which I will press to replace current fragment on another one then you will receive NUllpointer exception.I didnt understand such actions sequence. Firstly, you click and then you replace, but nullpointer exception see it vise versa - no onclick, no replacement. ANother situation when you have ActionBar and container android.R.id.contenT. When you click on one of hte action menu button in actionbar to replace fragment in android.r.id.content on another one, there will be everything ok, it will be replaced correctly.HOw to replace that fragments which has some actions to replace current fragment on another one?

Viktor V.
  • 3,413
  • 8
  • 32
  • 58
  • Your code is incorrect. You're trying to replace the current `Fragment` with the `Button` with an instance of the `LoginFragment` in an adapter which has none as it isn't tied to a `ViewPager`. Also instead of the id of the layout containing the replaced target Fragment you're passing the id of that fragment instead. – user Dec 09 '12 at 17:58
  • Thanks Luksprog, it helps me a bit, I have edit my code and represent it in my question again. Now I have the following situation: Old fragment is replaced by new fragment, there is no nullpointer exception even rotating and sweping. However, when it replaced I see not only the whole new fragment content but the button from old fragment which was used to replace these fragments. How to fix it? – Viktor V. Dec 09 '12 at 18:26
  • With `rootView.findViewById(R.id.HomePage)` you're still putting the new instance of the `LoginFragment` in the layout of the current fragment with the button. Try to pass the id of the `ViewPager` because there are the fragments being used. I'm not sure if it will work. – user Dec 09 '12 at 18:29
  • In this case I receive nullpointer exception. I`m not sure, may be, it occures because all tabs and action bar binded to view pager which we try to update by new content. Another thing when I use fragment_home layout as contatiner for new fragment, why I saw only part of old fragment(only button from old fragment) + all content from new fragment. That`s strange a bit too. – Viktor V. Dec 09 '12 at 18:44
  • Have a look at this http://stackoverflow.com/questions/7445437/replace-fragment-with-another-fragment-inside-viewpager . – user Dec 09 '12 at 19:06
  • Unfortunately, It didn`t help me. I have update my question adding NEW THOUGHTS concerning fragment replacement. – Viktor V. Dec 14 '12 at 15:22

0 Answers0