Add a LinearLayout below ListView - android

Actually it's not ListView but ExpandableListView but it doesn't really matter. Normally I'd do it this way:
<ScrollView >
<LinearLayout>
<ExpandableListView ... />
<TextView ... />
</LinearLayout>
</ScrollView>
..but I've read it's consuming to have ListView inside ScrollView. I tried solving this by modifying ExpandListAdapter (getChildView()) :
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view, ViewGroup parent) {
if(isLastChild){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.extra_info_bottom, null);
}
else{
//get normal item view
}
return view;
}
but this way I can only append childs to groups. How can I append LinearLayout on the bottom outside of any group?

Just add the following code to add the a linear layout at the last listview block.
View footerView = ((LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listfooter, null, false);
itemlist.addFooterView(footerView);
where the listfooter is the xml file where you can define your layout controlls.

Is there any reason why you want to have the listview inside the scroll?? wouldn't make sense for your layout to do something like:
<LinearLayout>
<ExpandableListView ... />
<ScrollView >
<LinearLayout>
<TextView ... />
</LinearLayout>
</ScrollView>
</LinearLayout>
With this solution you can use weights on the Expandable List and the Scrollview to define how much of the screen you want to use for the List and how much for the linear layout at the bottom.
If you want your linear layout to appear at the very bottom of the list, I would suggest you to use a footer instead of the getView thing.
Anyway, to help with the exact issue you have, I would need to look at the xml definition of what you are trying to inflate.

Try to figure out what object does cause this error and look for it's real className using myObject.getClass().getName(). So you can see what object you really inflated and maybe fix the problem.

Related

How to horizontally center composite list view items inside the list view?

I have a list view displaying items from a custom adapter which extends ArrayAdapter. Each item is a custom layout with a RelativeLayout being the root view. Now, I want this RelativeLayout to be centered horizontally inside the list view, but I everything I tried seems to fail.
Here's my custom adapter getView method:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = mInflater.inflate(R.layout.screens_listview_row, parent, false);
return row;
}
And here's the file screens_listview_row.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
.....
android:layout_gravity="center_horizontal" >
</RelativeLayout>
At first, it seemed like my layout parameters in the RelativeLayout were completely ignored, and it really was the case because i used inflate(R.layout.screens_listview_row, null), what is a problem like this answer says.
So now the only thing ignored is the layout_gravity parameter. I also tried layout_marginLeft (Everything in this layout is in absolute sizes so I could center it myself by giving a left margin...) but Android ignored it too. What is the problem here?
try to use gravity instead of layout_gravity (as i know gravity is for the content of layout)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
.....
android:gravity="center_horizontal" >
</RelativeLayout>
I didn't find out how to control the position of the items inside the ListView, so instead I made the ListView width exactly as the items' width, then controlled its position (Which practically controls the items' position).

drawing on top of a listview

I am trying to make a listview appear to fade to black towards the top of it. Essentially I want to turn something like this:
in to something like this:
I tried two different approaches to this:
The first one was to override the onDraw() of the ListView, this did not work, my "extra" drawing happened behind the listView. The second approach was to put another view on top of the listView, this looks right, but if the user tries to scroll the list by touching the screen where the view is it does not scroll, it seems like the view consumes the touchevent, so about a third of the list is untouchable.
Any tips on how I can implement this?
You can assign the listitem background in a customised view. In getview (of adapter class) based on the item position. Create a gradient in xml and increase the alpha value based on the position.
This is the peice of code which is working for me.
listItem.xml
<?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:gravity="center_vertical"
android:minHeight="64dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="17sp"
android:textColor="#android:color/white"
android:id="#+id/textView"/>
</RelativeLayout>
ItemAdapter.java
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(rowResourceId, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.textView);
int id = Integer.parseInt(Ids[position]);
textView.setText(Model.GetbyId(id).name);
// this is the main idea behind the UX look n feel.
rowView.setBackgroundColor(context.getResources().getColor(android.R.color.black));
textView.setAlpha((float) position/Ids.length);
return rowView;
}
Please feel free to use holder design pattern in the getView. This is just a proof of concept.

How to put divider at particular position in an Android list view

