I have a fragment with constraints that I want to preserve
<fragment
android:id="#+id/fr_test"
android:name="com.test.FragmentTest"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
I use transactions to hide/show it and all . works fine
fm.beginTransaction().hide(mainActivity.fr_test).commit()
fm.beginTransaction().show(mainActivity.fr_test).commit()
I use transactions to recreate fragment keeping the same container to use the same constraints
fm.beginTransaction().replace(R.id.mainActivity.fr_test, FragmentTest).commit()
But if now I try to hide/show the fragment with the same references as before it does nothing. I suppose that references are lost but I don't know how to find them. I tried to save the reference like this:
fragRef = FragmentTest()
viewsManager.fm.beginTransaction().replace(R.id.fr_test, fragRef).commit()
and then use:
fm.beginTransaction().hide(mainActivity.fragRef).commit()
fm.beginTransaction().show(mainActivity.fragRef).commit()
but still does the same.
What I'm doing wrong?
When you call replace, he calling remove(fragment) and after call add(int, fragment, string). I think that you should use add method instead replace and control your UI using hide and show
Related
I have a view pager that has a page for each subject in an array (English, Maths, Science, etc). The fragments in the view pager are all created from the same XML file. These fragments then have fragments added inside of them.
As all the parents inflate from the same XML file, I can not specify which fragment I want to add the child fragment to. I was wondering if their was a way to do this - Narrow the scope of the id maybe??
I think you want to implement multiple fragments with the capability to manipulate them depending on user selections. There is Google link Fragments
Review these code on that web page:
The many samples of Fragment and FragmentTransaction
Look at method showDetails in class TitlesFragment, for example.
If you want a working sample, look at Working with Android Fragments. Snippet from the webpage:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent">
<fragment
android:id="#+id/headFrag"
android:name="com.intertech.HeaderFrag"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<fragment
android:id="#+id/bodyFrag"
android:name="com.intertech.BodyFrag"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
</LinearLayout>
And the code
...
FragmentManager fragmentManager = getFragmentManager ();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction ();
// work here to change Activity fragments (add, remove, etc.).
fragmentTransaction.add (R.id.myFrame, myFrag);
fragmentTransaction.commit ();
From above, notice there are 2 fragments in the layout. And fragmentTransaction.add method should specify parent container in R.id form.
Someday I may want/need to implement this. So far I implemented show/hide Layouts instead (not regretting it), and they can have IDs for me to manipulate.
Have fun and keep us posted, Tommy Kwee.
First. I suggest you to try to avoid child fragment, if you really doesn't have very good reason to use them.
But I don't understand where is problem. I don't see any problem if more fragment use the same XML for the inflate. You can call setArguments() on all parent fragment and put here some Bundle which can be used to recognize which fragment it is inside of it by getArguments().
I get an Error
07-04 01:49:56.325: E/AndroidRuntime(9693): java.lang.NullPointerException
while try to inflate ViewStub in Fragment after transaction done
sendMessageView = ((ViewStub) rootView
.findViewById(R.id.send_message_viewstub)).inflate();
Here are XML
<ViewStub
android:id="#+id/send_message_viewstub"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:inflatedId="#+id/panel_import"
android:layout="#layout/fragment_send_message" />
Agree with Shawnic, that error line you are showing us doesn't tell much. I can tell you that using fragments is a little trickier than activities.
But with that said, I don't think you can use a fragment as the included layout?
What or where exactly is the Fragment within the context of your question?
Fragments have their own class files that take care of inflating a layout to be used as the Fragment.
Also I am concerned about this part you posted:
sendMessageView = ((ViewStub) rootView
.findViewById(R.id.send_message_viewstub)).inflate();
Now I have experience with this but it's been a while and I am not sure if this part of your code is correct?
This is how Android recommends you write it:
ViewStub stub = (ViewStub) findViewById(R.id.stub);
View inflated = stub.inflate();
In Your Code, what kind of object is
sendMessageView
You may want to change your code to this first just to make sure, we don't know exactly why Android suggests we do it this way but we probably should.
If you're always going to be inflating the same layout in this ViewStub, you would be better served using an include tag.
<include layout="#layout/fragment_send_message />
include replaces itself with the specified layout at runtime and allows your layouts to be both modular and readable.
I have FrameLayout element in my MainActivity's layout, what is used as "connection point" for multiple type of Fragments.
View:
<FrameLayout
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Fragment replace:
Fragment fragment = new CoursesFragment();
getFragmentManager().beginTransaction().replace(R.id.main_content, fragment).commit();
Now I'm at the situation I need change main_content directly from CoursesFragment (fragment replaces own view). What is best approach to do this? Is it safe? I can reach MainActivity's context and change it, but I don't know if it's correct way.
I don't know what your View is, but the simplest approach is to provide both Views inside their own ViewGroup, while setting 'the other view' on setVisibility(View.GONE). If you need to switch, just set the first shown View to View.GONE, and the second to View.VISIBLE.
This way you don't have to hack around with the Activity's context, or Fragment Managers hide and show methods.
I am skinning an app and I was wondering if there was a way to keep common elements the same between XML layouts without copying the same code around all the time.
For instance, I have a header and footer and background that will be the same between most pages. Can I make a "common" xml containing the header and footer and just load the individual page like a frame inside of it?
I'm not sure how I would reference that individual page within the XML. Maybe I could change an ID from the java side in an onCreate function, although it seems like more work now, if I changed something on the header and footer in the future I wouldn't have to change every Activity of the app.
Thanks for any insight!
I think it's the inclue tag you're looking for. Example:
<include layout="#layout/bar_header_top" />
Make a Java class that extends a View that holds all header elements and one that holds all footer elements and implement them in every view like this
<LinearLayout>
<com.[package].[classname of header] />
-- content here --
<com.[package].[clasname of footer] />
</LinearLayout>
I have a navigation bar in my app, the thing is that I want the navbar to be available in all activities. I suppose that I have to set contentView two times, but that doesn't work, of course.
I've been looking at and but I dont get it to work. I have a super class, can I set this second layout from my super class?
You should include the nav bar via <include> tag from the other layouts. Setting the content layout twice will not work, as Android is in the callbacks basically always using what the user has told last. So
setContentLayout(R.layout.nav);
setContentLayout(R.layout.main);
will result in only the main layout being used.
Have a look at this article which gives an example of using the include tag.
You can extend standard activities (Activity, ListActivity, etc.. if you use any others) and use them as a base for including a nav_bar.
For example:
Define a layout with nabar like this
<LinearLayout
...
android:orientation="vertical"
>
<YourNavBarComponent
...
/>
<FrameLayout
android:id="#+id/nav_content"
...
>
// Leave this empty for activity content
</FrameLayout>
</LinearLayout>
This will be your base layout to contain all other layouts in the nav_content frame.
Next, in create a base activity class, and do the following:
public abstract class NavActivity extends Activity {
protected LinearLayout fullLayout;
protected FrameLayout navContent;
#Override
public void setContentView(final int layoutResID) {
fullLayout= (LinearLayout) getLayoutInflater().inflate(R.layout.nav_layout, null); // Your base layout here
navContent= (FrameLayout) fullLayout.findViewById(R.id.nav_content);
getLayoutInflater().inflate(layoutResID, navContent, true); // Setting the content of layout your provided in the nav_content frame
setContentView(fullLayout);
// here you can get your navigation buttons and define how they should behave and what must they do, so you won't be needing to repeat it in every activity class
}
}
And now, when you create a new activity, where you need a nav bar, just extend NavActivity instead. And your nav bar will be placed where you need it, without repeating it in every layout over and over again, and polluting the layouts (not to mention repeating a code to control navigation in every activity class).
Try merging layouts, as described on Android Developers Blog.