All my fragments are android.support.v4.app.Fragment and the Viewpager extends FragmentStatePagerAdapter which also uses android.support.v4.app.Fragment.
I have a Fragment class which extends PreferenceFragment that I want to add in my Viewpager with my other two fragments.
How can I accomplish this?
Here's my ViewPager
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private ArrayList<Fragment> mFragments = new ArrayList<>();
private ArrayList<String> mFragmentsTitle = new ArrayList<>();
public void addFragment(Fragment fragment, String title){
mFragments.add(fragment);
mFragmentsTitle.add(title);
}
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
#Override
public int getCount() {
return mFragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentsTitle.get(position);
}
}
Here's what I have in my PreferenceFragment
public class GameNotesFragment extends PreferenceFragment {
public GameNotesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_game_notes, container, false);
return view;
}
}
When I try to add it in:
mSectionsPagerAdapter.addFragment(new GameNotesFragment(), "Note");
It gives me
Wrong firt argument com.example.fragments.GameNotesFragment', required: 'android.support.v4.app.Fragment'
PreferenceFragment extends the platform variant of the Fragment class. What you need is a PreferenceFragmentCompat that extends the support lib variant of Fragment (mind the different packages).
The support preferences require additional package(s) in your gradle file:
implementation 'com.android.support:preference-v7:27.1.0'
implementation 'com.android.support:preference-v14:27.1.0'
Also, while you're at it, make sure to check out the bug fix lib I created for the support preferences' common (and pretty annoying) bugs.
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private ArrayList<Fragment> mFragments = new ArrayList<>();
private ArrayList<String> mFragmentsTitle = new ArrayList<>();
public void addFragment(Fragment fragment, String title){
mFragments.add(fragment);
mFragmentsTitle.add(title);
}
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
android.support.v4.app.Fragment f = null;
if (position == 0) {
f = new GameNotesFragment();
}
if (position == 1) {
f = new GameNotesFragment(); //replace your fragment 2
}
if (position == 2) {
f = new GameNotesFragment();//replace your fragment 3
}
return f;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getResources().getString(R.string.name1);
case 1:
return getResources().getString(R.string.name2);
case 2:
return getResources().getString(R.string.name3);
return null;
}
}
and in activity:
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(MainActivity.this.getSupportFragmentManager());
tabLayout = v1.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
Related
In my viewpager i set listener from which i call methods from my interface in tab fragments.
But variable in this tab fragments in my interfaces methods always return null.
Tell me why ?
p.s. sorry for my english)
Parent fragment:
public class MyFragment
extends Fragment {
protected Context mContext;
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
}
#Override
public void onDetach() {
super.onDetach();
mContext = null;
} }
Container fragment with PagerAdapter:
public class FragmentContainer
extends MyFragment {
private ViewPager viewPager;
private ViewPager.OnPageChangeListener onPageChangeListener;
public interface IPageSelected {
void onPageSelected();
void onPageUnselected();
}
public static FragmentContainer newInstance() {
return new FragmentContainer();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(
R.layout.fragment_container, container, false);
viewPager = view.findViewById(R.id.pager);
PagerAdapter pagerAdapter = new PagerAdapter(getFragmentManager());
viewPager.setAdapter(pagerAdapter);
TabLayout tabLayout = view.findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(viewPager);
onPageChangeListener = new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
for(int x = 0; x < pagerAdapter.getCount(); x++) {
((IPageSelected) pagerAdapter.getItem(x)).onPageUnselected();
}
((IPageSelected) pagerAdapter.getItem(position)).onPageSelected();
}
#Override
public void onPageScrollStateChanged(int state) {
}
};
viewPager.addOnPageChangeListener(onPageChangeListener);
return view;
}
#Override
public void onResume() {
super.onResume();
setCurrentItem();
}
private void setCurrentItem() {
viewPager.post(() -> {
viewPager.setCurrentItem(0);
onPageChangeListener.onPageSelected(0);
});
}
class PagerAdapter
extends FragmentStatePagerAdapter {
PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return TestFragment1.newInstance();
case 1:
return TestFragment2.newInstance();
}
return null;
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Tab1";
case 1:
return "Tab2";
default:
return null;
}
}
} }
Tab fragments.
Question: why variable mContext in interface methods always return null ?
public class TestFragment1
extends MyFragment
implements FragmentContainer.IPageSelected {
public static TestFragment1 newInstance() {
return new TestFragment1();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment1, container, false);
}
#Override
public void onPageSelected() {
Log.d("myLog", "TestFragment1 onPageSelected: " + mContext); // WHY NULL ???
}
#Override
public void onPageUnselected() {
Log.d("myLog", "TestFragment1 onPageUnselected: " + mContext); // WHY NULL ???
} }
public class TestFragment2
extends MyFragment
implements FragmentContainer.IPageSelected {
public static TestFragment2 newInstance() {
return new TestFragment2();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment2, container, false);
}
#Override
public void onPageSelected() {
Log.d("myLog", "TestFragment2 onPageSelected: " + mContext); // WHY NULL ???
}
#Override
public void onPageUnselected() {
Log.d("myLog", "TestFragment2 onPageUnselected: " + mContext); // WHY NULL ???
} }
In your fragment container :
PagerAdapter pagerAdapter = new PagerAdapter(getFragmentManager()); here is the fault.
In order to attach your child fragments to your container fragment, consider passing child fragment manager getChildFragmentManager() to your viewpager adapter. (Right now your fragments are attached to same level as your container fragment).
I found solution.
Adapter class.
Old:
class PagerAdapter
extends FragmentStatePagerAdapter {
PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return TestFragment1.newInstance();
case 1:
return TestFragment2.newInstance();
}
return null;
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Tab1";
case 1:
return "Tab2";
default:
return null;
}
}
}
New:
class PagerAdapter
extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
Adapter initialization.
Old:
PagerAdapter pagerAdapter = new PagerAdapter(getFragmentManager());
viewPager.setAdapter(pagerAdapter);
New:
PagerAdapter pagerAdapter = new PagerAdapter(getFragmentManager());
pagerAdapter.addFragment(TestFragment1.newInstance(), "tab1");
pagerAdapter.addFragment(TestFragment2.newInstance(), "tab2");
viewPager.setAdapter(pagerAdapter);
And now new question: what's the differense with the first option ?
Now i initializing adapter in container fragment, it's a cause ?
Why didn't work when initializing was in the adapter ?
In my app i am using pager adapter to load 2 fragments, the fragments are not getting loaded and view pager remains null. Where i am going wrong? Any help will be appreciated
Here is my code
I am setting this adapter to my view pager from activity
public class ViewPagerActivityAdapter extends PagerAdapter {
ArrayList<Fragment> tablist;
public ViewPagerActivityAdapter(ArrayList<Fragment> tablist) {
this.tablist = tablist;
}
#Override
public int getCount() {
return tablist.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return false;
}
#Override
public Object instantiateItem(ViewGroup collection, int position) {
return null;
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view) {
}
}
Activity Part
private ViewPagerActivityAdapter viewPagerAdapter;
private ArrayList<Fragment> fragments_faq;
fragments_faq = new ArrayList<>();
FragmentOne frag1 = new FragmentOne();
tablayout.addTab(tablayout.newTab().setText("fragone"));
fragments_faq.add(frag1);
FragmentTwo frag2 = new FragmentTwo();
tablayout.addTab(tablayout.newTab().setText("fragtwo"));
fragments_faq.add(frag2);
private void setPagerAdapter() {
viewPagerAdapter = new ViewPagerActivityAdapter(fragments_faq);
viewpager.setAdapter(viewPagerAdapter);
viewpager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tablayout));
viewpager.setOffscreenPageLimit(2);
tablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewpager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
for details check this gist
https://gist.github.com/vinay6kr/33359c3f3b0e9f28e33bd383b01e9d9f
if you want to show fragments in viewpager you should use FragmentStatePagerAdapter
public class MyViewPagerAdapter extends FragmentStatePagerAdapter {
CharSequence Titles[];
public MyViewPagerAdapter(FragmentManager fm, CharSequence mTitles[]) {
super(fm);
this.Titles = mTitles;
}
#Override
public Fragment getItem(int position) {
if (position == 0)
return new Fragment1().getInstance();
else if (position == 1)
return new Fragment2().getInstance();
}
#Override
public CharSequence getPageTitle(int position) {
return Titles[position];
}
#Override
public int getCount() {
return Titles.length;
}
}
and to Set them
void setUpTabs() {
String Titles[] = {"Frag1","Frag2"};
MyViewPagerAdapter adapter = new MyViewPagerAdapter(this.getSupportFragmentManager(), Titles);
viewPager.setAdapter(adapter);
}
You can try like adapter look like
class ViewPagerActivityAdapter extends FragmentPagerAdapter {
// fragments to instantiate in the viewpager
private List<Fragment> fragments;
// constructor
public ViewPagerActivityAdapter(FragmentManager fm,List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
// return access to fragment from position, required override
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
// number of fragments in list, required override
#Override
public int getCount() {
return this.fragments.size();
}
}
Add Fragment
List<Fragment> fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this,
FragmentOne.class.getName()));
fragments.add(Fragment.instantiate(this,
FragmentTwo.class.getName()));
Add to view Pager
ViewPagerActivityAdapter mPagerAdapter;
this.mPagerAdapter = new ViewPagerActivityAdapter(
super.getSupportFragmentManager(), fragments);
mPager = (ViewPager) super.findViewById(R.id.pager);
mPager.setAdapter(this.mPagerAdapter);
You should use FragmentPagerAdapter or FragmentStatePagerAdapter for this.Here is sample code.
public class ViewPagerActivityAdapter extends FragmentPagerAdapter {
ArrayList<Fragment> tablist;
public ViewPagerActivityAdapter(ArrayList<Fragment> tablist) {
this.tablist = tablist;
}
#Override
public int getCount() {
return tablist.size();
}
#Override
public Fragment getItem(int position) {
return tablist.get(position);
}
}
Actually, i am implementing a TabLayout, so in main MainActivity, I load the TabFragment and in the tabFragment(contain two fragments) I used the ViewPager.
So the problem is when I am on fragment two in TabLayout and the after the screen goes off it will move to the Fragment one(Default one). So how can I tackle this one
Here is TabFragment Code:
public class TabFragment extends Fragment {
public TabFragment() {
// Required empty public constructor
}
public static TabLayout tabLayout;
public static ViewPager viewPager;
public static int int_items = 2 ;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View x=inflater.inflate(R.layout.content_main_menu,null);
tabLayout=(TabLayout) x.findViewById(R.id.tabs);
viewPager =(ViewPager) x.findViewById(R.id.viewpager);
setupViewPager(viewPager);
//viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
viewPager.setOffscreenPageLimit(1);
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return x;
}
private void setupViewPager(ViewPager viewPager) {
MyAdapter adapter = new MyAdapter(getChildFragmentManager());
adapter.addFragment(new HomeFragment(), "Fragment One");
adapter.addFragment(new Offers(), "fragment Two");
viewPager.setAdapter(adapter);
}
class MyAdapter extends FragmentPagerAdapter{
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public MyAdapter(FragmentManager fm) {
super(fm);
}
#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);
}
}
}
Use FragmentStatePagerAdapter instead of FragmentPagerAdapter. read documentation here. FragmentStatePagerAdapter only stores the savedInstanceState of fragments, and destroys all the fragments when they lose focus.
I have implemented a ViewPager in order to swipe between two Fragments like such:
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.statistics_general_vp, container, false);
mViewPager = (ViewPager) view.findViewById(R.id.pager);
mStatisticsPagerAdapter = new StatisticsPagerAdapter(getActivity().getSupportFragmentManager());
mViewPager.setAdapter(mStatisticsPagerAdapter);
return view;
}
public class StatisticsPagerAdapter extends FragmentStatePagerAdapter {
public StatisticsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
return new GeneralStatistics();
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
But for now my two slides display the same Fragment.
How may I have slide 1 display Fragment 1 and slide 2 Fragment 2?
have u created fragment1 and fragment 2 seperately?? if yes then do this - in activity holding these two fragments.
private void createViewPager(ViewPager viewPager) {
Log.d("activity", "viewpager");
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new Fragment1(), "");
adapter.addFrag(new Fragment2(), "");
viewPager.setAdapter(adapter);
}
create fragment like this -
public class Fragment1 extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.transaction_layout, container, false);
return v;
}
}
create viewpager like this -
class ViewPagerAdapter 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 addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
or if you want to make tab with icons use this method -
private void createTabIcons() {
Log.d("activity", "createtabicons");
TextView tabOne = (TextView) LayoutInflater.from(this).inflate(R.layout.tab_item2, null);
tabOne.setText("QR Scan");
tabOne.setTypeface(MRR);
tabOne.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.image1, 0, 0);
tabOne.setCompoundDrawablePadding(5);
tabLayout.getTabAt(0).setCustomView(tabOne);
tabLayout.getTabAt(0).getCustomView().setSelected(true);
TextView tabTwo = (TextView) LayoutInflater.from(this).inflate(R.layout.tab_item2, null);
tabTwo.setText("Mobile No.");
tabTwo.setTypeface(MRR);
tabTwo.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.image3, 0, 0);
tabLayout.getTabAt(1).setCustomView(tabTwo);
tabTwo.setCompoundDrawablePadding(5);
}
Hello i show you what i doing, i got 2 fragments in mainActivity
private void addFragments() {
List<Fragment> fragments = new ArrayList<>();
chatFragment = new ChatFragment();
remoteFragment = new RemoteFragment();
fragments.add(remoteFragment);
fragments.add(chatFragment);
MyPageAdapter adapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(TAB_REMOTE_POSITION)
.setIcon(getDrawable(R.drawable.ic_settings_remote_white_24dp));
tabLayout.getTabAt(TAB_SOCIAL_POSITION)
.setIcon(getDrawable(R.drawable.ic_group_white_24dp));
}
Here is my adapter:
class MyPageAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
}
and on OnCreate u should
addFragments();
also i bind the views with ButterKnife
#Bind(R.id.view_pager)
ViewPager viewPager;
#Bind(R.id.tab_layout)
TabLayout tabLayout;
but u can static implement this with android
And remember that u have listeners:
private void pageChangeListener() {
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) {
View view = getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager) getSystemService
(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
});
}
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());