I'm looking for some help in Android studio with replacing a parent fragment's view with the view of a child fragment when a view in the parent fragment is clicked. Thank you in advance for your help.
Right now I have a parent fragment which is a chat list, and a child fragment (the chat screen) that shows up when you click on an element of the chat screen (i.e. a button). The chat list looks like this:
<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.example.myapplication.ChatListFragment">
<!-- Empty Container for Fragment to Live in -->
<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" />
<ListView
android:id="#+id/chatListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/moonstone">
</ListView>
</FrameLayout>
I have set the onClickListener for the chatListView as follows:
_chatListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String chatName = _chatListAdapter.getItem(i).getChatTitle();
openChatScreen(chatName);
}
});
And the openChatScreenWindow() looks like this:
private void openChatScreen(String chatName)
{
_fragmentManager = getChildFragmentManager();
Log.i(CHAT_LIST_TAG, "starting chat screen fragment");
FragmentTransaction fragmentTransaction = _fragmentManager.beginTransaction();
ChatScreenFragment chatScreenFragment = ChatScreenFragment.newInstance(chatName);
fragmentTransaction.add(R.id.fragment_container, chatScreenFragment);
fragmentTransaction.addToBackStack(GlobalConstants.OPEN_CHAT_WINDOW_FRAGMENT_STRING + chatName);
fragmentTransaction.commit();
}
However, when I run this code, the child fragment is obscured, because both the frame layout (the view that the fragment is displayed in) and the chatListView have their widths and heights set to match_parent (I figured this out by testing the height and width of the chat list as 200dp, and I was able to see the child fragment behind it).
Is there a simple way to get the fragment to replace the chatListView whenever it is loaded?
For example, is there a way to change this view:
To this one:
... when an element in the chat list (the first one) is clicked?
I was thinking of changing the list view's visibility to invisible and visible based on whether the fragment is loaded, but that seems like a headache.
Please let me know what you think, thank you!
First off most modern way of managing fragments is - Navigation component
According your approach - you are adding child fragment on top of the prev fragment with fragmentTransaction.add, you can use fragmentTransaction.replace instead
Also, you might want to set child fragment background to solid color - to hide previous fragment, if you use this method - make child's fragment root clickable - to prevent fragments click through.
My recommendation - spend more time on learning Navigation component
Related
I have a main activity that launches a fragment through a fragment transaction. I want the fragment to completely fill the screen, showing no views at all from the parent. However, when I commit the fragment transaction I can still see the bottom nav view of the parent activity as well as it's buttons. I made a little demo app to show what I mean:
The main activity has a yellow background. The "Testclick" button starts a fragment transaction using the code below.
This is the result of the transaction. The red background of the fragment is now visible, but the bottomNavigationView and Buttons remain visible (Which is not desired).
Fragment Transaction
bttn.setOnClickListener {
supportFragmentManager
.beginTransaction()
.replace(R.id.contentview, Frag1())
.addToBackStack(null)
.commit()
}
Main Activity layout
<androidx.constraintlayout.widget.ConstraintLayout 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/contentview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/yellow"
tools:context=".MainActivity">
...
</androidx.constraintlayout.widget.ConstraintLayout>
Your R.id.contentview must be in the background behind the buttons
Ah actually you know what there is a good tool, called LayoutInspector in Tools -> Layout inspector, you can actually see how the layout is set up while your activity is running. In your case the layout of fragment is added inside the layout of activity.
Sorry didnt see the id at first
I have great problems getting the Navigation Tabs work. I am aware of this guide http://developer.android.com/guide/topics/ui/actionbar.html#Tabs
but I have problems understanding the article. It says the following:
To get started, your layout must include a ViewGroup in which you place each Fragment associated with a tab. Be sure the ViewGroup has a resource ID so you can reference it from your code and swap the tabs within it. Alternatively, if the tab content will fill the activity layout, then your activity doesn't need a layout at all (you don't even need to call setContentView()). Instead, you can place each fragment in the default root view, which you can refer to with the android.R.id.content ID.
As I don't use a Fragment for my Main Layout, but for others, I think the "alternative" way is right for me (I would like Tab 1 to be the Main Layout I have right now and then 2 and 3 to be my fragments), but I don't know how to accomplish this. Can someone maybe help out on this?
I was able to set up the tabs and the TabListener, so that is not the problem. The problem is that the first tab is NOT supposed to be a fragment, but my main activity layout! This is where I need help!
I did try to use my main activity-layout for a fragment, but for some reason if I click that tab, the tab changes but the screen stays white. I cannot see my fragment view.
The old code was:
mListView = (ListView) findViewById(R.id.list_view);
mListView.setAdapter(mAdapter);
mListView.setTextFilterEnabled(true);
and I've changed it in the fragment to:
View view = inflater.inflate(R.layout.list, container, false);
mListView = (ListView) view.findViewById(R.id.list_view);
mListView.setAdapter(mAdapter);
mListView.setTextFilterEnabled(true);
// do stuff here //
return view;
and this is list.xml:
<FrameLayout xmlns:android:="http://schemas.android.com/apk/res/android"
android:id="#id/main_fragment"
android:layout_width="match_parent"
android:layout:height=match_parent">
<ListView android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout:height=0dp"
android:layout_weight="1"
android:layout:marginTop="20dp"
android:descendantFocusability="blocksDescendants"/>
</FrameLayout>
how come I cannot see anything?
Solved: This was because I set the height to 0dp.
Please update your code by this:
<FrameLayout xmlns:android:="http://schemas.android.com/apk/res/android"
android:id="#+id/main_fragment"
android:layout_width="match_parent"
android:layout:height=match_parent">
<ListView android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
android:descendantFocusability="blocksDescendants"/>
</FrameLayout>
I have a requirement where i have an activity which shows list of items like facebook feeds and when clicking on a button from one of the list item a dialog has to popup which will show comments for that item.
I was going through the documentation and found out that we have to create a DialogFragment on the fly to achieve this. Please advice if this is the right approach.
You don't actually have to use a Dialog. I think dialogs are more appropriate when you want to show simple views or just an alert/confirmation to the user (normally done with an AlertDialog).
For your situation I guess the best approach would be to have a FrameLayout on your Activity, sibling of your main layout element, and add a Fragment to it when you want to show a popup like that over your main Activity's layout. As long as you put the fragment's view after your activity's root layout element, the fragment will be displayed on top of your main layout, as an overlay. e.g.:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- Activity's main layout here -->
</LinearLayout>
<FrameLayout android:id="#+id/overlay_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</merge>
and then on your Activity when you want to display the fragment you do:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.overlay_fragment_container, yourFragment)
.commit();
Hope it helps :) Luck!
I have an activity A with a fragment A inside.
Activity A uses layout X, and fragment A uses layout A.
code of layout X:
<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=".MainActivity" >
<fragment
android:id="#+id/fragment1"
android:name="android.app.DialogFragment"
android:layout_width="wrap_content"
android:layout_height="500dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="113dp"
class="com.example.fragtester.FragA" />
</RelativeLayout>
Layout A is just textview + linearlayout.
I set up another fragment B that uses layout B.
Now that I use the following code in activity A to change the fragments:
Fragment f = new FragB();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment1, f);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
I end up having layout B displaying under layout A.
So I use a FrameLayout to wrap the fragment in layout X and use
ft.replace(R.id.FrameLayout1, f);
Now the view is working nicely. Though, another problem arises.
Although layout B covers layout A, but the buttons are still active.
That means when I am viewing layout B, I can still click buttons on layout A, even if I am not seeing it.
And even when I add fragment C/D/E..... (layouts C/D/E....), the buttons on layout A is still active.
Can anybody explain why is that? Am I using fragments wrongly? Thanks!
A way to get through is to make layout A blank, and use other layout to cover it. But it doesn't seems to be the "right" way??
Remove the fragment and add a FrameLayout
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff" >
</FrameLayout>
then add fragments programmatically.
In android fragment button click pass through the fragments (i dont know if the fragments are suppose to work like that). what I used to do in such a situation is to make the layout of the fragment clickable. so the clicks wont pass through.
Instead of having fragment in your xml, try to create empty container for a fragments. For example empty frame layout. And then programmatically put your fragments in there.
Add the following attribute to the XML root layout of the fragment that goes on top.
android:clickable="true"
This will ensure that touch events will not propagate further than the top layer.
I want to implement a layout that has the following design:
Landscape:
List of items on the left, details on the right
Portrait:
List of items, only details after click
To get this working I followed those tutorials:
Tutorial 1
Tutorial 2
It worked as expected.
But instead of starting a new activity when in portrait and clicking a Listitem,
I want the fragment to be replaced by the detail, so that I can animate the transition.
So i played around and got problems with the views. After that I read the following article, and modified my layout to use placeholders an add the fragments programmatically:
Article
The action that is triggered when the listitem is clicked just replaces the list fragment in his container with the detail fragment.
But now if I revert to landscape, the list part of the layout is showing the detail instead of the list, because i replaced the content.
Is there any way to solve this problem?
At the moment I managed to get this working by using the two fragment placeholders in both layouts, landscape and portrait, with wrap content, and hiding and showing the fragments, but I don't know if this is the right approach? Perhaps a ViewFlipper would be better?
Also the animation here does not work properly, cause I hide and show in the same transaction.
Also if I am in Landscape mode and click a listitem and data is showing, and I return to portrait, I want the data view to be shown, not the list, but ONLY if data is already shown.
Atm I managed this with an flag passed to the intent data and again show/hide the correct view.
Any alternative ideas?
Thank you very much, have been trying for hours now!
EDIT
The main problem I have is, that the slide in/out animation I set is not played correctly, as i hide and show the fragments in one transaction. It just hides the one fragment and slides in the other, so the first fragment is not slided out :/
To see what I mean, here is how I implemented it in a fragment test app:
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<FrameLayout
android:id="#+id/details_Fragment_Placeholder"
android:layout_width="wrap_content"
android:layout_height="fill_parent" >
</FrameLayout>
<FrameLayout
android:id="#+id/main_Fragment_Placeholder"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</FrameLayout>
</LinearLayout>
The ListFragment onListItemClick:
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
FragmentManager fragmentManager = getFragmentManager();
Screen2Fragment fragment2 = (Screen2Fragment) fragmentManager
.findFragmentByTag(Screen2Fragment.TAG);
if (fragment != null) {
if ((getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)) {
.beginTransaction();
transaction.setCustomAnimations(R.anim.slide_in_right,
R.anim.slide_out_left, android.R.anim.slide_in_left,
android.R.anim.slide_out_right);
Screen1ListFragment fragment1 = (Screen1ListFragment) fragmentManager
.findFragmentByTag(Screen1ListFragment.TAG);
transaction.hide(fragment1);
transaction.show(fragment2);
transaction.addToBackStack("ReturnToScreen1");
transaction.commit();
}
}
}
When you place the list fragment initially you need to put it into the back stack, then override the back button in the detail fragment to pop the list view off the back stack when pressed.