I have a program that has fragment as arraylist, I am using it with TabLayout , As I remove a tab I want to remove the fragment also. But with my implementation it is not sequential. Tab 1 will remove Fragment2 etc. Please check where I am going wrong ?
Under onCreate of MainActivity this is how I add fragments
private TabPagerAdapter pagerAdapter;
public List<Fragment> fragmentList = new ArrayList<>();
protected void onCreate(Bundle savedInstanceState) {
fragmentList.add(NewsFragment.newInstance(Tab1));
fragmentList.add(NewsFragment.newInstance(Tab2));
fragmentList.add(NewsFragment.newInstance(Tab3));
mViewPager = (ViewPager) findViewById(R.id.pager);
pagerAdapter = new TabPagerAdapter(getSupportFragmentManager(), fragmentList);
mViewPager.setAdapter(pagerAdapter);
This is my FragmentStatePagerAdapter, removeFragment is where I am trying to remove the fragment
public class TabPagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragmentList;
private List<String> tabTitles = new ArrayList<>();
#Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
public TabPagerAdapter(FragmentManager fm, List<Fragment> fragmentList) {
super(fm);
mFragmentList = fragmentList;
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void removeFragment(int tabPosition) {
if (!mFragmentList.isEmpty()) {
mFragmentList.remove(tabPosition);
}
}
}
OnActivity result under mainactivity is where I am trying to remove both the tab & fragment
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK || data == null)
return;
settingList = (ArrayList<SettingCheckBox>) data.getSerializableExtra(SETTING_CHECK_BOX);
for (int i = 0; i < settingList.size(); i++) {
if (settingList.get(i).getChecked()) {
Log.d("**Checked Item**", String.valueOf(settingList.get(i).getDescription()));
String removeTab = String.valueOf(settingList.get(i).getDescription());
Boolean checkedValue = settingList.get(i).getChecked();
if (removeTab.equals("tab1")) {
//remove tab
tabLayout.removeTab(tab1);
//remove fragment
pagerAdapter.removeFragment(0);
// fragmentList.remove(i);
pagerAdapter.notifyDataSetChanged();
} else if (removeTab.equals("tab2")) {
tabLayout.removeTab(tab2);
pagerAdapter.removeFragment(1);
// fragmentList.remove(i);
pagerAdapter.notifyDataSetChanged();
} else if (removeTab.equals("tab3")) {
tabLayout.removeTab(tab3);
pagerAdapter.removeFragment(2);
// fragmentList.remove(i);
pagerAdapter.notifyDataSetChanged();
}
change you pagerAdapter.removeFragment(mViewPager.getCurrentItem()); to pagerAdapter.removeFragment(correctFragmentPosition);
correctFragmentPosition = calculate based on value of removeTab
Just to answer my own question. I added the fragment this way
public List<Fragment> fragmentList = new ArrayList<>();
private NewsFragment frag1
frag1 = NewsFragment.newInstance("https://www.yahoo.com");
fragmentList.add(frag1);
In case I need to find the position of the fragment
for (int i = 0; i < fragmentList.size(); i++) {
if (fragmentList.get(i).equals(frag1)) {
//found the position so removing it
pagerAdapter.removeFragment(i); }
}
Related
im trying to implement ViewPager + Adapter, without configChanges at the manifest, the result:
When i rotate the screen, the fragments views become null and it remove other views showing only one tab
my Adapter
private class TabsPagerAdapter extends FragmentStatePagerAdapter {
private Bundle bundle;
private String titulo;
private List<LeiAberta> fragments;
private TabsPagerAdapter(FragmentManager fm) {
super(fm);
fragments = new ArrayList<>();
}
#Override
public LeiAberta getItem(int position) {
return fragments.get(position);
}
private void addPage(LeiAberta page) {
page.setRetainInstance(true);
fragments.add(page);
notifyDataSetChanged();
}
public void removePage(int position) {
if(fragments.size() <= 1) {
finish();
} else {
fragments.remove(position);
notifyDataSetChanged();
}
}
#Override
public int getItemPosition(Object object) {
if (fragments.contains(object)) return fragments.indexOf(object);
else
return POSITION_NONE;
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
this.bundle = fragments.get(position).getArguments();
if (this.bundle != null) {
this.titulo = bundle.getString("titulo");
}
return titulo;
}
}
when activity is created:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leitura);
tabs = (TabLayout) findViewById(R.id.tabs);
viewPager = (ViewPager) findViewById(R.id.pager);
adapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setOffscreenPageLimit(20);
realm = Realm.getDefaultInstance();
bundle = getIntent().getExtras();
if (bundle != null && bundle.getInt("id") > 0) {
texto = RepositoryTexto.getActiveTextoById(realm, bundle.getInt("id"));
bundle = new Bundle();
bundle.putInt("id", texto.getId());
bundle.putString("titulo", texto.getTitulo());
leiAberta = new LeiAberta();
leiAberta.setArguments(bundle);
adapter.addPage(leiAberta);
}
at the first run, the views at the fragment are working well, when i rotate, it become null
is there any way to keep the same viewpager, adapter and fragments without recreating it? i already have onSaveInstance and restore but doesnt matter, since the getActivity become null at the fragment too
I would like to set the object of subclass of FragmentStatePagerAdapter in ViewPager by the method
viewPager.setAdapter(myPagerAdapter);
But i got error as follows
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.Fragment.setMenuVisibility(boolean)' on a null object reference
at android.support.v4.app.FragmentStatePagerAdapter.instantiateItem(FragmentStatePagerAdapter.java:120)
at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:1006)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1154)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1088)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1614)
Please help me to fix this issue.
The code snippet is
public class MainActivity extends AppCompatActivity {
Toolbar toolbar;
TabLayout tabLayout;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar)findViewById(R.id.toolbar);
toolbar.setTitle("My App");
toolbar.setSubtitle("this is my test");
tabLayout = (TabLayout)findViewById(R.id.tablayout);
tabLayout.addTab(tabLayout.newTab().setText("Left"));
tabLayout.addTab(tabLayout.newTab().setText("Cent"));
tabLayout.addTab(tabLayout.newTab().setText("Right"));
viewPager = (ViewPager)findViewById(R.id.viewpage);
MyPagerAdapter myPagerAdapter = new MyPagerAdapter(
getSupportFragmentManager(),
tabLayout.getTabCount()
);
viewPager.setAdapter(myPagerAdapter);
//viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
}
}
public class MyPagerAdapter extends FragmentStatePagerAdapter {
int tabCount;
public MyPagerAdapter(FragmentManager fm, int tabCount) {
super(fm);
this.tabCount = tabCount;
}
#Override
public Fragment getItem(int position) {
switch (position){
case 1:
Fragment1 fragment1 = new Fragment1();
return fragment1;
case 2:
Fragment2 fragment2 = new Fragment2();
return fragment2;
case 3:
Fragment3 fragment3 = new Fragment3();
return fragment3;
default:
return null;
}
}
#Override
public int getCount() {
return tabCount;
}
}
While you should probably be using tabLayout.setupWithViewPager(viewPager);
Here's the problem
switch (position){
// case 1, 2, 3...
default:
return null; // Here
Did you forget that lists start indexing at position 0? You've returned a null Fragment
Try the following.
MyPagerAdapter.java
public class MyPagerAdapter extends FragmentStatePagerAdapter {
private Context mContext;
private List<Fragment> mFragments = new ArrayList<>();
public FragmentPagerAdapter(Context context, FragmentManager fm) {
super(fm);
this.mContext = context;
}
public void addFragment(Fragment fragment) {
mFragments.add(fragment);
}
#Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
#Override
public int getCount() {
return mFragments.size();
}
}
In your MainActivity,
private void setUpViewPager(ViewPager viewPager) {
adapterViewPager = new MyPagerAdapter(getApplicationContext(), getSupportFragmentManager());
adapterViewPager.addFragment(new AFragment());
viewPager.setAdapter(adapterViewPager);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void setUpTabLayout(TabLayout tabLayout) {
tabLayout.setupWithViewPager(viewPager);
for (int i = 0; i < tabLayout.getTabCount(); i++) {
TabLayout.Tab tab = tabLayout.getTabAt(i);
//set your tab text, image etc here.
}
tabLayout.requestFocus();
}
Then in your onCreate(), just use the methods accordingly. setUpViewPager() follow by setUpTabLayout()
I am trying to set infinite view Pager(circular Scroll-able tab) using Infinite ViewPager but when I tried to set the adapter
1.It work only from the end side (last Position).
2.It is not working on the start(position 0) side.
3.It repeat the last fragment when scrolled further.
My adapter
private InfiniteViewPager pager = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pager = (InfiniteViewPager) findViewById(R.id.pager);
FragmentManager fragmentManager = getSupportFragmentManager();
pager.setAdapter(new MyAdapter(fragmentManager));
pager.setPageTransformer(true, new CubeOutTransformer());
pager.setCurrentItem(2);
}
My adapter class
class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
public int getActualPosition(int i){
return i < 5? i : 0;
}
#Override
public Fragment getItem(int i) {
Fragment fragment = null;
i = getActualPosition(i);
if (i == 0) {
fragment = new Albums();
}
if (i == 1) {
fragment = new Artists();
}
if (i == 2) {
fragment = new Songs();
}
if (i == 3) {
fragment = new Genres();
}
if (i == 4) {
fragment = new Playlists();
}
return fragment;
}
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
#Override
public CharSequence getPageTitle(int position) {
String title = new String();
if (position == 0) {
return "ALBUMS";
}
if (position == 1) {
return "ARTISTS";
}
if (position == 4) {
return "PLAYLIST";
}
if (position == 3) {
return "GENRES";
}
if (position == 2) {
return "SONGS";
}
return title;
}
}
I have gone through Infinite Pager Adapter and Mine pager adapter
but when I try to set the adapter inside another adapter I am getting an error in my adapter class.
where I am doing wrong and how I can fix the scrolling from both starting and ending.
You should set adapter like this
MyAdapter adapter=new MyAdapter(fragmentManager);
InfinitePagerAdapter myAdapter= new InfinitePagerAdapter(adapter);
pager.setAdapter(myAdapter);
Also in your adapter change this code
from this
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
to
#Override
public int getCount() {
return 5;
}
My host activity has a viewpager with two fragments A and B.My activity code looks like this:
public class MainActivity extends AppCompatActivity implements
OnDataLoadedListener {
private ViewPager pager;
private MyPagerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pager = (ViewPager) findViewById(R.id.pager);
adapter = new MyPagerAdapter(getSupportFragmentManager());
pager.setAdapter(adapter);
final int pageMargin = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 4, getResources()
.getDisplayMetrics());
pager.setPageMargin(pageMargin);
tabLayout.setupWithViewPager(pager);
}
public class MyPagerAdapter extends FragmentPagerAdapter {
private final String[] TITLES = { "A",
"B" };
public 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) {
switch (position) {
case 0:
return A.getInstance();
case 1:
return B.getInstance();
}
return null;
}
}
public Fragment findFragmentByPosition(int position) {
return getSupportFragmentManager().findFragmentByTag(
"android:switcher:" + pager.getId() + ":"
+ adapter.getItemId(position));
}
Now when activity start viewpager get populated with fragment properly and I try to access fragmentby using following code:
if (AFragment == null)
AFragment = (A) findFragmentByPosition(0);
if (BFragment == null)
BFragment = (B) findFragmentByPosition(1);
But AFragment and BFragment always contains null.I have read other simmilar question but it didn't help either.I need access to fragments as I want to call some methods defined in fragment from host activity.
Code to get an instance of fragment:
public static AFragment getInstance() {
AFragment fragment = new AFragment();
return fragment;
}
I'm think that the problem is that you need to move the method to the Adapter, because you need the original instance of the FragmentManager :
public class MyPagerAdapter extends FragmentPagerAdapter {
FragmentManager fm;
private final String[] TITLES = { "A",
"B" };
public MyPagerAdapter (FragmentManager fm) {
super(fm);
this.fm = fm;
}
#Override
public CharSequence getPageTitle(int position) {
return TITLES[position];
}
#Override
public int getCount() {
return TITLES.length;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return A.getInstance();
case 1:
return B.getInstance();
}
return null;
}
public Fragment findFragmentByPosition(int position, int pagerId) {
return fm.findFragmentByTag(
"android:switcher:" + pagerId + ":"
+ getItemId(position));
}
}
So now you can call:
adapter.findFragmentByPosition(position, pager.getId());
I have implemented the ViewPagerIndicator with ActionBarSherlock.
Now i would like to open a specific fragment inside the viewpager once the viewpager is created. Normally you should use setCurrentItem(pageid) or setViewPager(mPager, pageid);
But this doesn't work :( If I would like to open fragment 2 inside the viewpager, the
viewpager indicator shows that fragment 2 is shown, but in reality fragment one (standard) is shown in the viewpager.
I have the following code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_tabs);
mAdapter = new ColofonFragmentAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mIndicator = (TabPageIndicator)findViewById(R.id.indicator);
String page = "";
page = getIntent().getStringExtra("page");
int pageid = 0;
if(page.equals("contact")) { pageid = 0; }
else if(page.equals("colofon")) { pageid = 1; }
else if(page.equals("disclaimer")) { pageid = 2; }
mIndicator.setViewPager(mPager, pageid); // Doesn't work...
//mIndicator.setCurrentItem(pageid); // Doesn't work...
}
class ColofonFragmentAdapter extends FragmentPagerAdapter implements TitleProvider {
ArrayList<Fragment> fragments = new ArrayList<Fragment>();
ArrayList<String> titels = new ArrayList<String>();
public ColofonFragmentAdapter(FragmentManager fm) {
super(fm);
fragments.add(new LayoutFragment(R.layout.colofon_contactgegevens));
titels.add("Contact");
fragments.add(new LayoutFragment(R.layout.colofon_colofon));
titels.add("Colofon");
fragments.add(new LayoutFragment(R.layout.colofon_disclaimer));
titels.add("Disclaimer");
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public String getTitle(int position) {
return titels.get(position);
}
}
Can you tell me which method I should use to change the initial page?
Thank you!
I think it was a bug caused by setCurrentItem()
https://github.com/JakeWharton/Android-ViewPagerIndicator/pull/76
It's solved ^^