How to implement show and hide fragment inside fragment in android - 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

Related

Remove Fragment in FragmentTransaction cannot be applied to

I am having and issue about closing a Fragment.
The reason why I cannot close the Fragment, within the customized Fragment itself, with the following chaining
getActivity().getFragmentManager().beginTransaction().remove(this);
seem to be inheritance, since my customized Fragment inherits from ..
extends android.support.v4.app.Fragment
Android Studio is complaining about the argument in remove(), - "this"
remove (android.app.Fragment) in FragmentTransaction cannot be applied to se.fragmenttest.app.myfrafmentest180406.MyFragment)
The strange this is that the same call seem to work from within MainActivity where the Fragment is instanciated.
the whole class
public class MyFragment extends android.support.v4.app.Fragment {
private View fragmentView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup containter, Bundle savedInstanceState) {
fragmentView = inflater.inflate(R.layout.fragment_layout, containter, false);
Button button = (Button) fragmentView.findViewById(R.id.okbutton_id);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
closeFragment();
}
}
);
return fragmentView;
}
private void closeFragment() {
getActivity().getFragmentManager().beginTransaction().remove(this);
}
}
EDIT:
code for MainActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyFragment myFragment = new MyFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.container, myFragment, "myfragment");
fragmentTransaction.commit();
fragmentTransaction.remove(myFragment);
}
I tried to remove the fragment in the MainActiviy and there it WORKS. And more - I can put the reference in remove() which I cannot in the Fragment class
Use this
getActivity().getFragmentManager().popBackStack();
(or) use can specify tags
Example reference
You can pop the fragment by name. While adding fragments to the back stack, just give them a name.
fragmentTransaction.addToBackStack("fragB");
fragmentTransaction.addToBackStack("fragC");
Then in Fragment_C, pop the back stack using the name ie.. fragB and include POP_BACK_STACK_INCLUSIVE
someButtonInC.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fm = getActivity()
.getSupportFragmentManager();
fm.popBackStack ("fragB", FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
});
I'm not at my main computer right now, so can't check...
But i think you need to call getSupportFragmentManager() rather than getFragmentManager().
EDIT
Now I'm back at my computer I can confirm it is what I said above. It also helps that you have posted your activity code.
In your MainActivity you call:
MyFragment myFragment = new MyFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
i.e. you call getSupportFragmentManager() which is correct, and why it works.
..but in your Fragment you call the standard getFragmentManager() as below:
getActivity().getFragmentManager().beginTransaction().remove(this);
and as the fragment extends a Support fragment, when you try and call this it can't be found. However, if you change the above line to this:
getActivity().getSupportFragmentManager().beginTransaction().remove(this);
this will no longer not be found and your code should run.

Nested fragments - fragment started from a fragment does not inflate the layout xml

I am trying nested fragment because my xml layout starts to be difficult to maintain.
From a fragment I start a fragment when I click on the skip button. I tried both a normal start and a child fragment. On both case I get into the fragment in the inflate method but my screen stays empty. Of course when I call the fragment as a first level the layout inflates correctly.
Call to the 2nd fragment within the 1st one:
skip.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
SelectServiceFragment ssf = new SelectServiceFragment();
ft.add(ssf,"SelectService");
ft.commit();
}
});
SelectServiceFragment:
public class SelectServiceFragment extends Fragment {
Context context;
public SelectServiceFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootview = null;
rootview = inflater.inflate(R.layout.select_svce_fragment, container, false);
return rootview;
}
and my xml layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Select service!!!!"
android:textColor="#000000"
/>
</RelativeLayout>
Did I miss something in nested fragments?
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
SelectServiceFragment ssf= new SelectServiceFragment();
fragmentTransaction.add(R.id.fragment_container, ssf, "SelectService");
fragmentTransaction.commit();
try this way
Yes, you are missing the most important thing. that you can change fragment from the base class method. the class in which you first replace method. make that method as a public method and pass it parameters with fragment class name. Let say you have method in base class where you first replace or initiate fragment
public void replaceFragment( Fragment fragment) {
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_home, fragment);
fragmentTransaction.commit();
// if you have used drawer_layout
// othere wise no need of below lines
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
}
then call this method in any fragment and pass the fragment class name like this ((BaseClassName) getActivity()).replaceFragment(new ReportLostItem()); this way you will be able to replace the fragment from any fragment class. accept the answer if it solves your problem
My excuses guys for having you lose your time on this!
All is working as expected!
the only thing I was doing as I was jumping from RelativeLayout is setvisibility(invisible) on the RL where the framelayout is.
Sorry!

