I'm working with a ListView that is part of an ListFragment. I want to add a header with a specific/custom height but it does not matter what I put in the height of the header view, always it has the same height. Is possible to modify the header view height of a ListView?
Below the code I use:
header.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp" />
ListFragment
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView fakeHeader = (TextView)getActivity().getLayoutInflater().inflate(R.layout.header, null);
getListView().addHeaderView(fakeHeader);
}
When you pass in null as the second parameter to inflate(), you are saying there is no parent associated with the view. This has the unfortunate side effect where any layout_ attribute you use is ignored as layout_ parameters affect how the parent lays out the child view rather than directly affect the child (like other views): this pro-tip godes into more details on layout_ attributes.
You can use inflate(R.layout.header, getListView(), false) to pass in the ListView which will eventually the parent of your header view (note the false says to not add the view directly - ListView will do this automatically for you).
Related
I have a simple linear layout which I'm inflating in an adapter:
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.category_listview_row, parent, false);
} else {
((LinearLayout)convertView).removeAllViews();
}
if (LAYOUT_TYPES.GRID.equals(layoutType)) {
convertView = CategoryFragment.getViewForGridLayout(context, displayArray, position, convertView, listener);
} else {
convertView = CategoryFragment.getViewForListLayout(context, displayArray, position, convertView, listener);
}
return convertView;
}
Here, category_listview_row is the following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
The getViewForGridLayout method programmatically creates one or more views and adds them to convertView.
I would like all the child views to match this parent view in height, however I can't get this to work. This is the outer linear layout of the child views that are added programmatically:
<?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:id="#+id/base_listview_style_one_layout"
android:orientation="horizontal"
android:padding="#dimen/node_default_spacing"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="#5ab9c6">
This layout has subviews which are removed according to the actual data to be displayed, so some will be longer than others. However I want them all to be the height of the parent so it doesn't look weird.
This is a screenshot of what I'm seeing:
The first row is ok since both items have a title and a subtext
On the second row, the second item doesn't have a subtext so that view is smaller. However, I'd like it to take the full height of the row so all items in a single row will have the same height.
Any tips? Thanks!
I would advise using a Recyclerview with GridLayoutManager.
If you want certain items spanning multiple columns, you can do so by setting SpanSizeLookup on the GridLayoutManager.
Here is a simple example https://stackoverflow.com/a/26907508/4498224.
Propably your layout params are ignored. Be sure that you are adding child views to your convertView like this:
View view = inflater.inflate( R.layout.item /* resource id */,
convertView /* parent */,
true /*attachToRoot, you dont need to call addView then*/);
Instead of removing the textview, why not just make it invisible or set its color to white to it occupies the space?
Please change your linearlayout height from wrap content to "match_parent".
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content" />`
Set the height of parent layout to wrap_content.
Set the height of child view to match-parent.
Try this i hope it will resolve your issue.
#zundi you can use view holder design pattern with recycler view adapter and define which row needs to have two images and which one needs to have one. Its pretty much simpler than doing it with linear layout.
Recycleview show different view types has a pretty decent explanation on how to do this.
And also to answer you question of making
some rows with 2 items and other rows with 1 item
you can use setSpanSizeLookup (GridLayoutManager.SpanSizeLookup spanSizeLookup) method of GridLayoutManager and define it in the activity.
RecycleView's span size gives you more info on how to achieve that.
mLayoutManager.setSpanSizeLookUp(new GridLayoutManager.SpanSizeLookUp() {
#Override
public int getSpanSize(int position) {
if(position == 0)
return 2; //here the view takes up two spaces in a row(header)
else return 1; //here view takes 1 space i.e., 2 views in a total row
} });
In the above example my grid layout manager takes 2 view holders based on different positions and decides if its header or not and populates the data.
Other Solution:
Rather than giving match parent and wrap parent inside your layout give a fixed 'dp' for height. That should make the views look consistent.
#zundi if doing it right way with RecyclerView and LayoutManager which would simplify you life dramatically but have a bit of learning curve doesn't suits you, here is an option that hasn't been mentioned yet:
You can define android:lines=x on TextView which contains subtext.
Just match_parent is not going to work for you because you want LinearLayout to wrap height of its children and its children to match_parent which is a circular dependency
This method can be performed on both Linear Layout or TextView you are using
You have set
android:layout_height="match_parent"
but not the height, so it is simple case
android:layout_height="match_parent"
So, in case even if there will be no value in the string it will still contain the height allotted to it
I've a simple task - add child views to a LinearLayout dynamically, but I don't know, how to do it in a proper way.
There are two ways:
1. Inflate view and passed parent container to the inflate method.
View view = LayoutInflater.from(getActivity()).inflate(R.layout.item, container, true);
At this case, when I've more than one child, LayoutInfater returns the same child view object every time, when inflate it. So I can proper initialized other child views.
2. The next way is to use LinearLayout method addView(View view).
The problem is, that the child view lose it's LayoutParams state.
And I must set new LayoutParams for child programmatically. It's a not good practice.
Also we can put child in the complimentary wrapper layout in his own layout resource file. But it's also a not good practice put layout to the wrapper.
My child resource:
<RelativeLayout android:gravity="center_vertical"
android:paddingLeft="25dp"
android:layout_width="match_parent"
android:layout_height="#dimen/list_item_height">
<TextView android:id="#+id/tv_name"
android:text="Name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
So what is the proper way to add child to LinearLayout, without adding LayoutParams programmatically and without wrapper layout?
Thank's a lot for help!
Did you try this way?
View view= LayoutInflater.from(getActivity()).inflate(R.layout.item, null, false);
parentView.addView(view);
if you want to add child to a RelativeLayout,you need to set LayoutParams for child view ,and if you want to add child to a LinerLayout,you don't need to set LayoutParams,so if you want to custom layoutParams,i suggest you to use RelativeLayout,or you can make a wrapper view for child View ,just like:
//inflate a wrapper view
View child = LayoutInflater.from(getActivity()).inflate(R.layout.item, container, false);
//add to a linerLayout
LinerLayout.addChild(child)
Try this way,
View view = LayoutInflater.from(getActivity()).inflate(R.layout.item, **container**, false);
layout.addView(view);
I'm trying to set the ExpandableListView item (ViewGroup) height. Can it be set via xml (I don't need the divider height):
<ExpandableListView
android:id="#+id/lvExp"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
or it should be used this method, by manipulating the convertView:
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) { ... }
Thanks in advance.
ListView child views can be different heights, so we don't set a one-size-fits all height in the ListView's xml. Rather you can set a specific height in each of the different convertView xml's that you are inflating.
Are you trying to set the height of the group row item in the listview? Also the ViewGroup would be your ExpandableListView and all of its groups and group children row items.
Or are you asking to set the height of the child items in the expandable list view?
The group item and its children in the listview are the same as any other listview row item.
You can just simply provide fixed height in row layout XML:
android:layout_height="25dp"
Or you could use ViewGroup.LayoutParams
http://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html
Question is a bit old, but someone may be useful. As others said, height is not strict value (it changes according to its content). If you want to generally make more space between items (whether it is group or child), you can set padding to corresponding layouts.
This can be done either in XML layout or programmatically in list adapter.
I want to create a ListView (same question is relevant for a GridView) where the items have very specific LayoutParams. Take this example where I want each row to be a LinearLayout with a height of 100dp:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="100dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/pd_textview"
android:gravity="center_vertical"/>
</LinearLayout>
When I use this XML layout with a standard BaseAdapter implementation of getView() that inflates the views none of the LayoutParams for my LinearLayout get applied (each row simply wraps around the size of the text in the TextView):
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Inflate view if necessary
if (convertView == null) {
convertView = ((Activity) mContext).getLayoutInflater().inflate(ID_LAYOUT, null, false);
}
// Return the view
return convertView;
}
Fishing around in the appropriate section of the Android documentation, it says the following about getView() which explains the current behaviour:
Get a View that displays the data at the specified position in the
data set. You can either create a View manually or inflate it from an
XML layout file. When the View is inflated, the parent View (GridView,
ListView...) will apply default layout parameters unless you use
inflate(int, android.view.ViewGroup, boolean) to specify a root view
and to prevent attachment to the root.
My question is simply, how should I actually be doing this? The suggestion of using a root view with the desired LayoutParams seems convoluted given that the LayoutParams I want to inflate the view with are in the view that I'm trying to inflate (yes I could inflate a static view and leave it as a member of the class to reference against... but that seems silly). The other option would be to only define the contents of the row item in XML and manually create the container and its LayoutParams every time?
Is there a 'correct' way (i.e. not a wasteful hack) that I'm missing to simply create items with the LayoutParams defined in the XML?
I'd have preferred to put this in a comment, but I don't have the 50 reputation needed to do that...
There is detailed explanation of the issue here:
http://www.doubleencore.com/2013/05/layout-inflation-as-intended/
The main point is this:
"The problem with this is android:layout_xxx attributes are always be evaluated in the context of the parent view. As a result, without any known parent, all LayoutParams you declared on the root element of your XML tree will just get thrown away [,...]"
So, indeed, the solution is:
convertView = ((Activity) mContext).getLayoutInflater().inflate(ID_LAYOUT, parent, false);
I have a small project where I want to reuse a certain UI component a few time so I created a widget by expanding a ViewGroup. In that ViewGroup I inflated a view that contained a TextView inside a LinearLayout and added that inflated view to the ViewGroup trough addView.
The outer LinearLayout expands itself perfectly but the inner TextView have getHeight() = 0 and getWith() = 0 when I view it through Hierarchy Viewer. The strange thing is that layout_height and layout_width is the values I gave them in my xml.
I don't have the code here but it looked something like this:
xml:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="random text.."
android:layout_with="200px"
android:layout_height="50px" />
</LinearLayout>
Java:
class MyWidget extends ViewGroup {
...
//In constructor
myView = View.inflate(context, R.layout.xml, null);
addView(myView);
//In layout
myView.layout(l, t, r, b);
I have tried to give my text view fill_parent values for size but it didn't help.
Remember:getHeight() and getWidth()return 0 if components are not drawn yet.
To find the width And height of a View before it being drawn:
First call measure
view.measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED)
Now you can get width using getMeasuredWidth and height using getMeasuredHeight
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
I have posted some more ideas here: How to get width/height of a View
1) Here is some links to use Hierarchy Viewer on your dev phone.
http://developer.android.com/guide/developing/debugging/debugging-ui.html
and the class you'll need:
http://github.com/romainguy/ViewServer
2) You can also reuse layout like a component with the include tag:
<include android:id="#+id/your_id" layout="#layout/layout_name" />
So, I put a bounty on this one, and here is what I've found.
Inflating with a null reference is A Bad Idea(TM). Essentially, that View won't get the proper layout parameters it needs (its parent sets a whole bunch of them, with a whole bunch of magic/logic involved). So inflating into null means no parents, and no inherited layout parameters. One can manually set a number of these parameters, but due to the magic involved it might not solve your problem.
The "solution(s)" that I've come up with involve; using include (when you know how many you need) and pulling them into code, or inflating to a parent (when you need true dynamic, N things). And of course, the XML you inflate will have ID collisions, so I go about it by grabbing the last child (e.g. getChildAt(getChildCount()-1) ) of whatever I'm looking for, etc.
Did you try passing yourself as the root:
View.inflate(context, R.layout.xml, this);
Since you will be the parent of this View that complies with the javadoc spec.