I'm creating an Android app.
When I click on a menu item, I need to open an activity/view/fragment (I don't know what is the best). This activity/fragment/view need to be placed as an "overlay" of my app (it will have a transparent background and we could see the "regular" activity behind).
I'm using a navigation drawer and a couple of fragment inside my app.
First I tried this :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".AlertActivity"
android:id="#+id/alertLayoutRoot"
android:background="#android:color/transparent"
>
<TextView
android:layout_width="match_parent"
android:id="#+id/editText1"
android:text="#string/mes_favoris"
android:layout_height="match_parent"
>
</TextView>
</FrameLayout>
This is indeed showing my fragment, but this fragment isn't on top of all the others.
What could be the best way to do this (in working with Kotlin)?
EDIT : forgot to say, in this view, there will be a small slider.
Basicaly I want this : Overlay
You can use dialog fragment as it supports custom layouts like fragments and shows on top of another activity or fragment.
Here is a useful tutorial on dialog fragment.
Related
I'm having a problem when dealing with multiple NavHosts. This issue is very similar to the one asked here. I think the solution for this question would help me as well, but it's a post from 2017 and it still has no answer. Android Developers Documentation doesn't help and searching through the web shows absolutely nothing that could possibly help.
So basically I have one Activity and two Fragments. Let's call them
FruitsActivity, FruitListFragment, FruitDetailFragment, where FruitsActivity has no relevant code and its xml layout is composed by a <fragment> tag, serving as NavHost, like that:
<fragment
android:id="#+id/fragmentContainer"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="#navigation/fruits_nav_graph"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
The FruitListFragment is the startDestination of my NavGraph, it handles a list of fruits that will come from the server.
The FruitDetailFragment shows details about the Fruit selected in the list displayed by FruitListFragment.
So far we have Activity -> ListFragment -> DetailFragment.
Now I need to add one more Fragment, called GalleryFragment. It's a simple fragment that displays many pictures of the Fruit selected and it's called by FruitDetailFragment when clicking a button.
The problem here is: In Portrait mode I simply use findNavController().navigate(...) and I navigate through the Fragments like I want. but when I'm using a Tablet in Landscape mode, I'm using that Master Detail Flow to display List and Details on the same screen. There is an example of how it works here, and I want the GalleryFragment to replace the FruitDetailFragment, sharing the screen with the list of fruits, but so far I could only manage to make it replace the "main navigation" flow, occupying the entire screen and sending the FruitListFragment to the Back Stack.
I already tried to play around with findNavController() method, but no matter from where I call it I can only get the same NavController all the time, and it always navigates in the same linear way.
I tried to implement my own NavHost, but I get and error "class file for androidx.navigation.NavHost not found".
This is the xml of my FruitsActivity:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/fragmentContainer"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="#navigation/listing_nav_graph"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</layout>
This is the xml of the FruitListActivity in Landscape mode (in portrait mode there is just the RecyclerView):
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvFruits"
android:layout_weight="3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"/>
<FrameLayout
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/sideFragmentContainer"
android:name="fruits.example.FruitDetailFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</LinearLayout>
</RelativeLayout>
</layout>
And now I want to call the GalleryFragment and make it replace just the <fragment> of id 'sideFragmentContainer' instead of the whole screen (instead of replacing the <fragment> of id fragmentContainer in the Activity's xml).
I didn't find any explanations of how to handle multiple NavHosts or <fragment> inside <fragment>.
So based on that, is it possible to use Navigation Architecture and display a Fragment inside another Fragment? Do I need multiple NavHosts for that, or is there another way?
As suggested by jsmyth886, this blog post pointed me to the right direction.
The trick was to findFragmentById() to get the NavHost directly from the fragment container (in this case, the one sharing the screen with the rest of the Master Detail screen). This allowed me to access the correct NavController and navigate as expected.
It's important to create a second NavGraph too.
So a quick step-by-step:
Create the main NavGraph to make all the usual navigation (how it would work without the Master Detail Flow);
Create a secondary NavGraph containing only the possible Destinations that the Master Detail fragment will access. No Actions connecting then, just the Destinations.
In the main <fragment> container, set the attributes like that:
<fragment
android:id="#+id/fragmentContainer"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="#navigation/main_nav_graph"
app:defaultNavHost="true"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
The app:defaultNavHost="true" is important. Then the Master Detail layout will look like that:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvFruits"
android:layout_weight="3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"/>
<FrameLayout
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/sideFragmentContainer"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="#navigation/secondary_nav_graph"
app:defaultNavHost="false"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</LinearLayout>
</RelativeLayout>
</layout>
Again, the attribute app:defaultNavGraph is important, set it to false here.
In the code part, you should have a boolean flag to verify if your app is running on a Tablet or not (the link provided in the beginning of the answer explains how to do it). In my case, I have it as a MutableLiveData inside my ViewModel, like that I can observe it and change layouts accordingly.
If is not tablet (i.e. follows the normal navigation flow), simply call findNavController().navigate(R.id.your_action_id_from_detail_to_some_other_fragment). The main navigation will happen using the main NavController;
If is tablet using the Master Detail Flow, you must find the correct NavHost and NavController by finding the <fragment> that contains it, like that:
val navHostFragment = childFragmentManager.findFragmentById(R.id. sideFragmentContainer) as NavHostFragment
And finally you can navigate to the Fragment that you want to appear dividing the screen with the rest of the Master Detail screen by calling navHostFragment.navController.navigate(R.id.id_of_the_destination). Notice that here we don't call Actions, we call the Destination directly.
That's it, simpler than what I thought. Thank you Lara MartÃn for the blog post and jsmyth886 for pointing me to the right direction!
I am creating an app which does some tracking on a map. The tracking part works great inside my activity.
However, I want to have some kind of small overlay in the bottom right corner (like the minimalised video playback in the YouTube app) that stays there, even when I switch activities.
I have looked at this, but it's not really what I need. I don't need it to be moveable, and I think this is impossible to keep when switching activities.
Is there some kind of class that I can implement (Widget, Fragment, ...) that would fit my needs?
Thank you,
DebboR
This is a bit late and probably not relevant to you anymore, but maybe somebody else will find this helpful.
I don't think it's possible to switch activities and keep a certain view on screen. How I think this should be done is have a main activity with fragments that swap and in the activity's layout have a view overlay on top of the fragments container.
For example:
<?xml version="1.0" encoding="utf-8"?>
<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">
<!-- Container for the fragments -->
<FrameLayout
android:id="#+id/fragment_container"
android:layout_below="#id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<!-- This view will overlay the fragment in the bottom right corner -->
<View
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
I want to display two different activities in a single screen how can i do that in android?Please if anybody has idea share it.And I don't wanna use fragments.
I want to display a screen which contains some fields and below(at the bottom of the screen) I want another screen with some buttons.
Is this possible in android?
If so, How can i do this ?
You can't have two activities in one screen. You can have only one. So, ultimate solution is Fragments.
An activity is not directly a visual component, so I'm thinking that what you're really asking is how to have a single activity display different views.
There's nothing that says you can't rerun setContentView() with a different layout/view ID. But there's another non-fragments way of doing what your probably want.
You can define more than one full-size (match_parent) view in a layout. What you want to do is set the visibility for one of them to "visible" with android:visibility="visible" and all the others to "gone" with android:visibility="gone".
Then when you want to switch the displayed view, you'll run setVisibility(View.GONE) on the outgoing view and setVisibility(View.VISIBLE) on the incoming. It's important to use GONE and not INVISIBLE or the layouts won't render correctly.
Sample layout file:
<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=".MainActivity" >
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" />
<SurfaceView
android:id="#+id/video"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<WebView
android:id="#+id/web"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</FrameLayout>
Sample Code to switch view:
video.setVisibility(View.VISIBLE);
img.setVisibility(View.GONE);
web.setVisibility(View.GONE);
That said, you probably want to learn how to use fragments since you can handle switching the view along with other state in a single unit of work (a transaction). But the above approach above does work for simple view changes.
I have a main layout being hosted by an activity (setContentView method).
I have a button in the layout. I want to be able to click this button and a new layout will slide down from the left/top until the middle of the screen. So, the screen now will have two layouts where one is on top and another one is just beneath it.
This is something like the UI in Android Jelly Bean where you can pull the settings layout down using a touch gesture.
What are the possible implementations?
A method I have tried:
add the slide down layout into main.xml but set its visibility to gone
when button is clicked, run some code that will set the layout visibility to
VISIBLE and add some animations.
the result of this implementation is that this layout will push the rest of the
views down in order to have a "squeeze" space for itself which is not
what I intended to do (see above)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="5dp"
android:paddingTop="5dp" >
<LinearLayout
android:id="#+id/PR_slidedown" <---this is the intended slidedown layout
android:layout_width="8dp"
android:layout_height="40dp"
android:visibility="gone"
android:orientation="vertical" >
</LinearLayout>
....
Your implementation is partially correct, the other part is to host your two layouts in a FrameLayout so they can overlap with each other. Search for FrameLayout in here, there are a lot of example on how to use it.
Or try the SlidingDrawer
We are developing an app that in one point, we need a screen like Honeycomb Gmail application :
http://www.cnx-software.com/wp-content/uploads/2011/02/android_3.0_honeycomb_gmail_app_fragments_700px.png
We are trying to use fragments and includes a listview to show our items.
We did exactly the same thing on this link : http://www.vogella.com/articles/Android/article.html#fragments_tutorial
But in any way we did not able to view different layouts,
what i mean is that, the only thing that we can show on the right fragment a single textview.
but we need a listview there, that we can view a thumbnail,some explanations and this needs to be clickable.
anyone to help?
Should work. I think you want to instantiate a ListFragment that, upon the user selecting a row, instantiates another ListFragment.
Maybe read this article aswell.
Below is an example for a layout xml file that has two fragments next to each other with an even width.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<fragment
class="package.of.fragmentA"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:id="#+id/fragmentA"
/>
<fragment
class="package.of.fragmentB"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:id="#+id/fragmentB"
/>
</LinearLayout>
In the case of the GMail application the class fragmentA would be a ListFragment and fragmentB would be a normal fragment class with a custom layout file.