How to Add a Fragment to an Activity with a Programmatically Created Content View

How do I add a Fragment to an Activity with a programmatically created content view

It turns out there's more than one problem with that code. A fragment cannot be declared that way, inside the same java file as the activity but not as a public inner class. The framework expects the fragment's constructor (with no parameters) to be public and visible. Moving the fragment into the Activity as an inner class, or creating a new java file for the fragment fixes that.

The second issue is that when you're adding a fragment this way, you must pass a reference to the fragment's containing view, and that view must have a custom id. Using the default id will crash the app. Here's the updated code:

public class DebugExampleTwo extends Activity {

private static final int CONTENT_VIEW_ID = 10101010;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FrameLayout frame = new FrameLayout(this);
frame.setId(CONTENT_VIEW_ID);
setContentView(frame, new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

if (savedInstanceState == null) {
Fragment newFragment = new DebugExampleTwoFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(CONTENT_VIEW_ID, newFragment).commit();
}
}

public static class DebugExampleTwoFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
EditText v = new EditText(getActivity());
v.setText("Hello Fragment!");
return v;
}
}
}

Programmatically add Fragment to an Activity in Kotlin

The exception says you are trying to add the Fragment to be associated with a view that doesn't exist. In fact, I'm not sure where R.id.home_fragment comes from.

Solution is this:

<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/root_container">
</FrameLayout>

Then

if(savedInstanceState == null) { // initial transaction should be wrapped like this
supportFragmentManager.beginTransaction()
.replace(R.id.root_container, homeFragment)
.commitAllowingStateLoss()
}

So the other answer was also correct that said to use container and R.id.container, but you are also missing setContentView(R.layout.activity_main).

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

How to add an Android fragment to an activity?

i have started fragment from my MainActivity. main activity extends FragmentActivity. the way i have used is:

FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.body_frame, new MyFragment()).commit();

in your case, it should look like:

FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.title_fragment, new TitleFragment()).commit();

remember i have used an FragmentActivity to start Fragment. i have also used android-support-v4.jar
to support fragment in lower version OS. without android-support-v4.jar,
FragmentManager manager = getSupportFragmentManager(); may be look like : FragmentManager manager = getFragmentManager();

Edited:

you should modify your fragment class:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_title, container, false);
// you can use findViewById() using the above 'view'
......................
....your code........
................
return view;
}

Map inside fragment inside programmatically created view

Just solved the problem:

    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
FrameLayout mainView = (FrameLayout) inflater.inflate(R.layout.activity_main, null);
LinearLayout parent = (LinearLayout) mainView.findViewById(R.id.stepper_container);
step1 = inflater.inflate(R.layout.layout_step, null);
parent.addView(step1);
// Other steps
setContentView(mainView);
FrameLayout container = (FrameLayout) step1.findViewById(R.id.step_content_container);

fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
OfficeMapFragment map = OfficeMapFragment.newInstance();
transaction.add(container.getId(), map);
transaction.commit();

And it works fine (with minor layout bugs).

Working map in the step

Android: Adding a fragment to an activity

The problem here is that the fragment needs a container with a view id to reside within. Giving it a layout id will result in the error you saw.

You can add the fragment to your relative layout, but to do that properly you'll need to assign it appropriate layout parameters so that it can be placed. It would be easier to just create a FrameLayout within the relative layout that wraps its contents, and then add the fragment there.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<FrameLayout
android:id="@+id/FragmentContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/B1"/>

</RelativeLayout>

Then

fragmentTransaction.add(R.id.FragmentContainer, fragment);

How to add a fragment to a programmatically generated layout?

At some point, I suppose you will add your programatically created LinearLayout to some root layout that you defined in .xml.
This is just a suggestion of mine and probably one of many solutions, but it works:
Simply set an ID for the programatically created layout, and add it to the root layout that you defined in .xml, and then use the set ID to add the Fragment.

It could look like this:

LinearLayout rowLayout = new LinearLayout();
rowLayout.setId(whateveryouwantasid);
// add rowLayout to the root layout somewhere here

FragmentManager fragMan = getFragmentManager();
FragmentTransaction fragTransaction = fragMan.beginTransaction();

Fragment myFrag = new ImageFragment();
fragTransaction.add(rowLayout.getId(), myFrag , "fragment" + fragCount);
fragTransaction.commit();

Simply choose whatever Integer value you want for the ID:

rowLayout.setId(12345);

If you are using the above line of code not just once, it would probably be smart to figure out a way to create unique-IDs, in order to avoid duplicates.

UPDATE:

Here is the full code of how it should be done:
(this code is tested and works)
I am adding two Fragments to a LinearLayout with horizontal orientation, resulting in the Fragments being aligned next to each other. Please also be aware, that I used a fixed height and width of 200dp, so that one Fragment does not use the full screen as it would with "match_parent".

MainActivity.java:

public class MainActivity extends Activity {

@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

LinearLayout fragContainer = (LinearLayout) findViewById(R.id.llFragmentContainer);

LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);

ll.setId(12345);

getFragmentManager().beginTransaction().add(ll.getId(), TestFragment.newInstance("I am frag 1"), "someTag1").commit();
getFragmentManager().beginTransaction().add(ll.getId(), TestFragment.newInstance("I am frag 2"), "someTag2").commit();

fragContainer.addView(ll);
}
}

TestFragment.java:

public class TestFragment extends Fragment {

public static TestFragment newInstance(String text) {

TestFragment f = new TestFragment();

Bundle b = new Bundle();
b.putString("text", text);
f.setArguments(b);
return f;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

View v = inflater.inflate(R.layout.fragment, container, false);

((TextView) v.findViewById(R.id.tvFragText)).setText(getArguments().getString("text"));
return v;
}
}

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rlMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
tools:context=".MainActivity" >

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />

<LinearLayout
android:id="@+id/llFragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignLeft="@+id/textView1"
android:layout_below="@+id/textView1"
android:layout_marginTop="19dp"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>

fragment.xml:

  <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="200dp"
android:layout_height="200dp" >

<TextView
android:id="@+id/tvFragText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="" />

</RelativeLayout>

And this is the result of the above code: (the two Fragments are aligned next to each other)
result

Adding a Fragment Dynamically inside a view

You are probably getting message like this:

java.lang.ClassCastException: android.view.View cannot be cast to
android.view.ViewGroup

That's because fragment can be inserted into ViewGroup or something that inherits from ViewGroup. You cannot insert fragment into View. To make your code run change this line:

View view = new View(this);

into ,for example, this:

FrameLayout view = new FrameLayout(this);//FrameLayout inherits from ViewGroup


Related Topics



Leave a reply



Submit