I am following the vogella tutorial about multi-pane development in Android.
Now I would like to check if the a detail fragment is existing (multi-pane layout activated) to remove it and add it again with fresh data.
I need that to update the detail view when the user selects something in the main fragment.
As suggested in the tutorial I am checking for the Fragment like that:
ReviewMaschineFragment fragment = (ReviewMaschineFragment) getFragmentManager().
findFragmentById(R.id.detailreviewcontainer);
if (fragment == null || ! fragment.isInLayout()) {
Log.i("Detail Fragment", "Start new activity");
}
else {
Log.i("Detail Fragment", "Update...");
}
My Problem is that it always gets false even if the fragment exists.
Why is it not detecting the fragment as existing if it is present in the multi-pane layout?
I add my fragments like that to the layout:
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar_main);
setSupportActionBar(toolbar);
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.maschinelistcontainer, new MaschineFragment());
if(getResources().getBoolean(R.bool.dual_pane)){
ft.add(R.id.detailreviewcontainer, new ReviewMaschineFragment());
}
ft.commit();
The tablet layout file:
<?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"
>
<include
android:id="#+id/toolbar_main"
layout="#layout/toolbar"
></include>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="9"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/maschinelistcontainer"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
/>
<FrameLayout
android:id="#+id/detailreviewcontainer"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="6"
/>
</LinearLayout>
</LinearLayout>
While creating fragment add tag value with it
eg
ft.add(R.id.maschinelistcontainer, new MaschineFragment(), "sometag");
You can use findFragmentByTag() function to get fragment if it is giving null the fragment is not exist.
Fragment fragmentA = fragmentManager.findFragmentByTag("sometag");
if (fragmentA == null) {
// not exist
} else {
//fragment exist
}
for example:- http://wiki.workassis.com/android-load-two-fragments-in-one-framelayout/
Pls change
ReviewMaschineFragment fragment = (ReviewMaschineFragment) getFragmentManager().
to
ReviewMaschineFragment fragment = (ReviewMaschineFragment) getSupportFragmentManager().
Related
I'm using a navigation drawer along with a SwipeRefreshLayout for the main content and when the user selects a menu item in the navigation drawer, I want to replace the fragment inside the SwipeRefreshLayout with another fragment.
This is what my onNavigationItemSelected() looks like:
// Handle navigation view item clicks here.
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
selectedNavItem = item.getItemId();
if(selectedNavItem == R.id.nav_files){
filesFragment = new FilesFragment();
fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.swipeLayout,filesFragment,"files");
transaction.commit();
} else if(selectedNavItem == R.id.nav_accounts){
accountsFragment = new AccountsFragment();
fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.swipeLayout,accountsFragment,"accounts");
transaction.commit();
}
return true;
But this never works. When I click an item in the nav drawer, the fragment is replaced by a blank screen. My onCreate method also uses FragmentTransaction.replace() but that seems to work fine.
I also tried FragmentTransaction.remove() and then FragmentTransaction.add() but even that doesn't seem to work.
Edit: Layout files:
Layout of the content view of the navigation drawer:
<android.support.v4.widget.SwipeRefreshLayout
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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.harshallele.cloudpool.MainActivity"
tools:showIn="#layout/app_bar_main"
android:id="#+id/swipeLayout">
</android.support.v4.widget.SwipeRefreshLayout>
This is included inside another layout file which contains a CoordinatorLayout containing the toolbar.That file, in turn, is inside the main layout file of the activity inside a android.support.v4.widget.DrawerLayout
(Basically, this is the Navigation Drawer Activity provided by Android Studio when adding an Activity)
Layout for FilesFragment:
<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=".fragments.FilesFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/fileListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
/>
<ProgressBar
android:id="#+id/itemsLoadingProgress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
style="?android:attr/progressBarStyleHorizontal"
android:indeterminateOnly="true"
android:visibility="invisible"
/>
</FrameLayout>
Layout for AccountsFragment(this is just the default blank fragment, because i haven't finished this yet):
<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="com.harshallele.cloudpool.fragments.AccountsFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_blank_fragment" />
</FrameLayout>
Edit 2:
AccountsFragment:
public class AccountsFragment extends Fragment {
public AccountsFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_accounts, container, false);
}
}
With just this bit of code we can't help you so much. The problem can be that:
The FilesFragment and AccountsFragment aren't initialized in the right way;
The Layout with id swipeLayout can have visibility = gone;
The Layout of FilesFragment and AccountsFragment can be empty;
This are just some of the infinite reason why your code doesn't work properly so please share more code about the two Fragments and relative XML.
Im building dynamic UI for tablets with two fragments side by side.
I recognize which layout is displayed with getSupportFragmentManager().findFragmentById(R.id.my_fragment), where my_fragments is 2nd fragment which is shown next to primary listfragment. But after some rotations and clicks getSupportFragmentManager().findFragmentById() returns fragment even if it shouldn't (another layout is displayed, only listfragment).
#Override
public void onRSSMessageSelected(int position) {
AppEngine.getInstance().setRSSMessagePosition(position);
// The user selected the RSSMessge from the RSSMessagesList
// Capture the detail fragment from the activity layout
RSSMessageDetail fragment = (RSSMessageDetail)
getSupportFragmentManager().findFragmentById(R.id.rssmessage_detail);
// BUG: supportManager doesn't return null even if it should
if (fragment!=null) {
fragment.updateRSSMessageDetail();
} else {
fragment = new RSSMessageDetail();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
//add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
layout-land:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android:name="cz.cvut.sabattom.fragment.RSSMessagesList"
android:id="#+id/feed_messages_list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment android:name="cz.cvut.sabattom.fragment.RSSMessageDetail"
android:id="#+id/rssmessage_detail"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
I solved it with method isInLayout()
if (fragment!=null&&fragment.isInLayout()) {
fragment.updateRSSMessageDetail();
}
Basically this question has been asked many of times here and here.Solution given is not working for me. In some corrent answers were not posted by user.
I want to have nested fragments. My scenario is as below :
I have one MainActivity, ProductEnterFrag, and ProductListFrag,ProductDetailFrag.
I have add the ProductEnterFrag to MainActivity dynamically by the FragmentManager. Like this :
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container, new ProductEnterFrag());
ft.commit();
ProductEnter layout is as below :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
I have added the ProductListFrag to ProductEnterFrag like this :
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ProductListFrag(new ProductListFrag());
}
public void ProductListFrag(SherlockFragment frag) {
getChildFragmentManager().beginTransaction().add(R.id.fragContainer, frag).commit();
getChildFragmentManager().executePendingTransactions();`
}
ProductListFrag whose layout is, as below :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="product1" />
</LinearLayout>
Now on click of button, I want to add a another fragment say ProductDetailFrag,which should be another child fragment.
When I am trying to add ProductDetailFrag from ProductListFrag like this :
new ProductEnterFrag().ProductListFrag(new ProductDetailsFrag());
It is throwing me : java.lang.IllegalStateException: Activity has been destroyed
I am new in nested fragments. Please help me where I am doing wrong. I have stuck with this problem from last 2 days.
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'
I have such layout:
frame_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/items"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
Next, in FragmentActivity I do:
setContentView(R.layout.fragment_layout);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
String tag = MyListFragment.class.getName();
MyListFragment fragment = (MyListFragment)
getSupportFragmentManager().findFragmentByTag(tag);
if (fragment == null) {
fragment = new MyListFragment();
ft.add(R.id.items, fragment, tag);
}
else {
ft.replace(R.id.items, fragment, tag);
}
ft.addToBackStack(null);
ft.commit();
When I call this code once, fragment shown perfectly! But, when it called twice I see no content!
After some investigation, I found that problem's caused by this:
setContentView(R.layout.fragment_layout);
E.g., when it is called once, fragment content is perfectly shown! But I need to call setContentView a lot of times to show another fragments.
Where's the mistake?
P.S. It's possible to make MyListFragment hardcoded into XML, but this does not fit to me, because I need to replace layout contents with other fragments.
As nobody answers, I found another solution: keep layout for every frame and show/hide them.
That's how I did it.... Main layout:
<?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">
<FrameLayout
android:id="#+id/container1"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
<FrameLayout
android:id="#+id/container2"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
That's how I show fragment2 (belongs to container2) in fragment activity:
findViewById(R.id.container1).setVisibility(View.GONE);
findViewById(R.id.container2).setVisibility(View.VISIBLE);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
String tag = MyFragment.class.getName();
Fragment fragment = (Fragment)getSupportFragmentManager().findFragmentByTag(tag);
if (fragment == null) {
fragment = new MyFragment();
ft.add(R.id.container2, fragment, tag);
}
ft.addToBackStack(null);
ft.commit();