Inflating RelativeLayout within another RelativeLayout - android

I'm trying to contain the layout model for a custom list view in a single custom list view layout.xml file and inflate that using an custom adaptor class using kotlin.
The data seems to come through fine and the row formatting is accurate with the exception of the header being repeated for each row. I'm guessing I could just move the header out of the list view layout.xml file but I'd prefer to keep that self contained so it could be re-used.
This is the layout file in question:
<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" >
<!-- Header aligned to top -->
<RelativeLayout
android:id="#+id/estimated_ftp_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="#color/colorHeader"
android:gravity="start" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:text="#string/estimated_ftp"
android:textColor="#000"
android:textSize="20sp" />
</RelativeLayout>
<!-- Content below header -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_below="#id/estimated_ftp_header"
android:orientation="horizontal"
android:padding="6dip"
android:id="#+id/estimated_ftp_row">
<ImageView
android:contentDescription="#string/ftp_type"
android:id="#+id/ftp_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/centerPoint"
android:gravity = "center|end|end"
android:src="#drawable/glyphicons_13_heart"/>
<TextView
android:id="#+id/centerPoint"
android:text=""
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" />
<TextView
android:id="#+id/ftp_value"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_toRightOf="#+id/centerPoint"
android:gravity = "center|start|start"
android:text="141 bpm"/>
</RelativeLayout>
I believe the solution would be to figure out how to select the estimated_ftp_row id and inflate it instead of the the whole estimated_fto.xml file.
Here is the code in the adapter that selects the layout before inflating within the getView method:
val inflater = activity?.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
view = inflater.inflate(R.layout.estimated_ftp, null)
viewHolder = ViewHolder(view)
view?.tag = viewHolder
How would I change the inflater.inflate to inflate something within R.layout.estimated_ftp?
FWIW, the activity's XML layout has a ListView control in the location used for this as a placeholder. It doesn't reference the custom layout file. That connection is done via the adapter class noted above. Not sure that's a problem or not so I wanted to mention it...
Thanks in advance for any suggestions.
mike
Solution Update:
https://stackoverflow.com/users/2850651/mike-m had the guidance I needed. I was able to separate the row format from the header format XML layouts. The Adapter was unchanged and the Activity has new code to add the header if content is found for the list in question.
val headerView = layoutInflater.inflate(R.layout.estimated_ftp_head, null)
estimated_ftp_list.addHeaderView(headerView)

Solution:
https://stackoverflow.com/users/2850651/mike-m had the guidance I needed. I was able to separate the row format from the header format XML layouts. The Adapter was unchanged and the Activity has new code to add the header if content is found for the list in question.
val headerView = layoutInflater.inflate(R.layout.estimated_ftp_head, null)
estimated_ftp_list.addHeaderView(headerView)

Related

Adding LinearLayout to ListView using an adapter

I am trying to create a ListView where each entry in the list consists of a LinearLayout. I have an ArrayList that I have defined here:
ArrayList<LinearLayout> menuList;.
Later in my code, I define
LinearLayout dailyMenuLayout = new LinearLayout(ReturnMenus.this);, and every time I complete a layout to be added to the ListView, I use menuList.add(DailyMenuList)
The adapter that I have been trying to use is as follows -- but it crashes the app every time that it is triggered.
ListView myListView = (ListView)findViewById(android.R.id.list);
ArrayAdapter<LinearLayout> adapter = new ArrayAdapter<LinearLayout>(ReturnMenus.this, R.id.linear_layout_item, menuList);
myListView.setAdapter(adapter);
And this is the XML for the single row in the ListView:
<?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" >
<LinearLayout
android:id="#+id/linear_layout_item"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content" >
</LinearLayout>
</LinearLayout>
Can somebody show me how to accomplish this? Thanks.
Use something like following layout for the row layout in your list rather than you current layout:
<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/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
.
.
.
.
.
</LinearLayout>
Here if you do not know exactly how many textView that you are going to use, use maximum number of TextView that using in your application. Then in your adapter class inside getView() you can get those TextView. If some rows not going to use all of these textViews then set them invisible as like this:
TextView txtView3 = (TextView)findViewById(R.id.text3);
txtView3.setVisibility(View.GONE)
Following tutorial helps you to create the listView.
http://www.vogella.com/tutorials/AndroidListView/article.html
You should bind data to adapter,such as strings,not the layout.
To see how to use ListView and Adapter,please check the demo project in your-android-sdk-dir\samples\android-XX\ApiDemos.

