MapView messed up my fragment transactions? - android

I have a fragment with a mapview. I can open another fragment (call it listfragment) from the action bar, it works fine. But if I rotate the screen, and then try to open the listfragment, it does not load, instead the mapview flickers on time (the map in the view goes blank and then appears again). If I try to load the listfragment again by clicking the menuitem on the action bar, the app crashes with
java.lang.IllegalStateException: Fragment already added:
Part of MainActivity that loads the fragment:
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mNewTrackFragment = (NewTrackFragment) getFragmentManager()
.findFragmentByTag(TAG_NEW_TRACK_FRAGMENT);
if (mNewTrackFragment == null) {
mNewTrackFragment = NewTrackFragment.newInstance();
}
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.fragment_container, mNewTrackFragment)
.commit();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_track_list) {
if (null == mTrackListFragment) {
mTrackListFragment = TrackListFragment.newInstance();
}
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, mTrackListFragment, TAG_TRACK_LIST_FRAGMENT)
.addToBackStack(null)
.commit();
return true;
}
Part of NewTrackFragment with the MapView:
public NewTrackFragment() {
}
public static NewTrackFragment newInstance() {
NewTrackFragment fragment = new NewTrackFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_new_track, container, false);
mTrackTitleTV = (TextView) view.findViewById(R.id.tv_track_title);
mDistanceTV = (TextView) view.findViewById(R.id.tv_distance);
mElapsedTimeTV = (TextView) view.findViewById(R.id.tv_elapsed_time);
mSpeedTV = (TextView) view.findViewById(R.id.tv_speed);
mAscentTV = (TextView) view.findViewById(R.id.tv_ascent);
mDescentTV = (TextView) view.findViewById(R.id.tv_descent);
mAltitudeTV = (TextView) view.findViewById(R.id.tv_altitude);
mStartStopFab = (FloatingActionButton) view.findViewById(R.id.fab_startstop);
mMapView = (MapView) view.findViewById(R.id.new_track_mapview);
setupMapView(savedInstanceState);
return view;
}
private void setupMapView(Bundle savedInstanceState) {
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(this);
}
I googled the best of the evening for some info about it but found nothing similar.

There's a couple of things wrong here. Right now, you are not passing TAG_NEW_TRACK_FRAGMENT as a tag in the call to add within onCreate. Because of this, you are adding a NewTrackFragment instance without an associated tag, and therefore the call to findFragmentByTag will always return null. Essentially, you are creating a new instance of NewTrackFragment every time you rotate the device. This is not good, because the state of the FragmentManager is preserved across device rotations, meaning it is still holding on to each Fragment you add to it. Because you are unconditionally calling add, the FragmentManager will end up holding multiple instances of NewTrackFragment.
With that said, what you should do is add the tag in the call to add and only call add once you know the FragmentManager is not currently holding on to an instance of NewTrackFragment:
mNewTrackFragment = (NewTrackFragment) getFragmentManager()
.findFragmentByTag(TAG_NEW_TRACK_FRAGMENT);
if (mNewTrackFragment == null) {
mNewTrackFragment = NewTrackFragment.newInstance();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.fragment_container, mNewTrackFragment, TAG_NEW_TRACK_FRAGMENT)
.commit();
}
You might want to do something similar with your TrackListFragment as well:
if (id == R.id.action_track_list) {
FragmentManager fragmentManager = getFragmentManager();
mTrackListFragment = (TrackListFragment) fragmentManager.findFragmentByTag(TAG_TRACK_LIST_FRAGMENT);
if (null == mTrackListFragment) {
mTrackListFragment = TrackListFragment.newInstance();
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, mTrackListFragment, TAG_TRACK_LIST_FRAGMENT)
.addToBackStack(null)
.commit();
}
}

Related

After changing the screen orientation the fragment is duplicated

