I'm trying to create an application that has a similar framework to that of Snapchat, where I have three screens that can be swiped through. I have three screens (made with a fragment for each) and wish to slide to a screen on button press. Just to be clear, I have a table on one screen, from which a row is clickable and has a function that it calls onClick(). I wish to slide to the desired fragment using the mentioned function.
Fragment.Java:
public class ChatFragment extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.chat_fragment_layout, container, false);
rootView.findViewById(R.id.row0).setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
openfrag("1");
}
});
rootView.findViewById(R.id.row1).setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
openfrag("2");
}
});
rootView.findViewById(R.id.row2).setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
openfrag("3");
}
});
return rootView;
}
private void openfrag(String number){
}
I'm swiping through the fragments by using a PagerAdapter that extends FragmentPagerAdapter:
public class PagerAdapter extends FragmentPagerAdapter {
public PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int arg0) {
switch (arg0) {
case 0:
return new MessageFragment();
case 1:
return new ChatFragment();
case 2:
return new CameraFragment();
default:
break;
}
return null;
}
#Override
public int getCount() {
return 3;
}
I have tried the replace method with fragmentmanager, but that is not what I want, I want it to act as if I swiped to that fragment.
Thanks for the help.
You can use simply this given code
String tag = "android:switcher:" + R.id.pager + ":" + 0;
AddStudentFragment f = (AddStudentFragment) getActivity().getSupportFragmentManager().findFragmentByTag(tag);
String tag1 = "android:switcher:" + R.id.pager + ":" + 1;
AssignSubjectFragment a = (AssignSubjectFragment) getActivity().getSupportFragmentManager().findFragmentByTag(tag1);
I managed to get it to work with a small addition to my MainActivity class outside the onCreate method. Whenever you need to switch to another fragment in your pager, simply call this function with the item index and true/false depending if you want it to smooth scroll or not.
public void setCurrentItem (int item, boolean smoothScroll) {
mViewPager.setCurrentItem(item, smoothScroll);
}
Related
When I swipe to or select Fragment1 (Fragment Numbers are 0-3) from its adjacent Fragments(0 , 2) in viewPager its onCreateView, or onCreate function is not being called.
But when I swipe back from Fragment3 or select Fragment1 when Fragment3 is active then both of these functions are being called. I am confused about why not from the adjacent Fragments its being called.
this is the code of Fragment who's onCreateView is not being called properly
`public class Fragment1 extends Fragment {
ShimmerFrameLayout shimmerFrameLayout ;
ConstraintLayout contentLayout;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(getActivity(), "US News", Toast.LENGTH_SHORT).show();
Log.d("Called", "onCreate: ");
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.us_news_fragment_layout , container , false);
shimmerFrameLayout = view.findViewById(R.id.usNewsShimmerLayoutId);
contentLayout = view.findViewById(R.id.usNewsLayoutId);
shimmerFrameLayout.startShimmerAnimation();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
shimmerFrameLayout.stopShimmerAnimation();
shimmerFrameLayout.setVisibility(View.GONE);
contentLayout.setVisibility(View.VISIBLE);
}
},3000);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.d("USNews", "onCreateView: ");
}
}`
This is the code in the main Activity for handling the events related to the viewpager
viewPager = findViewById(R.id.homeViewPagerId);
tabLayout.setupWithViewPager(viewPager);
tabLayout.addTab(tabLayout.newTab().setText("Home"));
tabLayout.addTab(tabLayout.newTab().setText("US News"));
tabLayout.addTab(tabLayout.newTab().setText("Politics"));
tabLayout.addTab(tabLayout.newTab().setText("Live"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
int position = tab.getPosition();
viewPager.setCurrentItem(position);
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
homePagerAdapter = new HomePagerAdapter(getSupportFragmentManager() , tabLayout.getTabCount());
viewPager.setAdapter(homePagerAdapter);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Toast.makeText(MainActivity.this, String.valueOf(tabLayout.getTabAt(position).getText()) + " is Active Now", Toast.LENGTH_SHORT).show();
homePagerAdapter.getItem(position);
}
#Override
public void onPageSelected(int position) {
homePagerAdapter.getItem(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
homePagerAdapter.notifyDataSetChanged();
And this is the adapter of the ViewPager i am using
public class HomePagerAdapter extends FragmentStatePagerAdapter {
int NUM_OF_TABS;
private String[] tabTitles = new String[]{"Home", "US News", "Politics" , "Live"};
public HomePagerAdapter(#NonNull FragmentManager fm , int numberOfTabs) {
super(fm);
this.NUM_OF_TABS = numberOfTabs;
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
#NonNull
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
Fragment0 homeFragment = new Fragment0 ();
return homeFragment;
case 1:
Fragment1 usNewsFragment = new Fragment1 ();
return usNewsFragment;
case 2:
Fragment2 politicsFragment = new Fragment2 ();
return politicsFragment;
case 3:
Fragment3 liveFragment = new Fragment3 ();
return liveFragment;
default:
return null;
}
}
#Override
public int getCount() {
return NUM_OF_TABS;
}
}
Please assist me about this. I'll be very thankful to you.
Thanks in advance
maybe this layout is already created and drawn? ViewPager have some handy option - keeps at least two additional Views/Fragments in memory for fast switching between pages. you can change this value to some higher only by calling setOffscreenPageLimit. by default its set to 1 - means that ViewPager keeps up to 3 Fragments - one to the left, one to the right and one currently visible on screen. with finger fling UI can just slide left/right page without drawing it from scratch (making almost always some small glitch/hang)
I bet you have two onCreate calls on start of your Activity - Fragment0s and Fragment1s. when you switch to Fragment1 you will see Fragment2 log, as ViewPager will prepare it for potential next swipe-left gesture. you can always use setOffscreenPageLimit(Integer.MAX_VALUE); for forcing all Fragments to be drawn at start and kept in memory (but only if these Fragments aren't to heavy, according to your tab names they might be...)
also homePagerAdapter.getItem(position); call in onPageSelected and onPageScrolled is unnecessary - it is creating new Frament and returning it, thats all, it isn't used. thats ViewPagers job to call this method (from attached adapter), take this Fragment and draw (on the screen or just render in memory for potential future use when user swipe left/right)
First. Sorry for my English.
I have Activity class with ViewPager as a field and a Fragment class. My activity is a host for a fragment. In Fragment I want to call context menu registered for ImageView. For that, I override 2 methods: onCreateContextMenu and onContextItemSelected.
Problem is:
When onCreateContextMenu is called I get the correct page (that
on the screen now).
But when onContextItemSelected is called I get another page (this
depend on what parameter is set in
ViewPager.setOffscreenPageLimit(int)). For example, if it set 3, the returned page will be those, that on 3 positions to the left or to the right from current that on the screen.
How can I fix it?
Thank you.
Activity code
public class CrimePagerActivity extends FragmentActivity {
private ViewPager mViewPager;
private ArrayList<Crime> mCrimes;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewPager = new ViewPager(this);
mViewPager.setId(R.id.viewPager);
setContentView(mViewPager);
mCrimes = CrimeLab.get(this).getCrimes();
mViewPager.setOffscreenPageLimit(4);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mViewPager.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
FragmentManager fm = getSupportFragmentManager();
mViewPager.setAdapter(new FragmentStatePagerAdapter(fm) {
#Override
public Fragment getItem(int position) {
Crime crime = mCrimes.get(position);
return CrimeFragment.newInstance(crime.getId());
}
#Override
public int getCount() {
return mCrimes.size();
}
});
UUID crimeId = (UUID) getIntent().getSerializableExtra(CrimeFragment.EXTRA_CRIME_ID);
for (int i = 0; i< mCrimes.size(); i++){
if (mCrimes.get(i).getId().equals(crimeId)){
mViewPager.setCurrentItem(i);
break;
}
}
}
}
and fragment code
public class CrimeFragment extends Fragment {
.......
private ImageView mPhotoView;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
........
View v = inflater.inflate(R.layout.fragment_crime, container, false);
mPhotoView = (ImageView) v.findViewById(R.id.crime_imageView);
registerForContextMenu(mPhotoView);
return v;
}
.........
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
Log.i(TAG, mCrime.getTitle());
switch (v.getId()) {
case R.id.crime_imageView:
if (mCrime.getPhoto() != null)
getActivity().getMenuInflater().inflate(R.menu.crime_photo_context, menu);
break;
}
}
#Override
public boolean onContextItemSelected(MenuItem item) {
Log.i(TAG, mCrime.getTitle());
switch (item.getItemId()) {
case R.id.menu_item_delete_photo:
getActivity().deleteFile(mCrime.getPhoto().getFilename());
PictureUtils.cleanImageView(mPhotoView);
mCrime.setPhoto(null);
return true;
}
return super.onContextItemSelected(item);
}
}
ViewPager.setOffscreenPageLimit(int);
This will prepare the pages at both sides to the left and right (neighbours).
By default it is 1.
So, in your case to get the current fragment created by the viewPager.
You can store the fragments when created in an SparseArray by overriding the instantiateItem() and destroyItem() callback of viewPager with position.
private SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getFragment(int position) {
return registeredFragments.get(position);
}
And where you want to get the current fragment, get it by using the getFragment() method by passing the position.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
My app works with a TabLayout (and so a ViewPager).
I have a Fragment A and a Fragment B. My goal is to recover data from my EditTexts of Fragment A to, obviously, print and works with them in my Fragment B.
For this, I use an interface named ButtonCliked, but seems not to work well. Did I forgot something ?
TabFragment.java (use to manage my fragments)
public class TabFragment extends Fragment implements EquationsCalculFragment.ButtonClicked {
public static TabLayout tabLayout;
public static ViewPager viewPager;
public static int int_items = 3 ;
#Override
public void sendResultats(float a, float b) {
EquationsResultatFragment fragRes = (EquationsResultatFragment) getFragmentManager().findFragmentById(R.id.Equa_2nd_ResLayout);
fragRes.getResultat(a, b);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/**
*Inflate tab_layout and setup Views.
*/
View x = inflater.inflate(R.layout.tab_layout,null);
tabLayout = (TabLayout) x.findViewById(R.id.tabs);
viewPager = (ViewPager) x.findViewById(R.id.viewpager);
/**
*Set an Apater for the View Pager
*/
viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return x;
}
class MyAdapter extends FragmentPagerAdapter{
public MyAdapter(FragmentManager fm) {
super(fm);
}
/**
* Return fragment with respect to Position .
*/
#Override
public Fragment getItem(int position)
{
switch (position){
case 0 : return new EquationsCalculFragment();
case 1 : return new EquationsResultatFragment();
case 2 : return new EquationsInfosFragment();
}
return null;
}
#Override
public int getCount() {
return int_items;
}
/**
* This method returns the title of the tab according to the position.
*/
#Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return "Calcul";
case 1 :
return "Résultats";
case 2 :
return "Infos";
}
return null;
}
}
}
Fragment A : EquationsCalculFragment.java
public class EquationsCalculFragment extends Fragment {
private String aS;
private String bS;
private EquationsCalculFragment.ButtonClicked callEqua2ndRes;
public interface ButtonClicked {
void sendResultats(float a, float b);
}
private ViewPager viewPager;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_equations_calcul, container, false);
viewPager = (ViewPager) getActivity().findViewById(R.id.viewpager);
final EditText champ_a = (EditText) view.findViewById(R.id.equa_2nd_a);
final EditText champ_b = (EditText) view.findViewById(R.id.equa_2nd_b);
Button button = (Button) view.findViewById(R.id.btn_equations_resultats);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bS = champ_b.getText().toString();
aS = champ_a.getText().toString();
callEqua2ndRes.sendResultats(Float.parseFloat(aS), Float.parseFloat(bS));
viewPager.setCurrentItem(1, true);
}
});
return view;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
if (context instanceof EquationsCalculFragment.ButtonClicked) {
callEqua2ndRes = (EquationsCalculFragment.ButtonClicked) context;
}
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement ButtonClicked");
}
}
#Override
public void onDetach() {
callEqua2ndRes = null;
super.onDetach();
}
}
Fragment B : EquationsResultatFragment.java
public class EquationsResultatFragment extends Fragment {
private TextView results;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_equations_resultat, container, false);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
results = (TextView) getView().findViewById(R.id.equa_2nd_resultat);
}
public void getResultat(float a, float b) {
results.setText(String.valueOf((a*a)+(2*a*b)+(b*b)));
}
}
Is there anything I'm doing wrong ?
I thinkthe NPE is because you try to find the fragment with it's id, but you supply I guess the id of the ViewPager? Try finding it by tag, it should look something like this:
int position;
getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.yourViewPagerIdGoesHere + ":" + position);
Where the position is the pos of your targeted fragment just like in the adapter's public Fragment getItem(int position) method
Issue is you have declared an interface in EquationsCalculFragment but never initialied it :)
So here is what you can do :)
In EquationsCalculFragment, change
private EquationsCalculFragment.ButtonClicked callEqua2ndRes;
to
public EquationsCalculFragment.ButtonClicked callEqua2ndRes;
and in TabFragment, getItem methods case 0, make this change :)
case 0 : EquationsCalculFragment calculationFragment = new EquationsCalculFragment();
calculationFragment.callEqua2ndRes = TabFragment.this;
return calculationFragment;
Should solve your issue :) Hope my answer helped :)
P.S : Code provided above is to explain the concept and not for copy paste, might contain syntactic error :) If contains please modify and use it :D
Is it possible to pass a data from fragment to fragment by swipe?
There are many articles teaching us how to pass the data from fragment to fragment, but most of the article or questions had implemented OnClickListener in their first fragment, which used to pass value to another fragment.
But my case is pass the data from two fragments without any button click and finally save them in different tables by clicking button in the last fragment. What can I do to achieve this??
The flow is Information >> WorkForce >>WorkDetailsTable and save them to different table by one button click.
I have tried to work it out but I get NULL value in SQLite. I think I have miss out a lot but have no idea. PLEASE help me...I've been stuck at here for more than two days...Thanks
Tab.java
public class Tab extends ActionBarActivity implements ActionBar.TabListener {
ViewPager Tab;
TabPagerAdapter TabAdapter;
ActionBar actionBar;
public static String name = null;
public static String subContractors = null;
// will be used for data communication
public static Force force_bean;;
public static Info info_bean;
public static Force getForce(){
return force_bean;
}
public static void setForce(Force force){
force_bean=force;
}
public static Info getInfo(){
return info_bean;
}
public static void setInfo(Info info){
info_bean=info;
}
final Activity mActivity = (Activity) this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab1);
info_bean = new Info();
force_bean = new Force();
TabAdapter = new TabPagerAdapter(getSupportFragmentManager());
Tab = (ViewPager) findViewById(R.id.pager);
Tab.setOnPageChangeListener(
new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar = ((AppCompatActivity) mActivity).getSupportActionBar();
actionBar.setSelectedNavigationItem(position);
}
});
Tab.setAdapter(TabAdapter);
actionBar = ((AppCompatActivity) mActivity).getSupportActionBar();
//Enable Tabs on Action Bar
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//Add New Tabs
actionBar.addTab(actionBar.newTab().setText("Information").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Work Force").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Work Details").setTabListener(this));
}
#Override
public void onTabSelected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
}
#Override
public void onTabUnselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
}
}
TabPagerAdapter.java
public class TabPagerAdapter extends FragmentStatePagerAdapter {
public TabPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
return Information.newInstance("name");
case 1:
return WorkForce.newInstance("SubCon");
case 2:
return WorkDetailsTable.newInstance();
}
return null ;
}
#Override
public int getCount() {
return 3; //No of Tabs you can give your number of tabs
}
Informmation.java
public class Information extends Fragment implements View.OnClickListener {
private Spinner spinner, spinner2, spinner3;
private static String a;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View info = inflater.inflate(R.layout.information, container, false);
dialog = new DateDialog();
spinner = (Spinner)info.findViewById(R.id.spinner);
addItemsOnSpinner();
a= spinner.getSelectedItem().toString();
return info;
}
public static Information newInstance(String a)
{
Information fragment=new Information();
Bundle bundle=new Bundle();
bundle.putString("a",a);
fragment.setArguments(bundle);
return fragment;
}
public void addItemsOnSpinner() {
List<String> list = new ArrayList<String>();
list.add("1 ");
list.add("2");
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_dropdown_item, list);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
}
WorkForce.java
public class WorkForce extends Fragment {
private static EditText txt1;
private static String subCon;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View work = inflater.inflate(R.layout.workforce, container, false);
txt1 = (EditText) work.findViewById(R.id.editText);
subCon = txt1.getText().toString();
return work;
}
public static WorkForce newInstance(String subCon) {
WorkForce f = new WorkForce();
Bundle bundle = new Bundle();
bundle.putString("subCon", subCon);
f.setArguments(bundle);
return f;
}
}
WorkDetails.java
private com.example.project.project.API.InfoAPI ts;
private com.example.project.project.API.WorkDetailsAPI WD;
private com.example.project.project.API.WorkForceAPI WF;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View workDetails = inflater.inflate(R.layout.tableworkdetails, container, false);
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
spinnerTra = (Spinner) workDetails.findViewById(R.id.spinner6);
addItemsOnSpinner();
Button btn1 = (Button)workDetails.findViewById(R.id.button2);
WD = new com.example.project.project.API.WorkDetailsAPI(getActivity());
ts = new com.example.project.project.API.InfoAPI(getActivity());
WF = new com.example.project.project.API.WorkForceAPI(getActivity());
a1 = spinnerTra.getSelectedItem().toString();
Bundle bundle = new Bundle();
final String name = bundle.getString("a");
final String subContractors = bundle.getString("subCon");
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
add(name, subContractors);
}
});
return workDetails;
}
public void add(String name,String subContractors)
{
Toast.makeText(getActivity(),+name+subContractors, Toast.LENGTH_SHORT).show();
ts.insertTimeSheet(name);
WF.insertWorkForce(subContractors);
}
Note: My case is pass the data from two fragments without any button click and finally save them in different tables by clicking button in the last fragment.
If I understand your problem correctly, you are essentially implementing something a little bit like a "Wizard" where each step passes information to the next step as you swipe between the tabs or select them.
So in reality your problem is how to get the information out of a fragment when it is deselected and into a fragment when selected.
At the simplest level I would suggest your activity holds the "master" copy of all of the information and passes it into/takes it from each fragment in your tab pager adapter.
You would need some kind of "Domain" object to hold all the information you need to collect. Each tab would only update the bits of information it cares about..
public class WorkData {
string information;
string subCon;
... etc..
}
You add an instance of this to hold the master copy to your "tab" activity:
public class Tab extends ActionBarActivity implements ActionBar.TabListener {
...
WorkData workData = new WorkData();
...
I would then suggest a simple interface that each of your "tab" fragments implement; something like:
public interface DataUpdate {
void setData(WorkData data);
WorkData getData();
}
Each of your tab fragments would implement this interface, updating the WorkData as required..
public class WorkForce extends Fragment implements DataUpdate {
...
private WorkData workData; // this fragment's "copy" of the data
...
#Override
public WorkData getData() {
this.workData.subCon = this.subCon; // Assuming subcon has been updated.. else use txt1.getText();
return this.workData;
}
#Override
public void setData(WorkData workData) {
this.workData = workData;
// Update this page's views with the workData...
// This assumes the fragment has already been created and txt1 is set to a view
txt1.setText(workData.subCon);
this.subCon = workData.subCon; // Actually could just use subCon in workData, but be aware that workData actually points to the Activity's copy (kinda makes getdata redundant.. but I like symmetry and couldn't be bothered making lots of copies of the object).
}
Then you just need to add the code to pass the data backwards and forwards.. in your "Tab" activity which looks like...
#Override
public void onTabSelected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
int position = tab.getPosition();
DataUpdate dataUpdate = (DataUpdate) TabAdapter.getItem(position);
// Pass the master workdata to the selected fragment
dataUpdate.setData(this.workData);
}
#Override
public void onTabUnselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
int position = tab.getPosition();
DataUpdate dataUpdate = (DataUpdate) TabAdapter.getItem(position);
// Update the master workdata from the unselected fragment
this.workData = dataUpdate.getData();
}
#Override
public void onTabReselected(ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
// This might be pointless, but we'll do it anyway..
int position = tab.getPosition();
DataUpdate dataUpdate = (DataUpdate) TabAdapter.getItem(position);
// Pass the master workdata to the selected fragment
dataUpdate.setData(this.workData);
}
An important thing to notice here is that your TabPagerAdapter will create a new fragment every time you call getItem().. that will mean that we will never get any updates because each time we try to get the fragment it returns a new, empty fragment. We need to change this so that the fragments are still created when first asked for, but only created once so that we don't keep throwing away our work.
public class TabPagerAdapter extends FragmentStatePagerAdapter {
private static final int NUMBER_OF_TABS = 3;
private Fragment[] tabList = new Fragment[NUMBER_OF_TABS];
public TabPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
if (tabList[i] != null) {
// Return a tab we created earlier..
return tabList[i];
} else {
switch (i) {
case 0:
tabList[0] = Information.newInstance("name");
return tabList[0];
case 1:
tabList[1] = WorkForce.newInstance("SubCon");
return tabList[1];
case 2:
tabList[2] = WorkDetailsTable.newInstance();
return tabList[2];
}
}
return null ;
}
#Override
public int getCount() {
return NUMBER_OF_TABS;
}
Hope this helps. Good luck :-)
Although C James provides good tips to solve your problems, I would like to introduce another way without using implementing of interfaces. Please check below link out. If you use an event bus library such a http://square.github.io/otto/, you can easily pass data you want to share among fragments and even activities. Additionally, you can reduce a lot of code line since it only requires Sender(PUBLISHING), Receiver(Subscriber) while implementation of interfaces requires additional lines of code.
Here is a tutorial of Otto libarary.
http://www.vogella.com/tutorials/JavaLibrary-EventBusOtto/article.html
Hope it helps :)
I would more go the Observer Pattern way.
Each Fragments changes an POJO with is rendered in your Fragments in some way. You simply have to Observe the pojo in your Fragments. Changing Fragments will notify interested observers without knowing them.
I believe that's a much cleaner way to implement this.
Fragment A -> PojoInstance.setXY("foo");
Fragment A -> informs the Observers which e.b Informs Fragment B:
Fragment B will see the change tru the Observer.
Because ViewPagers or other Components will cache Fragments thats a way to get information in already created Fragments, even when their are not seen.
You could also try to use an EventBus where you pass the POJO around.
To transfer data from one fragment to another fragment when swipe is performed ,firstly you should get the view of the each fragment.here is the sample code that can help you out a bit.
write this code in Activity:
mviewpager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
mviewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
adapter = ((SOFragmentPagerAdapter) mviewpager.getAdapter());
//getting the view of fragments at positions
if(position==0)
{
View v = null;
Fragment1=(Fragment1)adapter.getFragment(position);
v=fragment1.getMyView();//this is how you get the view
ListView lv=(ListView)v.findViewById(R.id.lv_services);
ArrayAdapter<String> arrayAdapter=new ArrayAdapter<String>(SOListItemSelectedActivity.this,android.R.layout.simple_list_item_1,soRequestFragment.al_list_of_services);
lv.setAdapter(arrayAdapter);
}
if(position==1)
{
}
}
#Override
public void onPageSelected(int position) {
if(position==0)
{
View v = null;
soRequestFragment=(SORequestFragment)adapter.getFragment(position);
v=soRequestFragment.getMyView();
}
if(position==1)
{
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
mviewpager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
and create a FragmentPagerAdapter as:
public class SOFragmentPagerAdapter extends FragmentPagerAdapter {
HashMap<Integer,Fragment> mPageReferenceMap;
int mNumOfTabs;
public SOFragmentPagerAdapter(FragmentManager fm,int mNumOfTabs) {
super(fm);
this.mNumOfTabs=mNumOfTabs;
mPageReferenceMap=new HashMap<Integer,Fragment>();
}
#Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
Fragment1 fragment1=new tFragment1();
mPageReferenceMap.put(position,fragment1);
return fragment1;
case 1:
Fragment2 fragment2=new Fragment2();
mPageReferenceMap.put(position,fragment2);
return fragment2;
default:
return null;
}
}
public Fragment getFragment(int key) {
return mPageReferenceMap.get(key);
}
#Override
public int getCount() {
return 2;
}}
In Fragments add the getmyview() which will return the view of that fragment as:
public void getmyview()
{
return myview;//myview is fragment view which you will return in oncreateview method
}
Note: Viewpager execute onpagescroll first and get the position 0,1 and when you scroll ,views at position 1,2 will execute and page selected 0 will execute.
For tabselections: Tabunselected,Tabselected Tab reselected is the sequence of execution.
so write accordingly in the respective positions of fragments.
Hope this helps you.
I can't figure out why my bundle SavedInstanceState is not saving when the application closes. Chances are it's just something stupid that I didn't know about though! The main activity doesn't have much in it, just a page adapter for transitioning screens, because that is a major part of what I'm going to try to make. Most of the code right now is in my StandFragment.java, it's the first page that shows up when you open the app. That's where the save state and that sort of thing is.
MainActivity:
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
}
private class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int pos){
switch(pos){
case 0: return StandFragment.newInstance("STAND");
case 1: return CartFragment.newInstance("CART");
case 2: return ThirdFragment.newInstance("THIRD");
case 3: return ThirdFragment.newInstance("FOURTH");
case 4: return ThirdFragment.newInstance("FIFTH");
default: return ThirdFragment.newInstance("Default");
}
}
#Override
public int getCount(){
return 5;
}
}
}
StandFragment:
public class StandFragment extends Fragment{
private int totalMoney;
private int moneyPerSec;
private int moneyPerClick;
Handler handleCounter = new Handler();
TextView counter;
TextView perSecCounter;
Button buttonMoney;
Button buttonMoneyPerSec;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.stand_frag, container, false);
super.onCreate(savedInstanceState);
buttonMoney = (Button)v.findViewById(R.id.buttonMoney);
buttonMoneyPerSec = (Button)v.findViewById(R.id.buttonMoneyPerSec);
counter = (TextView)v.findViewById(R.id.tvMoney);
perSecCounter = (TextView)v.findViewById(R.id.tvMonPerSec);
TextView tv = (TextView) v.findViewById(R.id.tvStandFrag);
tv.setText(getArguments().getString("msg"));
handleCounter.post(updateCounter);
if (savedInstanceState==null){
moneyPerSec = 1;
moneyPerClick = 1;
totalMoney=0;
}
else{
moneyPerSec = savedInstanceState.getInt("moneyPerSec");
moneyPerClick = savedInstanceState.getInt("moneyPerClick");
totalMoney = savedInstanceState.getInt("totalMoney");
}
buttonMoney.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
totalMoney += moneyPerClick;
counter.setText(""+totalMoney);
perSecCounter.setText(""+moneyPerSec);
}
});
buttonMoneyPerSec.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
if (totalMoney>=10){
totalMoney-=10;
counter.setText(""+totalMoney);
moneyPerSec++;
perSecCounter.setText(""+moneyPerSec);
}
}
});
return v;
}
Runnable updateCounter = new Runnable(){
public void run(){
totalMoney += moneyPerSec;
counter.setText(""+totalMoney);
handleCounter.postDelayed(this, 1000);
}
};
public void onPause(Bundle savedInstanceState){
savedInstanceState.putInt("totalMoney",totalMoney);
savedInstanceState.putInt("moneyPerSec",moneyPerSec);
savedInstanceState.putInt("moneyPerClick",moneyPerClick);
super.onSaveInstanceState(savedInstanceState);
}
public static StandFragment newInstance(String text){
StandFragment f = new StandFragment();
Bundle b = new Bundle();
b.putString("msg", text);
f.setArguments(b);
return f;
}
}
onSaveInstanceState() is not for persistent storage. It is only there to save particular state about that instance of the Fragment (e.g. during configuration changes, or if your app is killed in the background and the Fragment should be recreated). If you're closing your app entirely (i.e. finishing the Activity) then your state will not be saved, as that instance is no longer needed.
For persistent storage, you could look into either SharedPreferences or SQLite, depending on your needs.
onSaveInstanceState() is only called when the Android system may need to recreate that particular instance of the Fragment.
You have to save your data on onSaveInstanceState() of your Activity