I've run into an issue with my code.
What I want
My Activity starts automatically with Fragment01.
On Fragment01, there is a button, which should replace Fragment01 with Fragment02
What happens
When I press the button, instead of replacing Fragment01, I can still see Fragment01 in the background
MainActivity.java:
package com.lucky.fragmentexample;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
Button bn;
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bn = (Button)findViewById(R.id.button1);
bn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Fragment02 fragment02 = new Fragment02();
fragmentTransaction.replace(R.id.button_fragment_container, fragment02);
fragmentTransaction.commit();
}
});
}
}
activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<FrameLayout
android:id="#+id/button_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/fragment01"
android:name="com.lucky.fragmentexample.Fragment01"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</LinearLayout>
Your fragment element in your layout XML can only ever refer to that single fragment and can't be swapped out in the way you intend. Instead, you need to remove the fragment element from your layout XML entirely and add your Fragment01 into your container FrameLayout in code in the onCreate() method of your activity.
So, remove the fragment element, like so;
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<FrameLayout
android:id="#+id/button_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
Then you can perform your transaction in the beginning of your onCreate() override, like so;
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
transaction.replace(R.id.button_fragment_container, new Fragment01());
transaction.commit();
You will want to instantiate a new FragmentTransaction for each new transaction, which means you'll probably want to remove the FragmentManager and FragmentTransaction from your instance members and declare them fresh each time you need to make a fragment transaction.
I hope this helps.
Further reading:
Official Fragments API Tutorial
Put beginTransaction inside onclick function and replace R.id.button_fragment_container for R.id.frame_container.
Use this inside onclick:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frame_container, new Fragment02()).commit();
Fragment inside xml file is not correct. Erase that part.
try this code :
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.fragment01, new Fragment02());
fragmentTransaction.commit();
also, change the 'fragment' to 'FrameLayout' in your xml. This prevents from any one fragment always remaining in the background.
Just go step by step:
First modify your layout, remove the fragment over there and make the reference of your FrameLayout in the activity.
Now initiate your fragment class which you want to add to the framelayout and call following code:
FragmentTransaction transaction = manager.beginTransaction();
transaction.remove(removePreviousFragmentIfAny);
transaction.add(R.id.button_fragment_container, newFragment);
transaction.commit();
Hope it will help you to go through.
Related
So my goal is to swap from my CalculatorFragment to my CalculatorResultsFragment using a parent FrameLayout through a a button. I'm getting the error:
java.lang.IllegalArgumentException: No view found for id 0x7f08020f (com.example.flexplan:id/parent_fragment) for fragment CalculatorResultsFragment{1046933} (71b49e01-2328-4454-870b-5acb04ccc3d0 id=0x7f08020f)
fragment_calculator_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".Calculator.CalculatorParentFragment">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/parent_fragment"/>
</LinearLayout>
CalculatorParentFragment.java
FragmentManager manager = getChildFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.parent_fragment, new CalculatorFragment());
transaction.commit();
CalculatorFragment.java
submitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager manager = getChildFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.parent_fragment, new CalculatorResultsFragment());
transaction.commit();
}
});
Anyone know how I can fix this?
Error says you do not have view for your fragment, check your layout files, for each fragment you need to have one layout, if not transaction can not send you there. After all layouts in place, follow the docs link like so:
FragmentManager fragmentManager = getChildFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setReorderingAllowed(true);
transaction.replace(R.id.parent_fragment, CalculatorResultsFragment.class, null);
transaction.commit();
I simply want to call a method from a fragment in my MainActivity(parent).
But as soon as I try to call the method I get an NullPointerException.
Attempt to invoke virtual method 'void
com.example.fragmenttest.TestFragment.testMethod()' on a null object
reference
Here is what I do in the onCreate of the MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.containerView, new TestFragment()).commit();
TestFragment fragment = (TestFragment) fragmentManager.findFragmentById(R.id.testfragment);
fragment.testMethod();
}
and here is the fragment:
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView=inflater.inflate(R.layout.activity_fragment,container,false);
return rootView;
}
public void testMethod(){
Toast.makeText(getContext(), "Test", Toast.LENGTH_LONG).show();
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<FrameLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/containerView">
</FrameLayout>
</RelativeLayout>
and activity_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.fragmenttest.MainActivity"
android:id="#+id/testfragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="50dp"
android:text="Fragment" />
</RelativeLayout>
Of course this is not my real project, I just created a new one to simplify my issue.
In my real project I want to call a method from my fragment as soon as the onRewardedVideoCompleted method gets called, which is in my MainActivity.
How do I call the method from my fragment without getting a null pointer exception and without using an interface? (Using an interface for this small problem seems unnecessary)
Thanks
commit() is asynchronous. This is why your project is crashing upon launch. Instead of using commit(), use commitNow(). Also, instead of using new TestFragment(), create a variable so you can call its methods.
TestFragment testFragment= new TestFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.containerView, testFragment).commitNow();
testFragment.testMethod();
Fragment transactions are asynchronous (unless you use executePendingTransactions()). Your transaction has likely not completed yet. You use runOnCommit on FragmentTransaction (in the support library) to execute code after it is done.
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
TestFragment yourFragment = newe TestFragment();
fragmentTransaction.replace(R.id.containerView, yourFragment).commit();
yourFragment.testMethod();
First of all, You must pass yourFragment to fragmentTransaction, then you can call any methods you want.
Just so know the listview in the image is fragment generated. But i dont think that should interfere with toolbar's layout. Here is the code for layout -
<RelativeLayout 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:id="#+id/fragment_songlistview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/croctooth"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"
tools:context="com.shaikhsakib.sounddemo.SongActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="#color/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:theme="#style/ThemeOverlay.AppCompat.Dark"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
/>
<ListView
android:id="#+id/fragmentSongListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar2" />
</RelativeLayout>
And here the the corresponding activity to the above layout -
package com.shaikhsakib.sounddemo;
import android.app.ActionBar;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
public class SongActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_song);
loadFragment();
Toolbar toolbar2 = (Toolbar) findViewById(R.id.toolbar2);
setSupportActionBar(toolbar2);
}
private void loadFragment() {
// create a FragmentManager
FragmentManager fm;
fm = getFragmentManager();
// create a FragmentTransaction to begin the transaction and replace the Fragment
FragmentTransaction fragmentTransaction = fm.beginTransaction();
// replace the FrameLayout with new Fragment
SongListFragment slv = new SongListFragment();
fragmentTransaction.replace(R.id.songFrameLayout, slv);
fragmentTransaction.commit(); // save the changes
}
}
I checked most of the white space toolbar related answers on Stack Overflow but nothing works. Maybe my problem is different.
EDIT 1
Here is my Main Activity. It also loads a fragment listview an ha custom toolbar. But no such whitespace here -
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadFragment();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
private void loadFragment() {
// create a FragmentManager
FragmentManager fm;
fm = getFragmentManager();
// create a FragmentTransaction to begin the transaction and replace the Fragment
FragmentTransaction fragmentTransaction = fm.beginTransaction();
// replace the FrameLayout with new Fragment
PLayListFragment flv = new PLayListFragment();
fragmentTransaction.replace(R.id.frameLayout, flv);
fragmentTransaction.commit(); // save the changes
}
}
Also notice that I am replacing the same R.id.frameLayout in both the activities but that should not have anything to do with toolbar. Can anybody tell why its not happening in MainActivity but in other activity.
The problem was not actually with Toolbar but with Status bar. It needed CoordinatorLayout instead of RelativeLayout as parent. So all i had to do was make the relative layout as child of CoordinatorLayout and pass an attribute like android:fitsSystemWindows="true". That solved the problem.
Here is the solution -
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true"
android:background="#color/croctooth"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"
tools:context="com.shaikhsakib.sounddemo.SongActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="#color/colorPrimary"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
/>
<ListView
android:id="#+id/fragmentSongListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar2" />
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
I am trying to run a class extending a fragment from a class extending AppCompactActivity, I have tried everything I have saw in Stackover flow and I cant get any to fix my problem. LineDetails is extending the Fragment
Progress1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Fragment fr = new LineDetails();
android.app.FragmentManager fm = getFragmentManager();
android.app.FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.fragment_place, fr);
fragmentTransaction.commit();
}
});
XML
<fragment android:name="com.almac.tracker.LineDetails"
android:id="#+id/fragment_place"
android:layout_width="match_parent"
android:layout_height="match_parent" />
PART OF XML FOR ACTIVITY CLASS
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:overScrollMode="never"
android:scrollbars="none"
tools:context=".Dashboard">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/fragment_place">
</FrameLayout>
</RelativeLayout >
If your activity extends AppCompatActivity, then you cannot use getFragmentManager().
In fact you should get rid of classes in the package android.app such as android.app.FragmentManager. You should use the support classes from the package android.support.v4.app such as android.support.v4.app.FragmentManager
Use getSupportFragmentManager() instead of getFragmentManager()
The stack trace reports that you don't have any Layout with id R.id.fragment_place inside your activity. Check the xml of your activity and correct the id of fragment holder.
You're replacing instead of adding without a refresh, just do an add. I also simplified one of your useless variables and just went straight to ft instead of having an intermediate fm.
Progress1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Fragment fr = new LineDetails();
android.app.FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fragment_place, fr);
ft.commit();
}
});
getSupportFragmentManager() should be used if activity extends AppcompatActivity
EDIT :
As per the Errors ! There is no View named fragment_place in the activity's layout that is #+id/fragment_place must exist in activity_main (If this is the layout attached to activity)
Double check your layout xml, It should have a FrameLayout with attribute #+id/fragment_place act as a placeholder for your LineDetails fragment.
If you already place <fragment /> in your layout, you don't need to replace() it programmatically.
I'm trying to have a fragment loaded as the default view for the activity, but I just get a blank screen and huge memory leaks.
Activity file onCreate method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
if (savedInstanceState == null) {
FragmentManager fragmentManager = getFragmentManager();
int fragmentTransaction = fragmentManager.beginTransaction()
.add(R.id.login_screen_fragment, new FragmentLogin())
.commit();
}
}
The XML for the activity:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LoginActivity">
<fragment
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/login_screen_fragment"
class="com.test.project.FragmentLogin"
/>
<fragment
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/forgotten_password_fragment"
class="com.test.project.FragmentForgottenPassword"
/>
</FrameLayout>
And the Fragment class (relevant parts):
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_login, container, false);
final Activity activity = getActivity();
... code ...
return view;
}
I followed instructions from a tutorial someone suggested earlier from a different question, but I must be doing something horribly wrong. Any ideas?
xml file
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/changeFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LoginActivity">
</FrameLayout>
your activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
if (savedInstanceState == null) {
FragmentLogin f1= new FragmentLogin();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.changeFragment, f1);
fragmentTransaction.commit();
}
}
I'm new to Android and I ran into the same problem. Here's how I fixed mine.
So in your onCreate method, use getSupportFragmentManager() from the FragmentManager class then declare FragmentTransaction separately. See below. I did this for my case and it worked.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
if (savedInstanceState == null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.login_screen_fragment, new FragmentLogin());
fragmentTransaction.commit();
}
Hope this helps solve your problem as well.
Sincerely,
sylvery
Just replace the fragment element with FrameLayout, then you can see your fragment.
If you wanted to add the Fragment programatically, then remove the <Fragment> in your Framelayout and add some ID unto it.
It should look like this:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/login_screen_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LoginActivity" />