How to find a custom fragment from an inflated layout? - android

I have a custom fragment in a inflated layout, how to access it?
I have tried many ways after inflated, but none of them worked:
getTransitionManager().findFragmentById(id_xxxxx) returns null;
getChildAt(x), get a View but not be able to cast to fragment;
I Tried to create a new fragment programmatically, and add to a container in the inflated view, but the app crashed says "No view found for id xxx for fragment fff"
code, I want to find ReportCalenderFragment and hold it:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
LayoutInflater inflater = LayoutInflater.from(getActivity());
mCalendar = inflater.inflate(R.layout.dlg_choose_report, null);
ConstraintLayout ly = (ConstraintLayout)mCalendar;
RelativeLayout rly = (RelativeLayout)ly.getChildAt(0);
LinearLayout lly = (LinearLayout)rly.getChildAt(0);
View v = (View)lly.getChildAt(0);
//lly.setId(R.id.report_calendar_con);
//ReportCalenderFragment frag = new ReportCalenderFragment();
//FragmentTransaction fragTrans = getChildFragmentManager().beginTransaction();
//fragTrans.add(R.id.report_calendar_con, frag);
//fragTrans.commit();
//ReportCalenderFragment frag = (ReportCalenderFragment)lly.getChildAt(0);
...
}
XML, ConstraintLayout was filtered by this text editor:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/report_calendar_con"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="#000"
android:orientation="vertical">
<fragment
android:id="#+id/frag_calendar_rp"
android:name="package.fragments.ReportCalenderFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" />
</LinearLayout>
</RelativeLayout>
</android.support.constraint.ConstraintLayout>

Try
ReportCalenderFragment frag = (ReportCalenderFragment) getParentFragment().getFragmentManager().findFragmentById(R.id.frag_calendar_rp);
If you are using ReportCalenderFragment inside a dialog, which is inside another fragment
You should use the ChildFragmentmanager from parent fragment while showing the dialog
MyDialogFragment dialogFragment = new MyDialogFragment();
dialogFragment.show(getChildFragmentManager(), "dialog");

Like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
ReportCalenderFragment fragment= (ReportCalenderFragment) getSupportFragmentManager().findFragmentById(R.id.frag_calendar_rp);//this method
Log.e(getClass().getSimpleName(),fragment.toString());
}

Related

How to show fragment only when button pressed?

I'm trying to show an image below a button only after the button has been pressed. My problem is that the fragment is shown immediately when the app is started and not only after the button has been pressed.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void say_hello(View view){
Fragment fragment = new ExampleFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment2, fragment).commit();
}
}
public class ExampleFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.news_articles, container, false);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:orientation="vertical"
android:layout_height="fill_parent"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center_vertical"
android:text="PRESS THIS"
android:id = "#+id/test_button"
android:background="#drawable/test_button"
android:onClick="say_hello"
/>
<fragment
android:id="#+id/fragment2"
android:name="com.example.tic_tac_toe.ExampleFragment"
android:layout_width="match_parent"
android:layout_height="643dp" />
</LinearLayout>
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/cool_dog">
</ImageView>
I'm guessing the fragment shows up when the app is started because of the name I give to the fragment in the XML, but the fragment needs a name otherwise I only get error. How do I get the fragment to display nothing before I have clicked the button?
Instead of using <fragment /> view in your xml, you can use Framelayout and add your fragment to this Framelayout on button click using the following code -
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.mainframe, fragment);
transaction.commit();
Where mainframe is the id of Framelayout.
You can try doing this
android.app.Fragment fragment = getActivity().getFragmentManager().findFragmentByTag("YOUR_FRAGMENT_TAG");
getActivity().getFragmentManager().beginTransaction().hide(fragment);
inside your click event.

Change fragments textview from activity

I want to change fragments textview from activity(not fragment class).How can I do it ? I am using this code:
public void startChat() {
FrameLayout layout = (FrameLayout)findViewById(R.id.container);
layout.setVisibility(View.VISIBLE);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.container, new ConversationFragment());
fragmentTransaction.commit();
viewPager.setVisibility(View.GONE);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayHomeAsUpEnabled(true);
TextView nameView=(TextView)findViewById(R.id.user_name);
nameView.setText("asd");
}
This code loads conversation_fragment.xml and wants change textview,but my app is crashing.
Here conversation_fragment.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#878787" >
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="dfgdfgdf"
android:textSize="20dp"
android:layout_centerInParent="true"
android:id="#+id/user_name"/>
<EditText
android:id="#+id/message"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:text="Gönder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="getFromUser"
android:layout_marginTop="40dp"
/>
</RelativeLayout>
You can either use findFragmentById to find your fragment and call a public method that changes the text
(ConversationFragment) getFragmentManager().findFragmentById(R.id.yourid);
or keep an instance of the class when you create it before you add it to the fragment manager
conv = new ConversationFragment()
fragmentTransaction.add(R.id.container, conv);
then just call the public method using conv or whatever you call it
EDIT:
you use a bundle to send in data to the fragment
Bundle b = new Bundle()
b.putString("text",data)
conv.setArguments(b);
then in your fragment get the arguments with getArguments() and pull the data from the bundle and use it however you need
You can make like this
public class ConversationFragment extends Fragment {
private TextView nameView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.conversation_fragment, null);
nameView = (TextView) view.findViewById(R.id.user_name);
}
public void setText(String yourText){
nameView.setText(yourText);
}
}
and in your activity call method setText()
ConversationFragment conv = new ConversationFragment();
conv.setText("asd");
With best regards.

