I'm writing an android application, which has one activity, which contains several fragments. Now I want to know is there a way to split that activity into several files - to have separate file for each fragment?
For making my question clearer here is structure of my activity
public class MainActivity extends Activity implements ActionBar.TabListener
{
#Override
public Fragment getItem(int position) {
switch(position)
{
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
case 3:
return new Fragment4();
}
}
public static class Fragment1 extends Fragment {}
public static class Fragment2 extends Fragment {}
public static class Fragment3 extends Fragment {}
public static class Fragment4 extends Fragment {}
}
Thank you in advance!
Now I want to know is there a way to split that activity into several files - to have separate file for each fragment
If the above means that you recently got all your Fragments as inner classes within your Activity class, then answer is yes - just create separate java class file for each fragment.
Related
I have a TabsPagerAdapter class as below. The classes FirstFragment, SecondFragment and ThirdFragment each extended Fragment and all was well.
Then I changed SecondFragment to extend ListFragment and now I get compile error:
Type mismatch: cannot convert from SecondFragment to Fragment
ListFragment extends Fragment, so in my mind. this shouldn't be a problem.
What do I do?
Import in SecondFragment is:
import android.app.ListFragment;
Class:
public class TabsPagerAdapter extends FragmentPagerAdapter {
private Context mContext;
public TabsPagerAdapter(FragmentManager fragmentManager, Context context) {
super(fragmentManager);
mContext = context;
}
#Override
public Fragment getItem(int index) {
Fragment returnFragment = null;
switch (index) {
case 0:
returnFragment = new FirstFragment(mContext);
break;
case 1:
returnFragment= new SecondFragment(mContext);
break;
case 2:
returnFragment = new ThirdFragment(mContext);
break;
}
return returnFragment;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 3;
}
}
The issue is usually due of a mismatch between the import in the different classes. You probably have the native Fragment in one class and the one from the support library in the other. Fix the imports and it will work.
check the imports. Also remove the constructor that takes a parameter in your Fragment subclasses. The system wants a public empty constructor (aka default constructor). If you need a context, you can use getActivity()
I have an activity A with 3 fragments. Each fragments replaces each other, hence at a given time only 1 is visible.
HomeFragment has 2 textviews wrapped inside 2 cardviews. Each cardview represents a text value which comes from Fragment1 and Fragment2. When I click on say Card1,I get to the Fragment1.
Fragment1 has some cardviews, when I selects any of them I navigate back to HomeFragment and update the cardview text based on my selection in Fragment1.Here is the switch statement, depending upon what card user selects I put that in a bundle and pass it to HomeFragment.
switch (v.getId()) {
case R.id.card_view0:
Fragment1Bundle.putString("Test", "Testing");
bundle.putBundle("Fragment1Bundle", Fragment1Bundle);
fragmentTransaction.setCustomAnimations(R.anim.slideup, R.anim.slidedown, R.anim.slideup, R.anim.slidedown);
fragmentTransaction.replace(R.id.content_frame, fragment);
fragment.setArguments(bundle);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
Fragment2 has same behavior as Fragment 1.
switch (v.getId()) {
case R.id.card_view0:
Fragment2Bundle.putString("Test2", "Tetsing");
bundle.putBundle("Fragment2Bundle", Fragment2Bundle);
fragmentTransaction.setCustomAnimations(R.anim.slideup, R.anim.slidedown, R.anim.slideup, R.anim.slidedown);
fragmentTransaction.replace(R.id.content_frame, fragment);
fragment.setArguments(bundle);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
My challenge is that I am using bundles to pass data between fragments, My home fragment gets updated with the data it from fragment1 but when I go to fragment 2 and after making the selection come back to Home fragment, my fragment1 data is set to default. This is what I am doing in Home Fragments onCreateView()
try {
bundle1 = getArguments().getBundle("Fragment1Bundle");
bundle2 = getArguments().getBundle("Fragment2Bundle");
tv.setText(bundle1.getString("Test") == null ? null : bundle1.getString("Test"));
tv2.setText(bundle2.getString("Test2") == null ? nul : bundle2.getString("Test2"));
} catch (NullPointerException e) {
Log.d(TAG, e.printStackTrace());
}
I know that I am creating a new Homefragment in my fragment transaction in both fragment1 and fragment2, How can I keep just 1 instance of Home fragment around.
Another design recommended by Google is to use the main Activity and 2 fragments (in your case Fragment1 and Fragment2). I can see your problem of passing data bundle to HomeFragment. This suggested design uses MainActivity which is declared static (may be required for scoping issue). And it uses an interface to be established between Activity and a Fragment. I think the interface is easier than passing bundle back to the HomeFragment.
A Google webpage is # Communicating with Other Fragments. This is not just my opinion. A good SO link, I think, is How to pass data between fragments.
Code snippet from the webpage...
An example of Fragment to Activity communication:
public class HeadlinesFragment extends ListFragment {
OnHeadlineSelectedListener mCallback;
// Container Activity must implement this interface
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
...
An example of Activity to Fragment communication:
public static class MainActivity extends Activity
implements HeadlinesFragment.OnHeadlineSelectedListener{
...
public void onArticleSelected(int position) {
// The user selected the headline of an article from the HeadlinesFragment
// Do something here to display that article
}
}
Note:
OnHeadlineSelectedListener is the interface created by the Fragment.
The created method onArticleSelected has a parameter position, which comes from the ListView in ListFragment (in the sample).
You can still set data bundles and send data between Activity and Fragment. However I have not sent back data from Fragment to Activity. I normally use Fragment to handle much of UI updates.
how to pass values from activity to already open fragment and update array-list help me please. when I using interface the array-list size is zero what I do? do not us bundle method.
public class Main2Activity extends AppCompatActivity{
String desc = "data";
OnDataPassedListener onDataPassedListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
String passedArg = getIntent().getExtras().getString("id");
Log.d("data",passedArg);
Scription scription = new Scription();
onDataPassedListener = (OnDataPassedListener)scription;
onDataPassedListener.onDataPassed(passedArg,desc);
}
public interface OnDataPassedListener {
void onDataPassed(String text,String name);
}
}
public class Test extends Fragment implements
Main2Activity.OnDataPassedListener{
.
.
.
.
#Override
public void onDataPassed(String text,String name) {
monthlylists.get(Integer.valueOf(text)).setFood_type(name);
}
I have a FragmentActivity with the following xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
and the view pager class is as follows:
public class MyPagerAdapter extends FragmentStatePagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
// profile fragment activity
Fragment f = new ProfileFragment();
return new ProfileFragment();
case 1:
// radar fragment activity
return new RadarFragment();
case 2:
// matches fragment activity
return new MatchesFragment();
}
return null;
}
#Override
public int getCount() {
return 3;
}
}
I also have a BroadcastReceiver class that has an instance variable of my custom FragmentActivity. Through this instance variable I would like to obtain any of the fragments above. I understand there are FragmentManager.findFragmentById() and findFragmentByTag() methods but I cant seem to find a way of using that in this case.
Since you only have 3 pages (3 fragments), I recommend that you use the FragmentPagerAdapter rather than the FragmentStatePagerAdapter. Then, you can use findFragmentByTag to find your fragments - read more about that in This SO question.
I have Main Activity with View Pager inside that activity. So, I have also FragmentStatePager adapter for handling which fragment is display inside ViewPager.
Anyway, as you know ViewPager loads previous, current and next fragment in memory and that's problem because I want to change content values in next fragment from current fragment based on user interaction from current fragment.
public class StageOneActivity extends FragmentActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_stage_one);
//ViewPager for Introduction
mStageOnePager = (ViewPager) findViewById(R.id.vp_stage_one);
mStageOnePager.setAdapter(new IntroFragmentPagerAdapter(getSupportFragmentManager()));
mStageOnePager.setOffscreenPageLimit(1);
//mStageOnePager.setCurrentItem(8);
}
private class IntroFragmentPagerAdapter extends FragmentStatePagerAdapter {
public IntroFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int pos) {
switch(pos) {
case 0:
return StageOneFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_01);
case 1:
return StageOneFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_02);
case 2:
return TitleSpinnerFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_03, R.drawable.bkg_page_1_50);
case 3:
return CurrencySpinnerFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_03, R.drawable.pack_of_20);
case 4:
return SimpleSpinnerFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_05, R.drawable.bkg_page_1_50);
case 5:
return MoneySpentFragment.newInstance(getResources().getColor(R.color.green), R.drawable.money_spent_1, R.drawable.money_spent_2, "0");
case 6:
return StageOneFragment.newInstance(getResources().getColor(R.color.green), R.drawable.stage1_07);
How I can send data to fragment who is already loaded and content is added in ViewPager?
I decided to try to use ViewPager.setOnPageChangeListener and detected when user scrolled to selected screen, but problem is how I can send that data to that Fragment and show it?
You can use eventbus:
https://github.com/greenrobot/EventBus
It's easy to setup and use.
HOWTO with example and code snippets:
https://github.com/greenrobot/EventBus/blob/master/HOWTO.md
You need to define an interface in the fragment and implement it within the Activity.Google documentation:
http://developer.android.com/training/basics/fragments/communicating.html
In your class it'd be something like this:
public Fragment StageOneFragment{
public interface itf{
}
...
}
public class StageOneActivity extends FragmentActivity implements StageOneFragment.itf{
...
}
Hope it helps, you should be able to implement the interface that way.
Using a ViewPager, I'm working on a guide that tells the user how to use my app.
This is how i currently add/setup the pages:
...
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new Guide_fragment();
case 1:
return new Guide_fragment_2();
case 2,3,4 etc.
default:
return null;
}
}
...
But this way I have to have a fragment class for each page, and since the pages are only images and text, I figured that it might not be necessary.
Is there a way I can just use the same fragment class for all pages and then just assign a different layouts to it?
Thanks
Is there a way I can just use the same fragment class for all pages and then just assign a different layouts to it?
Sure. Pass data into the fragment indicating what to display, typically via the factory pattern:
Create a static newInstance() method that takes the data you might ordinarily pass to the fragment constructor
newInstance() takes those parameters, puts them in a Bundle, and attaches the Bundle to a newly-constructed instance of your fragment via setArguments()
Your fragment, when it needs this data, calls getArguments() to retrieve the Bundle
This ensures that your data will survive configuration changes.