Using one adapter for multiple arrays - android

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!

Related

Implementing a ViewPager with Fragments, only one page is changing among all the pages in the ViewPager

I have been trying to implement a ViewPager with different fragments.
And the problem is when i run the app, in the ViewPager, out of all the pages, only one page is visible and that page only gets changed when I slide over to the other pages in the ViewPager.
Take a look at my code,(although I checked it many times referring it with online resources).
This is what each of my fragments look like:
public class fragment1 extends Fragment {
/* Variable to store reference to the ACtivity */
Activity mCurrentActivity;
/* Variable storing reference to the ArrayList */
private ArrayList<Word> mDefaultWords;
/**
* THe empty public Constructor
*/
public fragment1(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
/** Getting reference to the Activity */
mCurrentActivity = getActivity();
// Populating the ArrayList here
// And later in the onActivityCreated callback I set an adapter on the ArrayList
return inflater.inflate(R.layout.activity_others, container, false);
}
#Override
public void onActivityCreated(Bundle savedStateInstance){
super .onActivityCreated(savedStateInstance);
/**
* Creating {#link ArrayAdapter} to link the {#link String}
* from {#link ArrayList} {#param
*/
MyAdapter adaptItems = new MyAdapter(mCurrentActivity, mDefaultWords);
// Getting the id of the ListView in numberActivity.xml
ListView myList = (ListView) mCurrentActivity.findViewById(R.id.theList);
//Chaning background color
myList.setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.holo_purple));
// Setting the adapter with the {#link ListView}
myList.setAdapter(adaptItems);
}
}
}
My Activity setting the adapter class extending FragmentPagerAdapter as a private inner class and setting the adapter on the ViewPager.
public class Main2Activity extends AppCompatActivity {
private ViewPager mViewPager;
private FragmentPagerAdapter mFragmentStatePagerAdapter;
private FragmentManager mFragmentManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mFragmentManager = getSupportFragmentManager();
mViewPager = (ViewPager) findViewById(R.id.theViewPager);
mFragmentStatePagerAdapter = new MyFragmentStatePagerAdapter(mFragmentManager);
/* Setting the apdapter on the pager */
mViewPager.setAdapter(mFragmentStatePagerAdapter);
}
public class MyFragmentStatePagerAdapter extends FragmentPagerAdapter {
public MyFragmentStatePagerAdapter(FragmentManager fragmentManager){
super(fragmentManager);
}
#Override
public int getCount(){
return 4;
}
#Override
public Fragment getItem(int position) {
if (position == 0) {
return new fragment1();
} else if (position == 1){
return new fragment2();
} else if (position == 2) {
return new fragment3();
} else {
return new fragment4();
}
}
}
}
And here is the layout with the ViewPager
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/theViewPager"
android:visibility="visible" />
As I said, when I run the app only one page gets displayed, other pages are present in the ViewPager but they are blank and displays the default background color,
And the one page that is displayed is the one that gets changed when I swipe left or right in the ViewPager.
So what's the issue?
dont downvote the question, its a genuine problem.
So, I worked my way around, let me say how.
What happened is, I was working on a cloned project that had a old gradle version and sdktools version was also not updated and was quite old.
and the min API targetted was API 15
And I was testing my application on API 21.
So, what I did is I used a different layouts for each of my fragments.
That is for each fragment I created its own XML layout.
And that worked perfectly.
Odd problem, so I updated the gradle and sdktools, to avoid such weird problems.

how to pass data from activity to swipable fragments?

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!

Android Fragment from Layout - Retain variable data

