1

I'm making a web browser. I've used fragments for tabbing but when the user goes from one tab to another and back again the webview's url resets and the user's url is lost. My question is; how do I stop the webview resetting when fragment switching. I've researched left right and center trying to solve this but haven't had any luck. Thank you!

public class HomeFragment extends Fragment {

public HomeFragment(){}

private WebView WebViewB1;
private ProgressBar Pbar1;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_home, container, false);

    Pbar1 = (ProgressBar) rootView.findViewById(R.id.progBar1);
    WebViewB1 = (WebView) rootView.findViewById(R.id.wvBrowserTab1);

    WebSettings webSettings = WebViewB1.getSettings();
    webSettings.setJavaScriptEnabled(true);
    WebViewB1.getSettings().setLoadWithOverviewMode(true);
    WebViewB1.getSettings().setUseWideViewPort(true);
    WebViewB1.getSettings().setBuiltInZoomControls(true);
    WebViewB1.getSettings().setAllowFileAccess(true);

    WebViewB1.setWebViewClient(new InsideWebViewClient());
    WebViewB1.setWebChromeClient(new WebChromeClient() {
        public void onProgressChanged(WebView view, int progress) 
        {
        if(progress < 100 && Pbar1.getVisibility() == ProgressBar.GONE){
            Pbar1.setVisibility(ProgressBar.VISIBLE);
        }
        Pbar1.setProgress(progress);
        if(progress == 100) {
            Pbar1.setVisibility(ProgressBar.GONE);
        }
     }
 });

        WebViewB1.loadUrl("http://google.com");

    return rootView;
}

}

Sliding menu activity below

public class MainActivity extends Activity {

private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;


private CharSequence mDrawerTitle;

private CharSequence mTitle;

private String[] navMenuTitles;
private TypedArray navMenuIcons;

private ArrayList<NavDrawerItem> navDrawerItems;
private NavDrawerListAdapter adapter;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mTitle = mDrawerTitle = getTitle();

    navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);

    navMenuIcons = getResources()
            .obtainTypedArray(R.array.nav_drawer_icons);

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    mDrawerList = (ListView) findViewById(R.id.list_slidermenu);

    navDrawerItems = new ArrayList<NavDrawerItem>();

    navDrawerItems.add(new NavDrawerItem(navMenuTitles[0], navMenuIcons.getResourceId(0, -1)));

    navDrawerItems.add(new NavDrawerItem(navMenuTitles[1], navMenuIcons.getResourceId(1, -1)));

    navDrawerItems.add(new NavDrawerItem(navMenuTitles[2], navMenuIcons.getResourceId(2, -1)));

    navDrawerItems.add(new NavDrawerItem(navMenuTitles[3], navMenuIcons.getResourceId(3, -1)));

    navDrawerItems.add(new NavDrawerItem(navMenuTitles[4], navMenuIcons.getResourceId(4, -1)));

    navDrawerItems.add(new NavDrawerItem(navMenuTitles[5], navMenuIcons.getResourceId(5, -1)));

    navMenuIcons.recycle();

    mDrawerList.setOnItemClickListener(new SlideMenuClickListener());

    adapter = new NavDrawerListAdapter(getApplicationContext(),
            navDrawerItems);
    mDrawerList.setAdapter(adapter);

    getActionBar().setDisplayHomeAsUpEnabled(true);
    getActionBar().setHomeButtonEnabled(true);

    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
            R.drawable.ic_drawer,
            R.string.app_name,
            R.string.app_name
    ) {
        public void onDrawerClosed(View view) {
            getActionBar().setTitle(mTitle);
            invalidateOptionsMenu();
        }

        public void onDrawerOpened(View drawerView) {
            getActionBar().setTitle(mDrawerTitle);
            invalidateOptionsMenu();
        }
    };
    mDrawerLayout.setDrawerListener(mDrawerToggle);

    if (savedInstanceState == null) {
        displayView(0);
    }
}
private class SlideMenuClickListener implements
        ListView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        displayView(position);
    }
}
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }
    switch (item.getItemId()) {
    case R.id.action_settings:
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
    menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
    return super.onPrepareOptionsMenu(menu);
}

private void displayView(int position) {
    Fragment fragment = null;

    switch (position) {
    case 0:
        fragment = new HomeFragment();
        break;
    case 1:
        fragment = new Tab2();
        break;
    case 2:
        fragment = new Tab3();
        break;
    case 3:
        fragment = new Tab4();
        break;
    case 4:
        fragment = new Tab5();
        break;
    case 5:
        fragment = new Tab6();
        break;

    default:
        break;
    }

    if (fragment != null) {
        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.frame_container, fragment).commit();

        mDrawerList.setItemChecked(position, true);
        mDrawerList.setSelection(position);
        setTitle(navMenuTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
    } else {
        Log.e("MainActivity", "Error in creating fragment");
    }
}

@Override
public void setTitle(CharSequence title) {
    mTitle = title;
    getActionBar().setTitle(mTitle);
}

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    mDrawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mDrawerToggle.onConfigurationChanged(newConfig);
}
 }
