i have data in activity in which some data i want to show in activity itself and some data i want to show in three swipable fragments. so how do i pass data from activity to that fragments. i am gonna put image of what i want to do.
Please give solution about this.Thanks.
I think your main question is how to pass data from activity to fragment?Right?
You can pass data from activity to fragment by creating a Bundle and put some data to it and then pass it to the setArguments method.
YourFragment yourFragment = new YourFragment();
Bundle bundle = new Bundle();
bundle.putInt(KEY_RECIPE_INDEX, index);//you can use bundle.putString or others to pass different types of data
yourFragment.setArguments(bundle);
Now you can retrive the data in your fragment by using getArguments
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
int index = getArguments().getInt(ViewPagerFragment.KEY_RECIPE_INDEX);
//........
You also ask in your question that you have some data in your activity and some of the data you want to show on activity and some of them you want to show in swipable fragments.Now I am going to show you how to do that by using an example.
Suppose you have two swipable tab and each tab has a fragment
final IngredientsFragment ingredientsFragment = new IngredientsFragment();
Bundle bundle = new Bundle();
bundle.putInt(KEY_RECIPE_INDEX, index);
ingredientsFragment.setArguments(bundle);
final DirectionsFragment directionsFragment = new DirectionsFragment();
bundle = new Bundle();
bundle.putInt(KEY_RECIPE_INDEX, index);
directionsFragment.setArguments(bundle);
ViewPager viewPager = (ViewPager) view.findViewById(R.id.viewPager);
viewPager.setAdapter(new FragmentPagerAdapter(getChildFragmentManager()) {
#Override
public android.support.v4.app.Fragment getItem(int position) {
return position == 0 ? ingredientsFragment : directionsFragment;
}
#Override
public CharSequence getPageTitle(int position) {
return position == 0 ? "Ingredients" : "Directions";
}
#Override
public int getCount() {
return 2;
}
});
TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
I think there is no problem of the data that you want to show in your activity.
Qick recap: You pass the data to fragment by creating a bundle and put some data and use yourfragment.setArguments(yourBundle).
Now I think you can pass data to swipable views.
Hope this helps!
Related
In my app there's an Activity with three tabs, each of them contains a ListFragment.
The ListFragment must show different contents, but when I pass it through the bundle it gets overwritten and I get three fragments with the same content (the latest one)
Here's the code:
In the onCreate method of the Activity:
{...
Fragment fragment;
Bundle bundle= new Bundle();
for(int i = 0; i<CATEGORIES.size(); i++) {
fragment = new MyListFragment();
bundle.putSerializable("Data", data.get(i));
fragment.setArguments(bundle);
screens.put(CATEGORIES.get(i),fragment);
}
setUpViewPagerAndTabs();
...
... }
protected void setUpViewPagerAndTabs(){
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mViewPager.setOffscreenPageLimit(screens.size()+1);
mAdapter = new PageAdapter(screens, getSupportFragmentManager());
mViewPager.setAdapter(mAdapter);
tabs = (TabLayout) findViewById(R.id.tabs);
tabs.setTabGravity(TabLayout.GRAVITY_FILL);
tabs.setTabMode(TabLayout.MODE_FIXED);
tabs.setupWithViewPager(mViewPager);
}
In the Fragment class this line produces the overwriting of the corresponding data:
ArrayList<String> names = (ArrayList<String>)
b.getSerializable(Activity.DATA);
even if I try to pass the value of the counter (i) to the fragment, in order to pick the right element of data in the fragment, it gets overwritten.
How can I resolve this?
Thank you in advance
Not sure if it is the case. However you are passing the reference to the same bundle (out of the scope) to all the three fragments. It might depend on when the serialization / deserialization takes effect, but if it happen after the loop you have three fragment pointing to the same content of the bundle (the last one).
Try to move the bundle creation inside the loop:
for(int i = 0; i<CATEGORIES.size(); i++) {
Bundle bundle= new Bundle();
fragment = new MyListFragment();
bundle.putSerializable("Data", data.get(i));
fragment.setArguments(bundle);
screens.put(CATEGORIES.get(i),fragment);
}
I have a situation I need some advice on. I have an app that has an expandable list view. Each child click sends the user to the next activity, which is a tab layout with a list view. The tab layout has 3 tabs. I'm trying to figure out how to send data to the 3 tabs listviews when child is clicked on expandable listview.
Originally I was going to set it up in the setOnChildClickListener like so:
expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
if (groupPosition == 0) {
if (childPosition == 0) {
mCustomListViewAdapter.addAdapterItem(new CustomObject("Squats", "60%", "6", "150", false));
listViewFri.setAdapter(mCustomListViewAdapter);
EDIT: this is my tablayout activity that sets up the 3 tabs. I'm not sure where to access the bundled extras.
public class WorkoutDaysActivity extends BaseActivity {
ListView listViewFri = (ListView) findViewById(R.id.listViewFri);
ListView listViewMon = (ListView) findViewById(R.id.listViewMon);
ListView listViewWed = (ListView) findViewById(R.id.listViewWed);
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v4.app.FragmentStatePagerAdapter}.
*/
private SectionsPagerAdapter mSectionsPagerAdapter
/**
* The {#link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.workout_days);
Bundle extras = getIntent().getBundleExtra("args");
mToolBar = activateToolbarWithHomeEnabled();
setUpNavigationDrawer();
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_workout_days, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
switch (getArguments().getInt(ARG_SECTION_NUMBER)) {
case 1:
View rootView = inflater.inflate(R.layout.fragment_workout_days, container, false);
Bundle extras = getArguments();
CustomObject objects = (CustomObject) extras.getSerializable("w29w1");
return rootView;
case 2: View rootView2 = inflater.inflate(R.layout.fragment_sub_page1, container, false);
TextView textView2 = (TextView) rootView2.findViewById(R.id.textView2);
textView2.setText("Workout 29 Week 1");
return rootView2;
case 3:
View rootView3 = inflater.inflate(R.layout.fragment_sub_page2, container, false);
TextView textView3 = (TextView) rootView3.findViewById(R.id.txtFrag3);
textView3.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView3;
default: View rootView4 = inflater.inflate(R.layout.fragment_workout_days, container, false);
TextView textView4 = (TextView) rootView4.findViewById(R.id.txtFrag1);
textView4.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView4;
}
}
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Monday";
case 1:
return "Wednesday";
case 2:
return "Friday";
}
return null;
}
}
}
I thought it would go in this part like so:
switch (getArguments().getInt(ARG_SECTION_NUMBER)) {
case 1:
View rootView = inflater.inflate(R.layout.fragment_workout_days, container, false);
Bundle extras = getArguments();
CustomObject objects = (CustomObject) extras.getSerializable("w29w1");
CustomListViewAdapter customListViewAdapter = new CustomListViewAdapter(this, objects);
But im getting an error under (this, objects) saying "cannot be applied to .placeholderfragment .custom object" "PlaceholderFragment cannot be converted to Context"
This is what I put in the onChildClick:
Bundle extras = new Bundle();
final ArrayList<CustomObject> objects = new ArrayList<CustomObject>();
objects.add(new CustomObject("Squat", "65%", "6", "150", false));
extras.putSerializable("w29w1", objects);
Intent intent = new Intent(getApplicationContext(), WorkoutDaysActivity.class);
intent.putExtra("args", extras);
startActivity(intent);
Thanks for the help! please let me know if you need to see any of my code to better understand what I'm trying to do!
I'm having some difficulty understanding the question completely, but here's my thoughts so far.
Are you attempting to set the same instance of the list adapter on each list? If you want the same general behaviour, but to tie different data to a list, be sure you are instantiating new adapter instances for each list.
i.e.
myList1.setAdapter(new MyAdapter());
myList2.setAdapter(new MyAdapter());
rather than
MyAdapter myAdapter = new MyAdapter();
myList1.setAdapter(myAdapter);
myList2.setAdapter(myAdapter);
Additionally, it is wise to move data through intents when communicating with another activity. In your initial activity, when an action prompts launching the next activity, put the extras into the intent before calling startActivity(). Then, inside the next activity, you will call getIntent().getXXXExtra("...") where the XXX is type-matched to the extra you are extracting, and ... is the correct key you placed on the extra in the previous activity.
If you are using fragments contained in activities, make use of Fragment.setArguments() (in activity2) and Fragment.getArguments() (in fragment2) to pass the extras from fragment1 to activity2 to fragment2.
Passing Extras Around
When you click an item and want to launch a new activity (a new view to display), a good approach is to bundle up the information needed, pass it to the new activity, unwrap all that information and then apply it to the views as you desire.
For example...
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
if (groupPosition == 0) {
if (childPosition == 0) {
Bundle extras = new Bundle();
// Put all the extras you need. This can be primitives like int, boolean, double, or complex objects using the Serializable interface
// For example, say your CustomObject implements Serializable
CustomObject customObject = new CustomObject("Squats", "60%", "6", "150", false);
extras.putSerializable("object_key_here", customObject);
Intent intent = new Intent(getContext(), NextActivityHere.class);
intent.putExtra("args", extras);
startActivity(intent);
}
}
In the activity containing the fragment which contains the list:
// Likely in onCreate()
Bundle extras = getIntent.getBundleExtra("args");
MyFragment myFragment = new MyFragment();
myFragment.setArguments(extras);
// Use fragment manager to add the fragment to your view
In the fragment (myFragment) containing the list:
// Likely in onCreate()
Bundle extras = getArguments();
CustomObject customObject = (CustomObject) extras.getSerializable("object_key_here");
// Now you can use the object to set up the adapter, etc...
Hopefully this helps at least show how to get data from the original activity to the fragment containing the list. Usually I see myself passing an ArrayList of data if I'm going to be populating a list. Without knowing too much about your scenario, it's difficult to be more specific.
Layouts with Tabs
You may want to do some reading on TabLayouts and ViewPagers. These are the models used to create paged layouts with tabs.
Implementing these views should greatly reduce the complexity of the Activity. Inside your activity's onCreate() method, you would set up the TabLayout and ViewPager to host your Monday, Wednesday, and Friday fragments.
Each of Monday, Wednesday, and Friday fragment would be an instantiation of the same fragment class which contains the list you wish to fill (if I'm getting the correct vision of the app's layout).
List of MY Assumptions
Assume the XML file is named activity_tab_host.xml
Assume the TabLayout has an id="tab_layout"
Assume the ViewPager has an id="view_pager"
Assume the activity file is named TabHostActivity.java
Assume the fragment with the list is called WorkoutDetailFragment.java
Assume your fragment receives the data through its constructor. You can either do this or pass it through the arguments as you've done. I'm just attempting to minimize code while communicating the general idea. The fragment just needs to get the data! Try not to get hung up on specific methods and code shown here; you may find it easier to pass data through a constructor, etc.
Assume the list of data is ready in the ArrayLists of CustomObjects, simply referred to as mondayData, wednesdayData, and fridayData
Assume you've created your custom adapter called SectionsPagerAdapter
Guidance Code (Not 100% of what is needed)
Get the TabLayout and ViewPager views from the XML view source file:
// TabHostActivity.java::onCreate()
setContentView(R.layout.activity_tab_host);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
Set up your ViewPager:
// TabHostActivity.java::onCreate()
SectionsPagerAdapter adapter = new SectionsPagerAdapter(getFragmentManager());
// Create fragment to populate the tabs
WorkoutDetailFragment mondayFragment = new WorkoutDetailFragment(mondayData);
WorkoutDetailFragment wednesdayFragment = new WorkoutDetailFragment(wednesdayData);
WorkoutDetailFragment fridayFragment = new WorkoutDetailFragment(fridayData);
// Add pages (fragments) to the adapter, passing the fragment and tab title
adapter.addFragment(mondayFragment, "Monday");
adapter.addFragment(wednesdayFragment, "Wednesday");
adapter.addFragment(fridayFragment, "Friday");
// Tie the adapter to your ViewPager
viewPager.setAdapter(adapter);
Tie the ViewPager to the TabView:
// TabHostActivity.java::onCreate()
tabLayout.setupWithViewPager(viewPager);
The main takeaway regarding where to instantiate new fragments is...
The ViewPager is a device used for holding fragments, allowing the user to change between these fragments in a single activity. You should be instantiating fragments within the TabHostActivity.java activity and setting up the fragments within a ViewPager.
My above example simplifies the situation by passing list data in through the WorkoutDetailFragment constructor. This is one of two easy ways to pass data to a fragment.
Passing data through the fragment constructor:
public class WorkoutDetailFragment extends Fragment {
private ArrayList<Object> listData;
public WorkoutDetailFragment(ArrayList<Object> listData) {
this.listData = listData;
}
// Rest of the code for the fragment...
}
Passing data through fragment arguments
// TabHostActivity.java
Bundle args = new Bundle(); // May have received this bundle from extras already. If so, use Bundle args = getIntent.getExtra(...
args.putExtra("list_data", listData); // Where listData is an ArrayList<CustomObject> in your case (Monday/Wednesday/Friday data)
WorkoutDetailFragment fragment = new WorkoutDetailFragment();
fragment.setArguments(args);
// Add the fragment to the view pager...
// Inside WorkoutDetailFragment.java retrieve list data from args using getArguments().getSerializable("list_data")
Hopefully this helps!
I'm developing a Xamarin Android application, I've got a main activity and a Tab Fragment that holds four fragments. From the MainActivity I sent a parcelable object to the Tab Fragment, through arguments (which as I said holds the 4 fragments).
The thing is I that this object needs to be sent to the fragment 1, this fragment sent the object to the Fragment 2 and so on. Each one of these fragments needs to change some different properties of the same object. It's like a wizard form, where each tab is a step.
How can I approach that? How can I send the object from fragment to the next fragment?
I hope I made it clear.
Thanks in advance.
Here are some lines of code:
//In the MainActivity
private void ListItemClicked(int position)
{
//this way we don't load twice, but you might want to modify this a bit.
if (position == oldPosition)
return;
oldPosition = position;
Android.Support.V4.App.Fragment fragment = null;
switch (position)
{
case 0:
fragment = FragmentHome.NewInstance();
break;
case 1:
sheet = new Hoja();
bundle = new Bundle();
pa = Parcel.Obtain();
bundle.PutParcelable("sheet", sheet);
pa.WriteBundle(bundle);
pa.SetDataPosition(0);
fragment = TabFragment.NewInstance();
fragment.Arguments = bundle;
break;
}
SupportFragmentManager.BeginTransaction()
.Replace(Resource.Id.content_frame, fragment)
.Commit();
}
//In the TabFragments class receive the object
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
//var ignored = base.OnCreateView(inflater, container, savedInstanceState);
parcelable_sheet = (Hoja)Arguments.GetParcelable(PARCEL_KEY);
}
I have a List of items in an android app , and i want each item to be on a page . the problem is each item sets a layout with an imageview which downloads its image from a unique url. Is this possible to implement and how please ?
Help is needed (In any Form)
Each page should be a Fragment, depending on your item object, you may want to implement Parcelable and pass your object as an argument to your Fragment, like so :
in your FragmentPagerAdapter :
#Override
public Fragment getItem(int position) {
PageFragment fragment = new PageFragment();
Bundle bundle = new Bundle();
bundle.putParcelable("ARGUMENT_KEY_NAME", itemObjectsList.get(position));
fragment.setArguments(bundle);
return fragment;
}
and in your Fragment's code, read your object like so :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = this.getArguments();
Item item = bundle.getParcelable("ARGUMENT_KEY_NAME");
// do things with your Item object
}
Alternatively, if your item object is too large or if for any other reason you can't easily pass the whole object in a Bundle, you could just pass in the relevant info for the Fragment to be created, i.e. text and image urls etc ...
I have an enum describing three different sports:
public enum MatchType {
S1(0, "Sport1", "xml stream address", R.id.match_list, R.layout.fragment_match_list, R.color.separator_sport1),
S2(0, "Sport2", "xml stream address", R.id.match_list, R.layout.fragment_match_list, R.color.separator_sport2),
S3(0, "Sport3", "xml stream address", R.id.match_list, R.layout.fragment_match_list, R.color.separator_sport3);
...getters/setters
}
I then have fragment with
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
matchesArrayAdapter = new MatchListAdapter(getActivity(), new ArrayList<Match>());
return inflater.inflate(matchType.getLayout(), container, false);
}
Also in my fragment I have an AsyncTask where I have this
#Override
protected void onPostExecute(final List<Match> matches) {
if (matches != null) {
matchListView = (ListView) getActivity().findViewById(matchType.getRId());
[setup listeners]
matchesArrayAdapter.matchArrayList = matches;
matchListView.setAdapter(matchesArrayAdapter);
}
}
EDIT:
In my Activity I have an AppSectionsPagerAdapter with
public Fragment getItem(int i) {
MatchListSectionFragment fragment = new MatchListSectionFragment();
Bundle bundle = new Bundle();
bundle.putInt(Constants.MATCH_TYPE, i);
fragment.setArguments(bundle);
return fragment;
}
EDIT 2:
Here's my onCreate and onCreateView from my fragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
matchType = MatchType.getMatchType(bundle.getInt(Constants.MATCH_TYPE));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
matchesArrayAdapter = new MatchListAdapter(getActivity(), new ArrayList<Match>());
return inflater.inflate(matchType.getLayout(), container, false);
}
The AsyncTask reads an xml stream for each of the sports in my enum but my problem is that tab #1 is overwritten with data from tab #2 and subsequently tab #3.
Before I had a fragment defined for each sport but surely that can't be necessary?
How do I go about using the same fragment with the same layout for each sport?
When instantiating your fragment in your Activity set the Fragment's arguments with a Bundle.
Bundle myBundle = new Bundle();
myBundle.putInt(MY_EXTRA, 1);
myFragment.setArguments(myBundle);
In your bundle put some Extra that will be read in the fragment's onCreate() callback.
int i = getArguments().getInt(MY_EXTRA);
I am on mobile.
Put three FrameLayouts in a LinearLayout, named frame1, frame2 and frame 3. This will be your main Activity's layout.
Then in the Activity's oncreate() method, call getFragmentManager().getFragmentTransaction().
Instantiate the three fragments and send them the data, preferably through a Bundle.
On the Fragment Transaction call the add() or replace() method for each fragment, the first parameter is the id of the respective FrameLayout, the second parameter is the fragment itself.
Call commit().
You should create the newInstance method in your fragment, also you should store MatchType instansce in you fragment.
MatchType matchType;
public static MyFragment newInstance(MatchType matchType) {
MyFragment fragment = new MyFragment();
fragment.matchType = matchType;
return fragment;
}
In your Activity you should to create 3 instances of MyFragment with this method (with related to each fragment it owns MatchType). Then in onCreateView method you should insert data to your views from matchType.
Sorry, I'm on mobile. And sorry for my English.
Update
Check your variable matchType. Maybe it declared as static?