I have the following Layout with static fragment and RelativeLayout as parent:
<?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:padding="#dimen/activity_vertical_margin">
<fragment
android:id="#+id/list_fragment"
android:name="com.listfragmenttest.MyListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Yet the container or parent comes up null in OnCreateView:
public class MyListFragment extends ListFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.my_list_fragment, container, false);
}
}
Is this the normal behavior for Static fragment?
Yes, that's how it is implemented. Fragments inflated statically from XML get a null as parent container.
For details, consult FragmentManager source. In particular, onCreateView() that handles fragment instantiation from layout inflation, setting mInLayout = true and calls to performCreateView() that are conditional on mInLayout.
Related
I am working on a app and it runs just fine but there is an problem that it crashes when I dont write id in my fragment code but runs fine after using id attribute and the problem is that i have not used it's id anywhere in my app
Here is the xml file
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<fragment
class="com.hfad.workout.WorkoutList"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:id="#+id/listfrag"
/>
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:text="second text view"
android:layout_marginTop="20dp"
android:id="#+id/fragcont"
android:layout_weight="3"
/>
</LinearLayout>
workoutlist.jav
public class WorkoutList extends ListFragment {
MainActivity ma;
static interface WorkoutListListener{
void clickme(long at);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ArrayAdapter<Workout> arrayAdapter = new ArrayAdapter<Workout>(
inflater.getContext(), android.R.layout.simple_list_item_1,
Workout.workout);
setListAdapter(arrayAdapter);
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onAttach(Context ac){
super.onAttach(ac);
this.ma =(MainActivity) getActivity();
}
public void onListItemClick(ListView v, View vi, int position, long id){
ma.clickme(id);
}
}
Before an activity can talk to its fragment, the activity first needs
to get a reference to it. To get a reference to the fragment, you first
get a reference to the activity’s fragment manager using the
activity’s getFragmentManager() method. You then use its
findFragmentById() method to get a reference to the fragment:
findFragmentById() is a
bit like findViewById()
except you use it to get a
reference to a fragment
getFragmentManager().findFragmentById(R.id.fragment_id)
It's because if you do not specify fragment id, then FragmentManager cannot restore it after recreating.
You have to specify fragment id or tag.
I am trying to navigate from on fragment to another by click a button in original fragment. How ever I got a Exception
Image of exception
Image of my code for the original Fragment
The problem is that you are passing a Layout in your call of transaction.Replace(), instead you should pass the Id the of the ViewGroup where the fragment will be inserted in your layout.
so the layout of the activity containing your fragments should look something like this:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="fill_parent" />
</FrameLayout>
And in your FragmentStockSearch fragment, override OnCreateView to something like this:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
return inflater.Inflate(Resource.Layout.your_layout, null, false);
}
and finally your fragment transaction code:
var trans = new FragmentManager.BeginTransaction();
trans.Replace(Resource.Id.content_frame, new FragmentStockSearch(), "FragmentStockSearch");
trans.AddToBackStack(null);
trans.Commit();
I have the following layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/parentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/main_container_1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:id="#+id/main_container_2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<FrameLayout
android:id="#+id/leftDrawer"
android:layout_width="#dimen/some_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:paddingTop="?android:attr/actionBarSize" />
</android.support.v4.widget.DrawerLayout>
</FrameLayout>
I have inserted a fragment in main_container_1 which has a layout with a viewPager created programmatically. Here is the OnCreateView of the first fragment
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var frameLayout = new FrameLayout(Activity)
{
LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent)
};
_viewPager = new ViewPager(Activity);
//It is required that view pager have an ID othe than -1
_viewPager.Id = 0x00000001;
_viewPager.PageSelected += _viewPager_PageSelected;
_progressBar = new ProgressBar(Activity)
{
LayoutParameters = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent, GravityFlags.Center)
};
frameLayout.AddView(_viewPager);
frameLayout.AddView(_progressBar);
return frameLayout;
}
Of course, later on, I bind my data via an FragmentStatePagerAdapter to the viewPager.
Result: The child fragments contained in the first fragment display properly
I do the same operation for a second fragment in main_container_2 of a different type which has the following onCreateView
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
_myCustomContainer = (MyCustomLayout)inflater.Inflate(Resource.Layout.MyCustomLayout, container, false);
_viewPager = new ViewPager(Activity);
_myCustomContainer.AddView(_viewPager);
//It is required that view pager have an ID othe than -1
_viewPager.Id = 0x00000001;
return _myCustomContainer;
}
I use the same type of FragmentStatePagerAdapter as for the first viewPager of the first fragment.
Result: On Android version lower or equal to Jellybean (API 16), the child fragments of the second fragment are created but not displayed.
Here is the GetItem method of my implementation of the FragmentStatePagerAdapter
public override Fragment GetItem(int position)
{
if (!ActiveFragments.ContainsKey(position))
{
var fragment = PagedCustomFragment.NewPagedCustomFragment(position);
ActiveFragments[position] = fragment;
}
return ActiveFragments[position];
}
Question: Why are the child fragments of the second fragments not shown?
Both your ViewPagers seem to belong to the same parent and also have the same ID, which might be the root cause of your issue. Have you tried to use a different ID for each ViewPager?
I have a layout which contains a <fragment> called MenuFragment. Whenever I launch the application howver, I get a Trying to instantiate a class com.usmaan.whackem.MenuFragment that is not a Fragment.
Layout:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="#id/layoutHeader"
android:layout_marginTop="20dp">
<fragment android:name="com.usmaan.whackem.MenuFragment"
android:id="#+id/menu_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Fragment:
public class MenuFragment extends Fragment{
public MenuFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.menu_fragment, container, false);
}
}
I've tried
1) Adding an ID to the <fragment>
2) Adding a namespace to <fragment>
I fixed the issue by extending the Activity which holds the fragment from FragmentActivity and not Activity.
I'm trying to put 2 fragments inside a fragment. I found some code on internet but, as far as I could go, I don't succeed to put 2 fragments in 1 fragment.
I have seen tips dealing with FragmentManager and especially the method getChildFragmentManager() but I don't know how it works with 2 fragments.
For the story, I'm using an activity with ActionBar which creates 3 fragments. In one of them, I need to handle a graph and a kind of menu to change the graph scale. In this way, I need 2 fragments in one fragment.
Here is the code :
The fragment which handles the others:
public class GraphDisplayFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View myFragmentView = inflater.inflate(R.layout.graph_fragment, container, false);
return myFragmentView;
}
}
The code to draw the graph:
public class GraphFragment extends Fragment {
private static final int SERIES_NR = 1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
GraphicalView myFragmentView = ChartFactory.getTimeChartView(this.getActivity(), getDateDemoDataset(), getDemoRenderer(),null);
return myFragmentView;
}
//some functions to set graph propreties
}
The XML files :
graph_fragment.xml
<?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:orientation="vertical" >
<fragment
android:id="#+id/graph_fragment"
android:name="com.test.GraphFragment"
android:layout_width="match_parent"
android:layout_height="259dp" >
</fragment>
<fragment
android:name="com.test.GraphDetailFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/graph_detail_fragment">
</fragment>
</LinearLayout>
graph_detail.xml with a test implementation
<?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:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="211dp"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
The weird thing is, it works at the begining when I switch between fragments in the ActionBar but after 3-4 moves, I get this error :
android.view.InflateException: Binary XML file line #7: Error inflating class fragment
If anyone has the solution, it would be awesome!
So first off change your xml for graph_fragment.xml to this
<?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:orientation="vertical" >
<FrameLayout
android:id="#+id/graph_fragment_holder"
android:layout_width="match_parent"
android:layout_height="259dp" >
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/graph_detail_fragment_holder">
</FrameLayout>
</LinearLayout>
Then in code to inflate them from the fragment use something like this
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.graph_fragment,
container, false);
FirstChildFragment frag1 = (FirstChildFragment) getChildFragmentManager()
.findFragmentById(R.id.first_frag_layout);
SecondChildFragment frag1 = (SecondChildFragment) getChildFragmentManager()
.findFragmentById(R.id.second_frag_layout);
if (null == frag1) {
FirstChildFragment = new frag1();
FragmentTransaction transaction = getChildFragmentManager()
.beginTransaction();
transaction.add(R.id.graph_fragment_holder, frag1)
.addToBackStack(null).commit();
}
if (null == frag2) {
SecondChildFragment = new frag2();
FragmentTransaction transaction = getChildFragmentManager()
.beginTransaction();
transaction.add(R.id.graph_detail_fragment_holder, frag2)
.addToBackStack(null).commit();
}
return rootView;
}
MyFragment myFragment = (MyFragment)getChildFragmentManager().findFragmentById(R.id.my_fragment);
You can try to use the method *findFragmentById(fragment_id)* from SupportFragmentManager to get the instance of fragment from your .xml file and insert your fragment there.
Something like:
Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.myFragmentId);
I hope to help you.
Best regards.
Adriano