I've been searching for hours and tried numerous methods but cannot seem to grasp my head around the idea / figure out how to retain/restore data in a ViewPager Fragment when it is destroyed and then recreated.
Here is what I have -
An activity where I setup the ViewPager and PageAdapter
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_pager);
//Setup pager and adapter
mPager = (ViewPager) findViewById(R.id.viewpager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
My PageAdapter where I setup a fragment with a bundle using .newInstance()
#Override
public Fragment getItem(int position) {
ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
return fragment.newInstance(position);
}
My Fragment that has a layout that includes a TextView that shows the user a question, a picture, and two True/False buttons. New instance is returned back to the Adapter.
public static ScreenSlidePageFragment newInstance(int position) {
ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
Bundle args = new Bundle();
args.putInt("page_position", position + 1);
fragment.setArguments(args);
return fragment;
}
//the fragment is newly created for the first time or recreated when exiting the view
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_main, parent, false);
//Handle a question being displayed on each fragment
count = getArguments().getInt("page_position") - 1;
mQuestionText = (TextView)v.findViewById(R.id.questionText);
mQuestionText.setText(bank.get(count).getQuestion());
//change the image depending on correct / incorrect answer
mPhoto = (ImageView)v.findViewById(R.id.imageView);
trueButton = (Button)v.findViewById(R.id.true_button);
falseButton = (Button)v.findViewById(R.id.false_button);
//True Button is pressed
trueButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(bank.get(count).getAnswer()) {
mPhoto.setImageResource(R.drawable.right);
clickable = false;
}
else {
mPhoto.setImageResource(R.drawable.wrong);
clickable = false;
}
trueButton.setClickable(clickable);
falseButton.setClickable(clickable);
}
});
What I cannot figure out for the life of me, is how to retain/save that fact that the user has pressed a button and which picture to display when the fragment is restored. I have tried a number of options using onResume(), getArguments(), onSaveInstanceState(), onActivityCreated() etc but none of them seem to work.
I can fix the problem by keeping all my ViewPager pages alive using setOffscreenPageLimit(total pages) but have read this is a bad idea since it takes up a large amount of memory.
Here is an example that I use that can help you where an ArrayList of urls for pictures is saved for later when the view is recreated, you need to override onSavedInstanceState and save your variables in a bundle, then retrieve the values from the bundle when the view is created again, hope this can help
ArrayList<String> picutersUrl = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState!=null)
{
picutersUrl = savedInstanceState.getStringArrayList("My Pictures");
}
#Override
protected void onSaveInstanceState(Bundle bundle)
{
super.onSaveInstanceState(bundle);
bundle.putStringArrayList("My Pictures", picutersUrl );
}
I too have used PagerAdapter to support few static tab widgets. I think you need to add code to ScreenSlidePagerAdapter. Google webpage at PagerAdapter.
Note and read the details on override method instantiateItem. This is where you populate the UI.
Code example for ScreenSlidePagerAdapterfrom (PagerAdapter subclass), using your posted code:
#Override
public Object instantiateItem(ViewGroup container, int position) {
View v = inflater.inflate(R.layout.fragment_main, parent, false);
...
trueButton = (Button)v.findViewById(R.id.true_button);
}
In reality with Views in this framework, you're responsible on saving the state of UI elements. In my ListView, I am caching and saving up to 100 rows of data and refreshes it in an Adapter, for example. For caching, I created custom class containing the UI data.

ViewPagerAdapter returns wrong position

I'm developing an application in which i use a ViewPager.
Underneath the ViewPager, there are some bullet points that should indicate which page is displayed, but their behaviour is wrong.
Here's the activity part:
ind1 = (ImageView)findViewById(R.id.page1);
ind2 = (ImageView)findViewById(R.id.page2);
ind3 = (ImageView)findViewById(R.id.page3);
ind4 = (ImageView)findViewById(R.id.page4);
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
Here's the Adapter:
/*Adapter for ViewPager*/
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter{
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch(position){
case 0:
ind1.setImageResource(on);
ind2.setImageResource(off);
ind3.setImageResource(off);
ind4.setImageResource(off);
return Frag1.newInstance();
case 1:
ind1.setImageResource(off);
ind2.setImageResource(on);
ind3.setImageResource(off);
ind4.setImageResource(off);
return Frag2.newInstance();
case 2:
ind1.setImageResource(off);
ind2.setImageResource(off);
ind3.setImageResource(on);
ind4.setImageResource(off);
return Frag3.newInstance();
case 3:
ind1.setImageResource(off);
ind2.setImageResource(off);
ind3.setImageResource(off);
ind4.setImageResource(on);
return Frag4.newInstance();
default:
ind1.setImageResource(on);
ind2.setImageResource(off);
ind3.setImageResource(off);
ind4.setImageResource(off);
return Frag1.newInstance();
}
}
#Override
public int getCount() {
return NUM_PAGES; /*NUM_PAGES = 4*/
}
}
Here's Frag1 (the other Fragments are equal to Frag1, the only differences are the layout and the loaded HTML file):
public class Frag1 extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_page_1, container, false);
WebView wv = (WebView) rootView.findViewById(R.id.webView1);
wv.loadUrl("file:///android_asset/html/tabel1.html");
wv.setBackgroundColor(0x00000000);
wv.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
return rootView;
}
public static Frag1 newInstance(){
Frag1 f = new Frag1();
return f;
}
}
The wrong behaviour is the following: when activity starts, the first fragment is displayed but the 'active' bullet point is the second, for the second page the active point is the third, for the third page is active the fourth, for the fourth page the fourth point remains active. If i swipe back to the third page the second bullet point is active.
In simple terms, the active bullet point doesn't match with the displayed page.
I tried to print the position in the Adapter, like following, under each case::
Toast.makeText(context, String.valueOf(position), Toast.LENGTH_SHORT).show();
When activity starts, are printed two consecutive message, 0 and 1, without interacting with the ViewPager.
When i change page, the position is always wrong, but the relative fragment are displayed correctly.
I tried to set the bullet point state in the fragments class, but nothing changed.
Why the adapter indicates the wrong position? How can i make that the correct bullet point indicates the right displayed page?

