ListFragment Layout from xml - android

How to create a ListFragment (of the support v4 library) layout from xml?
ListFragment sets up its layout programmatically, so if you want to modify it, you need to mess with add/remove view.

I've converted the created layout to xml, you can add/remove your widgets or e.g. add pulltorefresh solutions. You shouldn't change the needed ids.
Because of internal ids needed for some of the widgets an helper function needs to be called and it needs to be in support v4 namespace since constants are internal with default visibility.
list_loader.xml
<?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" >
<LinearLayout
android:id="#+id/progress_container_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone" >
<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<FrameLayout
android:id="#+id/list_container_id"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/empty_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false" >
</ListView>
</FrameLayout>
</FrameLayout>
and the class ListFragmentLayout in android.support.v4.app (in your project, you don't need to modify support v4 jar)
package android.support.v4.app;
import your.package.R;
import android.view.View;
public class ListFragmentLayout
{
public static void setupIds(View view)
{
view.findViewById(R.id.empty_id).setId(ListFragment.INTERNAL_EMPTY_ID);
view.findViewById(R.id.progress_container_id).setId(ListFragment.INTERNAL_PROGRESS_CONTAINER_ID);
view.findViewById(R.id.list_container_id).setId(ListFragment.INTERNAL_LIST_CONTAINER_ID);
}
}
in your fragment that extends ListFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.list_loader, container, false);
ListFragmentLayout.setupIds(view);
return view;
}

From the android sdk (ListFragment) (http://developer.android.com/reference/android/app/ListFragment.html):
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
Provide default implementation to return a simple list view. Subclasses can override to replace with their own layout. If doing so, the returned view hierarchy must have a ListView whose id is android.R.id.list and can optionally have a sibling view id android.R.id.empty that is to be shown when the list is empty.
If you are overriding this method with your own custom content, consider including the standard layout list_content in your layout file, so that you continue to retain all of the standard behavior of ListFragment. In particular, this is currently the only way to have the built-in indeterminant progress state be shown.
So when you want your own layout.xml for a FragmentList overide onCreateView and inflate your own layout.
For example:
Create a android layout (yourlistlayout.xml) and put the following xml on the position where you want to show your ListFragment.
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
</ListView>
in your ListFragment class put the following code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.yourlistlayout, null);
return v;
}

Related

cannot show listView on fragment

I have a xml Layout file (ListLayout.xml) where i create listView and i want this layout to be shown on a fragment on main_activity_layout. so go to MainActivity_layout and i added a fragment , when it is proposed to choose a class i choosed the class Listfrg where i return the layout of listLayout.xml within OnCreateView methode , but nothing is shown why ?
ListLayout.xml
<?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" >
<LinearLayout
android:id="#+id/progress_container_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone" >
<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<FrameLayout
android:id="#+id/list_container_id"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/empty_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false" >
</ListView>
</FrameLayout>
</FrameLayout>
MainActivityLayout
<fragment
android:layout_width="162dp"
android:layout_height="match_parent"
android:name="com.example.pack2.t9ahbin.Listfrg"
android:id="#+id/fragment3" />
Class Listfrg :
public class Listfrg extends ListFragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frglist, container, false);
return view;
}
}
nothing is shown why?
Because there is no data in your list.
Please use an ArrayAdapter or some Adapter variant, put some data into it with adapter.add, and the use listView.setAdapter. To actually give data to your Listview.
You can do this in onCreateView and use getListView() or this to get the ListView.
ListView listView = (ListView) view.findViewById(android.R.id.list);
An Adapter is the data container for a ListView. Without one, how do you expect to display data?
Also your empty view needs to use android:id="#android:id/empty"
This is all well covered in AdapterViews

Using Fragment layour ..... findbyViewId always NULL