I have an activity that creates a fragment programmatically.
the fragment has another fragment inside it.
activity contains fragment A.
fragment A contains fragment B.
everything works perfectly,
except in case I change the orientation of the screen.
when the screen orientation is changed, the fragment is duplicated.
I looked for solutions to my problem on the web (here too),
I covered the official android documentation,
I tried to do my tests:
but I have not come back to find a solution!
I saw other people who have solved by putting the code to create the fragment in this if:
if (savedInstanceState == null) {
}
but it does not work for me!
if I put the code to create the fragment inside that one, no fragment is created.
I tried to segure the life cycle of the activity with the debugging.
when the activity is created for the first time the app passes here:
activity
fragment, onattach
fragment, oncreate
fragment, oncreateview
when I turn the screen horizontally, the app passes here:
fragment, onattach
fragment, oncreate
activity
fragment, oncreateview
fragment, onattach
fragment, oncreate
fragment, oncreateview
activity:
public class Activity extends AppCompatActivity {
ScrollView sv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
sv = findViewById(R.id.sv);
LinearLayout ll_fragment = new LinearLayout(this);
ll_fragment.setId(100);
ll_fragment.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams LLParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
ll_fragment.setLayoutParams(LLParams);
ll.addView(ll_fragment);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ArrayList<Integer> AL_Int = new ArrayList<Integer>();
AL_Int.add(sv.getId());
fragment = FragmentA.newInstance(AL_Int);
fragmentTransaction.add(ll_fragment.getId(), fragment);
fragmentTransaction.commit();
}
fragment:
public class FragmentA extends Fragment {
public static FragmentA newInstance(ArrayList<Integer> AL_Int_sv_ID) {
FragmentA f = new FragmentA();
Bundle b = new Bundle();
if(AL_Int_sv_ID.get(0) != null){
b.putInt("int_sv_ID", AL_Int_sv_ID.get(0));
b.putBoolean("bool_sv", true);
}else{
b.putInt("int_sv_ID", -1);
b.putBoolean("bool_sv", false);
}
f.setArguments(b);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
int int_ScrollView_ID = args.getInt("int_sv_ID");
boolean bool_ScrollView = args.getBoolean("bool_sv");
bool_sv = bool_ScrollView;
int_sv_ID = int_ScrollView_ID;
if(bool_sv){
sv = getActivity().findViewById(int_ScrollView_ID);
sv = FA.findViewById(int_ScrollView_ID);
}
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
LinearLayout ll = new LinearLayout(getActivity());
ll.setOrientation(LinearLayout.VERTICAL);
LLParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
ll.setLayoutParams(LLParams);
ll.setId(20);
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
FragmentB fragmentB = new FragmentB();
transaction.add(20, fragmentB);
transaction.commit();
return ll;
}
You need to try again the if (savedInstanceState == null) method. It is the correct way to handle it, you might be doing something wrong, only wrap this 3 lines in the if:
fragment = AutoCompleteTextView_Fragment.newInstance(AL_Int);
fragmentTransaction.add(ll_fragment.getId(), fragment);
fragmentTransaction.commit();
had this same problem, try fragmentTransaction.replace() instead of
fragmentTransaction.add()

Android OnBackpressed in Fragment Null Exception

Hello I'm trying to override back button to back to home page it gives me this error when press back from BasicInfoFragment then press back again in home fragment (MainFragment)
it gives
java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.v4.app.FragmentManager android.support.v4.app.FragmentActivity.getSupportFragmentManager()' on a null object reference
then the application crushs
java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.v4.app.FragmentManager android.support.v4.app.FragmentActivity.getSupportFragmentManager()' on a null object reference
at com.teqneia.blooddonation.BasicInfoFragment.doBack(BasicInfoFragment.java:245)
at com.teqneia.blooddonation.MainActivity.onBackPressed(MainActivity.java:258)
at android.app.Activity.onKeyUp(Activity.java:2530)
at android.view.KeyEvent.dispatch(KeyEvent.java:2726)
at android.app.Activity.dispatchKeyEvent(Activity.java:2798)
at android.support.v7.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:543)
at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:53)
at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:315)
at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:53)
at com.android.internal.policy.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2368)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4333)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4295)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3836)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3889)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3855)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3981)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3863)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4038)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3836)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3889)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3855)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3863)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3836)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3889)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3855)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4014)
at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:4175)
at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2378)
at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1999)
at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1990)
at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2355)
at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:330)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5546)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684)
BasicInfoFragment java
public class BasicInfoFragment extends Fragment implements MainActivity.OnBackPressedListener, View.OnClickListener {
.
.
public BasicInfoFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_basic_info, container, false);
initialize(view);
// Inflate the layout for this fragment
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((MainActivity) getActivity()).setOnBackPressedListener(this);
}
void initialize(View view) {
//VIEW OLD DATA AND ADD LISTENERS
name = (EditText) view.findViewById(R.id.name_edit);
email = (EditText) view.findViewById(R.id.email_edit);
mobile = (EditText) view.findViewById(R.id.mobile_edit);
LastDonation = (EditText) view.findViewById(R.id.date_edit);
LastDonation.setInputType(InputType.TYPE_NULL);
LastDonation.requestFocus();
LastDonation.setOnClickListener(this);
//TAKE DATA FROM SERVER
//name.setText("");
//email.setText();
//mob.setText();
//LastDonation.setText();
b = (Button) view.findViewById(R.id.save_edit);
b.setOnClickListener(this);
//get Radio Groups
radioBgGroup = (RadioGroup) view.findViewById(R.id.bg_edit);
radioRhGroup = (RadioGroup) view.findViewById(R.id.rh_edit);
if (mSharedGetter.getBloodType().equals("A")) {
}
#Override
public void doBack() {
Fragment fragment = null;
fragment = new MainFragment();
FragmentManager fm = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.commit();
}
MainActivity
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
.
.
.
.
.
.
protected OnBackPressedListener onBackPressedListener;
public interface OnBackPressedListener {
void doBack();
}
public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
this.onBackPressedListener = onBackPressedListener;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Initially Load MainFFragment xml
setContentView(R.layout.activity_main);
Fragment fragment = new MainFragment();
//Apply fragment
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
View header = navigationView.getHeaderView(0);
TVnav_name = (TextView) header.findViewById(R.id.nav_name);
navigationView.setNavigationItemSelectedListener(this);
TVnav_name.setText(mSharedGetter.getUserName());
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (onBackPressedListener != null)
onBackPressedListener.doBack();
else
super.onBackPressed();
}
#Override
protected void onDestroy() {
onBackPressedListener = null;
super.onDestroy();
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
Fragment fragment = null;
if (id == R.id.nav_edit_info) {
fragment = new BasicInfoFragment();
if (fragment != null) {
//Apply fragment
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
} else if (id == R.id.nav_home) {
fragment = new MainFragment();
if (fragment != null) {
//Apply fragment
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment, "MY_FRAGMENT");
fragmentTransaction.commit();
}
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
MainFragment
public class MainFragment extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_main, container, false);
return view;
}
//DIALOG BUILDER
new AlertDialog.Builder(getActivity())
.setTitle("DONATION REQUEST")
.setView(dialogView)
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Request now", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//Send the request
Dialog f = (Dialog) dialog;
}
}).show();
}
}
in doBack method getActivity() is returning null. It is also not needed as you can call getFragmentManager() from a Fragment. Here's how to do just that, with fewer lines.
#Override
public void doBack() {
Fragment fragment = new MainFragment();
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, fragment)
.commit();
}
in your BasicInfoFragment you have
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((MainActivity) getActivity()).setOnBackPressedListener(this);
}
MainFragment should have the same line, otherwise pressing back twice as you described will invoke BasicInfoFragment doBack() twice.
Since you detach it from its activity after the first back click you get a null value from getActivity() here when the second back arrives:
FragmentManager fm = getActivity().getSupportFragmentManager();
Always call like this.
//In Activity
FragmentManager fm = getSupportFragmentManager();
//In Fragment
FragmentManager fm = getActivity().getFragmentManager();
//For Nested Fragments
FragmentManager fm = getChildFragmentManager();
I think it would be better if you describe what you are trying to solve. I believe you may be having an error in the concept of how fragments work and the management of the back stack.
I believe the problem is your back event is being triggered but this is popping the fragment out but the reference is still there.
Take a look at:
https://aarcoraci.wordpress.com/2017/02/13/android-tutorial-drawer-and-fragment-navigation-made-easyier/

