So when the user swipes through each page, I want an intent to be launched at the end; to show the main activity. Right now I set the number of pages to be 4 so that when the user swipes to the 4th page, the user gets sent to my main activity. However my app crashes
Fragment activity
public class ScreenSlideActivity extends FragmentActivity {
private static final int NUM_PAGES = 4;
ViewPager mPager;
private PagerAdapter mPagerAdapter;
#Override
public void onBackPressed() {
int pos = mPager.getCurrentItem();
if (pos == 0) {
super.onBackPressed();
} else mPager.setCurrentItem(pos - 1);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_slide);
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new adapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
private class adapter extends FragmentStatePagerAdapter {
public adapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 4) {
Intent intent = new Intent(getApplication(), MainActivity.class);
startActivity(intent);
}
return ScreenSlidePageFragment.initialize(position);
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
}
fragment
public class ScreenSlidePageFragment extends Fragment {
int position;
String[] text = {"Be more productive", "Choose your own work and rest times", "Login to access full features"};
int[] images = {R.drawable.productivity, R.drawable.workingguy, R.drawable.logincmon};
public static ScreenSlidePageFragment initialize(int position) {
ScreenSlidePageFragment page = new ScreenSlidePageFragment();
Bundle args = new Bundle();
args.putInt("POSITION", position);
page.setArguments(args);
return page;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
position = getArguments().getInt("POSITION", 0);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_screen_slide_page, container, false);
TextView tv = (TextView) v.findViewById(R.id.MainText);
ImageView image = (ImageView) v.findViewById(R.id.MainImage);
tv.setText(text[position]);
image.setImageResource(images[position]);
return v;
}
}
Change the validation to start the Intent to 3, not 4.
Remember that lists start counting the indexes in 0.
#Override
public Fragment getItem(int position) {
if (position == 3) { // position 3 is the page #4
Intent intent = new Intent(getApplication(), MainActivity.class);
startActivity(intent);
finish();
}
return ScreenSlidePageFragment.initialize(position);
}
The error that you receive is that you are calling ScreenSlidePageFragment.initialize(3). In ScreenSlidePageFragment the String[] text and int[] images contains 3 elements (from index 0..2).
This will cause ArrayIndexOutOfBoundsException at runtime and crash the app.
Related
I have an Activity with 2 fragments.
Declared a ParentTabFragment in my Activity in which there is a TabLayout and a ViewPager.
There's a method in my ParentTabFragment called addPage which gets called in the Activity.
The addPage has another method called addFrag which is called from a ViewPagerAdapter creating the views in the ChildTabFragment dynamically.
There is a for loop which runs in the Activity, so the Fragments are created according to the number of items in the customList, creating the amount of tabs and pages in the Fragments.
In my ChildTabFragment I load a customList on tab selection event,
when I select a Tab in the ParentTabFragment, I call a getTabID() method from the ChildTabFragment and send the id of the Tab due to which I load the customList according to the id in the ParentTabFragment.
Problem is when I swipe or select tabs, duplicate/false data gets created in the customList.
I get the proper Id of the selected tab but when I try to pass it in the method, random id is called.
In my Activity Class:
for (int j =0;j<it.size();j++){
parentTabFragment.addPage(it.get(j).getTabMenuItem(), it.get(j).getTabMenuId() , selectedMenu);
}
ParentTabFragment:
public void addPage(String pagename, String pageId, String selectedMenu) {
Bundle bundle = new Bundle();
bundle.putString("data", pagename);
//bundle.putString("pageID", pageId);
childTabFragment = new ChildTabFragment();
childTabFragment.setArguments(bundle);
adapter.addFrag(childTabFragment, pagename, pageId);
adapter.notifyDataSetChanged();
if (selectedMenu == null) {
viewPager.setCurrentItem(0);
} else {
for (int i = 0; i < tabLayout.getTabCount(); i++) {
if (tabLayout.getTabAt(i).getText().equals(selectedMenu)) {
viewPager.setCurrentItem(i);
}
}
}
if (adapter.getCount() > 0) tabLayout.setupWithViewPager(viewPager);
setupTabLayout();
}
public void setupTabLayout() {
selectedTabPosition = viewPager.getCurrentItem();
for (int i = 0; i < tabLayout.getTabCount(); i++) {
tabLayout.getTabAt(i).setCustomView(adapter.getTabView(i));
}
}
ChildTabFragment:
public class ChildTabFragment extends Fragment {
String childname;
int menuItemId;
TextView textViewChildName, txtViewItemId;
ListView childTabMenuList;
private ArrayList<ChildTabMenu_POJO> childTabMenuPojoList = new ArrayList<>();
private ListView listView;
private ChildTabMenuAdapter childTabMenuAdapter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.child_tab_fragment, container, false);
Bundle bundle = getArguments();
childname = bundle.getString("data");
getIDs(view);
return view;
}
private void getIDs(View view) {
childTabMenuList = (ListView) view.findViewById(R.id.childTabMenuList);
loadChildMenu();
}
private void loadChildMenu(menuItemId) {
ChildTabMenu_POJO menu_pojo4 = new ChildTabMenu_POJO(String.valueOf(menuItemId), "4");
childTabMenuPojoList.add(menu_pojo4);
childTabMenuAdapter = new ChildTabMenuAdapter(childTabMenuPojoList, getActivity());
childTabMenuList.setAdapter(childTabMenuAdapter);
}
public void getTabID(int tabId) {
menuItemId = tabId;
Log.e("updatefrag", String.valueOf(menuItemId));
}
}
ViewPagerAdapter:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final ArrayList<Fragment> mFragmentList = new ArrayList<>();
private final ArrayList<Adapter_POJO> mFragmentTitleList = new ArrayList<>();
Context context;
ViewPager viewPager;
TabLayout tabLayout;
Adapter_POJO adapter_pojo;
public ViewPagerAdapter(FragmentManager manager, Context context, ViewPager viewPager,
TabLayout tabLayout) {
super(manager);
this.context = context;
this.viewPager = viewPager;
this.tabLayout = tabLayout;
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public int getItemCount() {
return mFragmentTitleList.size();
}
public void addFrag(Fragment fragment, String title, String pageId) {
mFragmentList.add(fragment);
adapter_pojo = new Adapter_POJO(title,pageId);
mFragmentTitleList.add(adapter_pojo);
}
public View getTabView(final int position) {
View view = LayoutInflater.from(context).inflate(R.layout.view_pager_adapter_layout, null);
TextView tabItemName = (TextView) view.findViewById(R.id.textViewTabItemName);
tabItemName.setText(mFragmentTitleList.get(position).adapterMenuItem);
tabItemName.setTextColor(context.getResources().getColor(android.R.color.background_light));
return view;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position).adapterMenuItem;
}
public String getPageId(int position){
return mFragmentTitleList.get(position).adapterMenuId;
}
}
If i understand your question so you need to create newInstance constructor for creating fragment with arguments
public static ChildTabFragment newInstance(int page, String title) {
FirstFragment fragmentFirst = new FirstFragment();
Bundle args = new Bundle();
args.putInt("someInt", page);
args.putString("someTitle", title);
fragmentFirst.setArguments(args);
return fragmentFirst;
}
And Store instance variables based on arguments passed in your ChildTabFragment .
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
page = getArguments().getInt("someInt", 0);
title = getArguments().getString("someTitle");
}
And now update the view in your onCreateView method
TextView tvLabel = (TextView) view.findViewById(R.id.tvLabel);
tvLabel.setText(page + " -- " + title);
And the main thing you should returns the ChildTabFragment to display for that page from your ViewPagerAdapter like this.
#Override
public Fragment getItem(int position) {
return ChildTabFragment.newInstance(position,"page "+String.valueOf(position));
}
I'm using an awesome library : Alerter. I have 3 fragments inside a ViewPager. When I display a fragment, I want to display an Alert with this library. However, the alert is not showing up the first time. When I click on a button to display a new one, the first one shuws and juste after the second one. Just like the alert was delayed until a new one is requested.
Here is the ocde I use for the Main Fragment :
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) view.findViewById(R.id.tabs);
ViewPager pager = (ViewPager) view.findViewById(R.id.pager);
final MyPagerAdapter adapter = new MyPagerAdapter(getChildFragmentManager());
pager.setAdapter(adapter);
pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
FragmentLifecycle fragmentToShow = (FragmentLifecycle) adapter.getItem(position);
fragmentToShow.onResumeFragment();
}
});
final int pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources()
.getDisplayMetrics());
pager.setPageMargin(pageMargin);
tabs.setViewPager(pager);
}
private class MyPagerAdapter extends FragmentPagerAdapter {
private final String[] TITLES = {"Cube", "Osselet", "Watch"};
private MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public Fragment getItem(int position) {
// Return Map Fragment
if (position == 0) {
return new RecordCubeFragment();
}
//Return Toilet List Fragment
else if (position == 1) {
return new RecordOsseletFragment();
}
else if (position == 2) {
return new RecordWatchFragment();
}
else {
return new RecordCubeFragment();
}
}
And there is the code of a child fragment in the ViewPager :
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Log.d(TAG, "call oncreateview");
View v = inflater.inflate(R.layout.fragment_record_cube, container, false);
lectureButton = (ImageButton) v.findViewById(R.id.lectureButton);
return v;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
Log.d(TAG, "call onview created");
super.onViewCreated(view, savedInstanceState);
lectureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Alerter.create(getActivity())
.setTitle("Warning !")
.setText("second alert.")
.setIcon(R.drawable.alert_icon)
.setBackgroundColorInt(Color.RED)
.setDuration(2000)
.show();
}
});
Alerter.create(getActivity())
.setTitle("Warning !")
.setText("first alert.")
.setIcon(R.drawable.alert_icon)
.setBackgroundColorInt(Color.RED)
.setDuration(2000)
.show();
}
Thx for the help, I know that lifeCycle of fragments is different in ViewPager, this is why I implemented an OnPageChangeListener but I cannot get rid of this problem.
I am working in a new Android project.
The first activity is using a slider menu and fragments. On the first fragment there is a list view (PrimaryFragmentDormir.java). After selecting one of the rows, a new activity is launched. This last activity uses three tabs, to show different information about the selected row object.
The listview is loaded from remote JSON files.
This is the onItemClick method at PrimaryFragmentDormir.java:
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Hotel hotelActual = (Hotel) adapter.getItem(position);
String msg = "Elegiste el hotel " + hotelActual.getNombre();
Toast.makeText(getActivity(), msg, Toast.LENGTH_LONG).show();
Intent intent = new Intent(getActivity(), Detalle_Hotel.class);
intent.putExtra("id_hotel", hotelActual.getId_hotel());
intent.putExtra("nombre_hotel", hotelActual.getId_hotel());
intent.putExtra("descripcion_hotel", hotelActual.getId_hotel());
intent.putExtra("latitud_hotel", hotelActual.getId_hotel());
intent.putExtra("longitud_hotel", hotelActual.getId_hotel());
intent.putExtra("direccion_hotel", hotelActual.getId_hotel());
intent.putExtra("web_hotel", hotelActual.getId_hotel());
intent.putExtra("tel_hotel", hotelActual.getId_hotel());
intent.putExtra("tel_reservas", hotelActual.getId_hotel());
intent.putExtra("foto_hotel", hotelActual.getId_hotel());
intent.putExtra("calificacion_hotel", hotelActual.getId_hotel());
intent.putExtra("num_estrellas", hotelActual.getId_hotel());
intent.putExtra("zona_hotel", hotelActual.getId_hotel());
intent.putExtra("facebook_hotel", hotelActual.getFacebook());
intent.putExtra("twitter_hotel", hotelActual.getTwitter());
startActivity(intent);
}
The Toast is shown and the activity Detalle_Hotel is shown also.
Detalle_Hotel has three tabs.
What I need is to get the values from hotelActual in the three tabs, in order to work with them separately.
This is Detalle_Hotel activity:
public class Detalle_Hotel extends AppCompatActivity {
// Declaring Your View and Variables
private String nombre_hotel, foto_hotel, descripcion_hotel,direccion_hotel,web_hotel,tel_hotel,tel_reservas,zona_hotel,facebook_hotel,twitter_hotel;
private int num_estrellas_hotel, id_hotel;
private double calificacion_hotel,latitud_hotel,longitud_hotel;
Toolbar toolbar;
ViewPager pager;
ViewPagerAdapter adapter;
SlidingTabLayout tabs;
CharSequence Titles[]={"Info","Mapa","OpiniĆ³n"};
int Numboftabs =3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detalle__hotel);
nombre_hotel = getIntent().getStringExtra("nombre_hotel");
// Creating The Toolbar and setting it as the Toolbar for the activity
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
// Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
adapter = new ViewPagerAdapter(getSupportFragmentManager(),Titles,Numboftabs);
// Assigning ViewPager View and setting the adapter
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
// Assiging the Sliding Tab Layout View
tabs = (SlidingTabLayout) findViewById(R.id.tabs);
tabs.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width
// Setting Custom Color for the Scroll bar indicator of the Tab View
tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.rojomodesto);
}
});
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);
}
}
Here I received the value from nombre_hotel (as test for the other values), and now how can I pass it to the tabs?
Here is tab1 code:
public class Tab1 extends Fragment {
private TextView hotel_nombre;
private String nombre_hotel;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_1,container,false);
return v;
}
#Override
public void onActivityCreated(Bundle state) {
super.onActivityCreated(state);
hotel_nombre = (TextView) getView().findViewById(R.id.nombre_hotel);
hotel_nombre.setText(getActivity().nombre_hotel));
}
}
The line hotel_nombre.setText(getActivity().nombre_hotel)); shows a warning at the second nombre_hotel: "Cannot resolve symbol 'nombre_hotel'.
Any help is welcome.
EDIT:
ViewPageAdapter.java
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
CharSequence Titles[]; // This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
int NumbOfTabs; // Store the number of tabs, this will also be passed when the ViewPagerAdapter is created
// Build a Constructor and assign the passed Values to appropriate values in the class
public ViewPagerAdapter(FragmentManager fm, CharSequence mTitles[], int mNumbOfTabsumb) {
super(fm);
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabsumb;
}
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
if (position == 0) // if the position is 0 we are returning the First tab
{
Tab1 tab1 = new Tab1();
return tab1;
}
if (position == 1) // if the position is 0 we are returning the First tab
{
Tab2 tab2 = new Tab2();
return tab2;
}
if (position == 2) // if the position is 0 we are returning the First tab
{
Tab3 tab3 = new Tab3();
return tab3;
}
return null;
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return Titles[position];
}
// This method return the Number of tabs for the tabs Strip
#Override
public int getCount() {
return NumbOfTabs;
}
}
In your adapter you need to initialize it properly now (with string as argument).
public class Tab1 extends Fragment {
private static final String HOTEL = "hotel";
private TextView hotel_nombre;
private String nombre_hotel;
public static Tab1 newInstance(String s) {
Tab1 result = new Tab1();
Bundle bundle = new Bundle();
bundle.putString(HOTEL, s);
result.setArguments(bundle);
return result;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = this.getArguments();
nombre_hotel = bundle.getString(HOTEL);
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_1,container,false);
return v;
}
#Override
public void onActivityCreated(Bundle state) {
super.onActivityCreated(state);
hotel_nombre = (TextView) getView().findViewById(R.id.nombre_hotel);
hotel_nombre.setText(nombre_hotel);
}
}
EDIT:
Change your in your Detalle_Hotel Activity, adapter to:
adapter = new ViewPagerAdapter(getSupportFragmentManager(),Titles,Numboftabs,nombre_hotel);
And then in adapter:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
CharSequence Titles[]; // This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
int NumbOfTabs; // Store the number of tabs, this will also be passed when the ViewPagerAdapter is created
private String hotelNumbre;
// Build a Constructor and assign the passed Values to appropriate values in the class
public ViewPagerAdapter(FragmentManager fm, CharSequence mTitles[], int mNumbOfTabsumb, String hotelNum) {
super(fm);
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabsumb;
this.hotelNumbre = hotelNum;
}
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
if (position == 0) // if the position is 0 we are returning the First tab
{
return Tab1.newInstance(hotelNumbre);
}
if (position == 1) // if the position is 0 we are returning the First tab
{
Tab2 tab2 = new Tab2();
return tab2;
}
if (position == 2) // if the position is 0 we are returning the First tab
{
Tab3 tab3 = new Tab3();
return tab3;
}
return null;
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return Titles[position];
}
// This method return the Number of tabs for the tabs Strip
#Override
public int getCount() {
return NumbOfTabs;
}
}
You need to make nombre_hotel field public instead of private, then use:
hotel_nombre.setText((Detalle_Hotel)getActivity().nombre_hotel));
val intent = Intent(activity, VoiceCommandServiceActivity::class.java)
intent.putExtra(SELECT_SERVICES, mServiceName as Serializable)
startActivity(activity, intent)
intent?.let {
it.extras?.let { extras ->
extras?.let { bundle ->
if (bundle.containsKey(SELECT_SERVICES)) {
val service = extras.getSerializable(SELECT_SERVICES) as MutableList<AppServiceModel>
}
}
}
}
I created a ViewPager that uses individual Fragments. There are 3, here is an example of one of them:
public class PainFragment extends Fragment {
private TextView mTxtScale;
private Button mBtnMinus;
private Button mBtnPlus;
private int mScale;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_pain, container, false);
mTxtScale = (TextView)v.findViewById(R.id.scale);
mBtnMinus = (Button)v.findViewById(R.id.minus);
mBtnPlus = (Button)v.findViewById(R.id.plus);
mScale = Integer.valueOf(mTxtScale.getText().toString());
mBtnMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mScale--;
if(mScale == -1) {
mScale = 9;
}
mTxtScale.setText(String.valueOf(mScale));
}
});
mBtnPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mScale++;
if(mScale == 10) {
mScale = 0;
}
mTxtScale.setText(String.valueOf(mScale));
}
});
return v;
}
public static PainFragment newInstance(String text) {
PainFragment f = new PainFragment();
Bundle b = new Bundle();
//b.putString("msg", text);
f.setArguments(b);
return f;
}
public int getScale() {
int scale = Integer.valueOf(mTxtScale.getText().toString());
return scale;
}
And I instantiated the ViewPager in my MainFragment:
public class MainFragment extends Fragment {
Entry mEntry = new Entry();
ViewPager mPager;
JournalPagerAdapter mAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main_screen, container, false);
mPager = (ViewPager)rootView.findViewById(R.id.pager);
mPager.setOffscreenPageLimit(2); // So all 3 pages are loaded at once.
mAdapter = new JournalPagerAdapter(getActivity().getSupportFragmentManager());
mPager.setAdapter(mAdapter);
...
I have button click listeners in the ViewPager Fragments. I would like to know the best way to set up a listener so that my main fragment can detect when a button is pressed on one of the ViewPager fragments.
/** Update - Here is my adapter class **/
public class JournalPagerAdapter extends FragmentPagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public JournalPagerAdapter(FragmentManager mgr) {
super(mgr);
}
#Override
public Fragment getItem(int pos) {
switch(pos) {
case 0: return PainFragment.newInstance("PainFragment");
case 1: return StressFragment.newInstance("StressFragment");
case 2: return SleepFragment.newInstance("SleepFragment");
default: return PainFragment.newInstance("PainFragment");
}
}
#Override
public int getCount() {
return 3;
}
/* Thanks to Streets of Boston (http://stackoverflow.com/questions/8785221/retrieve-a-fragment-from-a-viewpager)
* for the next 3 methods, should include in all PagerAdapters. Let's you get the fragment instances by position */
#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 getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
Second answer with pseudo example of using a ClickListener instead of the Callback. This should let you keep all logic out of the Activity.
Implement OnClickListener interface in MainFragment. Add a OnClickListener to your JournalPagerAdapter constructor. Presumably the Adapter is creating the PainFragments. Add OnClickListener to PainFragment newInstance and have the Adapter provide it when it creates each PainFragment.
public class PainFragment extends Fragment {
private TextView mTxtScale;
private Button mBtnMinus;
private Button mBtnPlus;
private int mScale;
protected OnClickListener mainClickListener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_pain, container, false);
mTxtScale = (TextView)v.findViewById(R.id.scale);
mBtnMinus = (Button)v.findViewById(R.id.minus);
mBtnPlus = (Button)v.findViewById(R.id.plus);
mScale = Integer.valueOf(mTxtScale.getText().toString());
mBtnMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mScale--;
if(mScale == -1) {
mScale = 9;
}
mTxtScale.setText(String.valueOf(mScale));
mainClickListener.onClick(view);
}
});
mBtnPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mScale++;
if(mScale == 10) {
mScale = 0;
}
mTxtScale.setText(String.valueOf(mScale));
mainClickListener.onClick(view);
}
});
return v;
}
public static PainFragment newInstance(String text, OnClickListener onClickListener) {
PainFragment f = new PainFragment();
f.mainClickListener = onClickListener;
Bundle b = new Bundle();
//b.putString("msg", text);
f.setArguments(b);
return f;
}
public int getScale() {
public class MainFragment extends Fragment implements OnClickListener {
Entry mEntry = new Entry();
ViewPager mPager;
JournalPagerAdapter mAdapter;
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main_screen, container, false);
mPager = (ViewPager)rootView.findViewById(R.id.pager);
mPager.setOffscreenPageLimit(2); // So all 3 pages are loaded at once.
mAdapter = new JournalPagerAdapter(getActivity().getSupportFragmentManager(), this);
mPager.setAdapter(mAdapter);
...
public class JournalPagerAdapter extends FragmentPagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
private OnClickListener mOnClickListener;
public JournalPagerAdapter(FragmentManager mgr, OnClickListener onClickListener) {
super(mgr);
mOnClickListener = onClickListener;
}
#Override
public Fragment getItem(int pos) {
switch(pos) {
case 0: return PainFragment.newInstance("PainFragment", mOnClickListener);
case 1: return StressFragment.newInstance("StressFragment", mOnClickListener);
case 2: return SleepFragment.newInstance("SleepFragment", mOnClickListener);
default: return PainFragment.newInstance("PainFragment", mOnClickListener);
}
}
...
The proper way to achieve this is probably through the use of a callback. Your fragment would utilize a normal click listener which would then use a callback to communicate back to the hosting Activity.
See the Android docs regarding communicating from a Fragment back to the Activity; then the Activity can communicate it to other Fragments.
http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
In some cases, you might need a fragment to share events with the activity. A good way to do that is to define a callback interface inside the fragment and require that the host activity implement it. When the activity receives a callback through the interface, it can share the information with other fragments in the layout as necessary.
I'm using FragmentPagerAdapter with FragmentActivity to create swipe-able Fragments.
My first fragment in that pagerAdapter look like this.
public class MySummaryFragment extends CommonFragment implements OnPageChangeListener
{
private Context mContext;
private View mMyView;
LinearLayout mDetailLayout;
TextView mDateTxtView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
System.out.println("onCreateView() Market summary");
mMyView = inflater.inflate(R.layout.my_page_summary_fragment_layout, container,false);
mDetailLayout = (LinearLayout)mMyView.findViewById(R.id.SummaryDetailLayout);
mDateTxtView = (TextView) mMyView.findViewById(R.id.txtDate);
Account_Id = AccountDetails.getInstance(mContext).getClientCodes().get(0);
sendRequest(Account_Id);
return mMyView;
}
#Override
public void onPageSelected(int arg0) {
System.out.println("inside onPageScrollStateChanged()");
System.out.println("mMyView is null ? = "+(mMyView==null));
mDateTxtView = (TextView) mMyView.findViewById(R.id.txtMarketSummaryDate);
Account_Id = AccountDetails.getInstance(mContext).getClientCodes().get(0);
mDateTxtView.setText("");
sendRequest(Account_Id);
}
}
The problem here is I'm getting NullPointerException when swipe-out to 5-6 fragments and swiping back to first fragment.
When I try to debug, I found that
mMyView is null ? = true
Why so?
Please help me.
Here is my Fragment contains the FragmentPagerAdapter,
public class MyPageDetailViewFragment extends CommonFragment {
private View mView;
Context mContext;
OnPageChangeListener pageChangeListener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.my_page_fragments, null);
mContext = getActivity();
setHasOptionsMenu(false);
setupSearchBarComponent();
PagerTabStrip pagerTabStrip = (PagerTabStrip)mView. findViewById(R.id.pager_title_strip);
pagerTabStrip.setDrawFullUnderline(true);
pagerTabStrip.setTabIndicatorColor(Color.BLACK);
/** Getting a reference to the ViewPager defined the layout file */
ViewPager pager = (ViewPager) mView.findViewById(R.id.pager);
/** Getting fragment manager */
FragmentManager fm = ((HomeScreenActivity)mContext).getSupportFragmentManager();
/** Instantiating FragmentPagerAdapter */
final MyFragmentPagerAdapter pagerAdapter = new MyFragmentPagerAdapter(fm);
pager.setAdapter(pagerAdapter);
pager.setCurrentItem(0);
pageChangeListener = new OnPageChangeListener() {
#Override
public void onPageSelected(int selectedIndex) {
System.out.println("selectedIndex = "+selectedIndex);
Object page = pagerAdapter.getItem(selectedIndex);
if( page instanceof OnPageChangeListener){
((OnPageChangeListener) page).onPageSelected(selectedIndex);
}
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
};
pager.setOnPageChangeListener(pageChangeListener);
return mView;
// return super.onCreateView(inflater, container, savedInstanceState);
}
And here is my implementation MyFragmentPagerAdapter,
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
/** Constructor of the class */
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
/** This method will be invoked when a page is requested to create */
#Override
public Fragment getItem(int index) {
System.out.println("getItem = "+index);
Bundle data = new Bundle();
data.putInt("current_page", index + 1);
CommonFragment fragment = getFragment(index);
fragment.setArguments(data);
return fragment;
}
public CommonFragment getFragment(int index) {
CommonFragment fragment = null;
if(fragment == null){
if(index == 0){
fragment = new MySummaryFragment();
}else if(index == 1){
fragment = new FragmentOne();
}else if(index == 4){
fragment = new FragmentFour();
}else if(index == 5){
fragment = new FragmentFive();
}else{
fragment = new MyFragment();
}
}
return fragment;
}
/** Returns the number of pages */
#Override
public int getCount() {
return titles.length;
}
#Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
}
pagerAdapter.getItem(selectedIndex) actually creates a new instance of the fragment.
See this answer: https://stackoverflow.com/a/23843743/1271907
You have to keep a reference to the actual fragment.
It looks like you are calling the wrong method on the inflater.
Try to change this line:
mView = inflater.inflate(R.layout.my_page_fragments, null);
to:
mView = inflater.inflate(R.layout.my_page_fragments,container, null);