Fragments inside a fragment Android application

I'm trying to put 2 fragments inside a fragment. I found some code on internet but, as far as I could go, I don't succeed to put 2 fragments in 1 fragment.
I have seen tips dealing with FragmentManager and especially the method getChildFragmentManager() but I don't know how it works with 2 fragments.
For the story, I'm using an activity with ActionBar which creates 3 fragments. In one of them, I need to handle a graph and a kind of menu to change the graph scale. In this way, I need 2 fragments in one fragment.
Here is the code :
The fragment which handles the others:
public class GraphDisplayFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View myFragmentView = inflater.inflate(R.layout.graph_fragment, container, false);
return myFragmentView;
}
}
The code to draw the graph:
public class GraphFragment extends Fragment {
private static final int SERIES_NR = 1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
GraphicalView myFragmentView = ChartFactory.getTimeChartView(this.getActivity(), getDateDemoDataset(), getDemoRenderer(),null);
return myFragmentView;
}
//some functions to set graph propreties
}
The XML files :
graph_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment
android:id="#+id/graph_fragment"
android:name="com.test.GraphFragment"
android:layout_width="match_parent"
android:layout_height="259dp" >
</fragment>
<fragment
android:name="com.test.GraphDetailFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/graph_detail_fragment">
</fragment>
</LinearLayout>
graph_detail.xml with a test implementation
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="211dp"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
The weird thing is, it works at the begining when I switch between fragments in the ActionBar but after 3-4 moves, I get this error :
android.view.InflateException: Binary XML file line #7: Error inflating class fragment
If anyone has the solution, it would be awesome!
So first off change your xml for graph_fragment.xml to this
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/graph_fragment_holder"
android:layout_width="match_parent"
android:layout_height="259dp" >
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/graph_detail_fragment_holder">
</FrameLayout>
</LinearLayout>
Then in code to inflate them from the fragment use something like this
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.graph_fragment,
container, false);
FirstChildFragment frag1 = (FirstChildFragment) getChildFragmentManager()
.findFragmentById(R.id.first_frag_layout);
SecondChildFragment frag1 = (SecondChildFragment) getChildFragmentManager()
.findFragmentById(R.id.second_frag_layout);
if (null == frag1) {
FirstChildFragment = new frag1();
FragmentTransaction transaction = getChildFragmentManager()
.beginTransaction();
transaction.add(R.id.graph_fragment_holder, frag1)
.addToBackStack(null).commit();
}
if (null == frag2) {
SecondChildFragment = new frag2();
FragmentTransaction transaction = getChildFragmentManager()
.beginTransaction();
transaction.add(R.id.graph_detail_fragment_holder, frag2)
.addToBackStack(null).commit();
}
return rootView;
}
MyFragment myFragment = (MyFragment)getChildFragmentManager().findFragmentById(R.id.my_fragment);
You can try to use the method *findFragmentById(fragment_id)* from SupportFragmentManager to get the instance of fragment from your .xml file and insert your fragment there.
Something like:
Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.myFragmentId);
I hope to help you.
Best regards.
Adriano

How to create multiple fragments programmatically?