Strange behavior of FragmentManager.findFragmentByTag()

Ok, today I noticed a strange behavior of findFragmentByTag(): if I rotate the screen one time the fragment is returned correctly, but on second rotation I always get null. Am I Doing something wrong? is there a way to fix this?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentByTag("frag");
if (f == null){
Log.e("Fragment","null");
f = new Fragment();
}
f.setRetainInstance(true);
fm.beginTransaction().remove(f).add(f, "frag").commit();
}
Try to call setRetainInstance(true); in fragment's onCreate() and change the code above to:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstance == null){
FragmentManager fm = getSupportFragmentManager();
Fragment f = new Fragment();
fm.beginTransaction().add(f, "frag").commit();
}
}
Set the id as well to show it in a layout view group

Android - Dynamic Fragment problems on orientation change

I'm having a problem with dynamic fragment . If I'm not change orientation , it work fine . When I change orientation , I click on ListView item . It's not change textview .
This is DynamicActivity class
public class DynamicActivity extends Activity implements FragmentCoordinator{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dynamic);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
ListContentFragment listContentFragment = new ListContentFragment();
DetailsContentFragment detailsContentFragment = new DetailsContentFragment();
transaction.add(R.id.listContainer, listContentFragment,"listContent");
transaction.add(R.id.detailsContainer, detailsContentFragment,"detailsContent");
transaction.commit();
}
#Override
public void onSetContentDetails(int index) {
FragmentManager fragmentManager = getFragmentManager();
DetailsContentFragment detailsContentFragment = (DetailsContentFragment)fragmentManager.findFragmentByTag("detailsContent");
detailsContentFragment.setContentDetails(index);
}
}
And DetailsContentFragment class
public class DetailsContentFragment extends Fragment {
TextView lbMess;
String[] array;
int saveIndex;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.details_content_fragment, container,false);
array = getResources().getStringArray(R.array.list_details);
lbMess = (TextView)v.findViewById(R.id.lbDetails);
int currentIndex = savedInstanceState == null ? 0 : savedInstanceState.getInt("indexContent",0);
setContentDetails(currentIndex);
return v;
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt("indexContent", saveIndex);
}
public void setContentDetails(int index) {
saveIndex = index;
lbMess.setText(array[saveIndex]);
}
}
I have debug but it doesn't have any error . Please give me some advice
I found the problems are :
When the system destroys and re-creates an activity because of a run-time configuration change, the activity automatically
re-instantiates existing fragments.
This isn’t a problem for “static” fragments declared in the activity’s layout.
But for “dynamic” fragments, i need to test for this situation to prevent creating a second instance of my fragment.
I check the Bundle argument passed to my activity’s onCreate() is null.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dynamic);
if(savedInstanceState == null)
{
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
ListContentFragment listContentFragment = new ListContentFragment();
DetailsContentFragment detailsContentFragment = new DetailsContentFragment();
transaction.add(R.id.listContainer, listContentFragment,"listContent");
transaction.add(R.id.detailsContainer, detailsContentFragment,"detailsContent");
transaction.commit();
}
}
And it work fine . I think is helpful for someone have same problems .