I am pretty newbie with android development and I am trying to make work an easy example.
When the layout contains fragments, this fragments are inflated and the method findByViewId returns a NULL pointer. I would like to konw how to avoid that.
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.todoit.MainActivity"
tools:ignore="MergeRootFrame" />
so far the only solution I found was to dont use fragment layout :/
fragment_main.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: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="com.example.todoit.MainActivity$PlaceholderFragment">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/myEditText"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true" />
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/myListView"
android:layout_below="#+id/myEditText"
android:layout_alignRight="#+id/myEditText"
android:footerDividersEnabled="false" /> </RelativeLayout>
this code returned a NULL pointer
setContentView(R.layout.activity_main); ListView myListView=
(ListView)findViewById(R.id.myListView);
the only way I found was to use this one instead.
setContentView(R.layout.fragment_main); ListView myListView=
(ListView)findViewById(R.id.myListView);
all this code in the onCreate method.
could someone tell me how to solve this issue? is there a way to inflate the whole layout including fragments?
thanks a lot.
Jose
You should inflate the fragment's view in the fragment code only, not in the activity code. You use onCreateView method to do this.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_main, container, false);
ListView myListView= (ListView) v.findViewById(R.id.myListView);
return v;
}
If you want to find your ListView after onCreateView has already been called, you can use getView() method:
ListView myListView= (ListView) getView().findViewById(R.id.myListView);
ListView myListView= (ListView) fragment.getView().findViewById(R.id.myListView); needs to be called from inside the fragment class code and not the main activity. Call it inside method onActivityCreated, by that time the onCreateView function of fragment would have succeeded

Fragment not showing up

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

design of one row in android listview

I need help with my android app. I need customize items in listview. My app works with fragments. I don’t know how to implement list_item.xml to my code.
KartyListFragment.java
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.karty_list, container, false);
return view;
}
karty_list.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="#android:id/list"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:visibility="gone" />
<TextView
android:id="#android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/prazdna_db"
android:textColor="#f00"
android:visibility="visible" />
</LinearLayout>
I want to designed one row in list_item.xml but i don´t know how to.
here you can find a good tutorial to build your list view.. I think it will be helpful for you.
Jus create the layout you want and pass it along to the list adapter as the view to be inflated. For example, using a SimpleAdapter:
mAdapter = new SimpleAdapter(context, list, R.layout.my_custom_list_item, from, to);
mListView.setAdapter(myAdapter);

ListView with custom adapter and other view elements

I am learning to use the Hierarch Viewer tool, but meanwhile any hint on why below layout is not rendering correctly is appreciated.
I am trying to render an "html" table view. The content (table body) is rendered correctly with a custom list adapter. This works. But, when I add a textView (text_test below) to use as header, the list is not rendered anymore. I could see the code flow through my adapter (populate view holder, etc), but on screen I only see the Title text, no listView. I used to use FrameLayout (as noted in the comment), but then switched to LinearLayout.
Thanks.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.my_list_view, container,
false);
ListView lv = (ListView)view.findViewById(R.id.my_list_view_one);
// Tell the list view which view to display when the list is empty
//lv.setEmptyView(getActivity().findViewById(R.id.my_list_view_empty));
// Set up the adapter
mCustomAdapter = new ListAdapterMyType(inflater, new ArrayList<MyType>());
lv.setAdapter(mCustomAdapter);
return view;
}
my_list_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The frame layout is here since we will be showing either
the empty view or the list view. -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/text_test"/>
<ListView
android:id="#+id/my_list_view_one"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false"/>
<!-- Here is the view to show if the list is emtpy -->
<TextView android:id="#+id/my_list_view_empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/list_no_items"
android:visibility="gone"/>
</LinearLayout>
</LinearLayout>
But, when I add a textView (text_test below) to use as header, the list is not rendered anymore.
The TextView is set to match_parent in both the width and height, so it will fill the entire screen... To put a TextView above your ListView try:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/text_test"/>
<ListView
android:id="#+id/my_list_view_one"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false"/>
<!-- Here is the view to show if the list is emtpy -->
<TextView android:id="#+id/my_list_view_empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/list_no_items"
android:visibility="gone"/>
</LinearLayout>
I removed the outer LinearLayout, since it only had one child it did nothing. I also changed the remaining LinearLayout's orientation to vertical and set the header TextView height to wrap_content.
If you want your custom header to scroll with your ListView, use the addHeaderView() method (before calling setAdapter()) instead of a separate TextView in your layout. This approach will also hide the header when the ListView is empty.

Categories

Resources