android viewpager notifyDatachange return to first - android

I'm working in an android projet. I use tab to display data with fragment. In the third fragment, when i update data, viewPager return to the first. I try everything.
This is my viewPagerAdapter
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
private int baseId=0;
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);
}
#Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
#Override
public long getItemId(int position) {
// give an ID different from position when position has been changed
return baseId + position;
}
/**
* Notify that the position of a fragment has been changed.
* Create a new ID for each position to force recreation of the fragment
* #param n number of items which have been changed
*/
public void notifyChangeInPosition(int n) {
// shift the ID returned by getItemId outside the range of all previous fragments
baseId += getCount() + n;
}
}
Thanks.

Related

Android: Viewpager refresh, edit text won't refresh

I wanted my view pager to call onCreate every time so am using the below code:
#Override
public void setUserVisibleHint(boolean isVisibleToUser)
{
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser && isChanged())
{
isChanged = false;
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
viewPagerUpdatedInterface.viewPagerUpdated(); // inteface called in main method this will adapter.notifyDataSetChanged();
}
}
Here I am able to see correct value of string which I needed to update in logs but the same is not showing on screen.
My adapter class is below:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
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);
}
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}

How can I remove a fragment and tab from ViewPager and Tablayout?

I have search a lot about this solution. I tried remove from mFragmentList and mFragmentTitleList directly. And I also tried call the destroyItem. Many methods have been tried. None of them worked. I have been stuck on this problem for few days. Is there Any answer could help? Thanks.
public final class OrdersViewPagerAdapter extends android.support.v4.app.FragmentPagerAdapter{
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public OrdersViewPagerAdapter(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 void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
if (position <= getCount()) {
FragmentManager manager = ((Fragment) object).getFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove((Fragment) object);
trans.commit();
}
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
public void removeView(String title, ViewGroup view, TabLayout tabLayout) {
int index=-1;
int count=mFragmentTitleList.size();
for (int i=0;i<count;i++){
String mtitle=mFragmentTitleList.get(i);
if (mtitle.equals(title)){
index=i;
break;
}
}
if (index!=-1) {
mFragmentTitleList.remove(index);
tabLayout.removeTabAt(index);
destroyItem(view,index,mFragmentList.get(index));
notifyDataSetChanged();
}
}
}

Remove a fragment of a specific index from a view pager

Im trying to remove a fragment from a specific index. But that is really happening is the viewpager and pagerAdapter are just hiding the last fragment.
This is the code:
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
ArrayList<String> data_fragment;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
data_fragment = new ArrayList<>();
data_fragment.add(0, "Página 0");
}
public void addNewFragmentData(String data) {
// int last_position = data_fragment.size();
data_fragment.add(data);
notifyDataSetChanged();
}
public void removeFragmentData(int index) {
// destroyItem(container, position, object);
data_fragment.remove(index);
notifyDataSetChanged();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
// #Override
// public void destroyItem(ViewGroup container, int position, Object object)
// {
// data_fragment.remove(position);
// super.destroyItem(container, position, object);
// }
#Override
public Fragment getItem(int position) {
Log.i("paginas", "getItem");
return LienzoFragment.newInstance(position);
}
#Override
public int getCount() {
return data_fragment.size();
}
#Override
public CharSequence getPageTitle(int position) {
return data_fragment.get(position);
}
}
As you see, I'm trying to avoid retain any fragment object. My approach is just keep the title and then each fragment manage its own save/restore state by itself.
int tab_selected = mViewPager.getCurrentItem();
mSectionsPagerAdapter.removeFragmentData(tab_selected);
//mSectionsPagerAdapter.destroyItem(mViewPager, tab_selected, mViewPager.getChildAt(tab_selected));
mViewPager.removeViewAt(tab_selected);
mViewPager.setCurrentItem(tab_selected-1, true);

How can I set the titles in a PagerTitleStrip for a View pager

I have problem setting the title view pager by using PagerTitleStrip. I added a child view of PagerTitleStrip in view pager.
Where can I provide the title strings to apply to each page?
How can I set the page title in the Page Adapter class?
Override the getPageTitle method and supply your static array of pages string to it.
String [] titlesArray =
new String []{
page1,
page2,
page3
};
public CharSequence getPageTitle(int position) {
return titlesArray [position];
}
Here is full example.
You have to implement public CharSequence getPageTitle(int position).
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment) {
mFragmentList.add(fragment);
}
#Override
public Fragment getItem(int position) {
if(position == 0){
return FragmentInner1.newInstance();
}
else {
return FragmentInner2.newInstance();
}
}
#Override
public CharSequence getPageTitle(int position) {
if(position == 0){
// public static final String PAGE_TITLE = "My Title #1" is within the layout FragmentInner1;
return FragmentInner1.PAGE_TITLE;
}
else {
// public static final String PAGE_TITLE = "My Title #2" is within the layout FragmentInner2;
return FragmentInner2.PAGE_TITLE;
}
}
}

insert and remove fragments into viewpager properly