Tssomas
  • 362
  • 1
  • 4
  • 16
  • any code to show how do you manage browser/webview in your fragment? – Stan Jan 22 '14 at 20:39
  • @Stan I added the activity of one of the fragments. – Tssomas Jan 22 '14 at 21:35
  • 1
    r u sure your fragment is not being killed by the system when you leaves it? looks like the onCreateView fires every time you return to the fragment and thats why the webview reloads. you could try to keep the view linked as property and check if its nulll or not in onCreate anf if its not then just return it as a view – Stan Jan 22 '14 at 21:39
  • @Stan Sorry I don't understand what you mean by link the view as property. – Tssomas Jan 22 '14 at 21:59
  • I mean a property of class or field like `private View view`. – Stan Jan 22 '14 at 22:37
  • @Stan I was wondering if it could be caused by how the fragments are handled? I edited that in. Thanks. – Tssomas Jan 24 '14 at 20:52

2 Answers2

2

Ok, I'm not sure if its good idea but the following is what Im talking about:

    public abstract class AbstractFragment extends Fragment {

        private View mFragmentView;
        protected View getOnCreateView(LayoutInflater inflater, int layoutId){

             if (mFragmentView== null)
                 mFragmentView = inflater.inflate(layoutId, null);
             else
                 ((ViewGroup) mFragmentView.getParent()).removeView(mFragmentView);

             return mFragmentView;
        }


// this method needed to detect if fragment's view init is needed
// via initView() - its the method where you do findViewById()
// and sets up your webveiw, etc. The idea is to set up the view
// only once - in case when it has not been init-ed
// this will prevent your webview from reload from the start url
            protected boolean isFragmentViewInitialized;
            @Override
            public void onStart() {
                super.onStart();

                if (!isFragmentViewInitialized){
                    isFragmentViewInitialized = true;
                    initView();
                }

    }

        // use this method to setup the view
        public abstract void initView();

The idea is to extend this fragment by every fragment you need to stay alive and call its getOnCreateView from onCreate() like:

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            return getOnCreateView(inflater,R.layout.activity_about);
        }
        public void initView(){
            View rootView = getView();
Pbar1 = (ProgressBar) rootView.findViewById(R.id.progBar1);
    WebViewB1 = (WebView) rootView.findViewById(R.id.wvBrowserTab1);

    WebSettings webSettings = WebViewB1.getSettings();
    webSettings.setJavaScriptEnabled(true);
    WebViewB1.getSettings().setLoadWithOverviewMode(true);
    WebViewB1.getSettings().setUseWideViewPort(true);
    WebViewB1.getSettings().setBuiltInZoomControls(true);
    WebViewB1.getSettings().setAllowFileAccess(true);

    WebViewB1.setWebViewClient(new InsideWebViewClient());
    WebViewB1.setWebChromeClient(new WebChromeClient() {
        public void onProgressChanged(WebView view, int progress) 
        {
        if(progress < 100 && Pbar1.getVisibility() == ProgressBar.GONE){
            Pbar1.setVisibility(ProgressBar.VISIBLE);
        }
        Pbar1.setProgress(progress);
        if(progress == 100) {
            Pbar1.setVisibility(ProgressBar.GONE);
        }
     }
 });

        WebViewB1.loadUrl("http://google.com");
        }
Stan
  • 6,511
  • 8
  • 55
  • 87
  • ((ViewGroup) mThisView.getParent()).removeView(mFragmentView); "mThisView" cannot be resolved, I'm not sure what it's meant to define. Also do you mean extend whatever fragments I don't want to reset by the AbstractFragment class? Thanks for helping btw – Tssomas Jan 23 '14 at 16:51
  • 1
    there was an error ThisView is mFragmentView, so I edited the src - must be a working smaple. And yes I mean it. Every fragment you don't want to reset must be extended from this AbstractFragment. Also you should accept the answer if its helpful 4u. – Stan Jan 24 '14 at 12:05
  • Thanks for helping, one last problem though. Do I setup the view under "public abstract void initView();" in AbstractFragment src or under the current one. Sorry to be a pain, I'm still learning. :) – Tssomas Jan 24 '14 at 14:52
  • As you can see the `initView()` is ABSTRACT method (I assume you know what does it mean and if not then you shoud read about it and lern it). This means you MUST OVERRIDE it in every class you extend from AbstractFragment (thats why it has the Abstract word in its name). And yes, since you must override the `initView()` its the place where you setup your view. And it is shown in 2nd part of src clearly - cant you see I moved YOUR part of code to the `initView()`? – Stan Jan 28 '14 at 09:55
1

The fragment's were reloading every time they where reselected because of my tab listener

if (fragment != null) {
    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.frame_container, fragment).commit();

After making a better tabListener things where A-OK. Check this link for how the tab listener was improved - http://developer.android.com/guide/topics/ui/actionbar.html#Tabs

Tssomas
  • 362
  • 1
  • 4
  • 16
  • 1
    I understand you already answered your question, but this thread proved to be really helpful to me when dealing with the same issue you dealt: http://stackoverflow.com/questions/13149446/android-fragments-when-to-use-hide-show-or-add-remove-replace – louis1204 Feb 14 '14 at 07:14