I am writing an app with a ListActivity with a footer whose contents are pretty dynamic based on certain situations. I wanted to use setFooterView like this:
Button addButton = new Button(this);
addButton.setText("Add");
addButton.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, 35));
lv.addFooterView(addButton, null, true);
But it causes a Runtime exception. While using a layoutInflater may work with an XML layout (I use that for the header), how do I add a footer with programmatically constructed views?
View footerview;
footerview = getLayoutInflater().inflate(R.layout.listfooter, null);
Listview = (ListView)findViewById(R.id.listview);
Listview.setAdapter(adp);
......
....
Listview.addFooterView(footerview);
I think this might be useful .
Related
As a little eperiment, I'm trying to do the following.
I have an AXML describing a vertical linear layout which contains a listview (only filling 200dp of the vertical linear layout ). The AXML is inflated when the activity starts with SetContentView. Then the listview is correctly populated with values using its Adapter.
In the GetView method of the listview Adapter, I am trying to also dynamically create a button and add it to the linear layout, but for some reason the button is not added.
If I try to add the button in the constructor method of the Adapter instead, it is correctly added.
Can you tell me what could be possibly going wrong?
Let me add some code:
class TracksAdapter : BaseAdapter<string> {
Activity context;
List<Dictionary<string,string>> trackList;
// constructor
public TracksAdapter (Activity context, List<Dictionary<string,string>> trackList) {
this.context = context;
this.trackList = trackList;
// Just as a little test, if I create the button from here it will be correctly added to linear layout:
var ll = context.FindViewById<LinearLayout>(Resource.Id.linLayForResultsActivity);
Button b1 = new Button(context);
b1.Text = "Btn";
ll.AddView(b1);
}
public override View GetView(int position, View oldView, ViewGroup parent) {
// if I create the button from here it will not be added to the layout
var ll = context.FindViewById<LinearLayout>(Resource.Id.linLayForResultsActivity);
Button b1 = new Button(context);
b1.Text = "Btn";
ll.AddView(b1);
// this other code is working
View view = context.LayoutInflater.Inflate(Resource.Layout.ResultItem, null);
var artistLabel = view.FindViewById<TextView>(Resource.Id.resultArtistNameTextView);
artistLabel.Text = trackList[position]["trackArtistName"];
return view;
}
}
Update: adding some more context information because I know this can be a bit weird to understand without it:
In GetView, I don't need to return the new button I am trying to create there. GetView only need to return a listview view item, but, along its execution, GetView also has to create and add a button to the linear layout containing the listview.
The real code is much more complex than that. I have simplified it in the question. In the real code, the listview items are made of text and a button. The GetView also attaches event handlers to the buttons. Then what I need is, when a user clicks a button in any of the listview items, another button is added below the listview. So I need the code for adding another button to be in GetView, and the button needs to be added outside of the listview, ie. to the linear layout containing the listview.
Use the LayoutInflator to create a view based on your layout template, and then inject it into the view where you need it.
LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = vi.inflate(R.layout.your_layout, null);
// fill in any details dynamically here
TextView textView = (TextView) v.findViewById(R.id.a_text_view);
textView.setText("your text");
// insert into main view
ViewGroup insertPoint = (ViewGroup) findViewById(R.id.insert_point);
insertPoint.addView(v, 0, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
I looked in you code, you are returning view, while you add the button to ll, you should return ll
what you return in getView() is what you see in the list item layout, since you're adding the button to ll and returning view, the button won't appear.
you can add the button to view as you implementation
Also check this:
Try using boolean addViewInLayout (View child, int index, ViewGroup.LayoutParams params)
http://developer.android.com/reference/android/view/ViewGroup.html#addViewInLayout(android.view.View, int, android.view.ViewGroup.LayoutParams)
It's working... Without making any changes now it's working as it should... ! Ugh!
I really don't know what I was doing wrong here... probably it was because of some sort of caching of older version of the installed APK.. ? I know this sort of stuff can happen, and that's why I've always been uninstalling the app before deplyoing the new version to the device... but still...!
i am progrmatically adding list view to a linear layout like this:
ArrayList<Answer> ans = (ArrayList<Answer>) ques.getAnswers();
adapter = new AnswerAdapter(Test.this, ans);
ansList = new ListView(Test.this); // my list view adding dynamically
ansList.setAdapter(adapter);
ansList.setVerticalScrollBarEnabled(false);
ansList.setOnItemClickListener(cellClickListener);
ansLayout.addView(ansList);
Now the problem is it has the default divider after each item except the last item, i want the divider to be visible after the last item also.
I have looked into many questions in SO where they are adding views in the layout but i need to add programatically.
You can add footer view in listview... so make a layout of footerview... and bind as below
View footerView = ((LayoutInflater)getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.track_footer_view, null, false);
listview.addFooterView(footerView);
so you can have footerview at end of last item..
- Add that separator as the footer to your ListView.
Eg:
View mfooter = View.inflate(MyClass.this, R.layout.imagelayout, null);
lv.addFooterView(mfooter, null, false);
I am currently populating an Adapter on startup with views inflated from XML using
private void addView(Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.deal_tile, this, null);
mViews.add(view);
}
However, I've found that storing the views in a list inside the AdapterView creates problems with controls within those views, so I want to change over to use the recycling functions in Adapter#getView(int position, View recycle, ViewGroup container).
For this reason I want to use a custom view class so I can do a sanity check (if(recycle!=null && recycle instanceof CustomView)) before I repopulate it in the adapter. However, I can't find out how you inflate a custom view class from XML. I can find out how you add an inflated view to a custom view, I can find out how you insert a custom view into an XML layout, etc, and obviously I am quite happily inflating these things directly using LayoutInflater, but I can't find an equivalent for generating the custom view itself. I want to reuse the XML I already have; consequently I don't want to program in the elements (and how they look) directly.
I used this to create my own slide gallery, i think it would help.
LinearLayout internalWrapper = new LinearLayout(getContext());
internalWrapper.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
internalWrapper.setOrientation(LinearLayout.HORIZONTAL);
addView(internalWrapper);
this.mItems = items;
LinearLayout generalLayout = new LinearLayout(this.getContext());
generalLayout = (LinearLayout) View.inflate(this.getContext(), R.layout.galleryrow, null);
// inside linear layout
LinearLayout generalLinear = (LinearLayout) generalLayout.findViewById(R.id.rowgenerallin);
// set height & width to the LINEAR
generalLinear.setLayoutParams(new LayoutParams(reference_width, reference_height));
ImageView ivl = (ImageView) generalLayout.findViewById(R.id.arrow_left);
ImageView ivr = (ImageView) generalLayout.findViewById(R.id.arrow_right);
internalWrapper.addView(generalLayout);
In my case, R.layout.gallery_row contains the two images I want to manage, nested by a LinearLayous (rowgenerllin), the internal wrapper is an empty LinearLayout declared in the main layout of your activity.
Double check the LayoutParams code or you will get a big NULL :)
Cheers!
Hi,
I want to place two imagebuttons between listview and footer tabbar. If listview contains 10items then the buttons appear at last of the listview after displaying 10items in listview.
Please help.
thanks in advance.
I think ListView.addFooterView() is what you're looking for.
http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)
use this
View view mInflater.inflate(R.layout.list_load_more_row, null);
Button footer = (Button) view.findViewById(R.id.loadMore);
getListView().addFooterView(footer);
setListAdapter(ListViewHelper.getAdapterForContentList(mContent, this));
u can add header also in ur listview
Add FooterView in list view:
LayoutInflater inflater = activity.getLayoutInflater();
LinearLayout listFooterView = (LinearLayout)inflater.inflate(
R.layout.footer_layout, null);
list.addFooterView(listFooterView);
I have an app that queries a database and get a recordset, on the display, I need to present these data with a row that is a complex layout. Each row contains some ImageView, many TextView etc...
It's really difficult to create the row layout programmatically, is there any way to get the entire row layout (container and children of the row layout) from an xml, edit some of the properties (like the TextViews of the row layout) and add the result to a LinearLayout?
is there any way to get the entire row layout (container and childs of the row layout) from an xml
What you are looking for is how to inflate a view (LayoutInflator)
Now that you have the right term, it should be easy to find examples, inflate is popular in ListView tutorials. For an example, take a look at at getView() in this tutorial for an example:
HowTo: ListView, Adapter, getView and different list items’ layouts in one ListView
http://android.amberfog.com/?p=296
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
...
convertView = mInflater.inflate(R.layout.item1, null);
... edit some of the properties (like the TextViews of the row layout) ...
Once you inflate the view, you can search for the widgets within it, so you can manipulate it.
holder.textView = (TextView) convertView.findViewById(R.id.text);
If your view is fairly complex and/or you will often be looking for widgets within it, I want to point out the ViewHolder technique, shown in the example referenced, relevant bits below:
// Data structure to save lookups
public static class ViewHolder {
public TextView textView;
}
...
// Save lookups to widgets for this view in ViewHolder in tag
ViewHolder holder = new ViewHolder();
holder.textView = (TextView) convertView.findViewById(R.id.text);
view.setTag(holder);
...
// Grab saved widgets - no need to search tree for them via lookup again
ViewHolder holder = (ViewHolder) convertView.getTag();
holder.textView.setText(mData.get(position));
... and add the result to a LinearLayout?
Presumably, you're already programatically adding to the LinearLayout, but if you want to see some code, here's an example that shows setting some layout parameters:
Android LinearLayout
http://developerlife.com/tutorials/?p=312
// main "enclosing" linearlayout container - mainPanel
final LinearLayout mainPanel = new LinearLayout(ctx);
{
mainPanel.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
mainPanel.setOrientation(LinearLayout.VERTICAL);
...
}
...
// top panel
LinearLayout topPanel = new LinearLayout(ctx);
{
// WEIGHT = 1f, GRAVITY = center
topPanel.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT,
1));
...
}
...
// bottom panel
LinearLayout bottomPanel = new LinearLayout(ctx);
{
LayoutUtils.Layout.WidthFill_HeightWrap.applyLinearLayoutParams(bottomPanel);
...
}
...
// add the panels
mainPanel.addView(topPanel);
mainPanel.addView(bottomPanel);
...
Lastly, you can do alot (including custom rows) with the AdapterView / Adapter paradigm, e.g. using ListView with a SimpleCursorAdapter. It may save you some code by looking into it. Some babbling about it here:
Android ListView with different layouts for each row
As a rule of thumb, whenever you create an instance of View using code, think twice.
Review LayoutInflater on how to create layout from resources. In your special case, you might also want to check ResourceCursorAdapter if you want to show multiple rows in a ListView.
What kind of table are you using? If your layout would be something like this:
<TableLayout>
<LinearLayout android:id="#+id/linearLayoutTest">
<TextView/>
<TextView ....
<ImageView ....
</LinearLayout>
<LinearLayout ....
</TableLayout>
It would be easy to access the row container through the id and then find by position the desirable child:
LinearLayout linearLayout = (LinearLayout)this.findViewById(R.id.linearLayoutTest);
TextView textView = (TextView)linearLayout.getChildAt(0);
textView.setText("New Text");