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 tab
s 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 didn
t 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?