I need to make a list view in which I want to have a divider at some position only not after every list item. I am using custom list view.
Is there any solution of this problem?
you can you this xml file in list adapter class like
ItemsAdapter ItemsAdapter = new ItemsAdapter(EnterpriseFertilisersScreen.this,
R.layout.list, Constant.FERTILIZERMANAGERARRAY);
R.layout."below xml file " and user as further white color.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:background="#color/list_bg" >
<TextView
android:id="#+id/post"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="7dp"
android:layout_toRightOf="#+id/bite_image"
android:gravity="center_vertical"
android:textColor="#android:color/white"
android:textSize="20sp" />
</RelativeLayout>
If you have another issues, ask feel free..
You can create Adapter for list, which will be place dividers as elements (via getView).
This is standart android approach
If you have used Custom ListView to show your .you need to make position where you need to show different View from xml by condition .you should have to do this in getView Method.
Either you need to see how this example use divider using CursorAdapter.
Check this https://github.com/cyrilmottier/ListViewTipsAndTricks/blob/master/src/com/cyrilmottier/android/listviewtipsandtricks/SectionedListActivity.java
you can add it to getview Methoid as follow :
public View getView(int position, View convertView, ViewGroup parent) {
if(items.get(position).get("name").startsWith("-")){
View divider = mInflater.inflate(R.layout."yourlayout",null);
return divider; }
also, you must add item names starting with "-" where you want to add a divider.
Hope this helpful

Android layout placeholder for dynamically added view

In my Android Activity, I need to add a single View dynamically (at runtime), at a specific position in a layout. The view to be added is determined at runtime. For example, may layout may look something like this:
<LinearLayout ...>
<TextView ... />
<!-- Dynamic item to be added here -->
<TextView ... />
</LinearLayout>
What is the best way to achieve this?
One solution is to use layout.addView(view, index), but I'd prefer not to hardcode the index.
Another solution is to use a FrameLayout as a placeholder, and place may dynamic view inside the FrameLayout, for example:
<LinearLayout ...>
<TextView ... />
<FrameLayout android:id="#+id/placeholder" />
<TextView ... />
</LinearLayout>
Then:
findViewById(R.id.placeholder).addView(view);
However, this adds an unnecessary view in the hierarchy.
What would be the recommended way to do this?
I think that using a FrameLayout as a placeholder for your view "added at runtime" is a good solution.
I would not worry about the impact of the extra "unnecesssary" view on performance.
You can also achieve this "lazy include" behaviour by using a ViewStub, as described in this (rather old) article from Android Developers.
You can use addView(View child, int index) without hard coding the exact index.
If one of the view's neighbors can be fixed (for example there is a specific label just before the place you want to insert the item), you can get the index of that view, and insert your dynamic view after that:
View previousView = findViewById(ID_OF_PREVIOUS_VIEW);
ViewGroup parent = (ViewGroup)previousView.getParent();
int previousIndex = parent.indexOfChild(previousView);
parent.addView(theDynamicallyCreatedView, previousIndex + 1);
Or you can use a ViewStub, but instead of inflating a layout, just remove it:
View placeholder = findViewById(ID_OF_STUB);
ViewGroup parent = (ViewGroup)previousView.getParent();
int index = parent.indexOfChild (placeholder);
parent.removeViewAt(index);
parent.addView(theDynamicallyCreatedView, index);
This way you won't end up with a huge view hierarchy.

Can a GridView have a footer and header just like ListView?

A quick question:
In ListView I use this code:
list.addHeaderView(headerView);
How to deal with it when working on gridview?
Thanks.
There is no support for header or footer views with GridView, sorry.
There is a quite good implementation of GridView with header support in Google Photos application, as it's OSS code you can use it as is or take it as a reference for your own implementation:
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/4.3_r2.1/com/android/photos/views/HeaderGridView.java
Basic idea is quite simple - WrapperAdapter creates an fake row by increasing number of items by number of columns and then return a header view for the item.
You can use this. The footer appears/hides at the bottom of the grid when you reach/leave the last number of items. It does not actually scroll, but I hardly notice the difference.
In your activity/fragment's onCreate/onCreateView you add an OnScrollListener to the GridView:
....
GridView gridview = (YMAnimatedGridview) v.findViewById(R.id.my_gridview);
gridview.setAdapter(adapter);
final View footerView = mainView
.findViewById(R.id.my_grid_footer_view);
gridview.setOnScrollListener(new GridView.OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (firstVisibleItem + visibleItemCount == totalItemCount) {
// last item in grid is on the screen, show footer:
footerView.setVisibility(View.VISIBLE);
} else if (footerView.getVisibility() != View.GONE) {
// last item in grid not on the screen, hide footer:
footerView.setVisibility(View.GONE);
}
}
#Override
public void onScrollStateChanged(AbsListView view,
int scrollState) {
}
});
Your layout should look something like the below. Notice the layout_weight (and layout_height) parameter in the gridview, it is needed to make the correct space for the footer when it becomes visible.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<GridView
android:id="#+id/my_gridview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:columnWidth="160dp"
android:gravity="center_horizontal"
android:horizontalSpacing="12dp"
android:numColumns="auto_fit"
android:layout_weight="1"
android:stretchMode="columnWidth"
android:verticalSpacing="6dp" />
<TextView
android:id="#+id/my_grid_footer_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:layout_marginBottom="8dp"
android:orientation="horizontal"
android:visibility="gone"
android:text="footer text here" >
</TextView>
</LinearLayout>
Sample code:
GridViewWithHeaderAndFooter gridView = (GridViewWithHeaderAndFooter) v.findViewById(R.id.ly_image_list_grid);
LayoutInflater layoutInflater = LayoutInflater.from(this);
View headerView = layoutInflater.inflate(R.layout.test_header_view, null);
View footerView = layoutInflater.inflate(R.layout.test_footer_view, null);
gridView.addHeaderView(headerView);
gridView.addFooterView(footerView);
Gradle build:
.
compile 'in.srain.cube:grid-view-with-header-footer:1.0.12'
You'd have to use a ListView, then make each row of the list look like it's actually a row of a grid. So if you have a 3 column grid, you'd make a layout for the ListView that looks like 3 columns. You'd then have to modify certain aspects of the Adapter to make it work so that each ListView row actually represents 3 lines of data -- so you know, getCount()/3 type stuff.
How about checking for the "0" index element in your adapter? You can inflate the custom view for the first one.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if(view==null){
if(position==0){
// ...inflate header view
}else{
// ...do as usual
Haven't tested it, but should work.
You can use AsymmetricGridView and specify headers/footers with a bigger rowSpan so they would take the entire row.
Why don't you change the appearance of the cells for the first rows? if you know how many columns you have, you know how many items will appear in the header = number of columns.It works for me
You could use this library, http://tonicartos.github.io/StickyGridHeaders/
which allows you to create headers that are sticky (for grouping the list and keeping the header visible for the current group). You can turn off the sticky feature as well.
There is a way to accomplish the desired functionality WITHOUT using a library or anything.
EDIT: Just borrow the HeaderGridView Implementation by google, see Here
You could also customize it for footer. The below suggestion is just too complicated and required more tweaking.
Without going into specific details, all you need to do is this.
1) Subclass GridView
2) override onScrollChanged
3) Calculate the offset everytime it scrolls
4) Set the parentView(view that contains the headerView and gridview) translation y to -Offset.(view.setTranslationY(-offset). Also have an if statement to that once it reaches a certain offset it would stop scrolling.
5) obviously you want to structure this well so your gridview can have a method like attachToGridview(View view). I have a complete implementation of this which works.
See Scroll offset of GridView for help on getting offset since GridView has a bug were the views get recycled.
<?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">
<com.test.Breadcrumbs android:layout_width="fill_parent" android:layout_height="100dp" />
<GridView
android:id="#+id/grid"
android:numColumns="auto_fit"
android:gravity="center"
android:stretchMode="columnWidth"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp">
</GridView>
</LinearLayout>
and Breadcrumbs:
public class Breadcrumbs extends LinearLayout {
public Breadcrumbs(final Context context, final AttributeSet attrs) {
super(context, attrs);
final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutView = inflater.inflate(R.layout.breadcrumbs, this, true);
works fine, scroll for grid works as well.

Categories

Resources