Android - Populating a listview using fragments and a Simple cursor adapter

I know that this question is probably asked a hundred times so far, but i still haven't manage to solve my problem. I have one activity that's comprised of 2 fragments. One fragment is a form that adds information to the database:
**R.layout.fragment_add_server:**
<?xml version="1.0" encoding="utf-8"?>
...
<LinearLayout
android:id="#+id/nameLinear"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp" >
<TextView
android:id="#+id/nameText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="70"
android:text="#string/strName"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="#+id/editName"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="30"
android:hint="#string/editName" />
</LinearLayout>
...
And another fragment that's just a listview.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/georgeback"
android:orientation="vertical" >
<ListView
android:id="#+id/listView1"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="60" >
</ListView>
<Button
android:id="#+id/connect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="#string/connectBTN" />
</LinearLayout>
That fragment, the listview, i want to populate it with whatever there is in the database, and auto refresh when something new is added(haven't got to that stage yet). When i'm using the following code below i manage to populate the listview with the entire fragment(i.e i see the listboxes,buttons etc and i can even interact with them. Inception.) instead of just the data.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_select_server,
container, false);
Cursor mNotesCursor = mDbHelper.fetchAllNotes();
String[] from = new String[]{mDbHelper.KEY_TITLE};
int[] to = new int[]{R.id.editName};
mCurAdapter = new SimpleCursorAdapter(view.getContext(),R.layout.fragment_add_server,mNotesCursor,from,to,0);
mMyListView=(ListView)view.findViewById(R.id.listView1);
mMyListView.setAdapter(mCurAdapter);
return view;
}
I believe that i'm doing something wrong with the from and to fields of the constructor. Any idea why i'm getting as an output the entire fragment view and not just the data in the database? Any other suggestions?
Your problem is when you pass the fragment layout instead of the list view item layout. From what I can see your list view item is included inside your fragment_add_server.xml layout (since you put ... before and after the xml snippet). Move the snippet into its own file, something like my_list_view_item.xml and use that when creating your SimpleCursorAdapter.
mCurAdapter = new SimpleCursorAdapter(view.getContext(),R.layout.my_list_view_item,mNotesCursor,from,to,0);
I solved the problem i had by changing the layout in the simplecursoradapter. Instead of
mCurAdapter = new SimpleCursorAdapter(view.getContext(),R.layout.fragment_add_server,mNotesCursor,from,to,0);
i did:
mCurAdapter = new SimpleCursorAdapter(view.getContext(),android.R.layout.simple_list_item_1,mNotesCursor,from,to,0);
Essentially changing the layout to the generic android list layout did the trick! :)

Android: margin/padding for the ListView without having the margin applied to the header?

