I am interested in creating some kind of View or Fragment that takes up a small amount (~33%) of the current View. This overlayed View will use the camera as input. I think this is analogous to the YouTube app's small video playing in the corner.
I have a crude sketch of what I want (below). I don't need a full writeup, just a starting point.
Not sure it is the good way for it, but you can try with a FrameLayout to host a Fragment and make the FrameLayout with a background transparent (if you don't know what is FrameLayout, in few words it serves to overlap views. I writed an answer on this). The layout of your Parent Activity (FragmentActivity) may be something like this:
<FrameLayout
android:id="#+id/FragmentContainer"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:background="#android:color/transparent" >
<TextView
android:layout_width="match_parent" android:layout_height="match_parent"
android:text="I'm a text of the content" />
</FrameLayout>
And the Fragment may be as below:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="match_parent" android:layout_height="250dip"
android:background="#color/blue"
android:layout_alignParentTop="true" >
<TextView
android:id="#+id/ReaderEdit"
android:layout_width="match_parent" android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="I'm a text in a fragment" >
</LinearLayout>
</RelativeLayout>
And then when you initialise your Fragment in the FrameLayout, you set hide() and show() methods for display it. For this, use FragmentSupportManager in your FragmentActivity and add() or replace() methods like the example below:
// Initialize your fragment:
FragmentTransaction mTransaction = this.getSupportFragmentManager().beginTransaction();
Fragment mFrag = new MyFragment(); // call your Fragment Class
mTransaction.add(R.id.FragmentContainer, mFrag, null).hide(mFrag).commit(); // add to the Container (FrameLayout) and hide it
// don't forget to commit at the end of every FragmentTransaction
// To display your fragment:
FragmentTransaction mTranDisplay = this.getSupportFragmentManager().beginTransaction();
mTranDisplay.show(mFrag).addToBackStack(null).commit(); // pass the Fragment to show + add the BackStack method (when the user press back button, the Fragment disappears without quit the Activity)
mTranDisplay.setCustomAnimations(R.anim.slide_in, 0, 0, R.anim.slide_out); // you can make an animation to the BackStack method, here it's a slide in/out from top to bottom
I think there is a proper way to do this. Maybe you can check this library and see, break, rebuild,... the code.
Hope this helps.
Related
My app has a log_in activity, a main activity, and a settings activity.
The main activity is currently working by flowing between multiple fragments:
In the first fragment, the user selects a topic (from a dynamically-populated recyclerview of cardviews), the topic is then parceled and sent to the second fragment.
The second fragment displays the appropriate list (another dynamically-populated recyclerview of cardviews (formatted very differently, with different cardviews). The user can go back to the first fragment and choose another topic, and that choice is again parceled and sent to the second fragment to display the relevant list etc.
I want to set up the 2nd "page" so that it has 1 fragment at the top, which covers the top 80% of the screen, and 1 fragment at the bottom, which covers the bottom 20% of the screen, while still having only 1 fragment on the first "page" that covers 100% of the screen.
This is how I'm switching between each fragment in the flow right now:
main.java
bundle = new Bundle();
bundle.putParcelable("itemlist", itemlist);
fragment = new fragment_2();
fragment.setArguments(bundle);
fragmentManager = getSupportFragmentManager();
transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.main_container, fragment).commit();
And my activity_main.xml (for the main activity) has this layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/ColorBG"
tools:context="com.app.activity.main">
<FrameLayout
android:id="#+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
</LinearLayout>
So main_container is the FrameLayout that I'm replacing with the relevant fragment.
I can't find any clean example of a way to do this, can anyone show me?
The only thing I can think of is to have 2 FrameLayouts in the activity_main.xml, and have the 2nd container start as layout_width="0" and layout_height="0", but I feel this is a bad way to do it. Is there any way to replace the LinearLayout itself with another LinearLayout that has 2 FrameLayouts in it, and then assign the appropriate fragments to those containers?
Or what is the best way to do it?
I want to do things "the right way" (so I do not want to have separate activities) and I'm targeting API 16, but I may be willing to go up to API 23/24.
You can use weightSum property of LinearLayout to divide in 80:20 ratio.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="3"
android:orientation="vertical">
<FrameLayout
android:id="#+id/frame1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"/>
<FrameLayout
android:id="#+id/frame2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
For using the same layout where you want to give 100% you can set the visibility of frame2 to GONE and can dynamically set the layout of frame1 to 3 (total of weightSum which will make it 100%).
My activity declares all of its GUI fragments in a single XML layout. It only needs to display a few of the fragments at launch time; the rest get shown as the user interacts with the app. A portion of the layout is as follows:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/map_panel"
android:name="com.example.MapPanel"
android:layout_width="match_parent"
android:layout_height="#dimen/map_panel_height" />
<fragment
android:id="#+id/list_panel"
android:name="com.example.ListPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/map_panel" />
<fragment
android:id="#+id/detail_panel"
android:name="com.example.DetailPanel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/map_panel"
android:visibility="gone" />
My intention is that the list_panel fragment is visible at startup, and the detail_panel fragment is hidden until the user selects something from the list.
By default, a fragment starts out with the isHidden attribute as false. That means my activity has to iterate through the loaded fragments and manually call isHidden(true) on fragments like detail_panel at startup time.
I would prefer to declare the isHidden status in the XML layout. However, setting android:visibility="gone" in a <fragment> declaration does not change the isHidden status, and I can't find any documentation on another attribute that would do the trick.
Is it possible to set an XML attribute on a <fragment> to cause it to be hidden?
Note: I'm not concerned with view visibility, I'm concerned with the fragment.isHidden() value. That affects how FragmentManager manipulates the back stack and performs animations. If you call transaction.show(fragment) on a fragment whose view is invisible or gone, but the fragment.isHidden() value is false, then the FragmentManager will not make the view visible. See http://developer.android.com/reference/android/app/Fragment.html#isHidden() for reference.
I faced a similar situation, where I had to hide a fragment.
I simply included the fragment inside a LinearLayout and marked the layout to be visible/gone.
<LinearLayout
android:id="#+id/map_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" >
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment" />
</LinearLayout>
Based off Jyo's post, use this:
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.hide(mFragment);
fragmentTransaction.commit();
This has worked for me on API Level 23. mFragment is the fragment that you want to hide.
This answer is a tad late thought it may be helpful for future reference. Visibility is part of the View class - Fragment extends object though not having access to the visibility values. A possibility is making the Fragment a child of a FrameLayout and calling invisible or gone on the layout. This will cause the fragment to appear to be hidden.
Hope it helps!
public void showHideFrgament(final Fragment fragment){
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.animator.fade_in,
android.R.animator.fade_out);
if (fragment.isHidden()) {
ft.show(fragment);
Log.d("hidden","Show");
} else {
ft.hide(fragment);
Log.d("Shown","Hide");
}
ft.commit();
}
we have isVisible Method for fragment
seeting visibilty to Gone does not take any space
Where as Invisble takes the actual view space.
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.
In a scenario where I've got multiple fragments on display (e.g. list fragment and detail fragment), and one of the fragments is showing an alert dialog (a DialogFrament), I'd like the dialog to be centered within the fragment that is showing it, not centered within the whole screen. Is there a way to do that without a whole lot of pixel calculations involving the dimensions of the screen, the dimensions and position of the fragment, etc.?
You can do this by using a FrameLayout, as Joe Simpson mentions. Say you want to put your dialog fragment over the top of the Details fragment that you mention. Put a FrameLayout around the details fragment in your activity layout, then embed the dialog fragment within the FrameLayout too (with layout_gravity="center"). Set the visibility="gone" until you need it. E.g.:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/my_details_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.my.fragment.DetailsFragment" />
<fragment
android:id="#+id/my_dialog_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.my.fragment.DialogFragment"
android:layout_gravity="center" />
</FrameLayout>
You can also start it programmatically. Put a holder view (e.g. a LinearLayout) in the xml:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/my_details_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.my.fragment.DetailsFragment" />
<LinearLayout
android:id="#+id/myfragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</FrameLayout>
... and then replace it in code like so:
final MyDialogFragment dialog = MyDialogFragment.getInstance();
// get an instance of FragmentTransaction from your Activity
FragmentTransaction fragmentTransaction = getSupportFragmentManager()
.beginTransaction();
fragmentTransaction.add(R.id.myfragment, dialog);
fragmentTransaction.commit();
Note that the docs on DialogFragment say it's fine to embed it like this: "A DialogFragment can still optionally be used as a normal fragment, if desired. This is useful if you have a fragment that in some cases should be shown as a dialog and others embedded in a larger UI."
I am trying to build an app for 3.0 using fragments. On the left side of the application there is a static fragment, and on the right side there is a dynamic one. Each of my fragments in the dynamic portion have a title. Whenever I go to replace the initial fragment, The title of the first is still shown above the title of the first. Successive replacements replace the lower portion but the initial title is still shown (sorry I cannot post images yet).
Best I can do for image:
Initial Header
New Header
Content(displays fine)
main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment
android:id="#+id/static_fragment"
android:name="ruleout.android.History_Fragment"
android:layout_width="500dp"
android:layout_height="match_parent" />
<fragment
android:id="#+id/dynamic_fragment"
android:name="ruleout.android.New_Screen_Fragment"
android:layout_width="fill_parent"
android:layout_height="match_parent" />
</LinearLayout>
Partial MainActivity used to change fragments
private void open(Fragment toShow)
{
FragmentTransaction fragmentTransaction = FragMag.beginTransaction();
fragmentTransaction.replace(R.id.dynamic_fragment, toShow);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
Please let me know if you need any additional information and thanks in advance for your help.
If you want to dynamically change fragments, you can't declare them in your layout. The Fragment documentation has an example of doing just what I think you are describing, where a layout has a static fragment declared in it along with a FrameLayout for holding a Fragment that will be dynamically added and replaced.