Is it possible to change fragment defined i xml?
<fragment
android:id="#+id/fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
A have a lot of screens to show and switch. A tab-like menu on the right. Every tab have another tabs. I want to simply change this one by one. Maybe someone have better idea?
SOLVED
I used ViewPager and FragmentPagerAdapter
http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html
private ViewPager pager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_content);
pager = (ViewPager) findViewById(R.id.pager);
ControllerFragment cf = new ControllerFragment(getSupportFragmentManager(), getFragment());
pager.setAdapter(cf);
}
private List<Fragment> getFragments() {
List<Fragment> list = new ArrayList<Fragment>();
FirstFragment fragment = new FirstFragment();
list.add(fragment);
return list;
}
public void onTabSelected(View v) {
switch (v.getId()) {
case R.id.ivProfile:
pager.setCurrentItem(0);
}
}
public class ControllerFragment extends FragmentPagerAdapter {
List<Fragment> fragments;
public ControllerFragment(FragmentManager fm, List<Fragment> fragments){
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int arg0){
return this.fragments.get(arg0);
}
#Override
public int getCount(){
return this.fragments.size();
}
}
Related
I have implemented swipe fragments using
https://developer.android.com/training/animation/screen-slide.html
or
https://developer.android.com/training/implementing-navigation/lateral.html
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/some_background_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Here is MyActivity.java:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_overlay);
// Instantiate a ViewPager and a PagerAdapter.
mPager = findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
mPager.setCurrentItem(1);
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter{
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 0)
return new Page0Fragment();
else
return new Page1Fragment();
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
Now I am trying to access the currently viewed fragment like this
public void myonclickmethod(View view) {
FragmentManager fm = getSupportFragmentManager();
fragment = fm.findFragmentById(R.id.pager);//<=**This is coming as instance of Page0Fragment inspite of me intializing the activity with Page1Fragment and also currently standing on Page1Fragment without any swiping**
}
First, you need to change your ScreenSlidePagerAdapter to return the same instance everytime instead of new Page0Fragment like:
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter{
List<Fragment> fragments = new ArrayList<>();
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
fragments.add(new Page0Fragment());
fragments.add(new Page1Fragment());
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
Now for getting visible fragment, do like:
public void myonclickmethod(View view) {
int currentPosition = mPager.getCurrentItem();
if(currentPosition == 0 {
Page0Fragment page0Fragment = (Page0Fragment)mPagerAdapter.getItem(currentPosition);
page0Fragment.doSomething();
} else {
Page1Fragment page1Fragment =(Page1Fragment)mPagerAdapter.getItem(currentPosition);
pag1Fragment.doSomething();
}
You can get the current fragment by calling getItem() with the current position on your adapter like this
public void myonclickmethod() {
Fragment fragment = adapter.getItem(viewpager.getCurrentItem())
}
but come across a problem. When i run the app i don't see that my screen is swipes, and also i can't see tabs. Can you help
Here is my code:
public class MainActivity extends AppCompatActivity {
Toolbar toolbar;
TabLayout tabLayout;
ViewPager viewPager;
ViewPagerAdapter viewPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar= (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
tabLayout= (TabLayout) findViewById(R.id.tablayout);
viewPager= (ViewPager) findViewById(R.id.viewpager);
viewPagerAdapter=new ViewPagerAdapter(getSupportFragmentManager());
viewPagerAdapter.addFragments(new Home(),"Home");
// viewPagerAdapter.addFragments(new Top(),"Top");
// viewPagerAdapter.addFragments(new Buttom(),"Buttom");
viewPager.setAdapter(viewPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
}
}
I'm getting an error on commented lines.
Here is my Pager Adapters code:
public class ViewPagerAdapter extends FragmentPagerAdapter {
ArrayList<Fragment> fragments= new ArrayList<>();
ArrayList<String> tabTitles = new ArrayList<>();
public void addFragments(Home fragments, String titles){
this.fragments.add(fragments);
this.tabTitles.add(titles);
}
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return tabTitles.get(position);
}
}
In my XML i've only Viewpager, Toolbarand TabLayout.
Please Help.
You need to change your type of parameter in addFragments
try this :
public void addFragments(Fragment fragments, String titles)
instead of
public void addFragments(Home fragments, String titles)
I hope this may help you
Probably is this:
Home fragments
Try change to this:
Fragment fragments
Method be like this:
public void addFragments(Fragment fragments, String titles){
this.fragments.add(fragments);
this.tabTitles.add(titles);
}
So you in the method you have Home fragments as paramter and when you call other fragments diferent than Home because parameter is Home you get error, to fix just do like I said change parameter to Fragment fragments. it's a small mistake.
Try this.
In your xml layout file.
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
app:tabSelectedTextColor="#android:color/white"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
In your mainactivity
tabLayout.addTab(tabLayout_ordering.newTab().setText("Tab 1"));
tabLayout.addTab(tabLayout_ordering.newTab().setText("Tab 2"));
viewPager.setAdapter(pagerAdapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout_ordering));
tabLayout_ordering.setOnTabSelectedListener(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) {
}
});
Then create a class for your pager adapter.
public class TabPagerAdapter extends FragmentPagerAdapter {
public TabPagerAdapter(FragmentManager fm, int tabCount) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
FragmentA fragmentA = new FragmentA();
return fragmentFoods;
case 1:
FragmentDrinks fragmentA = new FragmentA();
return fragmentA;
default:
return null;
}
}
#Override
public int getCount() {
return 2;
}
}
I have a ViewPager, and there's a button when clicked, deletes the current fragment from the PagerAdapter, and prevents the user from swiping there. I researched and found this Remove Fragment Page from ViewPager in Android to be the closest to what I want.
In my fragment to be deleted:
#Override
public void onClick(View v) {
db.delete(count); //SqliteDatabase deletion
displayActivity.removeCurrentFragment(0);
}
My PagerAdapter
public class PagerAdapter extends FragmentPagerAdapter {
long baseId = 0;
public static List<Fragment> fragmentArrayList = new ArrayList<Fragment>();
public PagerAdapter(FragmentManager fm){
super(fm);
fragmentArrayList.add(new FragmentOne());
fragmentArrayList.add(new FragmentTwo());
fragmentArrayList.add(new FragmentThree());
}
#Override
public Fragment getItem(int position) {
return fragmentArrayList.get(position);
}
}
#Override
public int getCount() {
return fragmentArrayList.size();
}
#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;
}
}
This is the activity (DisplayActivity) that hosts the pagerAdapter
public class DisplayActivity extends AppCompatActivity {
ViewPager viewPager;
PagerAdapter pagerAdapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.db_layout);
viewPager = (ViewPager) findViewById(R.id.pager);
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
}
public void removeCurrentFragment(int position){
pagerAdapter.fragmentArrayList.remove(position);
pagerAdapter.notifyDataSetChanged();
}
What did I do wrong here?
I'm getting an error of
.removeCurrentFragment(int)' on a null object reference
So this error suggests that my method call removeCurrentFragment is referencing a null object, how do I fix it?
You have used
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
so you are creating a new local variable instead of using your global variable. Instead change your line as
pagerAdapter = new PagerAdapter(getSupportFragmentManager());
It should work.
Your onCreate method should look like this.
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.db_layout);
viewPager = (ViewPager) findViewById(R.id.pager);
pagerAdapter = new PagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
}
In my project I have a tab layout and a fragments viewpager. When I load the fragments and tabs the tab index and the displayed fragment is out of sync, and also when I swipe back and forth the fragments are not in sync with the tabs. I checked the getItem(int position) and the getTitle(int position) methods both have the same position number and the corresponding entries in the ArrayList<Fragments> and the ArrayList<String> (for tab headings) are correct but some how the tabs display is out of sync with the view pager.
Here is my fragmentPagerAdapter.java
public class DetailsFragmentPagerAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragments;
private ArrayList<String> titles;
public DetailsFragmentPagerAdapter(FragmentManager fm) {
super(fm);
fragments = new ArrayList<>();
titles = new ArrayList<>();
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return titles.size();
}
#Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
public void setFragment(Fragment fragment, String title) {
fragments.add(fragment);
titles.add(title);
notifyDataSetChanged();
}
}
this is activity on create.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
tabLayout = (TabLayout) findViewById(R.id.detailsTabs);
viewPager = (ViewPager) findViewById(R.id.viewPager);
new GetCategoriesAsync2().execute();
}
the async task's doInBackground is calling is preparing arraylist
and the onPostExecute
#Override
protected void onPostExecute(Void aVoid) {
int size = lists.size();
ArrayList<Fragment> fragments = new ArrayList<>(size);
ArrayList<String> titles = new ArrayList<>(size);
for (int i = 0; i < lists.size(); i++) {
ArrayList<String> x = lists.get(i);
titles.add(x.remove(0));
fragments.add(DetailsListFragment.newInstance(x));
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentPagerAdapter = new DetailsFragmentPagerAdapter(fragmentManager);
fragmentPagerAdapter.setFragments(fragments,titles);
viewPager.setAdapter(fragmentPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
progressDialog.dismiss();
}
I am using design support library 23.0.1 and the build target is 23.
how can I fix this tab layout out of sync?
if you use a TabLayout, you need to connect it to the adapter
If you're using a ViewPager together with this layout, you can use
setTabsFromPagerAdapter(PagerAdapter) which will populate the tabs
using the given PagerAdapter's page titles. You should also use a
TabLayout.TabLayoutOnPageChangeListener to forward the scroll and
selection changes to this layout like so:
ViewPager viewPager = ...;
TabLayout tabLayout = ...;
viewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener(tabLayout));
Try this, it worked for me
public class DetailsFragmentPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragments= new ArrayList<Fragment>();
private final List<String> titles= new ArrayList<String>();
public DetailsFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
public void setFragment(Fragment fragment, String title) {
fragments.add(fragment);
titles.add(title);
}
}
And Change
fragmentPagerAdapter.setFragments(fragments,titles); To
for (int i=0;i<fragments.size();i++)
{
adapter.setFragments(fragments.get(i),titles.get(i));
}
Check this out
it's a demo app that uses a TabLayout with a ViewPager
https://github.com/chrisbanes/cheesesquare
and if you don't know the number of the fragments that you will have in the ViewPager
your pageadapter should extends FragmentStatePagerAdapter
https://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html
I know many applications using fragments in ViewPager. I need it in my application too. I have no found any guide how I can to do it exclude this. And here is my code:
public class MainActivity extends FragmentActivity {
Vector<Fragment> fragments;
ViewPager viewPager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
viewPager = (ViewPager) findViewById(R.id.pager);
fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, Fragment1.class.getName()));
fragments.add(Fragment.instantiate(this, Fragment2.class.getName()));
viewPager.setOffscreenPageLimit(fragments.size());
PagerAdapter pagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), fragments);
viewPager.setAdapter(pagerAdapter);
viewPager.setCurrentItem(0);
}
class PagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public PagerAdapter(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();
}
}
}
But this code doesn't working well. Sometimes I get error in my Fragment1 about getActivity() return null. I read many posts from this site and other about this error and now I know that is bad way - use Vector for storing fragments. But I still don't know, how to do ViewPager with fragments properly. Please, help.
Even I had trouble understanding the concept at first and I won't say that I fully understood it. But,
Here's how I am using fragment in my sample application:
Step 1: Creating my Adapter:
public class AllPagesAdapter extends FragmentStatePagerAdapter {
public AllPagesAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
case 3:
return new Fragment4();
case 4:
return new Fragment5();
}
return null;
}
#Override
public int getCount() {
return 5;
}
}
Step 2: In the main activity, I am extending fragment activity and implementing an ActionBar.TabListener. Here's how I am doing it:
public class SomeActivity extends FragmentActivity implements ActionBar.TabListener {
public ViewPager viewPager;
private AllPagesAdapter mAdapter;
private ActionBar actionBar;
private String [] tabs = {"Fragment1","Fragment2","Fragment3","Fragment4","Fragment5"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Initializing all stuff
viewPager = (ViewPager)findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new AllPagesAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//Add the tabs here
for(String tab_name:tabs){
actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
#Override
public void onPageSelected(int position){
//on Page change, that particular page should be selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0,float arg1,int arg2){
}
#Override
public void onPageScrollStateChanged(int position){
}
});
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction fragmentTransaction) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction fragmentTransaction) {
viewPager.setCurrentItem(tab.getPosition());
}
}
Step 3: I have just one fragment for this example:
Here's the code:
public class Fragment1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//Can be layout you want it to be.
View databaseview = inflater.inflate(R.layout.database, container, false);
return databaseview;
}
}
Step 4: Last part is the layout: This will be starting point.
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v4.view.ViewPager>
Lastly, one important thing is that, number of fragments should be equal to the string array defined in the main activity. If not, the app crashes.
Hope I explained it well..:)
I know this is a very old post but this answer can be used for future viewers.