I am creating swipe screens using ViewPager where i have two fragments to show using swipes inside FragmentActivity .Please consider the following code :
Fragment_One.java
public class Fragment_One extends Fragment {
private Button btnNext;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_one,null);
btnNext = (Button) v.findViewById(R.id.btnNext);
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment = new Fragment_Two();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmentOne,fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return v;
}
}
2.Fragment_Two.java
public class Fragment_Two extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_two,null);
}
}
3. PagerAdapter.java
public class PagerAdapter extends FragmentPagerAdapter {
List<Fragment> listFragments ;
public PagerAdapter(FragmentManager fm,List<Fragment> listFragments) {
super(fm);
this.listFragments = listFragments;
}
#Override
public Fragment getItem(int i) {
return listFragments.get(i);
}
#Override
public int getCount() {
return listFragments.size();
}
}
4.MainActivity.java
public class MainActivity extends FragmentActivity{
private List<Fragment> listFragments;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
Fragment_One fragment_one = new Fragment_One();
Fragment_Two fragment_two = new Fragment_Two();
listFragments = new ArrayList<>();
listFragments.add(fragment_one);
listFragments.add(fragment_two);
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager(),listFragments);
viewPager.setAdapter(pagerAdapter);
}
}
The above mentioned code is working fine while swiping screens .But i click on next button ,fragment is replaced with another but is displayed on the same screen.I am not able to fix the issue.Screenshot is given below :
Next button should work in the same way as we swipe the screen .Please help me to fix the issue.
Wouldn't that be easier to use:
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
viewPager .setCurrentItem(viewPage.getCurrentItem() + 1);
});
Related
I created two fragments: 'scheduleFragment' and 'clockFragment'. After setting up
public class ClockFragment extends AppCompatActivity implements View.OnClickListener {
private int notificationId = 1;
in MainActivity.java, the pageAdapter
scheduleFragment = new ScheduleFragment();
clockFragment = new ClockFragment();
tabLayout.setupWithViewPager(viewPager);
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), 0);
viewPagerAdapter.addFragment(clockFragment, "Clock");
viewPagerAdapter.addFragment(scheduleFragment, "Schedule");
viewPager.setAdapter(viewPagerAdapter);
creates an error that states I have to switch refactor the clockFragment into the scheduleFragment so one fragment is created.
I need these two fragments because, in the ClockFragment (tab), the clock must appear to users and on the ScheduleFragment (tab), the schedule of users is present. I am not sure how I can separate the two tabs without causing an error.
Some explanation over why this error occurs and a solution will be greatly appreciated.
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private ViewPager viewPager;
private TabLayout tabLayout;
private ScheduleFragment scheduleFragment;
private ClockFragment clockFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
viewPager = findViewById(R.id.view_pager);
tabLayout = findViewById(R.id.tab_layout);
scheduleFragment = new ScheduleFragment();
clockFragment = new ClockFragment();
tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(0).setIcon(R.drawable.ic_baseline_add_alarm_24);
tabLayout.getTabAt(1).setIcon(R.drawable.ic_baseline_assignment_turned_in_24);
}
private class ViewPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments = new ArrayList<>();
private List<String> fragmentTitle = new ArrayList<>();
public ViewPagerAdapter(#NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
}
public ViewPagerAdapter(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
public void addFragment(ClockFragment fragment, String title) {
fragments.add(fragment);
fragmentTitle.add(title);
}
#NonNull
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return fragmentTitle.get(position);
}
}
}
First ClockFragment extends Activity which means it is not a fragment.
I will give you an example of how you should do things:
public class ChildFragment1 extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(R.layout.child_fragment_1_layout, container, false);
Button buttonInFragment1 = rootView.findViewById(R.id.button_1);
buttonInFragment1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getContext(), "button in fragment 1", Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
}
Now do Fragment 2:
public class ChildFragment2 extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(R.layout.child_fragment_1_layout, container, false);
Button buttonInFragment1 = rootView.findViewById(R.id.button_1);
buttonInFragment1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getContext(), "button in fragment 2", Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
}
Now add a new class for the adapter:
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
return new ChildFragment1(); //ChildFragment1 at position 0
case 1:
return new ChildFragment2(); //ChildFragment2 at position 1
}
return null; //does not happen
}
#Override
public int getCount() {
return 2; //three fragments
}
}
And your MainActivity would look something like this:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
}
}
I'm trying to open a new fragment in viewpager's fragment using this as example. But I'm getting this error of IndexOutOfBoundsException in the line tabLayout.getTabAt(0).setIcon(tabIcons[0]);. I pasted the logcate here. Can any one tell me how to solve this as I need tablayout with my viewpager while the example didn't had one?
public class FirstFragment extends Fragment {
private static final String TAG = "FirstFragment";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.first_fragment, container, false);
Button btn = (Button) view.findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction trans = getFragmentManager()
.beginTransaction();
/*
* IMPORTANT: We use the "root frame" defined in
* "root_fragment.xml" as the reference to replace fragment
*/
trans.replace(R.id.root_frame, new SecondFragment());
/*
* IMPORTANT: The following lines allow us to add the fragment
* to the stack and return to it later, by pressing back
*/
trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
trans.addToBackStack(null);
trans.commit();
}
});
return view;
}
}
First tab:
public class RootFragment extends Fragment {
private static final String TAG = "RootFragment";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
/* Inflate the layout for this fragment */
View view = inflater.inflate(R.layout.root_fragment, container, false);
FragmentTransaction transaction = getFragmentManager()
.beginTransaction();
/*
* When this container fragment is created, we fill it with our first
* "real" fragment
*/
transaction.replace(R.id.root_frame, new FirstFragment());
transaction.commit();
return view;
}
}
Main Activity:
public class MainActivity extends AppCompatActivity {
// For this example, only two pages
static final int NUM_ITEMS = 2;
private TabLayout tabLayout;
private ViewPager mPager;
private int[] tabIcons = {
R.drawable.facebook,
R.drawable.twitter
};
SlidePagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Instantiate a ViewPager and a PagerAdapter. */
tabLayout=(TabLayout)findViewById(R.id.tabs);
mPager = (ViewPager) findViewById(R.id.viewpager);
mPagerAdapter = new SlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
setupTabIcons();
}
private void setupTabIcons() {
tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
}
/* PagerAdapter class */
public class SlidePagerAdapter extends FragmentPagerAdapter {
public SlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
/*
* IMPORTANT: This is the point. We create a RootFragment acting as
* a container for other fragments
*/
if (position == 0)
return new RootFragment();
else
return new StaticFragment();
}
#Override
public int getCount() {
return NUM_ITEMS;
}
}
}
use below function
private void setupTabIcons() {
tabLayout.addTab(tabLayout.newTab().setIcon(tabIcons[0]));
tabLayout.addTab(tabLayout.newTab().setIcon(tabIcons[1]));
}
you have not added any tab to your tabLayout, so you get IndexOutOfBoundsException
My ViewPager is not working correctly. I don't know what's wrong with my code. I am facing some problems with my Fragments:
Basically, I have a Fragment named MyListFragment that has a list and on the click event of list item I move to the second Fragment named FlowersFragment that has a ViewPager with three items(Another three Fragments) in it. And i have a Button in my FlowersFragment and on click of that Button i move to the third screen named WelcomeFragment. now i have a problem :
If i go back to FlowersFragment from WelcomeFragment then it loses some Fragments from ViewPager after some research i got a solution like use childFragmentManager while creating adapter. That is good for my pager all Fragments are now showing correctly in my FlowersFragment Pager. But if I go back to MyListFragment and I click on second or third item of ListFragment its showing me exception with NO ACTIVITY.
Here is my FirstFragment named MyListFragment
public class MyListFragment extends Fragment{
private View view;
private FragmentManager fm;
private FragmentTransaction ft;
private ListView listviewPlaces;
private FloristAdapter adapter;
private ArrayList<FloristItems> items = new ArrayList<FloristItems>();
private FlowersFragment frag;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflater = LayoutInflater.from(getActivity());
view = inflater.inflate(R.layout.fragment_list, container,false);
listviewPlaces = (ListView)view.findViewById(R.id.listviewPlaces);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
for (int i = 0; i < 10; i++) {
FloristItems florist = new FloristItems();
florist.away = "3 miles away";
florist.title = "Florist Flowers";
florist.price = "$45";
items.add(florist);
}
adapter = new FloristAdapter(getActivity().getApplicationContext(), items);
listviewPlaces.setAdapter(adapter);
listviewPlaces.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if(frag == null){
frag = new FlowersFragment();
}
handleFragments(frag);
}
});
}
private void handleFragments(Fragment fragment){
fm = getActivity().getSupportFragmentManager();
ft = fm.beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.addToBackStack(null);
ft.commit();
}
}
Here is my FlowersFragment class that have view pager with containing three fragments:
public class FlowersFragment extends Fragment{
private View view;
private FragmentManager fm;
private FragmentTransaction ft;
private ViewPager pager;
private Button btnSendThatFlower;
private FlowerPagerAdapter pageAdapter;
private WelcomeFragment welcomeFrag;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflater = LayoutInflater.from(getActivity());
view = inflater.inflate(R.layout.fragment_choose_flower_buyer, container,false);
pager = (ViewPager)view.findViewById(R.id.viewpager);
btnSendThatFlower = (Button)view.findViewById(R.id.btnSendThatFlower);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
pageAdapter = new FlowerPagerAdapter(getActivity().getSupportFragmentManager());
pager.setAdapter(pageAdapter);
btnSendThatFlower.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(welcomeFrag == null){
welcomeFrag = new WelcomeFragment();
}
handleFragments(welcomeFrag);
}
});
}
private void handleFragments(Fragment fragment){
fm = getActivity().getSupportFragmentManager();
ft = fm.beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.addToBackStack(null);
ft.commit();
} }
Here is my pager Adapter class:
public class FlowerPagerAdapter extends FragmentPagerAdapter{
private ArrayList<Fragment> pagerItems;
public FlowerPagerAdapter(FragmentManager fm) {
super(fm);
pagerItems = new ArrayList<Fragment>();
pagerItems.add(FlowerImage1.getInstance());
pagerItems.add(FlowerImage2.getInstance());
pagerItems.add(CustomFlowerFragment.getInstance());
}
#Override
public Fragment getItem(int num) {
if (num == 0) {
return new FlowerImage1();
}
else if(num == 1) {
return new FlowerImage2();
}
else{
return new CustomFlowerFragment.getInstance();
}
}
#Override
public int getCount() {
return pagerItems.size();
}
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
//super.restoreState(state, loader);
}}
FlowerImage1 FlowerImage1 CustomFlowerFragment are fragments with only imageview.
This is my last fragment WelcomeFragment
public class WelcomeFragment extends Fragment{
private View view;
private FragmentManager fm;
private FragmentTransaction ft;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflater = LayoutInflater.from(getActivity());
view = inflater.inflate(R.layout.fragment_write_note_buyer, container,false);
return view;
}}
when i am pressing back press then its not showing fragments in viewpager but after swipe on view pager its showing only first or sometimes last pager fragment.
I have also faced same issue ended up adding following code inside fragment adapter.
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
//super.restoreState(state, loader);
}
I was also faced with the same problem, but i fixed it by extending "FragmentStatePagerAdapter" instead of FragmentPagerAdapter. for your case,it would be:
public class FlowerPagerAdapter extends FragmentStatePagerAdapter{
private ArrayList<Fragment> pagerItems;
public FlowerPagerAdapter(FragmentManager fm) {
super(fm);
pagerItems = new ArrayList<Fragment>();
pagerItems.add(FlowerImage1.getInstance());
pagerItems.add(FlowerImage2.getInstance());
pagerItems.add(CustomFlowerFragment.getInstance());
}
#Override
public Fragment getItem(int num) {
if (num == 0) {
return new FlowerImage1();
}
else if(num == 1) {
return new FlowerImage2();
}
else{
return new CustomFlowerFragment.getInstance();
}
}
#Override
public int getCount() {
return pagerItems.size();
}
}
Here's my setup: I have MainActivity which has the following code:
public class MainActivity extends FragmentActivity {
FragmentList listFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
listFragment = new FragmentList();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.list_container, listFragment);
fragmentTransaction.commit();
}
}
I then have FragmentList, which is a ListView fragment and FragmentDetail, which is the fragment displayed when selecting a particular ListView row.
Here's a snippet of the FragmentList code:
public class FragmentList extends Fragment {
private ListView list;
private FragmentDetail detailFragment;
private long detailId;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// ListView gets set via an adapter
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
detailId = id;
mPager = (ViewPager)getActivity().findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
mPager.setAdapter(mPagerAdapter);
final FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.list_container, detailFragment);
fragmentTransaction.commit();
}
});
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
detailFragment = new FragmentDetail();
Bundle mBundle = new Bundle();
mBundle.putLong("detailId", detailId);
detailFragment.setArguments(mBundle);
return detailFragment;
}
#Override
public int getCount() {
return 5;
}
}
}
And FragmentDetail:
public class FragmentDetail extends Fragment {
private long id;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.activity_view, container, false);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Bundle bundle = getArguments();
id = bundle.getLong("detailId");
// Set views based on id
}
}
Here are my issues:
The line fragmentTransaction.replace(R.id.list_container, detailFragment); in FragmentList errors out saying that I cannot change ID of container. Why is that?
After I comment the line in issue #1 out, the detail fragment loads fine and lets me swipe. However, only one of the detail fragment pages contains any data; the rest are blank. How can I implement the following: say my ListView contains "iOS", "Android", "Windows" rows. When I click on "iOS", it brings up details fragment for iOS. When I swipe to the left, I want "Android" detail fragment to show up; then when I swipe again, "Windows" detail fragment, etc.
Thanks!
I have a viewpager with 2 pages, on each fragment i put a button to switching fragment,
but if i change orientation switching doesn't work.
For switching fragment I using my OnChangePageButtonClick interface
Why is this happening?
ViewPager Activity:
public class ViewPagerMusic extends FragmentActivity implements OnChangePageButtonClick {
private ViewPager vp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_pager_music);
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(super.getSupportFragmentManager(), fragments);
vp = (ViewPager)findViewById(R.id.viewpager);
vp.setAdapter(viewPagerAdapter);
}
private class ViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
MainPage mainPage = new MainPage();
mainPage.setOnChengeButtonListener(ViewPagerMusic.this);
return mainPage;
case 1:
PlaylistPage playlistPage = new PlaylistPage();
playlistPage.setOnChengeButtonListener(ViewPagerMusic.this);
return playlistPage;
}
return null;
}
#Override
public int getCount() {
return 2;
}
}
#Override
public void selectPage(int page) {
vp.setCurrentItem(page);
}
}
my Frgamnets:
public class MainPage extends Fragment {
public MainPage() {
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.music_main_page, container, false);
ImageButton btnPlaylist = (ImageButton)v.findViewById(R.id.btnGoPlaylist2);
btnPlaylist.setOnClickListener(onButtonListener);
return v;
}
private OnClickListener onButtonListener = new OnClickListener() {
#Override
public void onClick(View view) {
onChangePageButtonClick.selectPage(1);
}
};
public void setOnBackButtonListener(OnChangePageButtonClick onChangePageButtonClick) {
this.onChangePageButtonClick = onChangePageButtonClick;
}
private OnChangePageButtonClick onChangePageButtonClick;
}
Playlist fragment is similar to MainPage fragment.
Your fragments are storing a reference to the ViewPagerMusic activity. However, after rotation, the activity is destroyed and recreated, so the fragments now contain a reference to the old activity.
Instead of storing a reference to the activity, you can call the activity's method from the fragment like this:
((ViewPagerMusic) getActivity()).selectPage(1);
just create this method in your view pager
#Override
public void selectPage(int page) {
vp.setCurrentItem(page);
}
and then call this in your onclick method
((ViewPagerMusic) getActivity()).selectPage(1);