I am developing an app to present a map (using a fragment) and a list (using a ListFragment). So, I have an activity that starts the application as well as the mapfragment or the list fragment, according to the the user's preferences. I can easily replace the current activity for the mapfragment with FragmentManager and FragmentTransaction. The problem that I have is how I can call or start the ListFragment from the activity.
The listfragment uses a ListViewAdapter class to inflate a customized layout (repetedly with different information) so if i want to use transaction, it will be necessary to use a listview container in the layout. The problem is that I am using a layout for the items and not a container.
Any ideas to solve this problem or any other way to deal with starting a presenting the listfragment in the activity?
If you are trying to display two different fragments at the same time, have a look at this documentation, but the basic idea is to include multiple FrameLayouts in your activity layout. Also don't forget about View.setVisibility()
ListFragments are started the same as any other fragment.
For Example:
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, new MyListFragment()
.commit();
A more verbose example:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.plusButton).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, new MyListFragment())
.commit();
}
});
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/content_frame"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:text="Press For List"
android:id="#+id/plusButton"
android:layout_gravity="center"/>
</RelativeLayout>
Related
I have an activity with buttons and text fields and more stuff, And in that activity one of the buttons opens a fragment dynamically on top of the activity:
btnGate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sgFrag = new SetGateFragment();
fragmentManager = getFragmentManager();
transaction = fragmentManager.beginTransaction();
transaction.add(R.id.container,sgFrag);
transaction.addToBackStack(null);
transaction.commit();
}
});
In this fragment I also have a few buttons. Now, when I tested my app on my phone to check if all the buttons in the activity as well as the buttons in the fragment are working everything worked fine, I was able to click the buttons in the activity as well as the buttons in the fragment and they all correspondent accordingly, but then I decided to test my app on galaxy note5 , and this time when I clicked the button to open the fragment one of the buttons from the activity overlapped the fragment and was clickable while neither of the buttons in the fragment were clickable.
Wasn't sure what could be the cause , Here is the fragment opening tag:
<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="com.example.phonegate.SetGateFragment"
android:background="#drawable/backgroundfrag"
android:orientation="vertical"
android:weightSum="1" />
Here is my activitys layout opening tag:
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.example.phonegate.MainActivity"
tools:showIn="#layout/activity_main"
android:background="#drawable/background"
android:id = "#+id/container"
android:orientation="vertical">
Thanks!
Try this code..!
FragmentManager fm = getSupportFragmentManager();
SetGateFragment fragment = new SetGateFragment();
fm.beginTransaction().add(R.id.main_contenier,fragment).commit();
I have several activities which extend my class DrawerActivity, so they will have a navigation drawer. Only one of these activities requires a ViewPager.
Question: How can I add a ViewPager to only one of the activities, ActivityA?
I am somewhat familiar with creating a ViewPager, but in this situation I'm unsure of where to put the ViewPager code, and what layouts to use. I've seen a few examples including the official tutorial on Google's developer site, but I'm not sure how to best implement it into my application.
I've provided some relevant code below, but please let me know if you need to see more. Any advice is appreciated, thanks!
In DrawerActivity's onCreate:
setContentView(R.layout.activity_fragment);
if (fragment == null)
{
fragment = createFragment();
fm.beginTransaction()
.add(R.id.fragmentContainer, fragment)
.commit();
}
Layout activity_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
</RelativeLayout>
<ListView android:id="#+id/leftDrawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
In ActivityA:
public class ActivityA extends DrawerActivity
{
//this is all I do in this activity
#Override
protected Fragment createFragment()
{
UUID id = (UUID) getIntent().getSerializableExtra(FragmentA.EXTRA_ID);
return FragmentA.newInstance(id);
}
}
In FragmentA's onCreateView:
View v = inflater.inflate(R.layout.fragment_a, parent, false);
Layout fragment_a.xml is a simple LinearLayout with a few Button and TableLayout children.
fragment_a.xml:
<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" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
and create an adapter for example FragmentStatePagerAdapter and fill it with what you want to show in viewpager. notice that because you are using viewpager inside a fragment you should pass ChildFragmentManaget instead of activity FragmentManager.
I'm currently creating an app which can handle different screen support and multi-pane view using fragments. Now I used the default navigation drawer and actionbar using android studio and created two fragments to test for this and layouts for portrait: fragment_1 and fragment_2 which just replaces the container on the MainActivity. But now the problem is how can I implement the fragment_1 and fragment_2 in 1 layout? I Tried to research on the multi-pane development on this link but I think to properly implement it I need to use an ActivityFragment but in this case I am limited on using just Fragments which is why I'm lost on what to do. Here's the code so far:
#Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getSupportFragmentManager();
switch (position) {
case 0:
fragmentManager.beginTransaction()
.replace(R.id.container, FragmentMain.newInstance(position + 1))
.commit();
break;
case 1:
fragmentManager.beginTransaction()
.replace(R.id.container, FragmentAbout.newInstance(position + 1))
.commit();
break;
/*create the other cases here for navigation*/
}
}
fragment_main.xml (the 1st fragment)
<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="com.kahel.main.MainActivity$PlaceholderFragment">
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/list_news"
android:choiceMode="singleChoice" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
fragment_about.xml (2nd fragment)
<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="com.kahel.main.MainActivity$PlaceholderFragment">
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/list_news"
android:choiceMode="singleChoice" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
fragment_main.xml (landscape)
<LinearLayout 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.kahel.main.MainActivity$PlaceholderFragment"
android:orientation="horizontal"
android:weightSum="1">
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipe_container"
android:layout_width="#dimen/land_scoop_feed"
android:layout_height="match_parent">
<ListView
android:layout_width="150dp"
android:layout_height="match_parent"
android:id="#+id/list_news"
android:choiceMode="singleChoice" />
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
When I tried to change the layout it just force close my app. :/
Please let me know what to do or what to search for. Thanks! :)
Well, I ran into the exact same problem and after doing a lot of research I was surprised on the lack of documentation for this, in my opinion, common situation. But, after trying a few things I came up with a solution.
My first approach was to replace the Navigation Drawer container with a "root fragment" that at the same time would have two layouts available containing the fragments that I want. The problem was that nested fragments declared on the layout are not permitted.
To overcome this other issue, in my "final layouts" I replaced the Fragment definitions for FrameLayouts and then load the fragments programatically on the "root fragment".
To summarize: You have your Navigation Drawer and upon clicking what you want, you replace your fragment container with a "root fragment". This "Root fragment" has two layouts: a default one and another for landscape. These layouts contain FrameLayout elements arranged as we want that upon initialization are replaced by our "final fragments".
I doubt that this is the best way to achieve the goal of having Multi-pane layouts with a Navigation Drawer but is what I was able to do that best suited my needs. I welcome any suggestions!.
I illustrate the solution with some code.
MainActivity.java (The one with the navigation drawer)
...
void drawerOptionSelected(String option) {
if(option.equals(XXXX)) {
Fragment fragment = new RootFragment();
final FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.content_frame, fragment);
transaction.commit();
drawerList.setItemChecked(menuOptions.indexOf(option), true);
drawerLayout.closeDrawer(drawerList);
}
}
...
root_fragment_layout.xml (Default)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/entries_list_single"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="match_parent" />
root_fragment_layout.xml (Landscape)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:baselineAligned="false"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="#+id/entries_list"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
<FrameLayout android:id="#+id/entries_post"
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="match_parent" />
</LinearLayout>
RootFragment.java
public class RootFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.root_fragment_layout);
if(savedInstanceState != null) { //Fragments already loaded, avoid replacing them again
return;
}
ListFragment listFragment = new ListFragment();
final FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); //IMPORTANT! Use child fragment manager
if (findViewById(R.id.entries_list_single) == null) { //We are loading the landscape layout
PostFragment postFragment = new PostFragment();
transaction.replace(R.id.entries_list, listFragment);
transaction.replace(R.id.entries_post, postFragment);
transaction.commit();
} else { //We are loading the default layout
transaction.replace(R.id.entries_list_single, listFragment);
transaction.commit();
}
}
}
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....
I'm having an issue where I can create a Fragment, its view appears to be created, but it doesn't show up. The fragment itself is created and any code inside runs without issue, but it is just invisible somewhere. The back button also interacts with it just fine (it "closes" it), it just doesn't physically show up on screen (only the main layout is displayed).
From my FragmentActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_view);
// some logic here that sets a button listener that calls openAddNamePane() when pressed
}
public void openAddNamePane(){
AddNamePane addNamePane = new AddNamePane();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.layout_root, addNamePane, "AddnamePane");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
This is the layout for the View that is first displayed (activity_main_view.xml aka my 'root layout'):
<LinearLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
android:background="#color/white"
android:id="#+id/layout_root">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button android:id="#+id/addPlayerButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Player" />
<Button android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/buttonLabel" />
</LinearLayout>
<ListView android:id="#+id/playerListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="#color/white"
android:entries="#array/testStringArray" >
</ListView>
</LinearLayout>
This is my fragment class:
public class AddNamePane extends Fragment {
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
System.out.println("AddNamePane.onCreateView()");
View view = inflater.inflate(R.layout.add_player_pane_layout, container, false);
return view;
}
// a few other methods here, onAttach(), onStop(), onPause(), etc
// all are empty of logic with just a println to see if they are being called correctly (in which they are)
}
This is the layout for that "AddNamePane" fragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical" >
<EditText
android:id="#+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:text="test name here"
android:hint="Name here" >
<requestFocus />
</EditText>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
I am pretty new to using fragments, not too sure if my issue is in code or if it is something to do with the layouts. My goal is to add the "AddNamePane" to the 'root layout' replacing the main view temporarily. What I did to attempt this was to give my root layout an id and use that in the FragmentTransaction. If it matters, the api level I am using is 8 (Android 2.2) thus using things from android.support.v4.app package.
You're trying to programmatically replace a LinearLayout, while also expecting it to have the hard-coded children. This won't work. You should use a FrameLayout for your FragmentTransaction that is also a child of your layout_root.
If you update your post with the actual xml, I can show you exactly how to do this.
I had a similar problem, when fragment wasn't showing up. The problem was that I removed AndroidAnnotations, but forgot to move the code from onViewCreated and onCreate methods to the onCreateView. I found this mistake by comparing the code of two fragments - one, that was showing up and the other that wasn't. So, if you have similar problems, try to check the code of fragments. It may not show any errors at first glance, but will not still work or show up because of those errors.
Particularly, check that you have this method and that you inflate a view:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.your_fragment_layout, container, false);
return v;
}
tools:layout="#layout/fragment_up"
Use your layout file as above