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();
}
}
Related
I have an Android tabs with 3 fragments and a FAB. I want to replace to a new fragment when click the FAB but when i click the button it replace with a blank fragment. And when i click on my tabs, it doesn't show its fragment but an empty fragment instead (sometimes it show right but i don't know when)
Here is my MainActivity:
public class MainActivity extends AppCompatActivity {
/**
* The {#link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
private TabLayout tabLayout;
private FloatingActionButton fabAdd;
FragmentManager manager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) findViewById(R.id.container);
PageAdapter pageAdapter = new PageAdapter(getSupportFragmentManager());
pageAdapter.addFragment(new Wallet(), "Wallet");
pageAdapter.addFragment(new History(),"History");
pageAdapter.addFragment(new Setting(),"Setting");
mViewPager.setAdapter(pageAdapter);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
fabAdd = (FloatingActionButton) findViewById(R.id.fabAdd);
manager = getSupportFragmentManager();
fabAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AddAccount addAccount = new AddAccount();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.container,addAccount);
transaction.commit();
}
});
}
}
And here is my adapter:
public class AccountAdapter extends BaseAdapter {
private Context context;
private int layout;
private List<Account> accountList;
public AccountAdapter(Context context, int layout, List<Account> accountList) {
this.context = context;
this.layout = layout;
this.accountList = accountList;
}
#Override
public int getCount() {
return accountList.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(layout,null);
TextView accountName = (TextView) view.findViewById(R.id.tvAccount);
TextView accountAddress = (TextView) view.findViewById(R.id.tvAddress);
Account account = accountList.get(i);
accountName.setText(account.getAccountName());
accountAddress.setText(account.getAccountAddress());
return view;
}
}
Here is one of my Fragments (the other is same):
public class AddAccount extends Fragment {
public AddAccount() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.add_account,container,false);
}
}
I'm new to Android and not good English, so forgive me if i make grammar mistake.
Edit: Is there any way to show a new fragment to a viewpager?
Use this code inside onClick
Fragment fragment = new AddAccount();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container, fragment);
ft.commit();
and use this for your adapter
class AccountAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
I want to want to make ViewPager with each tab containing three fragments. FragmentPagerAdapter only works for one fragment, so I tried my best to make my own custom adapter extending PagerAdapter. Unfortunately, the code I wrote only displays these three Fragments in the first tab and after restarting the app all tabs are blank. I suspect that it has something to do with onSaveInstanceState, but I don't know how to make it properly. Also, I've read that I shouldn't add the fragments to FragmentTransaction in instantiateItem, but I don't know where else I could do it. Could you help me ?
TaskListPagerActivity:
public class TaskListPagerActivity extends AppCompatActivity implements BottomPanelFragment.OnBottomPanelSelectedListener {
private static final String TAG = "TaskListPagerActivity";
private ViewPager mViewPager;
FragmentStacker[] mStacker;
public static Intent newInstance(Context packageContext) {
Intent intent = new Intent(packageContext, TaskListPagerActivity.class);
return intent;
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_task_list_pager);
mStacker = new FragmentStacker[7];
mViewPager = (ViewPager) findViewById(R.id.activity_task_list_pager);
mViewPager.setAdapter(new TaskListPagerAdapter(this));
}
// Interface methods
private class TaskListPagerAdapter extends PagerAdapter {
private FragmentActivity mContext;
public TaskListPagerAdapter(FragmentActivity context) {
mContext = context;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment res;
FragmentManager fm = mContext.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
if (mStacker[position] == null) {
mStacker[position] = new FragmentStacker();
ft.add(container.getId(), mStacker[position]);
} else {
ft.attach(mStacker[position]);
}
res = mStacker[position];
ft.commit();
return res;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
#Override
public int getCount() {
return 7;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return ((Fragment) object).getView()==view;
}
}}
FragmentStacker:
public class FragmentStacker extends Fragment {
Fragment[] fragments = createFragments();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.task_list_activity_fragment, container, false);
FragmentManager fm = getFragmentManager();
Fragment customDateFragment = fm.findFragmentById(R.id.custom_date_fragment_container);
Fragment taskListFragment = fm.findFragmentById(R.id.task_list_fragment_container);
Fragment bottomPanelFragment = fm.findFragmentById(R.id.bottom_panel_container);
FragmentTransaction fragmentTransaction = fm.beginTransaction();
if (customDateFragment == null) {
customDateFragment = fragments[0];
taskListFragment = fragments[1];
bottomPanelFragment = fragments[2];
fragmentTransaction.add(R.id.custom_date_fragment_container, customDateFragment);
fragmentTransaction.add(R.id.task_list_fragment_container, taskListFragment);
fragmentTransaction.add(R.id.bottom_panel_container, bottomPanelFragment);
fragmentTransaction.commit();
} else {
fragmentTransaction.attach(customDateFragment);
fragmentTransaction.attach(taskListFragment);
fragmentTransaction.attach(bottomPanelFragment);
}
return v;
}
private Fragment[] createFragments() {
return new Fragment[]{new CustomDateFragment(), new TaskListFragment(), new BottomPanelFragment()};
}}
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);
});
I am trying to swipe item(from listview) in my detail activity using viewpager.
I have 20 items in my listview (data parsed from json) Instead of swiping the next/previous item , It's only the same item that I swipe (20 times).
here is my DetailActivity.
public class DetailsActivity extends FragmentActivity {
Article feed;
int pos;
private DescAdapter adapter;
private ViewPager pager;
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.item_details);
pos = getIntent().getExtras().getInt("pos");
adapter = new DescAdapter(getSupportFragmentManager());
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
pager.setCurrentItem(pos);
}
public class DescAdapter extends FragmentStatePagerAdapter {
public DescAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 20;
}
public Fragment getItem(int position) {
return DetailFragment.newInstance(position);
}
}
And my detailFragment
public class DetailFragment extends Fragment {
static DetailFragment newInstance(int position) {
DetailFragment f = new DetailFragment();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.detail_fragment, container, false);
String displaytitle= getActivity().getIntent().getStringExtra("title");
TextView titleF = (TextView)view.findViewById(R.id.title);
titleF.setText(displaytitle);
...
return view;
}
What am I doing wrong?
You are not using the correct argument:
You send the argument "pos2" but you retrieve the argument "title".
#Override
public Fragment getItem(int position) {
DetailFragment frag = new DetailFragment();
Bundle bundle = new Bundle();
bundle.putInt("fPos",position);
frag.setArguments(bundle);
return frag;
}
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!