Reading values from Fragments in ViewPager

I have three pages in my viewpager, each page is a fragment, And I have some EditText's in each page, I third page I have a Button called SAVE, Now in this button click event I have to the values from all EditText's. I have tried many way, but none is worked, Always I am getting NullPinterException. Any help will be highly appreciable.
Thanks,
Guna.
I have a very similar set up in my current app. What I did was create a subclass of Fragment that has the method:
public abstract String[] getForm();
the getForm method essentially returns a String[] containing the string stored in each form. Each Fragment has to implement that correctly. Now once you have that, in your Activity that contains the ViewPager initialize a list of fragments that your activity's ViewPagerAdapter should use to display. That way, now when you are in the final fragment and this button is clicked (and your fragment that contains the button click successfully informs the activity that the button click event occurred), your activity will know to iterate through the whole list of fragments, calling the fragments respective getForm method implementation.
Note that this will only work if you are not using a ViewStatePagerAdapter. The reason for this is because the ViewStatePagerAdapter is not guaranteed to keep all of your fragments in memory.
Here is a code example (In the code example, I have my view pager stored in a fragment but this design would most definitely work if you were keeping your viewpager in an activity). The real work is being done in the submit method. That is where we are collecting the fields from the other fragment (Hence this method should be called in you OnButtonClickListener code):
public class CreateAccountFragment extends RestCallExecutingFragment implements ViewPager.OnPageChangeListener {
private OnAccountCreationListener onAccountCreationListener;
public static final int VARIOUS_FRAG_POS = 2;
public static final int ACCOUNT_INFO_FRAG_POS = 0;
private static final int ADDRESS_FRAG_POS = 1;
public static final int CREATE_ACCOUNT_ID = 0;
public CreateAccountFragment() {
// Required empty public constructor
}
ArrayList<FormFragment> fragmentsToDisplay;
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link android.support.v13.app.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.v13.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link android.support.v4.view.ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
#InjectView(R.id.rb_accountInfo)
RadioButton rb_accountInfo;
#InjectView(R.id.rb_address)
RadioButton rb_address;
#InjectView(R.id.rb_various)
RadioButton rb_various;
#InjectView(R.id.rg_createAccount)
RadioGroup rg_createAccount;
#InjectView(R.id.tv_pageTitle)
TextView tv_pageTitle;
List<RadioButton> radioButtons;
CreateAccountCommand createAccountCommand;
private static ArrayList<FormFragment> getCreateAccountFragments(){
ArrayList<FormFragment> list = new ArrayList<>();
list.add(AccountInfoFragment.newInstance());
list.add(AddressFragment.newInstance());
list.add(VariousFragment.newInstance());
return list;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.frag_create_account, container, false);
ButterKnife.inject(this, view);
fragmentsToDisplay = getCreateAccountFragments();
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
//todo make it easier to press the radio button
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) view.findViewById(R.id.pager);
mViewPager.setOnPageChangeListener(this);
mViewPager.setAdapter(mSectionsPagerAdapter);
return view;
}
public void submit() {
//todo move the create account button to this activity's view
AccountSubmissionRDTO createAccountSubmissionDTO;
try {
AccountInfoData accountInfoData = (AccountInfoData) fragmentsToDisplay.get(ACCOUNT_INFO_FRAG_POS).submitForm();
AddressData addressData = (AddressData) fragmentsToDisplay.get(ADDRESS_FRAG_POS).submitForm();
VariousData variousData = (VariousData) fragmentsToDisplay.get(VARIOUS_FRAG_POS).submitForm();
// createAccountSubmissionDTO = new CreateAccountSubmissionRDTO(CREATE_ACCOUNT_ID,0, -1, accountInfoData,addressData,variousData); //todo create actual server and local ids
}
/**
* A {#link android.support.v13.app.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) {
FormFragment selectedFragment = fragmentsToDisplay.get(position);
Assert.assertNotNull("the fragment selected should be within list", selectedFragment);
return selectedFragment;
}
#Override
public int getCount() {
return fragmentsToDisplay.size();
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
String pageTitle = fragmentsToDisplay.get(position).getPageTitle();
return pageTitle.toUpperCase(l);
}
}
}

Categories

Resources