MapFragment: bad performance after using the back button - android

I have a performance issue when using MapFragment together with the action bar menu.
The bug emerges when three conditions are met
Have a MapFragment instantiated.
Trigger a fragment transaction from the options menu, replacing the map fragment with another fragment.
Hit the back button and return to the map fragment. The performance is now noticeably degraded. Panning and zooming is very jerky.
Opening the options menu again and dismissing it again fixes the issue.
The behavior does not arise when
Triggering the fragment replacement from a view button instead from the options menu.
Triggering the fragment replacement right in onCreate()
replacing the blank fragment with MapFragment from the options menu
calling popBackStack from the options menu
using a ListFragment instead of a MapView
Minimal working example (requires access to Google Maps API):
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import com.google.android.gms.maps.MapFragment;
public class MapFragmentBugActivity extends Activity {
Fragment mMapFragment;
String MAP = "Map";
String BLANK = "Blank";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_bug);
mMapFragment = new MapFragment();
getFragmentManager().beginTransaction()
.replace(R.id.main, mMapFragment)
.commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(MAP);
menu.add(BLANK);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Fragment fragment;
if (item.getTitle().equals(MAP)) {
fragment = mMapFragment;
} else {
fragment = new Fragment();
}
getFragmentManager()
.beginTransaction()
.replace(R.id.main, fragment)
.addToBackStack(null)
.commit();
return true;
}
}
Activity layout, nothing special
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />

The fragment transaction is performed before the options menu is closed, this causes the weird behavior.
Instead of directly performing the fragment transaction, post it on the Handler. Once the options menu is closed, then the fragment transaction will be performed.
Try this :
#Override
public boolean onOptionsItemSelected(MenuItem item) {
final Fragment fragment;
if (item.getTitle().equals(MAP)) {
fragment = mMapFragment;
} else {
fragment = new Fragment();
}
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
getFragmentManager()
.beginTransaction()
.replace(R.id.main, fragment)
.addToBackStack(null)
.commit();
}
});
return true;
}

Related

Create a tab indicator for a stack of fragments

I have an activity, and a bunch of fragments in it. The fragments are not transitioned by sliding, but by button click. I'm trying to build a tab indicator like the one in the bottom that shows which fragment the user is. I don't even know how it's called.
This is my main Activity where all the fragments belong, and with the actionbar menu the user navigates throught the fragments. In the activity it's switched straight to the first fragment out of 4 fragments (DetailsFragment)
public class CreateWorkoutActivity extends AppCompatActivity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_workout);
DetailsFragment fragment = new DetailsFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.create_activity_frameLayout, fragment)
.addToBackStack(null)
.commit();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack();
}
return true;
}
return false;
}
image example
as i cannot see your code, I have this to offer https://guides.codepath.com/android/ViewPager-with-FragmentPagerAdapter ... refer this

Android preferenceFragment doesn't display nothing and menu remain selected

I'm tryng study the Preference system of Android.
When from my navdrawer I call settings fragment, it doesn't show nothing and menu remain selected, also if I select another voice.
This is the screen at startup of my APP:
Where all is perfect. After I click on Impostazioni (settings, in English), Home (or the "Elenca" item) reamin checked, also with "Impostazioni"
Another one problem is that Settings frame is blank (no error in Log but it's all blank).
This is XML preferences.xml stored under res/xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="#string/pref_sms_storage_title"
android:key="pref_key_storage_settings">
<CheckBoxPreference
android:key="pref_sync"
android:title="#string/pref_sync"
android:summary="#string/pref_sync_summ"
android:defaultValue="true" />
</PreferenceCategory>
</PreferenceScreen>
This is my Settings Fragment:
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.support.v4.app.Fragment;
import com.xxxxxx.R;
public class SettingsFragment extends Fragment{
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
new InnerSettingsFragment();
}
public static class InnerSettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
}
}
And finally this is my BaseApp that mantains the navdrawer logic:
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Checking if the item is in checked state or not, if not make it in checked state
if (menuItem.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
//Closing drawer on item click
drawerLayout.closeDrawers();
//Check to see which item was being clicked and perform appropriate action
switch (menuItem.getItemId()) {
case R.id.home:
DashboardFragment dashboardFragment = new DashboardFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame, dashboardFragment,"DASHBOARD_FRAGMENT");
fragmentTransaction.commit();
return true;
case R.id.list_event:
ListEventFragment fragmentListEvent = new ListEventFragment();
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame, fragmentListEvent);
fragmentTransaction.commit();
return true;
case R.id.settings:
SettingsFragment fragmentSettings = new SettingsFragment();
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame, fragmentSettings);
fragmentTransaction.commit();
return true;
default:
return true;
}
}
});
You shouldn't make your PreferenceFragment an inner class, add your outer class in its place, and still expect things to work as usual. It won't because the outer onCreate() wouldn't delegate to the inner onCreate() by itself. So, just make your InnerSettingsFragment a regular top-level class and you'll start seeing your preferences get loaded from the XML resource.
public class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
}