adding same fragment more than once at runtime

i am designing an alarm application.
I am working with a fragment that acts as my alarms, the idea is to use the same one for each new alarm (i don't know if this is the right way).
Well, then i am basically trying to add, via pressing a "new alarm" button, the same fragment again into the layout of an activity, but when i press the button the app crashes. Any help?
I am inserting the fragment into a LinearLayout that is inside a ScrollView that is inside of the RelativeLayout
package com.example.roo.proyi;
import android.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
public class alarms extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarms);
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
final android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
alarm_fragment alarmFragment = new alarm_fragment();
fragmentTransaction.add(R.id.alarmListContainer,alarmFragment);
fragmentTransaction.commit();
Button button_newAlarm = (Button)findViewById(R.id.button_new_alarm);
button_newAlarm.setOnClickListener(
new Button.OnClickListener() {
public void onClick(View v) {
alarm_fragment alarmFragment2 = new alarm_fragment();
fragmentTransaction.add(R.id.alarmListContainer,alarmFragment2);
fragmentTransaction.commit();
}
;
}
);
.
.
.
.
.
.CONTINUES BUT IT IS IRRELEVANT
.
.
.
FINAL SOLUTION MADE BY CREATING A DIFFERENT FRAGMENTTRANSACTION
public class alarms extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarms);
final android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
final android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
final alarm_fragment alarmFragment = new alarm_fragment();
fragmentTransaction.add(R.id.alarmListContainer,alarmFragment);
fragmentTransaction.commit();
Button button_newAlarm = (Button)findViewById(R.id.button_new_alarm);
button_newAlarm.setOnClickListener(
new Button.OnClickListener() {
public void onClick(View v) {
android.support.v4.app.FragmentTransaction fragmentTransaction2 = fragmentManager.beginTransaction();
getSupportFragmentManager().beginTransaction();
alarm_fragment alarmFragment2 = new alarm_fragment();
fragmentTransaction2.add(R.id.alarmListContainer,alarmFragment2);
fragmentTransaction2.commit();
}
;
}
);
You cannot use the same FragmentTransaction to add the fragment inside of your OnClickListener. Once you call commit() on a transaction, you cannot use it again. Call getSupportFragmentManager().beginTransaction() to get a new transaction.
Check this code out -
1. It checks whether you have added a dialog fragment in the stack already or not. If yes, it will remove the fragment and add new fragment with a new argument, if it does not exist, it will add the fragment anyway.
see if you could incorporate this approach in your code -
void showDialog() {
mStackLevel++;
// DialogFragment.show() will take care of adding the fragment
// in a transaction. We also want to remove any currently showing
// dialog, so make our own transaction and take care of that here.
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment prev = getFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
// Create and show the dialog.
DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel);
newFragment.show(ft, "dialog");
}
Source is Android developer site

Android app design with several fragments

