I am sure I am doing this wrong. This is my first attempt at using a Fragment for anything. I have a very simple application. Nothing ever shows up in my tabs.
I am sure it's a stupid mistake somewhere. Anyone have any ideas?
Here is web.xml:
Next, here is the code from the main activity that should show this webview:
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Fragment fragment = new WebViewFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return 4;
}
}
public static class WebViewFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View mainView = (View) inflater.inflate(R.layout.web, container, false);
WebView webView = (WebView) mainView.findViewById(R.id.webview);
webView.loadUrl("http://www.google.com");
return mainView;
}
}
}
Well this is embarrassing. Apparently if you forget to specify permissions like say for the internet, the WebView doesn't do much. I wish Android errored out when you make a request you don't have permission for. I looked at this for 3 hours before posting here. Should have waited 10 more minutes!
Related
i have an activity with fragments and inside one fragment i nested 3 other fragments and i use viewpager to navigate between them, but when i want to change this "main fragment" which has the nested fragments i call transaction.replace and it changes the fragment but when i come back at this fragment the nested fragments are not shown again, how can i reload them everytime i launch my fragment ?
i have tried to implement them inside my xml layout but it doesn't seems to work, i need help please !
FragmentWithViewPager:
public class FragmentWithViewPager extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_fragwithviewpager, null);
mActionBar = getActivity().getActionBar();
mActionBar.show();
mActionBar.setTitle("MyFragment");
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mPager = (ViewPager) view
.findViewById(R.id.MyFragmentMainPager);
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mPager.setCurrentItem(tab.getPosition());
tab.setIcon(tabIcon_active[tab.getPosition()]);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// /tab.setIcon(null);
tab.setIcon(tabIcon[tab.getPosition()]);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
tab.setIcon(tabIcon_active[tab.getPosition()]);
}
};
if(mActionBar.getTabCount() < 3){
for (int i=0; i < tabIcon.length; i++)
{
mActionBar.addTab(mActionBar.newTab()
.setIcon(tabIcon[i])
.setTabListener(tabListener));
}
}
mPagerAdapter = new MyFragmentsMainPagerAdapter(getFragmentManager());
new setAdapterTask().execute();
return view;
}
rivate class setAdapterTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void result) {
mPager.setAdapter(mPagerAdapter);
mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
}
});
}
}
The Fragment that has the 3 other Fragments nested with the Viewpager should use the ChildFragmentManager.
In your activity you have your main_fragment_container in the xml that you replace or add your fragments. Correct? If true then inside the Fragment that has the Viewpager all the fragment transactions are automatically done for you if you used a FragmentPagerAdapter to accompany the Viewpager.
Then If you replace or add fragments in your main_fragment_container should not affect the contents of the Viewpager at all. When you reload the fragment with the viewpager the viewpager will reload as well if you have passed it the ChildFragmentManager.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_parent, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ViewPager mViewPager = (ViewPager) view.findViewById(R.id.viewPager);
mViewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
}
public static class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 4;
}
#Override
public Fragment getItem(int position) {
Bundle args = new Bundle();
args.putInt(TextViewFragment.POSITION_KEY, position);
return TextViewFragment.newInstance(args);
}
}
hide(MainFragment)
add(NewFragment)->
remove or hide(NewFragment)
show(MainFragment).
getSupportFragmentManager().beginTransition().hide(MainFragment).commit().
getSupportFragmentManager().beginTransition().add(R.id.containerid,MainFragment).commit().
This is the autogenerated code from android studio when selecting a 3 tabbed layout. The problem is when it starts at the first tab, it will call onCreateView in class PlaceholderFragment. When i switch to the 2nd tab, it calls it again for that tab. Now the problem starts with going back to tab1, it doesn't call onCreateView. Now if i go to tab3 it gets called for that tab, then go back to tab1 it now gets called. So tab1's onCreateView never gets called if i go from tab2 to tab1 but gets called going from tab3 to tab1. I can't figure out why it doesn't destroy this view in that specific sequence only.
I haven't modified this auto-generated code so i'd think it would have worked correctly.
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
public static class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
Viewpager has one public method named setOffScreenPageLimit() which indicates the number of pages that will be retained to either side of the current page in the view hierarchy in an idle state.
When you use the default implementation of setOffscreenPageLimit() it is only loading the one fragment which is to the right of it.
For example,
if you are currently on index1, it has index 2 loaded in memory but not index 0, so swiping to left will load a new fragment from scratch. Use setOffScreenLimit(1), setOffScreenLimit(2) etc. it will help clear out your doubts about the concept.
I used sherlock to have action bar in android 2.3, everythings is ok but the problem is:
I have 4 tabs, after doing some works on fisrt tab if I go to the second and third tab when I came back to first tab the contetnt is ok but when I go to the last tab and then came back to the first, the conent of first fragment was restarted and everything was gone, below is my codes, why is it like that?
MainActivity:
public class MainActivity extends SherlockFragmentActivity implements
TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private com.actionbarsherlock.app.ActionBar actionBar;
private String[] tabs = { "weblog", "news", "image", "web" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
actionBar.setHomeButtonEnabled(false);
viewPager.setAdapter(mAdapter);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.addTab(actionBar.newTab().setText(tabs[0])
.setTabListener(this), false);
actionBar.addTab(actionBar.newTab().setText(tabs[1])
.setTabListener(this), false);
actionBar.addTab(actionBar.newTab().setText(tabs[2])
.setTabListener(this), false);
actionBar.addTab(actionBar.newTab().setText(tabs[3])
.setTabListener(this), true);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public void onTabSelected(com.actionbarsherlock.app.ActionBar.Tab tab,
android.support.v4.app.FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(com.actionbarsherlock.app.ActionBar.Tab tab,
android.support.v4.app.FragmentTransaction ft) {
}
#Override
public void onTabReselected(com.actionbarsherlock.app.ActionBar.Tab tab,
android.support.v4.app.FragmentTransaction ft) {
}
}
TabsPagerAdapter:
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
return new Blog();
case 1:
return new News();
case 2:
return new Image();
case 3:
return new Search();
}
return null;
}
#Override
public int getCount() {
return 4;
}
}
The ViewPager typically only keeps a few fragments in an "idle" state and recreates the other fragments as a performance optimization. See this answer.
To override this behavior, you can call setOffscreenPageLimit
// keep 3 tabs in memory on either side of the current tab
viewPager.setOffscreenPageLimit(3);
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.
I've looked at quite a lot of code and can't figure this out. http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html
It has to be something simple.
I'm showing most of the code. The error is in the next section.
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener {
public static final int TAB_COUNT = 3;
public static InputMethodManager inputManager;
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSectionsPagerAdapter = new SectionsPagerAdapter(
getSupportFragmentManager());
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab.
mViewPager
.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
// To control keyboard pop-up
inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public void onTabUnselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabReselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
}
This is where my error is.
case 1 of getItem, Type mismatch: Cannot convert from MainActivity.HistoryFragment to Fragment. it is telling me to either change method return type to HistoryFragment or change return type of newInstance() to Fragment. Where I can't do either. Other examples I've seen look almost identical to my code. I have tried with and without passing an argument.
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
Fragment tipCalc = new TipCalcFragment();
return tipCalc;
case 1:
// Fragment history = new HistoryFragment();
return HistoryFragment.newInstance(i); //ERROR HERE
case 2:
Fragment stats = new StatsFragment();
return stats;
}
return null;
}
And my HistoryFragment that extends ListFragment. In the end it won't be pulling from the String[] values but from database resources. I just wanted to setup a structure first and see it/play with the layout.
public static class HistoryFragment extends ListFragment {
// public HistoryFragment() {
// }
String[] values = new String[] { ... };
static HistoryFragment newInstance(int num) {
HistoryFragment history = new HistoryFragment();
Bundle args = new Bundle();
args.putInt("num", num);
history.setArguments(args);
return history;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.history, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, android.R.id.text1,
values));
}
}
I figured it out after getting some sleep. I was importing android.app.ListFragment instead of android.support.v4.app.ListFragment
I think you will have to typecast to fragment before returning. So try this
Fragment history = HistoryFragment.newInstance(i);
return history;