Can't add a fragment when Creating a new Activity

i'm trying to create a wizard Like Android application, i want to Create an activity and Two dynamic Fragments, the first one will be added when the Activity is created, and the second when the user clicks on a button in the First fragment, right now i can't even add the Fragment to the activity :
Activity onCreate method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment fr = new FragmentNumber();
getSupportFragmentManager().beginTransaction().add(fr, "number_fragment").commit();
}
this is my activity code, when i run this, the screen is blank.
the R.layout.activity_main refer to an empty Linear Layout, i don't want to add the fragments there because i need them to be dynamic.
Thanks in advance.
EDIT : pasting more files
activity_main.XML
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello from main"
/>
</FrameLayout>
MaicActivity.java
package com.example.fragmenttraining;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(findViewById(android.R.id.content) != null)
{
Log.d("main activity", "content found");
}
FragmentNumber fr = new FragmentNumber();
//getSupportFragmentManager().beginTransaction().add(android.R.id.content, fr, "number_fragment").commit();
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, fr).commit();
}
FragmentNumber numberFragment;
FragmentFacebook facebookFragment;
public void facebookClicked(View view)
{
numberFragment = new FragmentNumber();
numberFragment.facebookClicked(view);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Now it's working, but the fragment is not replaced, it displays the content of the activity_main + the content of the FragmentNumber fragment even id i replace it ...
Follow these steps:
Create your main (activity layout) file. In it, add a frame layout which will act as a container for your fragments.
Now create your two fragments. This involves creating two xml files that will be inflated inside your fragment's onCreateView method.
One of your fragments (the first one) should have a button that the user will be able to click. That means you must attach an onClick listener to it inside the onCreateView method after finding it by id.
Now create an interface inside your first fragment and add a method in it that your activity should override after implementing the interface.
When the user clicks that button, inside onClick method, you should call the interface method to notify the activity of the click event.
Inside the activity, when the method is called, create a new instance of the second fragment and add it to view by replacing the first one - or it depends on whether you are using two-pane layout in your activity - in that case, you just add the fragment.
Remember to check if your fragment exists first before simply adding one to view.
I hope these steps help you.
Sample Code
public class WizardActivity extends Activity implements SecondFragment.OnButtonClickedListener
{
private FirstFragment firstFragment;
public void onCreate(Bundle saveInstanceState)
{
super.onCreate(saveInstanceState);
setContentView(R.layout.main);
firstFragment = new FirstFragment();
setFragment(firstFragment, "firstFragment");
}
#Override
public void loadSecondFragment()
{
SecondFragment secondFragment = new SecondFragment();
setFragment(secondFragment, "secondFragment");
}
public void setFragment(Fragment frag, String tag)
{
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragmentContainer);
if(fragment == null)
{
ft.add(R.id.fragmentContainer, frag, tag);
} else {
ft.replace(R.id.fragmentContainer, frag, tag);
}
ft.addToBackStack(null);
ft.commit()
}
}
Now the xml file for main layout.
<LinearLayout ........>
<!--add whatever you need here-->
<FrameLayout
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Now let us create one of your fragments - the first one:
FirstFragment.java
public class FirstFragment extends Fragment implements View.OnClickListener
{
private Activity mActivity;
#Override
public void onAttach(Activity act)
{
super.onAttach(act);
this.mActivity = act;
/*Initialize whatever you need here*/
}
#Override
public View onCreateView(LayoutInflator inflator, ViewGroup container, Bundle saveInstanceState)
{
View v = inflator.inflate(R.layout.first_fragment, container, false);
Button button = (Button)v.findViewById(R.id.button);
button.setOnClickListener(this);
}
#Override
public void onClick(View v)
{
((OnButtonClickListener), mActivity).loadSecondFragment();
}
public interface OnButtonClickListener
{
void loadSecondFragment();
}
}
You should be able to just create the second fragment and have it loaded in the activity when a button is clicked.
Good luck.