I am trying to show multiple fragments on the one screen by creating them programmatically. I am able to do this no problem by including each fragment into the activities layout file. However when I try and do it programmatically Im confused.This is what I have so far for two fragments on a screen.
Main Class:
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentOne one = new FragmentOne();
FragmentTwo two = new FragmentTwo();
FragmentThree three = new FragmentThree();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.imOne, one, "fragmentone");
ft.add(R.id.imTwo, two, "fragmenttwo");
ft.add(R.id.imThree, three, "fragmenthree");
ft.commit();
}
}
Fragment One:
public class FragmentOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.frag_one, container, false);
return view;
}
}
Fragment Two:
public class FragmentTwo extends Fragment{
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.frag_two, container, false);
return view;
}
}
The layout files for my two fragment classes just contain a simple TextView.
And then the activity_main.xml layout file for my main class:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/imOne"
android:name="com.david.twofragexample.FragmentOne"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
<FrameLayout
android:id="#+id/imTwo"
android:name="com.david.twofragexample.FragmentTwo"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
<FrameLayout
android:id="#+id/imThree"
android:name="com.david.twofragexample.FragmentThree"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
When I try and do it programatically I get confused as to what should be in my activity_main.xml file. So from the Android Developer Guide(http://developer.android.com/guide/components/fragments.html) it says to use
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
So when I add this code to my onCreate method what changes do I have to make to my activity_main.xml file to do this programmatically?I don't see where R.id.fragment_container comes from. How can I determine where on the screen my new fragment will go?Thanks
EDIT: I am developing this on a tablet and not a phone.This has now been solved and the above code will add three fragments programmatically.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/list"
android:name="com.david.twofragexample.FragmentOne"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
<FrameLayout
android:id="#+id/viewer"
android:name="com.david.twofragexample.FragmentTwo"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
In your Activity:
FragmentOne one = new FragmentOne();
FragmentTwo two = new FragmentTwo();
fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.list, one, "fragmentone").commit();
fm.beginTransaction().replace(R.id.viewer, two, "fragmenttwo").commit();
I suggest you study this:
http://developer.android.com/reference/android/app/Fragment.html
and fully understand the fragment lifecycle, etc. The way I show is quick and dirty, but not neccesarilly best.
As I don't have higher enough reps to comment yet, I will just leave the information here -- the way Rafael T suggested does work nicely, although I also had my doubt at the first place.
1) Define your xml like this:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
2) Add each fragment into the same slot:
View box = v.findViewById(R.id.container);
FragmentTransaction ft = getFragmentManager().beginTransaction();
for (String catalog : mCatalogs) {
Fragment fragment = HighlightedProductFragment.newInstance(catalog);
ft.add(R.id.container, fragment, catalog);
}
ft.commit();
Thanks for the solution for this tricky requirement.
Try it like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
as your activity_main.xml
You asked yourself the right question: where is the id fragment_container, and the answer was: nowhere. >ou also set your layout to horizontal, which makes it very likely, that added Views will be kind of 'out of screen'

Dynamically add fragment into fragment

I haven't been able to find a way how to dynamically add fragment into existing dynamically added fragment. Do you know, if it is possible?
I am generating fragments this way:
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction xact = fragMgr.beginTransaction();
if(null == fragMgr.findFragmentByTag(FRAG1_TAG)) {
xact.add(10101010, new DateTime(), FRAG1_TAG);
}
if(null == fragMgr.findFragmentByTag(FRAG4_TAG)) {
xact.add(7777, new loginForm(), FRAG4_TAG);
}
xact.commit();
How to add into FRAG4_TAG fragment another one?
Edit2:
I hard coded it's id to be able to work with it in future (where ll is my linearLayout in XML):
FrameLayout frml4 = (FrameLayout)inflater.inflate(R.layout.frame,null);
frml4.setId(7777);
frml4.setBackgroundColor(Color.YELLOW);
ll.addView(frml4);
I assume the problem that you are running into is that there is not an inflated view to add the fragment to because the original fragment, FRAG4_TAG, has not been inflated before you are trying to add it.
You can pass enough information to FRAG4_TAG in the Arguments to let it know that it should create and add a fragment (or what all fragments you need it to have) to itself during it's onCreateView, after the view has been inflated...
The layout for the activity...
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="MyActivity"/>
<LinearLayout
android:orientation="vertical"
android:id="#+id/main_frag_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
The Activity...
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragOne = new MyFragment();
Bundle arguments = new Bundle();
arguments.putBoolean("shouldYouCreateAChildFragment", true);
fragOne.setArguments(arguments);
ft.add(R.id.main_frag_container, fragOne);
ft.commit();
}
}
The layout for the fragment...
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="20dp">
<TextView
android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Some fragment"/>
<LinearLayout
android:orientation="vertical"
android:id="#+id/frag_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
The fragment...
public class MyFragment extends Fragment {
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.frag_layout, container, false);
boolean shouldCreateChild = getArguments().getBoolean("shouldYouCreateAChildFragment");
if (shouldCreateChild) {
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
fm.beginTransaction();
Fragment fragTwo = new MyFragment();
Bundle arguments = new Bundle();
arguments.putBoolean("shouldYouCreateAChildFragment", false);
fragTwo.setArguments(arguments);
ft.add(R.id.frag_container, fragTwo);
ft.commit();
}
return layout;
}
}
This example covers the case where you need to dynamically add fragments to a fragment that HAS NOT already been inflated and added to the hierarchy. Adding a fragment to a fragment that HAS already been inflated and added to the hierarchy is as simple as just specifying the target fragments container that you want to add to by ID like you would normally.
As the documentation states "A fragment must always be embedded in an activity".
So when you add a "sub-fragment" it will always belong to the activity even if you add it within your fragment class. For example if you later decide to remove the containing fragment the sub fragments won't be automatically removed.
When I had to do the same I had to store in a vector the sub fragments and manually remove them in the onDestroy methods of my container fragment.
I think that fragments are not thought to be used like this
You cannot insert Fragments into other Fragments. (At least, not yet)
You can however replace Fragments with other Fragments with FragmentTransaction.replace(containerViewId, Fragment).
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.linear1, new activity()).commit();
}

Categories

Resources