I need to change the drawer content dynamically. I plan to do it with fragments. Means start new fragments to change the view of drawer. Actually my drawer itself a fragment. I have given code like this inside the first fragment:
#Override
public void onActivityCreated (Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
LinearLayout helpLL = (LinearLayout) getView().findViewById(R.id.helpLL);
helpLL.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Fragment detail = new DetailFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.left_drawer, detail).commit();
}
});
}
I need to change the entire drawer view with this layout. left_drawer is the view in main.xml where my first fragment lies. But when I click, nothing is happening.
Please tell me what wrong I did with this code.
Thanks
Jomia
I finally found the solution. I did a mistake in my code.Actually I hard coded the fragment in xml for the first drawer. Fragments that are hard coded in XML, cannot be replaced. Thats why the second fragment is not created.
So I added the first fragment dynamically. Now it is working fine..
In main.xml
<LinearLayout android:layout_width="240dp"
android:layout_height="match_parent"
android:id="#+id/left_drawer"
android:layout_weight="1"
android:layout_gravity="right"
android:orientation="vertical">
</LinearLayout>
In Activity
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
settingsFragment = new SettingsFragment();
fragmentTransaction.add(R.id.left_drawer, settingsFragment, "settingsFragment");
fragmentTransaction.commit();
In SettingsFragment.java
#Override
public void onActivityCreated (Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
LinearLayout helpLL = (LinearLayout) getView().findViewById(R.id.helpLL);
helpLL.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Fragment detail = new DetailFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.left_drawer, detail,"Details").commit();
}
});
}
Thats all...
Related
I have an activity whose sole purpose is to show 5 different fragments in a frame layout. There are 5 buttons, each corresponding to one of the 5 fragments that can be displayed in the frame layout.
I'm trying to make it so that the activity doesn't respond to a button press of the button that corresponds to the SAME fragment, so that there are no animations or other unnecessary computation performed.
The problem is that BOTH findFragmentById and findFragmentByTag return null, even when I believe I'm passing in the correct parameter of the container view, i.e. the frame layout.
Here is how I dynamically switch the fragments when responding to button presses:
private void viewProfile(){
profile_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment profile = new ProfileFragment();
beginFragment(profile, "profile");
}
});
}
private void beginFragment(Fragment fragment, String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.animator.fade_in,
android.R.animator.fade_out);
fragmentTransaction.replace(R.id.fragment_display, fragment, tag);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
Here is how I'm trying to determine what fragment is being displayed in the container:
private void launchEvents(){
final Fragment current_frag = getSupportFragmentManager()
.findFragmentById(R.id.fragment_display);
events_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!current_frag.getTag().equals("events")) {
Fragment events = new EventsFragment();
beginFragment(events, "events");
events.setArguments(location_info);
}
}
});
}
And here is my XML file, in case I'm getting something wrong with the layout hierarchy:
<?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:id="#+id/home_screen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#323272"
tools:context=".HomeScreen">
<FrameLayout
android:id="#+id/fragment_display"
android:layout_width="match_parent"
android:layout_height="527dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
tools:background="#323272:color/background_dark">
</FrameLayout>
Any nudge in the right direction would be great! I feel so silly for being stuck on something so minor.
Move you findFragmentById in onClick methods as below and instant of checking a tag check the instanceof if fragment
private void launchEvents(){
events_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment current_frag = getSupportFragmentManager()
.findFragmentById(R.id.fragment_display);
if (!(current_frag instanceof EventsFragment)) {
Fragment events = new EventsFragment();
beginFragment(events, "events");
events.setArguments(location_info);
}
}
});
}
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!
I need help with code snippet for replacing a fragment with another fragment on click of a button.
Here is the XML for the MainActivity
What can i do to resolve this error?
Tried searching the web only to come up with the same solution.
If somebody could please help me out on this.
Code for Main.Activity
public class MainActivity extends AppCompatActivity{
Button button1, button2, button3, button4;
Fragment fragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1=(Button)findViewById(R.id.layout1);
button2=(Button)findViewById(R.id.layout2);
button3=(Button)findViewById(R.id.layout3);
button4=(Button)findViewById(R.id.layout4);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fragment = new Fragment2();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.frag, fragment);
transaction.commit();
}
});
I saw few issues in your code:
If you add your fragment inside xml file, you cant remove/replace it in the future. As described from Google Page:
Note: When you add a fragment to an activity layout by defining the fragment in the layout XML file, you cannot remove the fragment at runtime. If you plan to swap your fragments in and out during user interaction, you must add the fragment to the activity when the activity first starts, as shown in the next lesson.
Your error may come from casting fragment. You should check your Fragment2. it maybe a support fragment.
Update
Here's the link to learning more about creating/adding fragment: Google Guide
Based on your comments, you should check what you did import in the Fragment2 layout (import android.support.v4.app.Fragment; or not). Are all your fragments from the same package or not?
The variable 'fragment' is an object of class Fragment and you are creating it as a object of class Fragment2 (which is a subclass of Fragment). This is not valid hence it's showing an error. Also to replace any fragment the fragment it should be inside a container view (usually a FrameLayout) and then you can use the replace transaction to replace it on the button click. The code should be as follows:
XML Code:
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="frameLayout" />
Java Code:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.frameLayout,fragment2).commit();
}
});
Just replace your fragment in your xml with a FrameLayout.
Now within button's onClickListener
YourFragment fragment = YourFragment.getInstance();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.frLayout, fragment, "TAG");
transaction.commit();
Hope that helps.
You should try
<FrameLayout
android:id="#+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
in xml insted of fragment
and try this
Fragment2 frag2 = new Fragment2();
getSupportFragmentManager().beginTransaction().replace(R.id.frag, frag2);
in java code.
I have been trying to build an android app for the purpose of understanding basic concepts behind fragments. But I am completely unable to show and hide fragment. Here is my code for onClickListner
final FragmentManager fragmentManager = getFragmentManager();
b.setOnClickListener(new View.OnClickListener() {
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onClick(View v) {
FragmentTransaction ft = fragmentManager.beginTransaction();
PM_Fragment pm_fragment = new PM_Fragment();
ft.replace(android.R.id.content, pm_fragment);
if (pm_fragment.isHidden()) {
fragmentManager.beginTransaction()
.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
.show(pm_fragment)
.commit();
b.setText("Hide");
} else {
fragmentManager.beginTransaction()
.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
.hide(pm_fragment)
.commit();
b.setText("Show");
}
}
});
Fragment is simply a text line in my case. And what the button is supposed to do is toggle the visibility of the fragment.
Can anybody tell me what is wrong with this code?
And by not working, I mean that button does nothing when tapped, except for changing its text from "hide" to "show" and after that it keeps "show", no matter how many times you tap it. And this process has no effect on the behaviour of fragment at all.
I really don't understand what you are trying to do here, but you never commit ft so your Fragment is never added to the Activity. I also don't understand the purpose of the two inner FragmentTransaction, but it is save to say that you DO NOT need them at all...
Define this globally:
private PM_Fragment pmFragment = new PM_Fragment();
And your OnClickListener should look like this:
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
if(pmFragment.isAdded()) {
ft.remove(pmFragment);
} else {
ft.replace(android.R.id.content, pmFragment);
}
ft.commit();
}
});
IMPORTANT: For FragmentTransactions to work, the Fragment has to have been added in code! If you add them in XML then they cannot be affected by FragmentTransactions! So if added your Fragment like this:
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="at.example.fragments.SomeFragment" />
Or with some other similar method than I am sure that this is at least part of the problem. You need to add your Fragment solely in code like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
SomeFragment fragment = SomeFragment.newInstance();
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.flFragmentContainer, fragment);
transaction.commit();
}
}
Just replace the <fragment /> tag with something like this in the layout:
<FrameLayout
android:id="#+id/flFragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
It will serve as a container for the Fragment you want to add. You can use the FragmentTransaction above to add the Fragment to this FrameLayout.
I am developing application which contains 2 fragments and i want to show hide according to my need. Following code has simple example of my problem.
This simple Fragmentactivity contains 1 button and one listfragment.
This simple example works flawless. but i am not satisfied with show hide fragment. If you remove layout.setVisibility(View.GONE); from the code then ft.hide(f); will not hide fragment. In fact we are not hiding fragment we are hiding container.
My Question is, IS this a way to show hide fragments? If not then please explain with tested example How to hide and show Fragments because lots of people are facing this problem.
public class MainActivity extends FragmentActivity implements OnClickListener {
Fragment1 f;
Button b;
LinearLayout layout;
Fragment myf;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b = (Button) findViewById(R.id.button1);
layout = (LinearLayout) findViewById(R.id.ll);
f = new Fragment1();
}
#Override
public void onClick(View v) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
if (f.isHidden()) {
ft.show(f);
layout.setVisibility(View.VISIBLE);
b.setText("Hide");
} else {
ft.hide(f);
b.setText("Show");
layout.setVisibility(View.GONE);
}
ft.commit();
// TODO Auto-generated method stub
}
Don't mess with the visibility flags of the container - FragmentTransaction.hide/show does that internally for you.
So the correct way to do this is:
FragmentManager fm = getFragmentManager();
fm.beginTransaction()
.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
.show(somefrag)
.commit();
OR if you are using android.support.v4.app.Fragment
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction()
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
.show(somefrag)
.commit();
In addittion, you can do in a Fragment (for example when getting server data failed):
getView().setVisibility(View.GONE);
Hi you do it by using this approach, all fragments will remain in the container once added initially and then we are simply revealing the desired fragment and hiding the others within the container.
// Within an activity
private FragmentA fragmentA;
private FragmentB fragmentB;
private FragmentC fragmentC;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
fragmentA = FragmentA.newInstance("foo");
fragmentB = FragmentB.newInstance("bar");
fragmentC = FragmentC.newInstance("baz");
}
}
// Replace the switch method
protected void displayFragmentA() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (fragmentA.isAdded()) { // if the fragment is already in container
ft.show(fragmentA);
} else { // fragment needs to be added to frame container
ft.add(R.id.flContainer, fragmentA, "A");
}
// Hide fragment B
if (fragmentB.isAdded()) { ft.hide(fragmentB); }
// Hide fragment C
if (fragmentC.isAdded()) { ft.hide(fragmentC); }
// Commit changes
ft.commit();
}
Please see https://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragments for more info. I hope I get to help anyone. Even if it this is an old question.
public void showHideFragment(final Fragment fragment){
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.animator.fade_in,
android.R.animator.fade_out);
if (fragment.isHidden()) {
ft.show(fragment);
Log.d("hidden","Show");
} else {
ft.hide(fragment);
Log.d("Shown","Hide");
}
ft.commit();
}
Try this:
MapFragment mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.mapview);
mapFragment.getView().setVisibility(View.GONE);
I may be way way too late but it could help someone in the future.
This answer is a modification to mangu23 answer
I only added a for loop to avoid repetition and to easily add more fragments without boilerplate code.
We first need a list of the fragments that should be displayed
public class MainActivity extends AppCompatActivity{
//...
List<Fragment> fragmentList = new ArrayList<>();
}
Then we need to fill it with our fragments
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
HomeFragment homeFragment = new HomeFragment();
MessagesFragment messagesFragment = new MessagesFragment();
UserFragment userFragment = new UserFragment();
FavoriteFragment favoriteFragment = new FavoriteFragment();
MapFragment mapFragment = new MapFragment();
fragmentList.add(homeFragment);
fragmentList.add(messagesFragment);
fragmentList.add(userFragment);
fragmentList.add(favoriteFragment);
fragmentList.add(mapFragment);
}
And we need a way to know which fragment were selected from the list, so we need getFragmentIndex function
private int getFragmentIndex(Fragment fragment) {
int index = -1;
for (int i = 0; i < fragmentList.size(); i++) {
if (fragment.hashCode() == fragmentList.get(i).hashCode()){
return i;
}
}
return index;
}
And finally, the displayFragment method will like this:
private void displayFragment(Fragment fragment) {
int index = getFragmentIndex(fragment);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (fragment.isAdded()) { // if the fragment is already in container
transaction.show(fragment);
} else { // fragment needs to be added to frame container
transaction.add(R.id.placeholder, fragment);
}
// hiding the other fragments
for (int i = 0; i < fragmentList.size(); i++) {
if (fragmentList.get(i).isAdded() && i != index) {
transaction.hide(fragmentList.get(i));
}
}
transaction.commit();
}
In this way, we can call displayFragment(homeFragment) for example.
This will automatically show the HomeFragment and hide any other fragment in the list.
This solution allows you to append more fragments to the fragmentList without having to repeat the if statements in the old displayFragment version.
I hope someone will find this useful.
From my code, comparing to above solution, the simplest way is to define a layout which contains the fragment, then you could hide or unhide the fragment by controlling the layout attribute which is align with the general way of view. No additional code needed in this case and the additional deployment attributes of the fragment could be moved to the outer layout.
<LinearLayout style="#style/StHorizontalLinearView"
>
<fragment
android:layout_width="match_parent"
android:layout_height="390dp"
android:layout_alignParentTop="true"
/>
</LinearLayout>
final Fragment fragment1 = new fragment1();
final Fragment fragment2 = new fragment2();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;
In onCreate, after setContentView, i hid two fragments and committed them to the fragment manager, but i didn't hide the first fragment that will serve as home.
fm.beginTransaction().add(R.id.main_container, fragment2, "2").hide(fragment2).commit();
fm.beginTransaction().add(R.id.main_container,fragment1, "1").commit();
#Override
public void onClick(View v) {
Fragment another = fragment1;
if(active==fragment1){
another = fragment2;
}
fm.beginTransaction().hide(active).show(another).commit();
active = another;
}
Ref : https://medium.com/#oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711
This worked for me
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if(tag.equalsIgnoreCase("dashboard")){
DashboardFragment dashboardFragment = (DashboardFragment)
fragmentManager.findFragmentByTag("dashboard");
if(dashboardFragment!=null) ft.show(dashboardFragment);
ShowcaseFragment showcaseFragment = (ShowcaseFragment)
fragmentManager.findFragmentByTag("showcase");
if(showcaseFragment!=null) ft.hide(showcaseFragment);
} else if(tag.equalsIgnoreCase("showcase")){
DashboardFragment dashboardFragment = (DashboardFragment)
fragmentManager.findFragmentByTag("dashboard");
if(dashboardFragment!=null) ft.hide(dashboardFragment);
ShowcaseFragment showcaseFragment = (ShowcaseFragment)
fragmentManager.findFragmentByTag("showcase");
if(showcaseFragment!=null) ft.show(showcaseFragment);
}
ft.commit();
the answers here are correct and i liked #Jyo the Whiff idea of a show and hide fragment implementation except the way he has it currently would hide the fragment on the first run so i added a slight change in that i added the isAdded check and show the fragment if its not already
public void showHideCardPreview(int id) {
FragmentManager fm = getSupportFragmentManager();
Bundle b = new Bundle();
b.putInt(Constants.CARD, id);
cardPreviewFragment.setArguments(b);
FragmentTransaction ft = fm.beginTransaction()
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
if (!cardPreviewFragment.isAdded()){
ft.add(R.id.full_screen_container, cardPreviewFragment);
ft.show(cardPreviewFragment);
} else {
if (cardPreviewFragment.isHidden()) {
Log.d(TAG,"++++++++++++++++++++ show");
ft.show(cardPreviewFragment);
} else {
Log.d(TAG,"++++++++++++++++++++ hide");
ft.hide(cardPreviewFragment);
}
}
ft.commit();
}