I've got a question.
I have a fragment, which inflates two other fragments (Fragment A is left, Fragment B is right)
I want to hide Fragment A when the user changes the mode to portrait-mode.
I added in the layout-port/xml a DrawerLayout and added the code for the NavigationDrawer in my Fragment, but it doesn't work.
Does anyone have an idea, how to realize it?
Thanks :)
I've solved the first problem with this code:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
orientation = newConfig.orientation;
switch (orientation) {
case Configuration.ORIENTATION_LANDSCAPE:
FragmentA fragmentleft = new FragmentA();
FragmentB fragmentright = new FragmentB();
FragmentTransaction transaction1 = getSupportFragmentManager()
.beginTransaction();
FragmentTransaction transaction2 = getSupportFragmentManager()
.beginTransaction();
transaction1.replace(R.id.framelayout_left, fragmentleft);
transaction2.replace(R.id.framelayout_right, fragmentright);
transaction1.commit();
transaction2.commit();
break;
case Configuration.ORIENTATION_PORTRAIT:
createNavigationDrawer();
Log.d("TEST", "Portrait");
break;
}
}
But now I have the problem, that i have to inflate FragmentA in my ListView of the DrawerLayout:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="#+id/framelayout_right"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="#+id/framelayout_left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
But how can I do this?
It doesn't work properly :(
I had also tried to change the ListView to a FrameLayout and inflate the FragmentA within it, but it didn't work too:(
I would be very thankful, if somebody could help me :)
Related
So I'm working in Fragments that has 2 Fragments in it. take a look at the image below:
The first fragment that shows the list of the inventory is named fragment_purchase_item_list and on the right side is the fragment_purchase_list
What I want to do is when I clicked SCAN from the toolbar on the right fragment, fragment_qrscan will replace fragment_purchase_item_list. Like this image below:
Can someone please see and check why my code is not working? Thanks!
PurchaseListFragment.java
<-- start of code snippet -->
#Override
public void onClick(View v) {
int id = v.getId();
switch (id){
case R.id.btn_paypurchasetransaction:
Fragment chargeFragment = new ChargeFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.customersales_content, chargeFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
case R.id.layout_transaction_qrcode:
// Toast.makeText(getActivity(), "Scan Item", Toast.LENGTH_SHORT).show();
Fragment scanQRCodeFragment = new QRScanFragment();
FragmentManager fragmentManager1 = getFragmentManager();
FragmentTransaction fragmentTransaction1 = fragmentManager1.beginTransaction();
fragmentTransaction1.replace(R.id.inventory_fragment, scanQRCodeFragment);
fragmentTransaction1.addToBackStack(null);
fragmentTransaction1.commit();
break;
case R.id.layout_transaction_new:
Toast.makeText(getActivity(), "New Transaction", Toast.LENGTH_SHORT).show();
break;
}
}
<-- end of code snippet>
fragment_sales.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"
tools:context=".Fragments.SalesFragment"
android:orientation="horizontal"
android:id="#+id/customersales_content">
<fragment
android:id="#+id/inventory_fragment"
android:name="com.example.devcash.Fragments.PurchaseItemListFragment"
tools:layout="#layout/fragment_purchase_item_list"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3">
</fragment>
<View
style="#style/Divider"
android:layout_width="1dp"
android:layout_height="wrap_content" />
<fragment
android:id="#+id/purchaselist_fragment"
android:name="com.example.devcash.Fragments.PurchaseListFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
tools:layout="#layout/fragment_purchase_list">
</fragment>
</LinearLayout>
Try replacing getFragmentManager() with getChildFragmentManager()
I have a main activity , it contains lots of fragments.
Main activity layout looks like this:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.user.taiwandigestionsociety_v11.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF">
<include layout="#layout/toolbar"/>
//switch fragment over here
<FrameLayout
android:id="#+id/mainFrame"
android:layout_gravity="end"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</android.support.design.widget.AppBarLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#android:color/transparent"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
and I click the drawer item it will change to first fragment:
#Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.activitiesContents) {
//change to first fragment successful
switchFragment(ActivityList.newInstance());
toolbar.setTitle(R.string.activitiesContents);
drawerLayout.closeDrawer(GravityCompat.START);
}
}
my switch fragment function:
public void switchFragment(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.mainFrame, fragment, null);
//transaction.addToBackStack(null);
transaction.commit();
}
then i click the button in first fragment, it changes to second fragment too:
//take me to second fragment succeed
switchFragment(ActivityHomePage.newInstance());
finally i click the button in second fragment, it crashed
//i want to switch to third fragment , just the same with previous
switchFragment(NewsInformation.newInstance());
the error log:
Why i got crash when i switch to third fragment? I completely have no clue.
I found the crash function function , because I set the class:
public class CommonSwitch extends Fragment {
//switch Fragment
public void switchFragment(Fragment fragment) {
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.mainFrame, fragment, null);
//transaction.addToBackStack(null);
transaction.commit();
}
}
and I try to call it new CommonSwitch.switchFragment(goToFragment);
now I have set public void switchFragment every Fragment class.
Why when I set new CommonSwitch will cause crash ?
Your Activity state is Not Maintain.
On second layer use Activity instead of Fragment . Follow Android Standards.
According to standards Third Fragment should be Activity. otherwise you have to maintain MainActivity state.
Thanks
I've got an activity in which there are 2 fragments which changes basing on a button click.
I'd like to show an animation when the replacement appens, so i searched for the code and here's what i concluded:
public void displayView(int page){
switch (page){
case 1:
FragmentHome fragmentHome = new FragmentHome();
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment, fragmentHome)
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out).commit();
break;
case 2:
FragmentHomeBack fragmentHomeBack = new FragmentHomeBack();
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment, fragmentHomeBack)
.setCustomAnimations(android.R.anim.accelerate_decelerate_interpolator, android.R.anim.anticipate_interpolator).commit();
break;
}
}
I don't know why but the animations don't works, the new fragment just replace the other without animation.
Here's the activity layout code:
<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/activity_master"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/space10"
tools:context="context">
<include
android:id="#+id/ll_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="#dimen/space5"
android:orientation="vertical"
android:layout_marginLeft="#dimen/space5"
android:layout_marginRight="#dimen/space15"
layout="#layout/menu"
android:layout_alignParentTop="true"
android:layout_above="#+id/imageView" />
<FrameLayout
android:id="#+id/fragment_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="#id/ll_left">
</FrameLayout>
<ImageView
app:srcCompat="#drawable/xlink"
android:id="#+id/imageView"
android:layout_width="150dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:scaleType="fitEnd"
android:layout_height="70dp" />
The frame layout "fragment_holder" is where the Fragments are.
Thanks to everybody!
That should do the trick buddy. I have the same code and it works well.
getSupportFragmentManager()
.beginTransaction()
.setCustomAnimations(android.R.anim.fade_in,android.R.anim.fade_out)
.replace(R.id.layout_container, fragment)
.commit();
But..
I see what is the difference in our code. Try setting customAnimations before replace to see what happens.
And I have a suggestion to improve your code. In your "if" or "switch" statement set the fragment like
Fragment fragment;
if(page==0){
fragment = new MyFragment();
}else{
fragment = new MySecondFragment();
}
then you only have this code once
getChildFragmentManager()
.beginTransaction()
.setCustomAnimations(android.R.anim.fade_in,android.R.anim.fade_out)
.replace(R.id.layout_container, fragment)
.commit();
Here's my navigation:
HomeFragment -> LoginFragment -> CreateEventFragment
My HomeFragment is my first Fragment inside my MainActivity.
In my code, I'm replacing each one of them using the same view id( a FrameLayout inside my MainActivity's layout: R.id.container).
So every replace() is being called like this:
FragmentManager fragmentManager = mContext.getSupportFragmentManager();
fragmentManager.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(containerId, nextFragment).addToBackStack(null).commit();
Except for LoginFragment to CreateEventFragment, because after the user logs in, he doesn't have to go back to LoginFragment so I don't call addToBackStack().
But something strange is happening:
When I'm on CreateEventFragment, after logging in successfully, and press the back button, my CreateEventFragment onDestroy() is not being called.
Debugging it I noticed that it isn't removed from the backStack, what am I doing wrong?
EDIT
Some code:
Common replace fragment method, inside BaseFragment, parent class of all three Fragments
public void replaceFragment(int containerId, Fragment nextFragment, boolean addToBackStack){
FragmentManager fragmentManager = mContext.getSupportFragmentManager();
if (addToBackStack)
fragmentManager.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(containerId, nextFragment).addToBackStack(null).commit();
else
fragmentManager.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(containerId, nextFragment).commit();
}
On HomeFragment:
BaseFragment nextFragment =
(PreferencesHandler.isLogged()) ?
CreateEventFragment.newInstance() :
LoginFragment.newInstance("create_event") ;
replaceFragment(R.id.main_fragment_container, nextFragment, true);
On LoginFragment:
public void goToNextFragment(){
Fragment nextFragment;
switch (mIntent){
case "create_event":
nextFragment = new CreateEventFragment();
break;
case "participate":
nextFragment = new ListsFragment();
break;
default:
nextFragment = new HomeFragment();
break;
}
replaceFragment(R.id.main_fragment_container, nextFragment, false);
}
My MainActivity's layout:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar_actionbar"
layout="#layout/toolbar_actionbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:layout_below="#+id/toolbar_actionbar"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/main_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar_actionbar"
/>
<fragment android:id="#+id/navigation_drawer"
android:layout_width="#dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:name="Fragments.`NavigationDrawerFragment`"
tools:layout="#layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
EDIT 2
Noticed that pressing back button calls LoginFragment onDestroy, but not CreateFragment's. Also noticed that backStack has LoginFragment, guess it shouldn't, right?
I have strange behaviour. Every time i replace the same type of fragment in Activity (using transaction), the new Fragment instance is added to Fragment List. The old instances remains active in Fragment Manager and after orientation change are visible on the screen (although not clickable).
My Activity Layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
-->
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
<android.support.v4.widget.DrawerLayout
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.cubesoft.zenfolio.moments.app.activity.MainActivity" >
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
<fragment
android:id="#+id/navigation_drawer"
android:name="com.cubesoft.zenfolio.moments.app.fragment.NavigationDrawerFragment"
android:layout_width="#dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
tools:layout="#layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
<fragment
android:id="#+id/fragmentConnectionStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
class="com.cubesoft.zenfolio.fragment.ConnectionStatusFragment" />
My code that changes fragments:
#Override
public void onNavigationDrawerItemSelected(int position) {
mCurrentDrawerPosition = position;
// update the main content by replacing fragments
List<Fragment> fragmemts = getSupportFragmentManager().getFragments();
switch (position) {
case 0:{
if ( getMyApplication().getGroupModel().getUsersCount() > 0 ) {
final Fragment fragment = UserSelectionFragment.newInstance();
final FragmentManager fragmentManager = getSupportFragmentManager();
//fragmentManager.popBackStack();
final FragmentTransaction tr = fragmentManager
.beginTransaction();
tr.replace(R.id.container, fragment);
tr.addToBackStack(null);
tr.setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out);
tr.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
tr.commit();
} else {
final Fragment fragment = MomentsFragment.newInstance(mUsername);
final FragmentManager fragmentManager = getSupportFragmentManager();
//fragmentManager.popBackStack();
final FragmentTransaction tr = fragmentManager
.beginTransaction();
tr.replace(R.id.container, fragment);
//tr.setCustomAnimations(R.anim.abc_fade_in, R.anim.abc_fade_out);
tr.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
tr.addToBackStack(null);
tr.commit();
}
break;
}
case 1: {
final Fragment fragment = DownloadFragment.newInstance();
final FragmentManager fragmentManager = getSupportFragmentManager();
//fragmentManager.popBackStack();
final FragmentTransaction tr = fragmentManager
.beginTransaction();
tr.replace(R.id.container, fragment);
tr.addToBackStack(null);
tr.commit();
break;
}
/*case 2:
fragment = UserSelectionFragment.newInstance();
break;*/
}
}
The UserSelectionFragment is displayed incorrectly after several orientation changes, old instances of UserSelectionFragment remains in Fragment List but their View objects are null.
What is wrong?
Try removing
tr.addToBackStack(null);
To me this adds your frgament to the backstack and thats the reason why they are kept in your fragment list. Their view are null because they have been destroyed before going to backgroud.