I have an activity whose root layout is a drawer layout, with main content being a view pager (and com.astuetz.viewpager.extensions.PagerSlidingTabStrip to assist viewpager. Now what i want to do is that when a particular item is selected in the navigation drawer, the view pager (along with the tab names strip) gets replaced by a single fragment. My activity layout file is this:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
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" >
<com.astuetz.viewpager.extensions.PagerSlidingTabStrip
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="48dip"
android:background="#drawable/background_tab"
app:underlineColor="#E67E22"
app:indicatorColor="#E67E22" />
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/tabs"
tools:context=".UserActivity" >
</android.support.v4.view.ViewPager>
<FrameLayout android:id="#+id/fragmentToSwap"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
<ListView android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#666"
android:background="#E8E8E8"
/>
</android.support.v4.widget.DrawerLayout>
Now this is what i am trying to replace the view pager with fragment. I am not sure about this myself, a bit confused which element to put in replace method.
UserProfileActivity userProfileFragment = new UserProfileActivity();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragmentToSwap, userProfileFragment);
transaction.addToBackStack(null);
transaction.commit();
What currently is happening is the new fragment elements overlap the view pager while i am still able to use the view pager in background. Please help me figure it out.
The fragment overlaps the ViewPager because they are all in a RelativeLayout together - if you want to hide the ViewPager and the tab strip, you can call setVisibility(View.GONE) on each of them to hide them from view.
// assuming you do not already have a reference to them,
// find them by their ID and hide them
findViewById(R.id.tabs).setVisibility(View.GONE);
findViewById(R.id.pager).setVisibility(View.GONE);
Edit: Actually, you could place the ViewPager and tab strip in a fragment of its own, and attach that to the fragmentToSwap FrameLayout so that your fragment transaction would actually do the replacement - depending on how your app is architected, that may make more sense.
Related
i have problem with my FragmentLayout in main class. i have app for location, in my main activity is map (google API) and i have a menu, FragmentLayout (in my main activity XML) is wrap_content (height), when i click on Settings, FragmentLayout is shows but its not cover the whole screen just a part and under settings i see map (which not should be there). When i set up match_parent for my FragmentLaout then i dont see the map in from my main activity.
Here is my code:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.globallogic.cityguide.MainActivity"
android:id="#+id/mainLayout"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="#layout/navigation_action"
android:layout_height="wrap_content"
android:layout_width="match_parent" />
// THIS IS MY FRAGMENTS:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" //here is this option which cover my whole screen when i put there match_parent
android:id="#+id/main_container"
android:layout_gravity="center"
>
</FrameLayout>
<include layout="#layout/activity_outdoor_map"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<android.support.design.widget.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="#+id/navigation_view"
app:menu="#menu/navigation_menu"
app:headerLayout="#layout/navigation_action"
android:layout_gravity="start"
>
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
You are using different containers, while for this purpose you'd probably rather want to just use one main container (like your xml says) and replace the fragments in it.
This way you can set your FrameLayout to fit the whole screen and just replace the settings Fragment and the Map fragment when necessary.
So the code should be changed in your MainActivity.
Let's suppose your MainActivity already extends AppCompatActivity and we have an instance of mapFragment, then you'll want to load your Map Fragment first, something like so:
// Add the fragment to the 'main_container' FrameLayout
getSupportFragmentManager().beginTransaction().add(R.id.main_container, mapFragment).commit();
now when you press the settings button you will just replace the fragment:
SettingsFragment settingsFragment = new SettingsFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the main_container view with this fragment,
// and add the transaction to the back stack if you want the user to be able to navigate back
transaction.replace(R.id.main_container, settingsFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
More info: here
You can add this in your layout file. And other menu option from your java file.
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="342dp"
android:layout_height="473dp" android:id="#+id/map" tools:context=".MapsActivity"
android:name="com.google.android.gms.maps.SupportMapFragment" />
</LinearLayout>
</LinearLayout>
What is the best way to handle the situation where I have fragments that should not include a ToolBar (Those would be handle by the Activity) and some including the Toolbar? I know how to make it transparent, but how can I create a template that can easily be modular to handle both situation?
For a specific Fragment I want a transparent Toolbar with the Fragment content partly behind the Toolbar like this:
I tried to have another FrameLayout that cover all the screen and then is replace by the FragmentTransaction but nothing happens...
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activityv2.ActivityHome">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<include layout="#layout/action_bar" />
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout
android:id="#+id/left_drawer_item"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:alpha="0.92"
android:background="#color/gray_very_dark"
android:orientation="vertical">
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/full_content_frame"
android:background="#color/dark_red"
android:fitsSystemWindows="true"/>
</android.support.v4.widget.DrawerLayout>
For the fragment that doesn't require a Toolbar, I replace the FrameLayout "content_frame" and for the one that require an invisible ToolBar I replace "full_content_Frame". For the second one, nothing happens when I replace it. Here is the code to replace the fragment:
private void selectProfilFragment() {
BackHandledFragment fragment = new FragmentUserProfil();
setSelectedFragment(fragment);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.pull_in_right, R.anim.push_out_left, R.anim.pull_in_left, R.anim.push_out_right);
ft.replace(R.id.full_content_frame, fragment)
.addToBackStack(fragment.getTagText())
.commit();
setTitle("Profil");
mDrawerLayout.closeDrawer(mDrawerLinear);
}
My app consists of multiple activities, they all have a common layout in the sense that they are drawer layout, have a tool bar, but they have different main content. Specifically, their complete layouts are as follows
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/relative_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/action_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
/>
.......main content, this is different for each activity..........
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
Since the shared components are defined at "parent level", I'm not sure how to structure these layouts so that the generic layout is only defined once. Is it possible to achieve that? Thanks.
Two options:
1. ViewStub
Define the main layout with a ViewStub where you will have different sub-layouts.
A ViewStub is an invisible, zero-sized View that can be used to lazily
inflate layout resources at runtime. When a ViewStub is made visible,
or when inflate() is invoked, the layout resource is inflated. The
ViewStub then replaces itself in its parent with the inflated View or
Views.
In each Activity you set the same layout and then inflate the specific sub-layout onto the ViewStub.
2. Fragments
If you want to avoid having massive quantities of code on a single Activity you might want to think about using Fragments.
Some other topics to guide you:
How to use View Stub in android
Loading Views On Demand
Yes it is possible by using Fragment. For this structure first you need to define a FrameLayout in your activity_main.xml . This framelayout will be replaced by the contents of the fragments over the time.
<android.support.v4.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/container_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
</LinearLayout>
<FrameLayout
android:id="#+id/container_body"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</FrameLayout>
</LinearLayout>
<fragment
android:id="#+id/fragment_navigation_drawer"
android:name="com.safallwa.zahan.oreader.FragmentDrawer"
android:layout_width="#dimen/nav_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
app:layout="#layout/fragment_navigation_drawer"
tools:layout="#layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
Then you can create your layouts as you want and classes as those extends Fragment . Set these new layouts as contentView of Fragment classes. Now these fragments can replace that FrameLayout of activity_main. Suppose we have a Framgent class name First_Fragment.Java then we can show that fragment by replacing activity_main framelayout by below code
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);//container_body is the id of the framelayout
fragmentTransaction.commit();
For full featured example with navigation drawer also we can follow below link
http://www.codedisect.com/?p=134
I have an activity that holds a ViewPager, set up as the template Swipe ViewPager. I have attached two fragments to that ViewPager via an adapter. I am now trying to open a new fragment but I am having great trouble getting it to work. I don't fully understand this idea of changing fragments with FragmentTransaction (I tried reading the Android docs to no avail) so I pieced the FragmentTransaction code together from places over the web.
This is my activity_main.xml
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"/>
This is the code I used to try to open the fragment
private void openVolumeSettingsFragment() {
Activity activity = getActivity();
FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.pager, new VolumeSettingsFragment());
transaction.addToBackStack(null);
transaction.commit();
}
This is the blank xml file for my new fragment fragment_volume_settings.xml
<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.velixo.bitchtalkandroid.fragments.VolumeSettingsFragment">
<ListView
android:id="#+id/volume_settings_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
The only thing this does is freezes my current fragment from being swipeable. Does anybody have any idea of what I should be doing?
Posted the same question on reddit, x-posting the answer from jeffinmadison in case anyone reading this question will need it:
If you want to replace the pager fragment with your settings fragment you should make the activity_main be a FrameLayout with a #+id/content and within the FrameLayout put the ViewPager with #+id/pager and then call the replaceFragment on the R.id.content
<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"
android:id="#+id/content">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"/>
</FrameLayout>
I have main activity with only ViewPager on it. The first tab page fragment contains:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/llEventsTabPage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/lvEvents"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
I want to show details fragment when user taps item in ListView:
lvEvents.setAdapter(adapter);
lvEvents.setOnItemClickListener(
new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
Fragment eventFragment = new EventFragment();
FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(R.id.llEventsTabPage, eventFragment);
fragmentTransaction.commit();
}
}
);
Code 'fragmentTransaction.commit();' is called, onCreateView of EventFragment is called, but after 'fragmentTransaction.commit();' nothing happens. No errors, no result. Just list view is still displaying and working.
What am I doing wrong? I've found a few examples, my code looks the same, but not working and I can do nothing with that.
Thank you!
When you do a replace or add, all it's going to do is add the Fragment's View to the container that you specify. The only difference is this:
replace will remove the first existing Fragment inside the container previously that is handled by the FragmentManager specified.
add will simply add the Fragment to the container.
In your case, you have a LinearLayout container which holds a ListView that is of size match_parent. What this means is, when the ChildFragmentManager adds your Fragment to the container, it will add it to a LinearLayout. The fragment is actually below the ListView outside the scope of the View.
Change LinearLayout to FrameLayout and your Fragment will appear over the ListView.
I'm not be sure. but I use two layout structures.
first layout structure
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
in this case, you need two fragment.
one is a EventFragment and other one is a Fragment for ListView.
so you should additionally create fragment for ListView.
second layout structure
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<FrameLayout android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
in this case, you commit R.id.fragment_container instead R.id.llEventsTabPage.
I think it would operate....