I have a viewpager which has 10 fragments.
when i swipe back to 2nd fragment from 9th fragment, textview's content is getting trimmed as shown in below image!
It is only showing first letter of all textviews.
What's the issue?
Code ViewPagerAdapter:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
ArrayList<String> arrayList;
int baseId = 0;
public ArrayList<Fragment> fragmentList = new ArrayList<>();
Bundle bundle = new Bundle();
public int fid;
public ViewPagerAdapter(FragmentManager fm, ArrayList<String> checkPointList) {
super(fm);
arrayList = checkPointList;
// bundle.putParcelableArrayList("data",checkPointList);
// nodesFragment.setArguments(checkPointList);
}
public ViewPagerAdapter(FragmentManager fm, boolean f) {
super(fm);
// this.checkPointList = checkPointList;
// nodesFragment = new NodesFragment(checkPointList);
// fragmentList.add(nodesFragment);
// bundle.putParcelableArrayList("data",checkPointList);
// nodesFragment.setArguments(checkPointList);
}
#Override
public Fragment getItem(int position) {
VideoSliderFragment f = new VideoSliderFragment();
Bundle bundle = new Bundle();
bundle.putString(IntentParams.VIDEO_URL, arrayList.get(position));
bundle.putInt(IntentParams.POSITION, position);
f.setArguments(bundle);
fragmentList.add(f);
return f;
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public void destroyItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
// super.destroyItem(container, position, object);
}
}
Related
I am setting up the fragment A,B thru FragmentStatePagerAdapter and having activity with FragmentActivity inside
Acitivity#onCreate
journeyDetailInfos = Manager.INSTANCE.getSeatOffline();
binding = DataBindingUtil.setContentView(this, R.layout.layout);
viewModel = ViewModelProviders.of(this).get(XYZModelView.class);
binding.pager.setAdapter(new SeatJourneyAdapter(this, getSupportFragmentManager(), journeyDetailInfos));
binding.pager.setOffscreenPageLimit(10);
binding.pager.addOnPageChangeListener(this);
binding.tablayout.setupWithViewPager(binding.pager);
binding.tablayout.setOnClickListener(view -> onTabChange());
lastSelectedPage = binding.tablayout.getSelectedTabPosition();
int length = binding.tablayout.getTabCount();
for (int i = 0; i < length; i++) {
binding.tablayout.getTabAt(i).setCustomView(getTabView(i));
}
SeatJourneyAdapter.java Adpater has following code
HashMap<Integer,XYZFragment> fragments;
ArrayList<JourneyDetailsInfo> journeyDetailInfos;
Context context;
private int container_id;
HashMap mFragmentTags ;
SeatJourneyAdapter(Context context, FragmentManager fragmentManager, ArrayList<JourneyDetailsInfo> journeyDetailInfos)
{
super(fragmentManager);
frgaments = new HashMap<Integer,XYZFragment>();
this.journeyDetailInfos = journeyDetailInfos;
mFragmentTags = new HashMap<Integer, String>();
}
#Override
public Fragment getItem(int position) {
XYZFragement fragment = null;
fragment = new XYZFragement();
fragment.setPosition(position);
fragment.setSeatDetails(journeyDetailInfos.get(position).getPaxDetailsInfos());
fragment.setCountJourney(journeyDetailInfos.size());
frgaments.put(position,fragment);
return fragment;
}
#Override
public int getCount() {
return journeyDetailInfos.size();
}
And onCreateView of Fragment is
binding = DataBindingUtil.inflate(inflater, R.layout.layout_name, container, false);
binding.paxWithSeatList.setLayoutManager(new LinearLayoutManager(this.getContext()));
binding.setSeatPax(viewModel);
viewModel.setPassengers(seatDetails);
return binding.getRoot();
Problem is when the data list "journeyDetailInfos" has count of 2 the Fragment shows a data of second item of data list "journeyDetailInfos". It works smooth if the count is more than 2 While I tried with all possible solution discussed in issue nothing worked for me.
Try FragmentPagerAdapter instead of FragmentStatePagerAdapter and Override getItemId to update pager smoothly.
SeatJourneyAdapter.java
private class SeatJourneyAdapter extends FragmentPagerAdapter {
final SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public SeatJourneyAdapter() {
super(getChildFragmentManager());
}
#Override
public Fragment getItem(final int pos) {
XYZFragement fragment = null;
fragment = new XYZFragement();
fragment.setPosition(position);
fragment.setSeatDetails(journeyDetailInfos.get(position).getPaxDetailsInfos());
fragment.setCountJourney(journeyDetailInfos.size());
frgaments.put(position,fragment);
return fragment;
}
/**
* Implementing this method is IMPORTANT for detorying the fragment.
* Use unique id for each item on pagerData.
*/
#Override
public long getItemId(int position) {
return journeyDetailInfos.get(position).getId(); // Unique id by position and pager data.
}
#NonNull
#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);
}
#Override
public int getCount() {
return journeyDetailInfos.size();
}
}
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));
}
Here's the inner class that contains fragments and changes fragment views on swipe. This class is defined in an Activity.
private class ViewPagerAdapter extends FragmentPagerAdapter {
private int count;
ViewPagerAdapter(FragmentManager fm, int count) {
super(fm);
this.count = count;
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new FriendsListFragment();
case 1:
Bundle bundle = new Bundle();
bundle.putString(Keys.TAG, ChatListFragment.class.getSimpleName());
ChatListFragment chatListFragment = new ChatListFragment();
chatListFragment.setArguments(bundle);
return chatListFragment;
case 2:
return new MoreFragment();
default:
return null;
}
}
#Override
public int getCount() {
return count;
}
}
Here I would like to add a code that sets tags to each fragment, so that I can recognize which fragment I'm at.
I searched quite much, and I haven't found a proper answer for this question, so please help.
You can override the setPrimaryItem method of your FragmentPagerAdapter.
private class ViewPagerAdapter extends FragmentPagerAdapter {
protected int currentPosition = -1;
protected Fragment currentFragment;
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// ....
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
this.currentPosition = position;
if (object instanceof Fragment) {
this.currentFragment = (Fragment) object;
}
}
public int getCurrentPosition() {
return currentPosition;
}
public Fragment getCurrentFragment() {
return currentFragment;
}
}
Just use getCurrentPosition or getCurrentFragment methods to get information about current Fragment.
I need to hide the second tab on particular condition, I have tried in following way, Tab hided, and text also changed, but fragment didn't changed, I mean, If I hided the second tab then I am getting FragmentStep2[second tab's content] on third tab,
public class PagerAdapter extends FragmentPagerAdapter {
private static final String TAG = "PagerAdapter";
private final String[] TITLES_WITH_STEP2 = {"step1", "step2", "step3", "step4"};
private final String[] TITLES_WITHOUT_STEP2 = {"step1", "step3", "step4"};
private ArrayList<Fragment> fragmentsList;
private boolean isShowStep2Tab = true;
public PagerAdapter(FragmentManager fm) {
super(fm);
fragmentsList = new ArrayList<>();
fragmentsList.add(new FragmentStep1());
fragmentsList.add(new FragmentStep2());
fragmentsList.add(new FragmentStep3());
fragmentsList.add(new FragmentStep4());
}
#Override
public CharSequence getPageTitle(int position) {
Log.v(TAG, "getPageTitle isShowStep2Tab : " + isShowStep2Tab);
fragmentsList = new ArrayList<>();
return isShowStep2Tab ? TITLES_WITH_STEP2[position] : TITLES_WITHOUT_STEP2[position];
}
#Override
public Fragment getItem(int position) {
/*Log.v(TAG, "getItem isShowStep2Tab : " + isShowStep2Tab);
if (getPageTitle(position).equals("Step1")) {
return new FragmentStep1();
} else if (getPageTitle(position).equals("Step2")) {
return new FragmentStep2();
} else if (getPageTitle(position).equals("Step3")) {
return new FragmentStep3();
} else if (getPageTitle(position).equals("Step4")) {
return new FragmentStep4();
}else {
return new FragmentStep4();
}*/
return fragmentsList.get(position);
}
#Override
public int getCount() {
Log.v(TAG, "getCount isShowStep2Tab : " + isShowStep2Tab);
fragmentsList = new ArrayList<>();
return isShowStep2Tab ? TITLES_WITH_STEP2.length : TITLES_WITHOUT_STEP2.length;
}
public void setShowFamilyTab(boolean isShowStep2Tab) {
this.isShowStep2Tab = isShowStep2Tab;
fragmentsList = new ArrayList<>();
if (isShowStep2Tab) {
fragmentsList.add(new FragmentStep1());
fragmentsList.add(new FragmentStep2());
fragmentsList.add(new FragmentStep3());
fragmentsList.add(new FragmentStep4());
} else {
fragmentsList.add(new FragmentStep1());
fragmentsList.add(new FragmentStep3());
fragmentsList.add(new FragmentStep4());
}
notifyDataSetChanged();
}
}
I don't know what is the problem here.
I would suggest you to pass only position to the getItem method of the adapter.
#Override
public Fragment getItem(int i) {
Fragment fragment = new DemoObjectFragment();
Bundle args = new Bundle();
args.putInt(DemoObjectFragment.ARG_OBJECT, i); // Our object is just an integer :-P
fragment.setArguments(args);
return fragment;
}
After that, you could get the position from your list of objects ( your pages) and check for condition (to show or not to show).
in your DemoObjectFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_collection_object, container, false);
Bundle args = getArguments();
FragmentPageToShow tempFragmentPage = fragmentDataList.get(args.getInt(ARG_OBJECT));
Use the same list of objects when you create the fragment page adapter.
public static class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter {
private Fragment mCurrentFragment;
public Fragment getCurrentFragment() {
return mCurrentFragment;
}
public DemoCollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Fragment fragment = new DemoObjectFragment();
Bundle args = new Bundle();
args.putInt(DemoObjectFragment.ARG_OBJECT, i); // Our object is just an integer :-P
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
// For this contrived example, we have a 100-object collection.
return fragmentDataList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return fragmentDataList.get(position).name;
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentFragment() != object) {
mCurrentFragment = ((Fragment) object);
}
super.setPrimaryItem(container, position, object);
}
}
Do not create FragmentStepX classes for each page. Just use one Fragment and pass data appropriately.
Either create array list of your data objects initially only for 'objects to show' or refresh your adapter dynamically whenever your array list changes.
You could always have the list of items to show before setting/refreshing the adapter.
I know there is a lot of different issues about PageViewers but I can't find solution to my problem.
The problem is that in my app i have one PageViewin another lets say that in PageViewA i have PageView B. In A i keep some informations in TextViews and B. B keeps ImageView and should display images for my fragments. A has few pages and on every page I have right data on TextViews but only one(the first visible one) contains images. When i switch pages none of B ViewPager have images but have right TextViews.
Adapter for A and getFragments() method:
class MyPageAdapter extends FragmentPagerAdapter {
private List<Fragment> pages;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.pages = fragments;
}
#Override
public Fragment getItem(int position) {
return this.pages.get(position);
}
#Override
public int getCount() {
return this.pages.size();
}
}
private ArrayList<Fragment> getFragments(){
ArrayList<Fragment> fList = new ArrayList<Fragment>();
for(int i=0;i<diary.getList().get(index).events.size();i++){
fList.add(EventPageFragment.newInstance("",index,i));
}
return fList;
}
CreateView and adapter in EventPageFragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String message = getArguments().getString(EXTRA_MESSAGE);
int index = getArguments().getInt(INDEX);
int eventIndex = getArguments().getInt(EVENT);
View v = inflater.inflate(R.layout.page_eventview, container, false);
TextView title = (TextView)v.findViewById(R.id.event_past_title);
TextView date = (TextView)v.findViewById(R.id.event_past_date);
TextView description = (TextView)v.findViewById(R.id.event_past_desc);
title.bringToFront();
images = getFragments(index,eventIndex);
pager = (ViewPager)v.findViewById(R.id.event_pager);
pageAdapter = new MyPageAdapter(getFragmentManager(),images);
pager.setAdapter(pageAdapter);
pageAdapter.notifyDataSetChanged();
pager.invalidate();
title.setText(diary.getList().get(index).events.get(eventIndex).getTitle());
date.setText(getResources().getString(R.string.date)+": "+diary.getList().get(index).events.get(eventIndex).getDate()[0]+"/"+
diary.getList().get(index).events.get(eventIndex).getDate()[1]+"/"+
diary.getList().get(index).events.get(eventIndex).getDate()[2]);
description.setText(getResources().getString(R.string.description)+": "+diary.getList().get(index).events.get(eventIndex).getDescription());
return v;
}
class MyPageAdapter extends FragmentPagerAdapter {
private List<Fragment> images;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.images = fragments;
}
#Override
public Fragment getItem(int position) {
return this.images.get(position);
}
#Override
public int getCount() {
return this.images.size();
}
}
private ArrayList<Fragment> getFragments(int index, int event){
ArrayList<Fragment> fList = new ArrayList<Fragment>();
for(int i=0;i<diary.getList().get(index).events.get(event).photoReference.size();i++){
fList.add(PhotoFragment.newInstance("",index,event,i));
}
return fList;
}
And finally PhotoFragment that represents images in B:
public static final PhotoFragment newInstance(String message, int personIndex, int eventIndex, int photoIndex)
{
PhotoFragment f = new PhotoFragment();
Bundle bdl = new Bundle(1);
bdl.putString(EXTRA_MESSAGE, message);
bdl.putInt(INDEX, personIndex);
bdl.putInt(EVENT, eventIndex);
bdl.putInt(PHOTO, photoIndex);
f.setArguments(bdl);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String message = getArguments().getString(EXTRA_MESSAGE);
int index = getArguments().getInt(INDEX);
int eventIndex = getArguments().getInt(EVENT);
int photoIndex = getArguments().getInt(PHOTO);
View v = inflater.inflate(R.layout.page_photo_fragment, container, false);
ImageView image = (ImageView)v.findViewById(R.id.event_photo_image);
image.setImageBitmap(PhotoManager.decodeFile(diary.getList().get(index).events.get(eventIndex).photoReference.get(photoIndex),300));
return v;
}
}
I have no idea why only one EventPage loads images from PhotoFragment