How to create an overlay view within an activity - android

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!

Related

Android: How to show a fragment over parent activity and its button/nav views

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

Fitting second fragment to an activity

In my Activity I ad a fragment dynamically which occupies a dynamic porportion of the screen (you can slide it up or down to cover the entire screen or just the bottom ~250dp).
I now want to dynamically add another fragment to the same activity but I need this new fragment to fit next to the first one. Meaning you can slide the first one still up and down but the second will then either stay behind the first or move to make room.
Google tells me to use the same fragment manager and just add a fragment but the same fragment manager has already done a commit (with the adding of the first).
Is there any way to achieve this? Thank you!
CODE:
In my activity onCreate I added a fragment called buildingFragment (blue)
fragmentTransaction = getFragmentManager().beginTransaction().add(R.id.fragment_container, buildingFragment, "BUILDINGPAGE");
fragmentTransaction.hide(buildingFragment);
fragmentTransaction.commit();
The buildingFragment animates itself in onCreateView so that most of its content is out of screen (bottom direction):
// ANIMATE THE BUILDING PAGE TO PEAK FROM BOTTOM
ObjectAnimator anim = ObjectAnimator.ofFloat(buildingPageView, "y", USEABLE_HEIGHT, USEABLE_HEIGHT-TOOLBAR_HEIGHT-VIRT_NAV_BAR);
anim.setDuration(500);
anim.start();
Now this BuildingFragment works and it can be slided up or down.
With a push of a button I want to add another fargment (red) to the activity but I need it to take the rest of the space on the screen that the BuildingFragment (blue) is currently not occupying.
No when I slide the BuildingFragment (blue) I need the second fragment (red) either to stay behind the Building Fragment or just make room by moving up or down. Either way is acceptable.
Here is an illustration:
Second question:
If I DONT want to replace fragments but add a new one, how can I bring the older fragment on top of the new one?
Check this lib its may be help you that you want achieve.
<com.sothree.slidinguppanel.SlidingUpPanelLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:sothree="http://schemas.android.com/apk/res-auto"
android:id="#+id/sliding_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
sothree:umanoPanelHeight="68dp"
sothree:umanoShadowHeight="4dp"
sothree:umanoParallaxOffset="100dp"
sothree:umanoDragView="#+id/dragView"
sothree:umanoOverlay="true"
sothree:umanoScrollableView="#+id/list">
<!-- MAIN CONTENT -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--LOAD FIRST FRAGMENT-->
</FrameLayout>
<!-- SLIDING LAYOUT -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--LOAD SECOND FRAGMENT-->
</FrameLayout>
</com.sothree.slidinguppanel.SlidingUpPanelLayout>
You can do commit as many times as you wish on a FragmentManager, BTW there is only one instance of FragmentManager that getFragmentManager() returns on each call. You can add a Fragment to any view any no of times.
So even if you have added a fragment, you can add same Fragment again to a view.
It is nothing but another instance of Fragment that will work as a isolated entity.

Android Fragment for tablets and phone

I want to do something like that. An picture is easier than words:
And when the user clicks on a button on the Fragment B, the fragment B changed but not the A.
I've made two different layout (A portrait and a land one). The first one has a layout like
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.my.app.ContactsFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/contacts_fragment" />
I've a button in my fragment layout with a simple activity call:
Intent intent = new Intent(getActivity(), NextActivity.class);
startActivity(intent);
And the land one is like that:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.my.app.ContactsFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/contacts_fragment" />
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.my.app.HomeFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_container" />
</LinearLayout>
I change the inner fragment using the following code:
FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction();
NextFragment nextFrag = new NextFragment();
ft.replace(R.id.fragment_container, nextFrag);
ft.addToBackStack(null);
ft.commit();
This part works well.
I have two questions now:
How to put these two ways to change the content in the main activity? I mean, in the main activity, a fragment should call the second way, but in a normal activity, I need to call the first.
If I click on an item in the fragment A, and then I click on the button in fragment B that changes the fragment to NextFragment. If I click on another item and i do the same. I can go back to the first user. Is there a way to dump the stack when clicking on a new item ?
Thanks for your help.
Ps: I'm using the native fragment lib not the support v4.
I'm struggling to understand the specifics of your 2 questions, as they are vague and do not give enough detail.
However, since you want your Fragments to be changed out at runtime, you should not put <fragment/> in your layout files. Your current architecture makes it impossible to change out the Fragments in your layouts, which is not what you want.
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.
You should be using FrameLayout containers for your Fragments in your layout files, and have a single Activity add Fragments to those FrameLayout containers depending on if they are there. This will allow the app to create 1 Fragment in portrait and 2 Fragments in landscape (given you have have a layout for each orientation). This will also allow you to be able to swap out Fragments as your please, and add them to the back stack.
And example of this Google recommended approach can be found here.
You can find a good solution from here.

Android fragments overlap previous view and button listeners

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.

using androids back stack correctly

I have several fragments within one Activity.
I am trying to make my app compatible with both small and large screens.
I have created a main layout with a LinearLayout as the root. This LinearLayout contains two FrameLayouts. One FrameLayout is used to store Fragments which will store lists or any other side details. I only want this to be in view when specific buttons are pressed.
The other FrameLayout is used to display the main part of the app (a map) which is in its own fragment.
To begin with I add my main map fragment using:
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.viewer, viewModeFragment);
ft.commit();
When I want the side panel to appear with a list fragment I call something like this:
FrameLayout fl = (FrameLayout)findViewById(R.id.list);
fl.setVisibility(View.VISIBLE);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.list, editOsmInfoFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.show(editOsmInfoFragment);
ft.commit();
Here is my XML file for the main Activity layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/myFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/list"
android:name="com.srose.cyclopathed.view.LoadRoutesFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="gone"/>
<FrameLayout
android:id="#+id/viewer"
android:name="com.srose.cyclopathed.view.ViewModeFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
This seems to work some what ok but the main problem is that if I use the app on the tablet and the side bar appears with a list fragment contained within it, if the back button is pressed the fragment vanishes as expected but the blank list FrameLayout remains on screen because it was not part of the transaction.
I guess I am not using this properly but I have no idea how to implement it so that the whole side bar whole slide to the left in the back button is pressed.
Can anyone please help?
Thanks
Do not explicitly set the visibility on R.id.list.
In your layout XML, remove the android:visiblility attribute on R.id.list FrameLayout to make it visible. Since this FrameLayout is initially empty, it will not show up on screen. When the side panel is added to it programmatically via the FragmentTransaction, you will see it, and when it is removed (via the back button), it will go away. You must call FrameLayout# setConsiderGoneChildrenWhenMeasuring() in order for the layout to collapse when the Fragment is removed.

Categories

Resources