i have created a program for list fragment where my layout contains a fragment and the fragment contains a inflated listview
the problem is if a give the listview any other id except android:list it is not working .
why it is so
what android:list refers to.
the code is
Main layout :
<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/lfrag1"
android:name="com.example.chap5.lfrag"
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1" />
</LinearLayout>
Layout which is inflated for each fragment
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/android:list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
The id of the listview that is given here as android:list ,it is working for it .but for any other id it is not working
kindly update
thanks
tejinder
This is a requirement of using ListFragment
http://developer.android.com/reference/android/app/ListFragment.html
ListFragment has a default layout that consists of a single list view. However, if you desire, you can customize the fragment layout by returning your own view hierarchy from onCreateView(LayoutInflater, ViewGroup, Bundle). To do this, your view hierarchy must contain a ListView object with the id "#android:id/list" (or list if it's in code)
If you want to use another id, don't extend ListFragment, just extend Fragment and do it yourself.
Related
I have a custom view CustomSettingEntry this is its xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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/layout_custom_setting_entry_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/custom_setting_entry_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
</LinearLayout>
Then I use it in a fragment and assign it an id:
<com.mypackage.name.CustomSettingEntry
android:id="#+id/layout_notification_setting"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:setting_title="#string/title"
app:setting_subtitle="#string/subtitle" />
My question is what's the difference between the LinearLayout with id layout_custom_setting_entry_container and the usage with id layout_notification_setting? do they refer to the same thing?
If I set a click listener on the custom view inside the fragment, then later in some condition disabled clicking on the root LinearLayout inside the custom view, will this stop the listener?
I understand your custom view is a subclass of LinearLayout which inflates an xml layout. If so, the resulting view hierarchy is
[LinearLayout (actually a CustomSettingEntry), id : layout_notification_setting]
[LinearLayout, id : layout_custom_setting_entry_container]
...
So there are two levels of viewgroups, each one with it own id.
By the way this is inefficient because, the outer viewgroup (your custom class) has only one child (the root of the xml).
On solution is to use a <merge> as root of the xml layout to skip one level. See Optimize by merging or Inflating layout for your custom view
for more details.
I have two fragments (MyListFragment, MyDetailFragment) in one activity(MyActivity). The first fragment is a list of items, the second one is detail of an item (which is another list, but I think it doesn't matter). The first list fragment is shown when MyActivity starts.
MyListFragment view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment class="myapp.ActionsList"
android:id="#+id/actions_list_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
MyDetailFragment view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="#android:id/list"
android:tag="#string/activities_list_tag"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
There is a click handler on MyListFragment which calls method in MyActivity which opens the MyDetailFragment.
#Override
public void onActionSelected(MAction action, Integer position){
/**some code...*/
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container,
new MyDetailFragment(mAction,position)).commit();
}
The problem is:
that when I click on any item in MyListFragment, the MyDetailFragment won't show up (although I know it's lifecycle methods are called properly).
I found out that when I put android:layout_weight="1" to fragment definition in MyListFragment, it works. Does anybody know why?
As I understand the android:layout_weight property, it should play some role only when there are more view in LinearLaoyout, but I have only one.
This is the working layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment class="myapp.ActionsList"
android:id="#+id/actions_list_fragment"
**android:layout_weight="1"**
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Thanks
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container,
new MyDetailFragment(mAction,position)).commit();
You are completely replacing a fragment, so there's only one fragment's view in fragment_container at a time. Better make fragment_container a FrameLayout and set height and width of fragment layout roots to match_parent.
You are using layout_weight wrong and i don't think u understood it's functionality. In order to function in LinearLayout parrent you must have a weightSum which will be the total weight of the layout. The second thing would be to set childs weight or height 0dp depending on the LinearLayout orientation. Every child of the layout must have a layout_weight and the total sum of the weight to be equal to weightSum. Such that the Layout will be splited automatically depending you're weight.
Ok, I was doing wrong one thing.
Only fragments loaded programmatically can be replaced. Not fragments defined in xml.
But I didn't know it. Because MyListFragmentView contains fragment in xml definition, so although I called replaced, the method didn't replace actions_list_fragment with new one but put new one after actions_list_fragment. That's why layout_weights made it work - there were two childs in root LinearLayout but I though there is only one.
I place two ListFragment in my MainActivity.
This is the ListFragment xml file: fragment1.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" >
<ListView
android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawSelectorOnTop="false" />
</LinearLayout>
My question is, why must I use android:id="#id/android:list" here? When I use, e.g., #+id/frag_list, the program crashes with Error "inflating class fragment".
ListActivity has a default layout that consists of a single, full-screen list in the center of the screen. However, if you desire, you can customize the screen layout by setting your own view layout with setContentView() in onCreate(). To do this, your own view MUST contain a ListView object with the id "#android:id/list" (or list if it's in code). Its same when your class extends ListFragment.
For more info do check the docs
http://developer.android.com/reference/android/app/ListActivity.html.
You can extend Fragment instead of ListFragment. Have a custom layout with ListView. Then you can provide any id for your listview.
I'm developing an android application making use of fragments which is more of a Master/Detail form. I want the main activity to consist of a list fragment on the left side, based on the item chosen on the left i want to display a fragment with different layout on the right side.
(Note: each fragment on the right require different layouts/views)
All the examples that I've come across make use of only one common fragment on the right by changing some values in it or swapping/replacing new fragments having same layout.
If someone could shed some light on this problem then it will help me immensely. Thanks!
If you are using framelayouts to hold your fragments, it's the same as those other you mention. You just instantiate your fragment (whatever the layout) and swap it into the framelayout in place of the other one.
If you have hardcoded your fragments into the XML, you won't be able to do that (as far as I've been able to determine).
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frames"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#id/hline1"
android:layout_below="#id/horizontalline"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/leftpane"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight=".4" />
<TextView
android:id="#+id/verticalline"
android:layout_width="2dp"
android:layout_height="match_parent"
android:background="#color/bar_background"
android:gravity="center_horizontal"
android:paddingLeft="5dip"
android:paddingRight="5dip" />
<FrameLayout
android:id="#+id/rightpane"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1" >
</FrameLayout>
</LinearLayout>
Then you use the id for the framelayout and the name of your instantiated fragment to put your fragment into the framelayout.
EventListFragment eventlist = new EventListFragment();
getFragmentManager().beginTransaction().replace(R.id.leftpane, eventlist).commit();
EventDetailFragment eventadd = new EventDetailFragment();
getFragmentManager().beginTransaction().replace(R.id.rightpane, eventadd).commit();
When you want to change the contents, you do the same thing again (the following would replace the fragment in the right pane with a new/different fragment, which can have it's own, different, layout associated with it):
EventSuperDetailFragment eventsuper = new EventSuperDetailFragment();
getFragmentManager().beginTransaction().replace(R.id.rightpane, eventsuper).commit();
I'm trying to replace a fragment in a composite layout. Here's my root layout XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/buttons"
android:name="com.kippygo.android.touch_talker.ButtonsFragment"
android:layout_width="200dp"
android:layout_height="match_parent"
class="com.kippygo.android.touch_talker.ButtonsFragment" >
<!-- Preview: layout=#layout/buttons_fragment -->
</fragment>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/buffer"
android:name="com.kippygo.android.touch_talker.BufferFragment"
android:layout_width="match_parent"
android:layout_height="80dp" >
<!-- Preview: layout=#layout/buffer_fragment -->
</fragment>
<FrameLayout
android:id="#+id/grid_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground" >
</FrameLayout>
</LinearLayout>
</LinearLayout>
As you can see, I have three areas in my layout, a fixed left column containing a fragment with buttons the rest of the layout is divided vertically with a fragment managing a textView at the top and a grid of data in the lower section.
I want to use a common layout to place various GridView elements in the "grid_frame" as I press buttons in the "buttons" fragment. Here is the "grid_fragment" layout that I want to use for each GridView fragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/grid_fragment_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical">
<GridView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="80dp"
android:clipToPadding="true"
android:gravity="center"
android:horizontalSpacing="20dp"
android:numColumns="auto_fit"
android:orientation="vertical"
android:stretchMode="columnWidth"
android:verticalSpacing="20dp" >
<!-- Preview: listitem=#android:layout/simple_list_item_2 -->
</GridView>
<TextView
android:id="#+id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="22sp"
android:textStyle="bold"
android:text="#string/no_list_items"/>
</LinearLayout>
This composite layout opens up fine when I start my app. and I set my first fragment in the FrameLayout id "grid_frame" in my initial activity with the following code:
// Execute a transaction to put the categoriesFragment in the grid_view
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.grid_frame, new CategoriesFragment(), "category_fragment");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
This works perfectly fine and I see my buttons on the left, text input box on top and a grid of nicely filled cells to the right of the buttons.
When I click one of the list items in the GridView presented by the dynamic fragment I want to replace the fragment in the "grid_frame" FrameLayout. I do this with the following code in the onItemClick listener method of the "grid_frame" fragment with the following code:
// Execute a transaction to put the categoriesFragment in the grid_view
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.grid_frame, categoryWordsFragment, "category_words_fragment");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
Which looks remarkably similar to the code I used in the activity to set the initial fragment which worked fine.
When I do this my entire screen is replaced with the new fragment layout, which is another GridView with different data. My root layout appears to be totally replaced with the layout that was inflated by the new fragment even though I specify the "grid_frame" FrameLayout as the container view id in the replace method call.
I have tried everything I can find to make my layout stay intact and just change the fragment in the FrameLayout container.
What am I doing wrong please?
Problem solved! It was a very stupid mistake. I had converted my Activity classes to Fragment classes and in this one class I had forgotten to remove the call to setContentView in the class onCreate method. So the fragment was setting a new layout each time I created a new instance