I am trying to create a tablet application with fragments. The left part of the screen will have four buttons and the right part of the screen will change depending on what button was clicked.
I have created main activity and four fragments. Each fragment has its own layout with several TextView fields. When applications starts it loads all fragments to RAM - this way it can keep the fragments status so that when user switch from one fragment to another all the text fields keep their text values until he clicks the final submit button. The app is based on SDK 4.1. The app is a little bit slow especially when it starts. I was wondering if it has been designed properly and if there are some way to improve it?
Below is the main activity class:
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
private Button buttonOne;
private Button buttonTwo;
private Button buttonThree;
private Button buttonFour;
private Fragment fragmentOne;
private Fragment fragmentTwo;
private Fragment fragmentThree;
private Fragment fragmentFour;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonOne = (Button) findViewById(R.id.button_one);
buttonTwo = (Button) findViewById(R.id.button_two);
buttonThree = (Button) findViewById(R.id.button_three);
buttonFour = (Button) findViewById(R.id.button_four);
fragmentOne = new FragmentOne();
fragmentTwo = new FragmentTwo();
fragmentThree = new FragmentThree();
fragmentFour = new FragmentFour();
FragmentTransaction fragmentTransaction = getFragmentManager()
.beginTransaction();
fragmentTransaction.add(R.id.frameLayout_one, fragmentOne);
fragmentTransaction.add(R.id.frameLayout_one, fragmentTwo);
fragmentTransaction.add(R.id.frameLayout_one, fragmentThree);
fragmentTransaction.add(R.id.frameLayout_one, fragmentFour);
fragmentTransaction.commit();
buttonOne.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
FragmentTransaction fragmentTransaction = getFragmentManager()
.beginTransaction();
fragmentTransaction.show(fragmentOne);
fragmentTransaction.hide(fragmentTwo);
fragmentTransaction.hide(fragmentThree);
fragmentTransaction.hide(fragmentFour);
fragmentTransaction.commit();
}
});
buttonTwo.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
FragmentTransaction fragmentTransaction = getFragmentManager()
.beginTransaction();
fragmentTransaction.hide(fragmentOne);
fragmentTransaction.show(fragmentTwo);
fragmentTransaction.hide(fragmentThree);
fragmentTransaction.hide(fragmentFour);
fragmentTransaction.commit();
}
});
buttonThree.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
FragmentTransaction fragmentTransaction = getFragmentManager()
.beginTransaction();
fragmentTransaction.hide(fragmentOne);
fragmentTransaction.hide(fragmentTwo);
fragmentTransaction.show(fragmentThree);
fragmentTransaction.hide(fragmentFour);
fragmentTransaction.commit();
}
});
buttonFour.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
FragmentTransaction fragmentTransaction = getFragmentManager()
.beginTransaction();
fragmentTransaction.hide(fragmentOne);
fragmentTransaction.hide(fragmentTwo);
fragmentTransaction.hide(fragmentThree);
fragmentTransaction.show(fragmentFour);
fragmentTransaction.commit();
}
});
}
Consider using a FragmentStateViewPager.
In an ideal world, if you have several Fragments you are switching between like in your case, you'll probably not want to keep them around in RAM. 2 or 3 fragments is probably okay, 4 or more is starting to push it.
The FragmentStateViewPager will automatically detach and save the state of your Fragments as they move "off screen"
You will have to implement onSaveInstanceState in each one of your fragments to save any state of any non-UI member variables (UI Views save their state automagically). Then restore them in onCreate or onCreateView.
*Of course, if your Fragments' onCreate/onCreateViews are slow, then this won't help much. First make sure your Fragments' creations are fast... Start by looking for code that can be moved from onCreate/onCreate view to onResume.

How to add a dynamic number of fragments in android from an activity

I hava a fragment named DetailFragment which extends Fragment class with neccessary Override methods:
public class DetailFragment extends Fragment{
//Some neccessary methods are over here
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.details, container, false);
return view;
}
}
I hava a main activity: FragmentActivity extends FragmentActivity which set content: setContentView(R.layout.main);. If I want to add DetailFragment from FragmentActivity, I have to declare a LinearLayout (or whatever layout) with android:id="#+id/container_fragment" inside the main.xml layout file. With this way, I can add a DetailFragment:
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
DetailFragment df = new DetailFragment();
ft.add(R.id.container_fragment, df);
ft.commit();
However, I can only add 1 DetailFragment into that container_fragment. If I want to add 2 or more DetailFragment from the activity, do I have to add 2 or more other container_fragment in the main.xml layout? And if not, what I should do and can you give an example? Thanks!
The layout can contain several fragments, you just have to specify different tags when calling the add function of the FragmentTransaction class.
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.container_fragment, new DetailFragment(), "df_1");
ft.add(R.id.container_fragment, new DetailFragment(), "df_2");
ft.commit();

Categories

Resources