How to add a Footer to a listView with Adapter ?
<?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="fill_parent>
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
I've try this :
public class message extends ListActivity {
List<SMSData2> smsList2 = new ArrayList<SMSData2>();
private Context context = null;
private ListView list = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
list = (ListView)findViewById(android.R.id.list);
//code to set adapter to populate
for (int i=0;; i < 10; i++) {
SMSData2 sms2 = new
sms2.setBody(c.getString("some text");
smsList2.add(sms2);
setListAdapter(new ListAdapter2(this, smsList2));
}
View footerView = ((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer, null, false);
list.addFooterView(footerView);
}
}
but it returns java.lang.NullPointerException !
possible issues :
bug with the inflater !
Bug with the context !
thanks !
Call the method
addFooterView (View v)
and pass the view you want to add to the listview.
The listview is already having this method.
Have a look on the docs.
simplest solutin is to define a linear layout that has 2 items first is your list view and the second is the footer.
if however you still insist on using a footer by the footer method you do so from activity code:
//after code to set adapter to populate list
View footerView = ((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_layout, null, false);
list.addFooterView(footerView);
Related
I got a android app with java version(not flutter and not kotlin).
There is a AlertDialog,normally with title(setTitle) and listview(setItems).
Now I would add a editable textbox between title and listview
(Or let the title become the textbox).
How can I do??
Thx for help~
Here is your answer, custom layout for dialog
https://developer.android.com/guide/topics/ui/dialogs#CustomLayout
If you want an editable textbox between title and list view , then you need to create custom layout. Here is full code and its working fine as shown in image.
public class DialogActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dialog);
String names[] ={"A","B","C","D"};
AlertDialog.Builder alertDialog = new AlertDialog.Builder(DialogActivity.this);
LayoutInflater inflater = getLayoutInflater();
View convertView = (View) inflater.inflate(R.layout.list_item, null);
alertDialog.setView(convertView);
alertDialog.setTitle("List");
ListView lv = (ListView) convertView.findViewById(R.id.lv);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_list_item_1,names);
lv.setAdapter(adapter);
alertDialog.show();
}}
Here is custom list_item layout
<?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="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Edit Text Here"
android:id="#+id/edit_text"/>
<ListView
android:id="#+id/lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/edit_text"/>
</RelativeLayout>
I have a ListFragment that might have no items in the listview. I've added the empty view in the xml:
<TextView
android:id="#+id/empty"
android:text="#string/empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"/>
Usually, when using a ListActivity, one would do:
#Override
public void onContentChanged() {
super.onContentChanged();
View empty = findViewById(R.id.empty);
ListView list = (ListView) findViewById(R.id.list);
list.setEmptyView(empty);
}
This will hide/show the empty view depending if the listview has items or not.
What is the equivalent of a ListActivity.onContentChanged for a ListFragment?
This does the trick, without the need to override methods or create observers:
final View emptyView = view.findViewById(R.id.empty);
getListView().setEmptyView(emptyView);
I need to create a custom ListPreference dialog so that I can add some header text (a TextView) above the List (ListView).
I've created MyListPreference class that extends ListPreference and overrides onCreateDialogView():
#Override
protected View onCreateDialogView() {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = (View) inflater.inflate(R.layout.dialog_preference_list, null);
return v;
}
My XML layout dialog_preference_list.xml contains:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<ListView
android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawSelectorOnTop="false"
android:scrollbarAlwaysDrawVerticalTrack="true" />
</LinearLayout>
Problem: The TextView is displayed below the ListView instead of above. I need the TextView to be above. I've tried both with LinearLayout and RelativeLayout (using "below" or "above" attributes) with no success: I can't find a way to put the TextView above the ListView... The layout is pretty simple and I cannot see why the list stays above...
Also, note that the problem occurs on both a real device (Nexus 4, Android 4.2.2) and the emulator. However, when looking at the layout rendered in Eclipse's graphical layout, the layout is correct! See both attached pictures.
Any idea on how to solve this?
Layout rendered on the device (incorrect):
Layout rendered on Eclipse (correct):
Edit with solution 10.07.2013
As suggested by the accepted answer, the problem comes from the use of builder.setSingleChoiceItems() in ListPreference's onPrepareDialogBuilder().
I've fixed it by extending ListPreference and overriding onCreateDialogView() to build the Dialog without the builder so that I can create a custom View showing the header text above the list items.
GPListPreference.java:
public class GPListPreference extends ListPreference {
...
#Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
builder.setNegativeButton(null, null);
builder.setPositiveButton(null, null);
}
private int getValueIndex() {
return findIndexOfValue(getValue());
}
#Override
protected View onCreateDialogView() {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ListView lv = (ListView) inflater.inflate(R.layout.dialog_preference_list, null);
TextView header = (TextView) inflater.inflate(R.layout.dialog_preference_list_header, null);
header.setText(getDialogMessage()); // you should set the header text as android:dialogMessage in the preference XML
lv.addHeaderView(header);
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(getContext(), R.layout.dialog_preference_list_singlechoice, getEntries());
lv.setAdapter(adapter);
lv.setClickable(true);
lv.setEnabled(true);
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lv.setItemChecked(getValueIndex() + 1, true);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
setValueIndex(position - 1);
getDialog().dismiss();
}
});
return lv;
}
}
dialog_preference_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawSelectorOnTop="false"
android:scrollbarAlwaysDrawVerticalTrack="true" />
dialog_preference_list_singlechoice.xml
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorSingle"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingBottom="2dip"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:paddingTop="2dip"
android:textAppearance="?android:attr/textAppearanceMedium" />
dialog_preference_list_header.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dip"
android:textAppearance="?android:attr/textAppearanceSmall">
</TextView>
I think the problem is with the way ListPreference works. ListPreference uses Builder.setSingleChoiceItems() to create the rows with the RadioButtons, and it has preference over the custom layout you are trying to add (in your case a TextView and a ListView inside a LinearLayout. The solution is extending DialogPreference instead. Here is a link to a GitHub where I created a custom DialogPreference that does what you need. I haven't coded the RadioButton logic.
I guess it's a theming issue. Try changing the theme of your dialog inside the constructor make it something like setStyle(STYLE_NO_TITLE, R.style.AppTheme). Your base app theme with no_title style.
If this is not the issue than it might be related with the ListPreference class itself. It might be overriding your layout for consistency in theming the preference views. However, I have not used ListPreference before, so its just a guess.
Can you reproduce the same result by playing with the themes in XML graphical layout preview?
Another option you can try is to add the TextView as a header to the ListView like this:
TextView textView = new TextView(getActivity());
ListView listView = new ListView(getActivity());
listView.addHeaderView(textView);
The addHeaderView takes a View so you theoretically have anything you want to be the header, but I have only used a TextView.
The link above is broken. On this solution the idea is overriding the ListPreference, and inflating your own listview, with the data defined on the ListPreference.
#Override
protected View onCreateDialogView() {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ListView lv = new ListView(getContext());
// Inflate the view into the header only if a message was set
if (getDialogMessage() != null && ! getDialogMessage().equals("") ) {
TextView header = (TextView) inflater.inflate(R.layout.dialog_preference_list_header, null);
header.setText(getDialogMessage());
lv.addHeaderView(header, null, false);
}
// Create a new adapter and a list view and feed it with the ListPreference entries
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(getContext(),
R.layout.custom_dialog_single_choice_list_adapter, getEntries());
lv.setAdapter(adapter);
lv.setClickable(true);
lv.setEnabled(true);
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lv.setItemChecked(getValueIndex() + 1, true);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
setValueIndex(position - 1);
getDialog().dismiss();
}
});
return lv;
}
Another important thing is to call onPrepareDialogBuilder and not calling super in it. This will avoid that the listview appears twice.
#Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
// Not calling super, to avoid having 2 listviews
// Set the positive button as null
builder.setPositiveButton(null, null);
}
private int getValueIndex() {
return findIndexOfValue(getValue());
}
Where dialog_preference_list_header is in my case only a TestView, but it could be a more complex view, and custom_dialog_single_choice_list_adapter could be something like this:
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorSingle"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingBottom="2dip"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:paddingTop="2dip"
android:textAppearance="?android:attr/textAppearanceMedium" />
So I'm trying to make a tabbed application...But it keeps crashing with null pointer exception . I checked through all the variables that could be causing a null pointer and I think I've narrowed it down.
ListView activeList = (ListView) findViewById(R.id.activelist);
if(activeList == null) {
Log.e("com.name.app", "activeList null");
}
This returns a null. Should it? I'm using fragments to try and build a tabbed layout. This is the xml it's referencing.
<?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="#+id/activelist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:persistent="true" >
</ListView>
</LinearLayout>
Thank you for any help!
Edit:
super.onCreate(savedInstanceState);
setContentView(R.layout.tabs_layout);
That's what my contentview looks like.
Edit:
This is what my final code looked like!
LayoutInflater inflater = (LayoutInflater) getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout mContainer = (LinearLayout) inflater.inflate(R.layout.tab_frag1_layout, null);
ListView activeList = (ListView) mContainer.findViewById(R.id.activelist);
LinearLayout mContainer = inflater.inflate(R.layout.linear_layout, null);
ListView activeList = (ListView) mContainer.findViewById(R.id.activelist);
Where R.layout.linear_layout is the id of LinearLayout which contains your ListView.
Did you reffer in your activity to your XML layout?
You can do this in your oncreate method:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView.(R.layout.your_XML_file_name);
}
I've got 2 layouts (main.xml and footer_layout.xml) and am trying to append the footer_layout to my listview in main. I can get it to display but it won't set the text when I use tvFooter.setText();
Main.xml:
<?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" >
<ListView
android:id="#+id/listIssues"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</ListView>
</LinearLayout>
footer_layout.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="horizontal"
android:gravity="center"
android:layout_gravity="center" >
<TextView
android:id="#+id/footerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dip"
android:textStyle="bold"
android:layout_marginRight="5dip">
</TextView>
</LinearLayout>
MainActivity code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.footer_layout);
//Context context = getBaseContext();
tvFooter = (TextView)findViewById(R.id.footerText);
//Load listview control.
setContentView(R.layout.main);
final Context context = getBaseContext();
mListViewIssues = (ListView)findViewById(R.id.listIssues);
int DBVersion = 3;
tvFooter.setText("DBVersion = " + String.valueOf(DBVersion));
View footerView =
((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_layout, null, false);
mListViewIssues.addFooterView(footerView);
//add data to listview through adapter.
mListViewIssues.setAdapter(new IssueInfoAdapter(this, creator.queryAll()));
}
**Note that I removed the code for 'creator' as it wasn't necessary.
This app runs and displays the data but it doesn't display "DBVersion = 3" in the footer like I want.
Any ideas?
this line:
tvFooter = (TextView)findViewById(R.id.footerText);
requires that the view you are finding be "inside" your applications parent layout already.
try moving the findViewById(), and the setText() to after this line:
mListViewIssues.addFooterView(footerView);
Or better yet (and this might actually be neccessary, I am not certain it will work the other way) change it so that you are calling findViewById on one of the views in between the tvFooter and your parent view i.e. the ListView, or the plain View after you inflate it. Like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.footer_layout);
//Context context = getBaseContext();
tvFooter = (TextView)findViewById(R.id.footerText);
//Load listview control.
setContentView(R.layout.main);
final Context context = getBaseContext();
mListViewIssues = (ListView)findViewById(R.id.listIssues);
int DBVersion = 3;
View footerView =
((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_layout, null, false);
mListViewIssues.addFooterView(footerView);
tvFooter = (TextView)footerView.findViewById(R.id.footerText);
tvFooter.setText("DBVersion = " + String.valueOf(DBVersion));
//add data to listview through adapter.
mListViewIssues.setAdapter(new IssueInfoAdapter(this, creator.queryAll()));
}
note the use of footerView.findViewById(), I think you might have better luck if you explicitly call it on the footerView object rather than just from your activity, which is essentially the same as calling it on your activities parent layout.
You shouldn't set footer_layout as activity layout. The right code looks like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Load listview control.
setContentView(R.layout.main);
final Context context = getBaseContext();
mListViewIssues = (ListView)findViewById(R.id.listIssues);
int DBVersion = 3;
View footerView =((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_layout, null, false);
tvFooter = (TextView)footerView.findViewById(R.id.footerText);
tvFooter.setText("DBVersion = " + String.valueOf(DBVersion));
mListViewIssues.addFooterView(footerView);
//add data to listview through adapter.
mListViewIssues.setAdapter(new IssueInfoAdapter(this, creator.queryAll()));
}