I'm trying to figure out how fragments are working.
I have 3 classes, MainActivity, Fragment1 and Fragment2.
MainActivity extends SherlockFragmentActivity
and
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment1 firstFragment = new Fragment1();
firstFragment.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container1, firstFragment).commit();
Now, I load Fragment1 into my fragment_container, and it displays nice.
(So main_activity.xml has only one )
Ok, Fragment1 extends SherlockFragment, does nothing more then
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment1layout, container, false);
So I just inflate it from my .xml that has one text view and one button.
Where in the world now can I instance Button, and give him code to replace Fragment1 with Fragment2?
What is the code for that, as I'm now "in Fragment1" so I need to somehow communicate with Fragment holder and tell it "replace me with Fragment2".
Fragment2 also extends SherlockFragment, and does nothing, inflates it's empty .xml
You have to call your fragment2 from fragment1 like below
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment1layout, container, false);
Button button = (Button)view.findViewById(R.id.yourButton);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Replace your fragment
}
});
return view;
}
I'm now "in Fragment1" so I need to somehow communicate with Fragment holder and tell it "replace me with Fragment2".
If you want replace Fragment1 to Fragment2 when you click on button which is into Fragment1:
(best practices)
you should create callbacks from fragment1 to MainActivity like it is described here
into MainActivity place logics which will replace fragment1 to fragment2.
(bad practices)
Create method into MainActivity which will replace one fragment to another for example changeFirstFragmentToAnother()
then when you need to change fragment1 to fragment2 you may call this method manually (from fragment1) like this:
((MainActivity)getActivity()).changeFirstFragmentToAnother();
Related
I am developing an application where i need to call two fragments on an activity replacing another fragment,one of the fragment will contain a Form and another fragment will contain another Form ,i don't have any idea how to do this,so any suggestion will be cordially appreciated,thanks in advance....
I want to replace Form on Click button. by R&D i come to know at this point i need to use to fragment with two layout each layout will contain Forms.
Main Activity.
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Fragment 1.
public class Fragment1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment1, container, false);
}
Fragment 2.
public class Fragment2 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment2, container, false);
}
}
You can try like this
FragmentTransaction ft=getSupportFragmentManager().beginTransaction();
ft.add(Home.newInstance(),"First");
ft.add(Second.newInstance(),"Second");
ft.commit();
So here you are added multiple fragment into the stack
If you are trying to replace Fragment1 with Fragment2, you replace the fragment.
https://developer.android.com/reference/android/support/v4/app/FragmentTransaction.html#replace(int,%20android.support.v4.app.Fragment)
I have 2 Fragments - ButtonFragment and ListViewFragment - in my Activity MainActivity.
ButtonFragment contains a Button, ListViewFragment contains a ListView.
Each time I click on the ButtonFragment Button I want the ListViewFragment to show/hide.
How do I code this properly?
Currently my code looks like this:
MainActivity.java
public class MainActivity extends Activity implements Communicator {
ButtonFragment buttonFrag;
ListViewFragment listviewFrag;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonFrag= new ButtonFragment();
listviewFrag = new ListViewFragment();
manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.button_fragment, buttonFrag, "Fragment1");
transaction.add(R.id.listview_fragment, listviewFrag, "Fragment2");
transaction.commit();
}
}
ButtonFragment.java
public class DynamicButtonsFragment extends Fragment implements View.OnClickListener {
Button btn;
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.button_fragment_layout, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onClick(View v) {
//?? hide listview fragment from here ??
}
}
ListViewFragment.java
public class ListViewFragment1 extends Fragment {
protected ArrayAdapter<String> adapter1;
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.list_view_fragment, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
}
So my question is where do I implement the showing/hiding of ListViewFragment? I feel like I should send data to the MainActivity through the onClick method of ButtonFragment. But I do not know how to do so.
Or do I only add code in the MainActivity since the MainActivity has access to all the Fragments?
I am having trouble becase the Button is in a Fragment, not part of the MainActivity. I haven't really seen cases like this...
Can someone please help?
You cannot show/hide a Fragment directly. You may show/hide a UI object like Listview. If you like, you can show/hide Fragment indirectly by using the FragmentTransaction, and you can call its method add, remove or replace.
A link for sample code is Fragments
Do this ..
android.app.Fragment fragment = getActivity().getFragmentManager().findFragmentByTag("YOUR_FRAGMENT_TAG");
getActivity().getFragmentManager().beginTransaction().hide(fragment);
inside your click event!
One more thing when you add fragments like this..
transaction.add(R.id.button_fragment, buttonFrag, "Fragment1");
transaction.add(R.id.listview_fragment, listviewFrag, "Fragment2");
you're expected to provide the container id instead of the id of the fragment.
Example: For MainActivity container use R.id.containerMain
If you in fragment want to do some MainActivity function , you can try
#Override
public void onClick(View v) {
//?? hide listview fragment from here ??
((MainActivity)getActivity()).hidelistView();
//hidelistView you should imp in your MainActivity
}
If you have fragments within the same layout, you can use the following code:
http://www.java2s.com/Code/Android/Core-Class/Demonstrationofhidingandshowingfragments.htm
If not, than you can use several possibilities...
You can use an Intent to send data to MainActivity.
You can have a singleton instance where you store pointer to your MainActivity.
You can also use Handler to send messages, but the ways discribed above are easier to implement and should be enough for you.
I am using sliding menu in andorid, when i click on slide menu's list item, that time i can change fragment-A, and now my question is that One Button-A in Fragment-A, i want to change another Fragment-B on Button-A click listener, Fragment-B must have default back button on Actionbar, when press on Default Back button it goes to the Fragment-A, How to do this?
I am using this code:
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, My_Fragment_B_Object).commit();
getSlidingMenu().showContent();
// Fragment B class Code:
public class FragOne extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_b, container, false);
((FragmentChangeActivity) getActivity()).getSupportActionBar().setHomeButtonEnabled(true);
return view;
}
}
Let say the target application is built from 3 fragments which are all in the same activity public class MainActivity extends android.support.v4.app.FragmentActivity implements ActionBar.TabListener. Starting fragment is public class ButtonSectionFragment extends Fragment where there is a Button:
public class ButtonSectionFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.btn, container, false);
Button mybutton = (Button) rootView.findViewById(R.id.mybutton);
mybutton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
????????????????????
}
});
}
There are ?? in the onClick method, I will get to that. And there is another fragment like this:
public static class TextSectionFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tv, container, false);
TextView textv = (TextView) rootView.findViewById(R.id.texty);
}
Both of the fragments are using different layouts so this is why rootView is being used right in front of findViewById.
The outcome I would like to achieve is: by Button from 1st fragment click set the TextView from 2nd fragment to Hello. What should I put in the ??? part to make it all work?
You need to use interface as callback to the activity then set the textview in fragment.
Two framgents should never communicate directly.
http://developer.android.com/training/basics/fragments/communicating.html.
Framgent1 -->Activity -->Fragment2.
You can comunicate value from fragment2 to activity first then from activity to fragment2. Then set text in fragment2
You just have to use getActivity().findViewById() instead of getView().findViewById()
final TextView tv = (TextView) getActivity().findViewById(R.id.texty);
if (tv != null)
tv.setText("Hello");
Fragments are just branches inside the common layout tree of activity. All fragment views of a common activity can be accessed through Activity.findViewByXXX(). The only complication is that fragments can be dynamically added, removed, replaced, etc. So you to be sure that the needed fragment is already inflated into the layout hierarchy. You can make initialization of the UI in onViewCreated() of the other fragment. That guarantees you the layout has been loaded already.
Fragment frag1 = new ButtonSectionFragment ();
Fragment frag2 = new TextSectionFragment();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(layout, frag1);
ft.add(layout, frag2);
ft.commit();
View frag1RootView = frag1.getView();
View frag2RootView = frag2.getView();
Button btn = (Button)frag1RootView.findViewById(id);
TextView tv = (TextView)frag2RootView.findViewById(id);
untested but... I think that would do it...
EDIT: You should get the root views onActivityCreated(); or it'll throw you a null...
In continuation to Raghunandan's answer, you could check similar implementation in the link.
update TextView in fragment A when clicking button in fragment B
Do not forget to get a reference of the textview of the TextSectionFragment into the MainActivity.
I have created a MainActivity which consists of 3 tabs which are scrollable (by using ViewPager). Now each of these 3 tabs is a Fragment. Also, I am using ActionBarSherlock (ABS).
For the 1st Fragment, I have created the following class:
public class Fragment_1 extends SherlockFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View v = inflater.inflate(R.layout.fragment1, container, false);
return v;
/* R.layout.fragment1 only contains a TextView. */
}
}
For the 2nd Fragment, I want to extend a FragmentActivity as shown below.
public class Fragment_2 extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment2);
}
}
The 3rd Fragment is same as the first one.
But when I launch the app, it crashes. So, am I wrong in extending FragmentActivity for the class Fragment_2? Is it illegal to extend a FragmentActivity or even an Activity to fragment classes? If not, what is the problem here?
Thanks.
EDIT: After #CommonsWare's answer I updated my class as follows:
public class Fragment_2 extends SherlockFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button send = (Button) findViewById(R.id.bSend); //Error at this line
//some error free code
FragmentTransaction t = getSupportFragmentManager().beginTransaction(); //Error at this line
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View v = inflater.inflate(R.layout.fragment2, container, false);
return v;
}
My final two questions are:
How should I access my R.id.bSend Button in the Fragment_2 class.
Eclipse is giving the suggestion to change getSupportFragmentManager() to getFragmentManager(). Is that change all right?
Thanks!
Is it illegal to extend a FragmentActivity or even an Activity to fragment classes?
Fragment is a Java class. Your fragment implementations (for use as pages in your ViewPager) must inherit from Fragment, directly or indirectly.
Activity does not inherit from Fragment. FragmentActivity does not inherit from Fragment. Hence, you cannot inherit from Activity or FragmentActivity and somehow also inherit from Fragment.