WebView inside SherlockFragment - FragmentTransaction.Detach() does not remove the webview

I am using ActionBarSherlock's action bar tabs in my application with each tab populated by a single fragment inside a SherlockActivity Tabs.
One of my Tabs contains a fragment, FragmentHome, with a list of news articles. When an article is selected, FragmentHome is replaced by another fragment, FragmentNews.
FragmentNews just contains a webview to load the selected article. The article is loaded fine. I override the onBackPressed in my activity so that FragmentHome is reattached and FragmentNews is removed.
While there are no errors, the webview inside FragmentHome is never removed from the view and overlaps with other fragments. (See screenshots)
Its weird because the same code works for a another SherlockFragment with ListView in it but is messed up when using a WebView. Here is the code to replace FragmentHome with FragmentNews initially:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
listNews.setItemChecked(position, true);
Bundle bundle = new Bundle();
bundle.putStringArray("NEWS",
new String[] {
mNews.newsFeed.get(position).getTitle(),
mNews.newsFeed.get(position).getLink()
.toExternalForm() });
FragmentTransaction ft = getSherlockActivity()
.getSupportFragmentManager().beginTransaction();
Fragment frag = SherlockFragment.instantiate(getSherlockActivity(),
FragmentNews.class.getName(), bundle);
ft.detach(getSherlockActivity().getSupportFragmentManager()
.findFragmentById(getId()));
ft.add(android.R.id.content, frag, Tabs.FRAG_NEWS);
ft.commit();
}
Overriden onBackPressed in Tabs:
#Override
public void onBackPressed() {
Fragment frag = getSupportFragmentManager().findFragmentByTag(
FRAG_DETAILS);
if (frag != null && frag.isVisible()) {
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.remove(frag);
Fragment mFragment = getSupportFragmentManager().findFragmentByTag(
TAB_PORTFOLIO);
if (mFragment == null) {
mFragment = SherlockFragment.instantiate(this,
FragmentPortfolioList.class.getName(), null);
ft.add(android.R.id.content, mFragment, TAB_PORTFOLIO);
} else {
ft.attach(mFragment);
}
ft.commit();
} else {
frag = getSupportFragmentManager().findFragmentByTag(FRAG_NEWS);
if (frag != null && !frag.isDetached()) {
Log.e("onBackPressed", "for " + frag.getTag());
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.remove(frag);
Fragment mFragment = getSupportFragmentManager()
.findFragmentByTag(TAB_HOME);
if (mFragment == null) {
mFragment = SherlockFragment.instantiate(this,
FragmentHome.class.getName(), null);
ft.add(android.R.id.content, mFragment, TAB_HOME);
} else {
ft.attach(mFragment);
}
ft.commit();
} else {
Log.e("onBackPressed", "inside else");
super.onBackPressed();
}
}
}
Snippet from FragmentNews
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
arr = getArguments().getStringArray("NEWS");
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_news, container);
newsView = (WebView) view.findViewById(R.id.news_WV_Brief);
newsView.getSettings()
.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
newsView.getSettings().setGeolocationEnabled(false);
newsView.getSettings().setAllowFileAccess(false);
newsView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.e("override", url);
return true;
}
});
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onResume() {
super.onResume();
newsView.loadUrl(arr[1]);
}
I have seen posts talking about FlashPlayer causing issues because of SurfaceView cutting a hole but I am just displaying simple webpages without any videos. Help highly appreciated.
I figured out the problem while going over the source code of WebViewFragment. I realized there isn't much going on other than pause/resume of webview.
I had two serious errors in my code:
I never returned the inflated view in onCreatView in
FragmentNews. I was returning super.onCreateView(inflater,
container, savedInstanceState).
I forgot to set attachToRoot to false in onCreateView when
inflating the XML layout - View view =
inflater.inflate(R.layout.fragment_news, container, **false**)
Therefore, the inflated view was just standing on its own without being attached to the fragment. When the fragment was replaced, it resulted in a mashed up display because the inflated layout containing the WebView was never removed. Unfortunately, this complied without errors.

Categories

Resources