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);
Related
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);
Given the ListView below, I wanted to perform two different actions depending on whether the user selects the text (create a new activity) or clicks the associated checkbox (add it to a favorites list). Is this possible in with this setup or will I have to use a custom adapter or even a different layout?
<LinearLayout 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"
android:orientation="vertical">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, teams));
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String team_name = adapterView.getItemAtPosition(i).toString().trim();
Intent intent = new Intent("blah.blah.blah");
intent.putExtra("team", team_name);
startActivity(intent);
}
});
A
If I am understanding you correctly, your ListView should contain TextBox and CheckBox and TextBox and CheckBox are clickable, not ListView itself.
For this you have to make custom adapter, where you will make listeners for both the TextBox and CheckBox.
public class CustomAdapter extends BaseAdapter {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// your_costum_view should contain textbox and checkboc
view = inflater.inflate(R.layout.your_costum_view, null);
// Get your checkbox and textbox and add listeners
TextView textView = (TextView) view.findById(R.id.textView);
textView.setOnClickListener...
Checkbox checkbox=(CheckBox)view.findById(R.id.checkBox);
checkBox.setOnClickListener...
return view;
}
}
your_costum_view layout example
<?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="wrap_content" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Using a custom adapter will help you keep trace of your views, it will be easier than use a default adapter that you can't control. For references: http://www.vogella.com/tutorials/AndroidListView/article.html#adapterown_custom
Using a custom adapter will definitely make your life easier. In the adapter you can make reference to both the checkbox and the textView and add an onClick Listener to each - from there you can also add code to handle each event. I would also suggest using a recyclerView instead of a ListView. It is the new thing in Android 5.0 and it really is easier to use then a regular ListView. Hope this helps:
RecyclerView Help
Set the CheckBox as focusable="false" in your XML layout.
android:focusable="false"
if don't run go to this link and see example because you need a create custom row in list view and set:
Checkbox checkbox=(CheckBox)view.findById(R.id.checkboxID);
checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//do stuff
}
});
Ok so I'm running into problems creating an app (force closing) and I think it has to do with the way I implemented the layout. So a few questions: First, I have a relative layout that includes a text input with a button next to it, a list view (still within the relative layout) and another button below that. This is my main xml file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<EditText
android:id="#+id/edit_choice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/Button1"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/Button1"
android:hint="#string/edit_choice" />
<Button
android:id="#+id/Button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:onClick="addString"
android:text="#string/button_add" />
<Button
android:id="#+id/Button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="22dp"
android:text="#string/button_random" />
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/Button2"
android:layout_alignParentLeft="true"
android:layout_below="#+id/Button1"
tools:listitem="#android:layout/simple_list_item_1" >
</ListView>
</RelativeLayout>
Before I even changed anything in the .java files when I tried running this, only the text input and the 2 buttons appeared and the theme changed from Holo to Holo light. So I'm wondering if this works, I've only seen examples where the list view matches the parent layout completely.
My second question is how do I handle using the input to add values to the list view, can I do that in the main activity class or can I have another class to handle the list view and still reference the main layout.
This is my Main class:
public class MainActivity extends Activity
{
public ArrayList <String> choices = new ArrayList <String>();
public ListView listView = (ListView) findViewById(R.id.listView1);
public String [] choicesArray;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.listView1);
choicesArray = new String [] {"You have not entered a choice yet"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, choicesArray);
listView.setAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
//adds the string to the list
public void addString(View view)
{
choicesArray = (String[]) choices.toArray();
EditText editText = (EditText) findViewById(R.id.edit_choice);
String message = editText.getText().toString();
choices.add(message);
}
}
Hopefully this makes sense and thank you for any help.
Problem is you are calling this line
public ListView listView = (ListView) findViewById(R.id.listView1);
before setting content view by setContentView() method in onCreate() so you are getting NullPointerException. Do not forget that before calling findViewById you have to set content view. So delete above line because you are creating function scope listView in onCreate method and your NullPointerException problem will be solved. And also change first line of addString method like this
choicesArray = choices.toArray(choicesArray);
Define your ArrayAdapter as member for your class (not as variable
in onCreate()).
Set the adapter to your listView in onCreate().
Set the onClickListener for your button.
Add the text from EditText to your adapter when you click on the
button.
Profit!
I am facing problem while putting Spinner in layout. My acctual requirement is to place Spinner once, at the top of layout.
This output I am getting:
I have Relative layout
<Spinner
android:id="#+id/spinner1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:entries="#array/string_array"
android:prompt="#string/spinner_msg"
/>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/notesTextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceMedium"
</TextView>`
MyActivity class is extended by ListActivity here's onCreate method
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listView=getListView();
listView.setOnItemClickListener(listener);
spinner1=(Spinner)findViewById(R.id.spinner1);
getDetailsCursor();
String[] from = new String[] {"db_column"};
int[] to = new int[] { R.id.notesTextView};
curAdapter=new SimpleCursorAdapter(MyActivity.this, R.layout.mylist, null, from, to);
setListAdapter(curAdapter);
registerForContextMenu(listView);
}`
Here is the code in which spinner inflates on the top of listview :
listView= (ListView) findViewById(R.id.list);
LayoutInflater inflater = LayoutInflater.from(this);
View mTop = inflater.inflate(R.layout.spin, null);
authorityView.addHeaderView(mTop);
R.layout.spin is that layout which contains only spinner.
And inside the List you have to inflate textView only. as you are doing in mylist.xml ,
just remove spinner from it and made seprate xml for spinner.
so spinner is once, at the top of layout (ListView).
I have some difficulty making out what your actual question is, some layout.xml code would help here, too. I think, that you are placing the spinner inside the listitem.xml instead of the main.xml, so that it gets replicated for each item in your listview. Please share some code.
Since you declare both the TextView and the Spinner in mylist.xml, you get both those elements in each Item of your List.
If you only want one spinner, you shouldn't use a ListActivity, but instead create a normal Activity with a Spinner and a ListView in the Layout. Then define another layout to use for the list items (e.g. with only the TextView).
I'm using a custom listview I found here:
http://developer.android.com/resources/samples/ApiDemos/res/layout/linear_layout_9.html
Seems to be valid in Eclipse, and looks good in the preview tab. It's just a listview that has a button on the bottom. So i've added it as R.layout.buttonlist
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:id="#+id/testbutton"
android:text="#string/hello" android:layout_alignParentBottom="true" />
<ListView android:layout_width="fill_parent"
android:layout_height="fill_parent" android:id="#+id/list"
android:layout_alignParentTop="true" android:layout_above="#id/testbutton" />
</RelativeLayout>
Unfortunately when I run it, i get a pop up window that says Android has closed unexpecitdly:
setListAdapter(new ArrayAdapter<String>(this, R.layout.buttonlist , data));
When I try using a built in list view:
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1 , data));
everything works fine. I dont see any errors or warnings in logcat, so I'm not sure how to pinpoint the problem. Does anyone have any ideas? Thanks
Edit: adding activity
public class TestActivity extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
List<String> data = new ArrayList<String>();
data.add("hello");
data.add("world");
setContentView(R.layout.buttonlist);
//setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1 , data));
}
}
Hoofamon, I would like to correct you here. You are not creating a custom ListView but a custom layout with a ListView. Also, I believe that you have not completely understood what the setListAdapter is doing here.
This line that you have is telling the listview to consume 'android.R.layout.simple_list_item_1' as the content of its layout. This layout comes pre-defined in the Android SDK. It would just contain text in each item of a listview. The third attribute 'data' indicates the content of each listview item.
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1 , data));
So, as Mike L. has suggested, if your intent is to have a listview with only text (having the default format), then the line above would serve the purpose well. You can set 'R.layout.buttonlist' as the layout of your activity using
setContentView(R.layout.buttonlist);
However, if you are planning to include additional content in the listview (read images) or want to change the styling of the text, you would have to define a custom layout for the listview. We can direct you to appropriate sources if you want to know how that can be done.
EDIT: A possible way of loading data into a normal ListView
TestActivity.java
public class TestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.buttonlist);
List<String> data = new ArrayList<String>();
data.add("hello");
data.add("world");
ListView mListView = (ListView)findViewById(R.id.list);
mListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1 , data));
}
}
buttonlist.xml
<?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">
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/testbutton"
android:text="#string/hello"
android:layout_alignParentBottom="true" />
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/list"
android:layout_alignParentTop="true"
android:layout_above="#+id/testbutton" />
</RelativeLayout>
This is how it should look like on the emulator:
I don't think you can have a listview in the layout of an adapter. The passed in layout should just describe a row in the listview. So buttonlist should just contain the xml for the button. The listview needs to be in a separate layout file. If this is a list activity then you don't need another layout file, just call setListAdapter like you are doing.
If you want to use your R.layout.buttonlist to fill up your listview,you can do it as follows(your TestActivity should extend Activity,not ListActivity):
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.buttonlist);
String data[]=new String[]{"Item_1","Item_2","Item_3"}
Button b=(Button)findViewById(R.id.testbutton);
ListView lv=(ListView)findViewById(R.id.list);
ArrayAdapter aa=new ArrayAdapter(context,android.R.layout.simple_list_item_1, data);
lv.setAdapter(aa);
//Your code...
}
Now if you want to create custom listitem to be displayed in the listview,then you need to do like this:
Create your custom listitem xml file.
Ex: custom_listitem.xml
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/icon"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:id="#+id/text"
/>
Create custom ArrayAdapter:
Ex. CustomArrayAdapter.class
public class CustomArrayAdapter extends ArrayAdapter<String> {
String[] array;
LayoutInflater mInflater;
public CustomArrayAdapter(Context context, int textViewResourceId,
String[] objects)
{
super(context, textViewResourceId, objects);
array=objects;
mInflater = LayoutInflater.from(context);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
if(convertView==null)
{
convertView = mInflater.inflate(R.layout.custom_listitem, null);
holder = new ViewHolder();
holder.text=(TextView)convertView.findViewById(R.id.text);
holder.img=(ImageView)convertView.findViewById(R.id.icon);
convertView.setTag(holder);
}
else
holder=(ViewHolder)convertView.getTag();
holder.text.setText(array[position]);
if(position==0)
holder.img.setImageResource(R.drawable.img1);
else if(position==1)
holder.img.setImageResource(R.drawable.img2);
else if(position==2)
holder.img.setImageResource(R.drawable.img3);
return convertView;
}
static class ViewHolder
{
TextView text;
ImageView img;
}
}
Use this custom adapter class in your main activity to fill up listview:
Be sure,this main activity extends Activity and not ListActivity
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context=getApplicationContext();
lv=(ListView)findViewById(R.id.listview);
CustomArrayAdapter aa=new CustomArrayAdapter(context,R.layout.custom_listitem, new String[]{"item_1","item_2","item_3"});
lv.setAdapter(aa);
// other lines of code
.
.
.