Is it possible to have a margin/padding for the ListView without having the margin applied to the header? I want my ListView to be like the Google Now layout. I've got everything working except for this little problem.
Question: Is it possible to not have layout parameters of the ListView apply to its header?
EDIT1:More info
The purple view is the header to the listView.
I have tried adding margin to the list item layout.This doesnt work either.
All i need is a way to apply margin to the listview so that it doesnt apply the margin to the header in the listView.
EDIT2:
My layouts
header.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:orientation="vertical" >
<View
android:layout_width="match_parent"
android:layout_height="#dimen/top_height"
android:background="#color/top_item" />
<View
android:id="#+id/placeholder"
android:layout_width="match_parent"
android:layout_height="#dimen/sticky_height"
android:layout_gravity="bottom" />
</FrameLayout>
root_list.xml
<LinearLayout>
<com.test.CustomListView
android:id="#android:id/list"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_height="wrap_content" /></LinearLayout>
list_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/card_background"
android:orientation="vertical" >
<TextView
android:id="#+id/textview_note"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textview_note_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"/></LinearLayout>
I've removed uselsess layout properties here due to length of this post.
After much digging around i found that its is not posssible to decouple the listView layout params from its headers and the header is part of listView. So in order to get the desirred margin effect, After much looking around I found out that adding margin to your root of the layout in the list view item didnt work. So I added another dummy LinearLayout inside the existing root LinearLayout(a nested LinearLayout) and added the children inside the nested layout.Now setting margin to the inner layout gives the desired effect.
Code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:layout_marginLeft="16dp"
android:background="#drawable/list_selector"
android:orientation="vertical" >
<TextView
android:id="#+id/textview_note"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textview_note_date"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
In your header part, add the following tag:
android:layout_alignParentLeft="true"
this will solve your problem.
// Temp is the root view that was found in the xml
final View temp = createViewFromTag(root, name, attrs, false);
ViewGroup.LayoutParams params = null;
if (root != null) {
if (DEBUG) {
System.out.println("Creating params from root: " +
root);
}
// Create layout params that match root, if supplied
params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
// Set the layout params for temp if we are not
// attaching. (If we are, we use addView, below)
temp.setLayoutParams(params);
}
// We are supposed to attach all the views we found (int temp)
// to root. Do that now.
if (root != null && attachToRoot) {
root.addView(temp, params);
}
// Decide whether to return the root that was passed in or the
// top view found in xml.
if (root == null || !attachToRoot) {
result = temp;
}
...
return result;
this is the code of LayoutInflater,as you can see ,if you add a root,it's not null,generated the layoutParams from root.
and then if the thrid param is false,there is only make temp.setLayoutParams(params) which params is generated by root!! and the temp is as return....
if attachToRoot is true,root will execute root.addView(temp, params),and then the root is as return..
if you just do LayoutInflater.from(this).inflate(R.layout.popup_choose_type, null);,and if you had set some attribute as paddingBottom,it will surprised you that is will not work!!because of loss LayoutParams!
As for how to solve it,you can see
here
you can do it by give margin in listview's layout file then you will get it the output.

Force EmptyView to display?

I have a ListView that I am creating. The content is set from a separate adapter class. When the adapter returns zero items I want the empty view to display from a separate xml. This is happening inside a SherlockFragment. However for some reason I cannot get the emptyView to display.
Help Please?
Code:
RelativeLayout fragView = new RelativeLayout(getActivity());
ListView listView = new ListView(getActivity());
listView.setEmptyView(getActivity().findViewById(R.id.emptyView));//This is having no effect
scoreViewAdapter = new ScoreViewAdapter(getActivity(),
databaseHelper.getAllTimeRecords());
listView.setAdapter(scoreViewAdapter);
if (scoreViewAdapter.getCount() < 1)
listView.//can I set something here to force or change my view? From the methods available to ListView I don't see any potential solutions..
fragView.addView(listView);
Here is the xml....pretty standard.:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/emptyView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/emptyText"
android:src="#drawable/ic_android_logo" />
<TextView
android:id="#+id/emptyText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:gravity="center_vertical"
android:text="No Items Found"
android:textAppearance="?android:attr/textAppearanceLarge" />
Thanks to Faizan's feedback to lead me here. Here is the solution:
View empty_view = inflater.inflate(R.layout.empty_view, null);
...
if (scoreViewAdapter.getCount() < 1)
fragView.addView(empty_view);
fragView.addView(listView);
You have to inflate that xml using LayoutInflater and then call
listView.setEmptyView(inflated_view);
You can get get the inflater from the onCreateView overrided method anc do
View inflated_view = inflater.inflate(R.layout.my_empty_layout,null);
I hope it will resolve the problem.
I believe you extends FragmentList and not ListActivity
so you actually can use setEmptyView

service show view getLayoutInflater

I would like to show two views in a service context. One is a TextView, and the other is a class that I have developed extending the basic View class.
prompt.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mtPrompt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/background_dark"
android:text="#string/demoString"
android:textColor="#android:color/white"
android:minLines="2"
android:textSize="25dp" >
</TextView>
and input.xml:
<com.xxx.ime.sssView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/inputView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/translucent_gray"
android:cacheColorHint="#null" >
</com.xxx.ime.sssView>
in my onInitializeInterface() implementation I inflate them as follows:
sssView sv =
(sssView) getLayoutInflater().inflate(R.layout.input, null);
TextView tv =
(TextView) getLayoutInflater().inflate(R.layout.prompt, null);
I see the sssView, but not the TextView. Any ideas why?
This isn't quite an answer, but it is a solution. Rather than having two separate views, all I needed to do was inherit my sssView from TextView rather than view. Then I inflated the one view, and placed my text where I want it using gravity.

Categories

Resources