Action items from Viewpager initial fragment not being displayed

In the application I am developing I am using a ViewPager with fragments and each fragment constructs its own menu independently of all of the other fragments in the ViewPager.
The issue is that sometimes the fragments that are initialised by the ViewPager by default (i.e in it's initial state) are not having their items populated into the action items menu. What's worse is that this issue only occurs intermittently. If I swipe through the ViewPager enough so that the fragments are forced to re-initialise them selves, when I swipe back, the menu populates correctly.
Activity code:
package net.solarnz.apps.fragmentsample;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
public class FragmentSampleActivity extends Activity {
private ViewPagerAdapter mViewPagerAdapter;
private ViewPager mViewPager;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (mViewPagerAdapter == null) {
mViewPagerAdapter = new ViewPagerAdapter(getFragmentManager());
}
mViewPager = (ViewPager) findViewById(R.id.log_pager);
mViewPager.setAdapter(mViewPagerAdapter);
mViewPager.setCurrentItem(0);
}
private class ViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 8;
}
#Override
public Fragment getItem(int position) {
Fragment f = Fragment1.newInstance(position);
// f.setRetainInstance(true);
f.setHasOptionsMenu(true);
return f;
}
}
}
Fragment code:
package net.solarnz.apps.fragmentsample;
import android.app.Fragment;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
public class Fragment1 extends Fragment {
int mNum;
static Fragment newInstance(int num) {
Fragment1 f = new Fragment1();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mNum = getArguments() != null ? getArguments().getInt("num") : 0;
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_list, menu);
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<android.support.v4.view.ViewPager
android:id="#+id/log_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/menu_refresh"
android:title="Refresh"
android:icon="#android:drawable/ic_delete"
android:showAsAction="ifRoom|withText" />
</menu>
Action menu being populated:
http://i.stack.imgur.com/QFMDd.png
Action menu not being populated:
http://i.stack.imgur.com/sH5Pp.png
You should read this (by xcolw...)
Through experimentation it seems like the root cause is invalidateOptionsMenu getting called more than one without a break on the main thread to process queued up jobs. A guess - this would matter if some critical part of menu creation was deferred via a post, leaving the action bar in a bad state until it runs.
There are a few spots this can happen that aren't obvious:
calling viewPager.setCurrentItem multiple times for the same item
calling viewPager.setCurrentItem in onCreate of the activity. setCurrentItem causes an option menu invalidate, which is immediately followed by the activity's option menu invalidate
Workarounds I've found for each
Guard the call to viewPager.setCurrentItem
if (viewPager.getCurrentItem() != position)
viewPager.setCurrentItem(position);
Defer the call to viewPager.setCurrentItem in onCreate
public void onCreate(...) {
...
view.post(new Runnable() {
public void run() {
// guarded viewPager.setCurrentItem
}
}
}
After these changes options menu inside the view pager seems to work as expected. I hope someone can shed more light into this.
source http://code.google.com/p/android/issues/detail?id=29472
The simple answer is to not use menus within fragments in the ViewPager.
If you do need to use menus within the fragments, what I suggest is loading the menu's through the onCreateOptionsMenu method in the parent Activity. Obviously you will need to be able to determine which menu to show.
I was able to achieve this by using class reflection.
You will also need to use the invalidateOptionsMenu method each time you switch pages. You will need a OnPageChangeListener to call this when the ViewPager changes pages.
I also had same issue. In my case I have one activity with viewpager that contains two fragments, every fragment inflate its own action menu but fragment actions menu not shown.
View pager adapter code
public class ScreensAdapter extends FragmentPagerAdapter {
public TrackerScreensAdapter(Context context, FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 2;
}
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position){
case 0:
fragment = new Fragment1();
break;
case 1:
fragment = new Fragment2();
break;
}
return fragment;
}
}
Activity on create
screensAdapter = new ScreensAdapter(this, getFragmentManager());
viewPager.setAdapter(screensAdapter);
This way my viewPager has two fragments, every fragment fire its own task in onActivityCreated, obtain data and draw its layout based on obtained data. Also every fragment has onCreateOptionsMenu
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
MyTask task = new MyTask();
task.setTaskListener(this);
task.execute();
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_menu, menu);
}
Spent many times to solve this problem and figure out why fragment menu not shows.
All that I was need is
screenAdapter = new ScreenAdapter(this, getFragmentManager());
viewPager.post(new Runnable() {
public void run() {
viewPager.setAdapter(screenAdapter);
}
});
In my case I traced the root cause of the issue to what I believe is a bug in FragmentStatePagerAdapter which is calling Fragment#setMenuVisibility to false and failing to properly set it back to true when it restores it's state.
Workarounds:
Use FragmentPagerAdapter instead of FragmentStatePagerAdapter
If you must use FragmentStatePagerAdapter, in your adapter subclass override setPrimaryItem like so:
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
//This is a workaround for a bug in FragmentStatePagerAdapter
Fragment currentItem = getItem(position);
if (currentItem != null) {
currentItem.setMenuVisibility(true);
currentItem.setUserVisibleHint(true);
}
}
First create a method in the sub class of FragmentPagerAdapter to get the current fragment
public SherlockFragment getFragment() {
return currentFragment;
}
#Override
public void onTabSelected(final Tab tab, FragmentTransaction ft) {
((SherlockFragmentActivity) mContext).invalidateOptionsMenu();
Fragment f = ((SherlockFragmentActivity) mContext)
.getSupportFragmentManager().findFragmentByTag(
makeFragmentName(tab.getPosition()));
currentFragment=(SherlockFragment) f;
}
Now override below methods in Main Actvity
#Override
public boolean onCreateOptionsMenu(Menu menu) {
if (mTabsAdapter.getPositionOfTabSelected() != 0) {
menu.add("Read").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add("Write").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add("Clear").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add("Factory data reset").setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
return super.onCreateOptionsMenu(menu);
}
Now call the onOptionItemSelected from activity to fragment
#Override
public boolean onOptionsItemSelected(MenuItem item) {
mTabsAdapter.getFragment().onOptionsItemSelected(item);
return super.onOptionsItemSelected(item);
}
I solved a very similar issue in which the Action bar icons assigned by the fragment inside of a ViewPager were disappearing onPause(). They would reappear when the Fragment came back into view and the user swiped left or right, but not immediately. The solution was calling notifyDataSetChanged() on the PagerAdapter in the onResume() method of the fragment.
#Override
public void onResume() {
mPagerAdapter.notifyDataSetChanged();
}
I was having this problem with the Action Bar Items while I was using HorizontalScrollView to show the tabs but I changed to PagerTitleStrip and the problem was solved.
Perhaps this information can help someone else.
My solution to this problem was to only inflate fragment menus if the fragment is currently visible. This solution may be too specific for your purposes, but it might help someone.
In the main activity:
boolean isFragmentVisible(int fragmentIndex) { ... }
In onCreateOptionsMenu() in your fragment:
if ( getActivity().isFragmentVisible(HOME_FRAGMENT_POS) ) {
inflater.inflate(R.menu.menu_home_fragment, menu);
}

How to implement show and hide fragment inside fragment in android

How to implement show and hide fragment inside fragment in Android? I have added two fragment inside activity. One fragment containing menu and one fragment contain sub menu. I have lot of button in menu fragment like home, idea, etc. If i click idea button. I have to show sub menu. If I again click idea button, I have to hide the sub menu. Can anybody provide example, or how to access one view fragment in another fragment?
this is my layout main
?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<fragment class="com.gcm.fragment.CommonFragment"
android:id="#+id/the_frag"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<fragment class="com.gcm.fragment.SubFragment"
android:id="#+id/the_frag1"
android:layout_marginTop="130dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
In My fragment
package com.gcm.fragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class CommonFragment extends Fragment implements OnClickListener {
TextView txtIhaveIdea=null;
boolean menuVisible=false;
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.collapsed_menu2, container, false);
txtIhaveIdea=(TextView)layout.findViewById(R.id.txtIhaveAnIdea);
txtIhaveIdea.setOnClickListener(this);
return layout;
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(!menuVisible)
{
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
fm.beginTransaction();
Fragment fragOne = new SubFragment();
ft.show(fragOne);
}
else
{
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
fm.beginTransaction();
Fragment fragOne = new SubFragment();
ft.hide(fragOne);
}
}
}
Thanks
You could try get framelayout or fragment by id and change its visibility
View frag = findViewById(R.id.my_fragment);
frag.setVisibility(View.VISIBLE);
Considering this question has over 2K .. an answer may still help new readers so here it goes:
You don't really want to have FragmentManager and FragmentTransactions happening inside fragments not to have Casts nor potential harmful references to your Activity(s)
So what I do and works just fine is set an interface to the Fragment and give a method, say needsHide():
public class MyFrag extends Fragment {
public interface MyFragInterface {
public void needsHide();
}
Then implement it on your Activity:
public class MainActivity extends FragmentActivity implements MyFrag.MyFragInterface {
public void needsHide() {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//find the fragment by View or Tag
MyFrag myFrag = (MyFrag)fragmentManager.findFragmentByTag(SOME_TAG);
fragmentTransaction.hide(myFrag);
fragmentTransaction.commit();
//do more if you must
}}
The only part that requires thought is when to call needsHide(), this you might do in your Fragment's onViewCreated, since you are sure that it's not too early for your MainActivity to commit transactions. If you place it onCreate() it may not work depending on what you do with oter fragments:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// Making sure Main activity implemented interface
try {
if (USE_A_CONDITION) {
((MyFragInterface)this.getActivity()).needsHide();
}
} catch (ClassCastException e) {
throw new ClassCastException("Calling activity must implement MyFragInterface");
}
super.onViewCreated(view, savedInstanceState);
}
Simply, create a public method in your "parent" activity. which hides the fragment.
Then from within the fragment in your click event get the "parent|' activity, cast it and then call the method you created.
((ParentActitity)getActivity()).hideFragment();
You need to use an Interface to communicate with your parent Activity.
Take a look on Vogella's tutorial, "3.4. Application communication with Fragments". Here is the link
method hide():Hides an existing fragment. This is only relevant for fragments whose views have been added to a container, as this will cause the view to be hidden.
your code :
#Override
public void onClick(View v) {
if(!menuVisible)
{
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
fm.beginTransaction();
Fragment fragOne = new SubFragment();
ft.show(fragOne);
}
else
{
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
fm.beginTransaction();
// it's wrong , you just hide the fragment that not added to FragmentTransaction
Fragment fragOne = new SubFragment();
ft.hide(fragOne);
}
}
Below code worked for me..
View frag = findViewById(R.id.fragment);
frag.setVisibility(View.GONE);//Or View.INVISBLE

Categories

Resources