I'm making an adroid application with viewpager and fragments. I want to make an option to add or remove fragment pages to the pager dynamically. I have a custom FragmentPagerAdapter:
public class MyAdapter extends FragmentPagerAdapter implements TitleProvider{
protected final List<PageFragment> fragments;
/**
* #param fm
* #param fragments
*/
public MyAdapter(FragmentManager fm, List<PageFragment> fragments) {
super(fm);
this.fragments = fragments;
}
public void addItem(PageFragment f){
fragments.add(f);
notifyDataSetChanged();
}
public void addItem(int pos, PageFragment f){
for(int i=0;i<fragments.size();i++){
if(i>=pos){
getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentByTag(getFragmentTag(i))).commit();
}
}
fragments.add(pos,f);
notifyDataSetChanged();
pager.setAdapter(this);
pager.setCurrentItem(pos);
}
public void removeItem(int pos){
getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentByTag(getFragmentTag(pos))).commit();
for(int i=0;i<fragments.size();i++){
if(i>pos){
getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentByTag(getFragmentTag(i))).commit();
}
}
fragments.remove(pos);
notifyDataSetChanged();
pager.setAdapter(this);
if(pos<fragments.size()){
pager.setCurrentItem(pos);
}else{
pager.setCurrentItem(pos-1);
}
}
#Override
public Fragment getItem(int position) {
return fragments.get(position).toFragment();
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
private String getFragmentTag(int pos){
return "android:switcher:"+R.id.pager+":"+pos;
}
public String getTitle(int position) {
String name = fragments.get(position).getName();
if(name.equals(""))
return "- "+position+" -";
return name;
}
}
I can remove any fragment except the 0. when I try to remove it I got a NullPointerException on the notifyDataSetChanged(); or on the pager.setAdapter(this); if i comment out the notify.
I also got a NullPointerException when I try to insert a new page. When I add the new page to the end of the list it's working fine.
I even tried to readd the fragments in the insert with this after the fragments.add(pos,f)
for(int i=0;i<fragments.size();i++){
if(i>=pos){
getSupportFragmentManager().beginTransaction().add(fragments.get(i).toFragment(),getFragmentTag(i-1)).commit();
}
}
if I use getFragmentTag(i-1) I got nullpointer again. With using just i I got illegalstateexception because can not modify fragment's tag. With beginTransaction().add(pager.getId,fragments.get(i).toFragment()) it is still nullpointer...
My question is: what am I doing wrong, and how can it be done properly? (and maybe: from where notyfyDataSetChanged() get the data when causes nullpointerexception?)
This is what I used to get around the problem with fragments being tagged when instantiated and the fact that previously tagged fragments cannot change position within the ViewPager when trying to add or remove pages, i.e. getting the exception:
java.lang.IllegalStateException: Can't change tag of fragment
MyFragment{4055f558 id=0x7f050034 android:switcher:2131034164:3}: was
android:switcher:2131034164:3 now android:switcher:2131034164:4
This adapter is created with a list of all pages upfront and you can then use setEnabled(int position, boolean enabled) to disable or enable certain pages which hides or shows these pages in the ViewPager.
It works by maintaining an internal list of all fragments but exposing to the ViewPager and mapping the positions of enabled fragments only.
public class DynamicFragmentPagerAdapter extends FragmentPagerAdapter {
public final ArrayList<Fragment> screens = new ArrayList<Fragment>();
private Context context;
private List<AtomicBoolean> flags = new ArrayList<AtomicBoolean>();
public DynamicFragmentPagerAdapter(FragmentManager fm, Context context, List<Class<?>> screens) {
super(fm);
this.context = context;
for(Class<?> screen : screens)
addScreen(screen, null);
notifyDataSetChanged();
}
public DynamicFragmentPagerAdapter(FragmentManager fm, Context context, Map<Class<?>, Bundle> screens) {
super(fm);
this.context = context;
for(Class<?> screen : screens.keySet())
addScreen(screen, screens.get(screen));
notifyDataSetChanged();
}
private void addScreen(Class<?> clazz, Bundle args) {
screens.add(Fragment.instantiate(context, clazz.getName(), args));
flags.add(new AtomicBoolean(true));
}
public boolean isEnabled(int position) {
return flags.get(position).get();
}
public void setEnabled(int position, boolean enabled) {
AtomicBoolean flag = flags.get(position);
if(flag.get() != enabled) {
flag.set(enabled);
notifyDataSetChanged();
}
}
#Override
public int getCount() {
int n = 0;
for(AtomicBoolean flag : flags) {
if(flag.get())
n++;
}
return n;
}
#Override
public Fragment getItem(int position) {
return screens.get(position);
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE; // To make notifyDataSetChanged() do something
}
#Override
public void notifyDataSetChanged() {
try {
super.notifyDataSetChanged();
} catch (Exception e) {
Log.w("", e);
}
}
private List<Fragment> getEnabledScreens() {
List<Fragment> res = new ArrayList<Fragment>();
for(int n = 0; n < screens.size(); n++) {
if(flags.get(n).get())
res.add(screens.get(n));
}
return res;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
// We map the requested position to the position as per our screens array list
Fragment fragment = getEnabledScreens().get(position);
int internalPosition = screens.indexOf(fragment);
return super.instantiateItem(container, internalPosition);
}
#Override
public CharSequence getPageTitle(int position) {
Fragment fragment = getEnabledScreens().get(position);
if(fragment instanceof TitledFragment)
return ((TitledFragment)fragment).getTitle(context);
return super.getPageTitle(position);
}
public static interface TitledFragment {
public String getTitle(Context context);
}
}
I have a solution that works with a non-fragment based adapter. Take a look at my post and see if it helps.
I can remove any fragment except the 0.
For me it works if just use a >= condition whitin the removeItem's for-loop:
if (i >= pos){
fm.beginTransaction().remove(fragments.get(i).getFragment()).commit();
}

Categories

Resources