I need to create a more advanced list in my android application, that will contain more then just one string per item. Actually, I'm looking for something similar to the appointments view in the calendar app: I want to categories my items by day, and show something similar to the hour of the appointment.
No idea how to go about this though, I'm guessing it's not possible with the ListActivity?
What do you guys suggest?
Edit:
If someone could give a code example I'd really appreciate it, I'm not sure how to execute what was suggested in the current replies..
It's easily doable with ListACtivity. You need to create a subclass within it, that extends ArrayAdapter (or any other list adapter) and overrides it's getView() method. You will want to create an xml file defining the "view" for each list item. Then within your overridden getView() method, you will need to inflate that view, then use findViewById() for each of the elements you want to assign a value to.
public class YourListActivity extends ListActivity {
private String[] values = new String[]{"Row 1", "Row 2", "Row 3"};
private class Adapter extends ArrayAdapter<String> {
private LayoutInflater li = LayoutInflater.from(this.getContext());
public Adapter() {
super(YourListActivity.this, 0, values);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
View v = li.inflate(R.layout.row, parent);
TextView field1 = (TextView) v.findViewById(R.id.field1);
field1.setText(values[position]);
return v;
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setListAdapter(new Adapter());
}
}
row.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/field1"
/>
</LinearLayout>
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#android:id/list"
/>
</LinearLayout>
You can further modify the appearance of the row, and the fields it holds, by adding additional TextViews to the row.xml, and using the position passed through to getView() to set the values of your extra fields as appropriate, and you can even customise the rows on a row-by-row basis if you need.
This recorded talk from Google I/O last year explains what you want to know: http://www.google.com/events/io/2010/sessions/world-of-listview-android.html
Create a ListAdapter. That's the class responsible for providing the list with its UI elements. With its getView you can create whatever Views you like. If you have more than one type of list element, beware not to reuse the convertView that getView receives.
Related
I want to write an activity that is similar to the about screen of android phones. I want it to display some information in the style of the about screen of android phones.
Like this
title1
info
-----------------
title2
info
-----------------
etc.
Is there a special view that I can use or is it just a result of multiple views placed in a specific way? Or is there an activity template in android studio that I can use?
Use ListView. You can create a custom layout for cells and then use an array or a cursor to fill the data.
ListView: A view that shows items in a vertically scrolling list. The
items come from the ListAdapter associated with this view.
ListAdapter can receive data as input. The adapter would inflate the layout for each cell in its getView() method and assign the data to the individual views in the cell.
Read more about ListView here: http://developer.android.com/reference/android/widget/ListView.html
See PreferenceActivity or PreferenceFragment. They are special list views populated either from code or from a xml file. There are many different preference types to choose from (checkbox, switch, list etc)
An example preference fragment:
You can use ListView and a custom ArrayAdapter to create a screen like that. If you need any help about how to create a custom ArrayAdapter check this useful tutorial here.
If you want to create a simple list, then ListView is probably the simplest option. You may also want to look into ListActivity and/or ListFragment as well to further simplify the process.
If you intend to use complex animations, or have the list update dynamically with animations, you may be better served with RecyclerView, although using it is more complex.
An straightforward implementation of ListActivity could look something like this:
public class MainActivity extends ListActivity {
String[] titles = { "title one", "title two" };
String[] descriptions = { "desc 1", "desc 2" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ListAdapter() {
leave everything the same, except for getCount() and getView()
#Override
public int getCount() {
return titles.length;
}
This will ensure you list is always the correct length as your array.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) parent.getContext().
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.row, parent, false);
} else {
view = convertView;
}
TextView title = (TextView) view.findViewById(R.id.title);
TextView description = (TextView) view.findViewById(R.id.description);
title.setText(titles[position]);
description.setText(descriptions[position]);
return view;
}
And row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/title"
android:textSize="24sp"
android:textStyle="bold"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/description"
android:textSize="20sp"/>
</LinearLayout>
I am trying to create an item in a ListView that has multiple options; view and edit. I would like to create it in exactly the same way as android's contact system - see below:
I have added the red boxes to illustrate the behaviour I want. If you press within the left red-box, you call the contact. If you press within the right red-box, you send a text message to the contact. I have already created a similar layout in XML, but I am having trouble implementing this functionality in code.
I have tried to create custom android:onClick function calls for the separate layouts within the item, but calling an onClick method only allows you to pass in the View as a parameter, but not the position. Needing the position to use listview.getItemAtPosition function, I tried to use listview.getPositionForView to return the position but found this was extremely unstable and was very easy to return incorrect positioning due to recycling of views.
I then tried to set the item's position as the 'tag' in the getView method of my adapter, like so: convertView.setTag(position). But on the onClick method of my activity, I try and use getTag and cast it back to an integer, and it always returns null, which I find puzzling.
What is the best way of implementing a list populated by items with multiple buttons/layouts on each item?
You can create an onClick event on each views in your row like this :
<?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" >
<TextView
android:id="#+id/text_id"
android:layout_width="0sp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:onClick="textOnClickEvent"/>
<ImageButton
android:id="#+id/button_id"
android:layout_width="#dimen/width_button"
android:layout_height="match_parent"
android:onClick="imageOnClickEvent"
android:src="#android:drawable/ic_menu_delete" />
</LinearLayout>
Or even, add onClick listeners on each views in the getView method...
more info on this here.
In the list view when you define getview method, this is where you provide all the details of the single list item. There you can mention onlick event of each of the views.
in adapter class, add View.OnClickListener to the getView method:
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
if(view == null) {
final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
view = layoutInflater.inflate(R.layout.grid_vendor_item, null);
}
final TextView textName = (TextView) view.findViewById(R.id.text_id);
final ImageButton imageProfil = (TextView) view.findViewById(R.id.button_id);
textName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// add your edit codes
}
});
imageProfil.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// add your open prodil codes
}
});
return view;
}
I'm new to the this excellent site and in the Java programming Android. I started to make a small test application for the listing of my favorite places in my town. I tried to follow some tutorials on different pages, but when I do I put in my project in Eclipse always gives me more than a million mistakes although imports classes and other methods.
I want to build on the example image discotheque next to the image name discos and under that name Diskotek smaller text additional info.
It would be really grateful for all the help
A Custom ListView requires total 4 basic stuff 2 in design (layout .xml) & 2 class (.java)
2 Layout
a) Basically a container which has a listview with either a heading or button depends on you
b) How each row should look like should they have buttons, images, textview how ever you want.
2 Java Class File
a) One is the Activity which you will have definitely.
b) Custom Adapter which says which value from your Activity will go to which View (Button , image ) depending on your requirement.
The best example is to follow this Tutorial
The first thing I think when someone says 'I tried to follow some tutorials...' but they don't work, It gets kind of hard to believe.
Where's the code you tried?
What are the import errors on the editor?
That'd be an easier problem to address.
To give you a simple ListView example:
First, create a resource file at your preference: (example.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/disco_image"
android:layout_alignParentTop="true"
android:src="#drawable/ic_home"
android:layout_width="96dp"
android:layout_height="96dp"/>
<TextView
android:id="#+id/disco_title"
android:padding="12dp"
android:layout_toRightOf="#+id/disco_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/disco_info"
android:padding="12dp"
android:layout_toRightOf="#+id/disco_image"
android:layout_below="#+id/disco_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
Then, create a custom adapter, they are very simple. Just extend a BaseAdapter for now.
public class ExampleAdapter extends BaseAdapter {
//Let's create some constants first, to fill out the rows
private static final String [] DISCO_NAMES = {"Disco One", "Disco Two", "Disco Three", "Disco Four"};
private static final String [] DISCO_INFO = {"Some Info One", "Some Info Two", "Some Info Three", "Some Info Four"};
private LayoutInflater mInflater;
//Our custom adapter needs a constructor, so you can create from your activity.
public ExampleAdapter (final Context context) {
//for now, let's just get the context, we'll need it to inflate views
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
//this needs to return to the amount of rows you want to display.
//right now we return a fixed value, this could vary based on your needs
return DISCO_NAMES.length;
}
#Override
public Object getItem(int pos) {
//this is useful for knowing what item is at what position
//for now, let's just return the disco name shall we?
return DISCO_NAMES[pos];
}
#Override
public long getItemId(int pos) {
//This returns an id to the item
//personally I don't use this, so you can just return the position
return pos;
}
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
//Ha, here's the important part
//ListViews reuse rows, so let's check if the view (also known as convertview) is new or being reused
if (view == null) {
//this means it's a new view, so we need to inflate it
view = mInflater.inflate(R.layout.example, null);
}
((TextView) view.findViewById(R.id.disco_title)).setText(DISCO_NAMES[position]);
((TextView) view.findViewById(R.id.disco_info)).setText(DISCO_INFO[position]);
//You can also set some images to the imageview on the layout we created earlier
return view;
}
}
Then, let's create a ListActivity for example purposes. NOTE ListActivit does not require a Layout Resource to be set via setContentView, so we don't call it here.
public class ExampleListActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//create the adapter
ExampleAdapter mExampleAdapter = new ExampleAdapter(this);
//fill the listView
setListAdapter(mExampleAdapter);
}
}
That should compile as is, but you may want to look into ViewHolder patterns and blah blah blah for performance reasons. Obviously you need to read more, but I hope this helps as a starting point.
I came across a number of these which answered the question but didn't exactly structure the classes in a matter I found expandable, a lot of the time it would override functions especially as I was using an SimpleCursorAdapter rather than a BaseAdapter which handles the population of SQLite data into the list item automatically on getView.
The code provided in my answer is provided as a way of showing you how to develop a ListAdapter which will add buttons that can handle click events, WITHOUT enabling click events on the list items or without fully overriding original draw events of the class your extending.
Firstly your XML for the row, only the ID of the4 button needs to be updated in code if your going to make any changes to it, the rest is not required by the custom part:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:id="#+id/tag_row_layout"
android:orientation="horizontal" android:layout_width="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="fill_parent" android:id="#+id/name"
/>
<Button
android:id="#+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="Do Stuff"
/>
</LinearLayout>
This is a very simple list view and using LinearLayout it'll just display the button next to the text, it's nothing amazing.
The next part then is to have the code for the Adapter like this...
public class CustomListAdapter extends SimpleCursorAdapter {
public CustomListAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = super.getView(position, convertView, parent);
Button btn = (Button)convertView.findViewById(R.id.delete_button);
btn.setOnClickListener(new DeleteButton());
return convertView;
}
protected final static class DeleteButton implements OnClickListener {
public void onClick(View v) {
Log.e("TestButton", "It's been fired!!!");
}
}
}
You can then extend this to multiple buttons but creating more in the list item's XML and then by creating another static class in the CustomListAdapter. This is great for extending the SimpleCursorAdapter because it will still inject the right data into the correct text views.
I want to pass a value that will be generated at runtime,through a TextView. the text property is used for some other data and the data that I want to pass will not be displayed. So, it's a like a hidden tag. Is it possible to do with TextView? If so, which property of the TextView.
For simplicity's sake imagine I pull the ID and TEXT from the data table. Now the TEXT is displayed on the TextView but when I want to pass the reference to that particular row of the table to some other function I want to pass the ID as an argument/handle. So, the ID will be hidden and associated with the TextView. How can I do it? If not possible can you suggest any alternative to accomplish this? BTW, the TextView is embedded within a ListView.
Adapter code :
cursor = db.rawQuery("SELECT * FROM EmpTable", null);
adapter = new SimpleCursorAdapter(
this,
R.layout.item_row,
cursor,
new String[] {"Emp_Name"},
new int[] {R.id.txtEmployee});
Try setTag(int, Object) and getTag(int). There are even versions that don't take a key, if you just want to store one value. From the docs:
Sets the tag associated with this
view. A tag can be used to mark a view
in its hierarchy and does not have to
be unique within the hierarchy. Tags
can also be used to store data within
a view without resorting to another
data structure.
So you can do:
textView.setTag(myValue);
and get it back later with:
myValue = textView.getTag();
Since the interface uses Object, you will need to add casts. For example, if your value is an int:
textView.setTag(Integer.valueOf(myInt));
and:
myInt = (Integer) textView.getTag();
Edit - to subclass and add the tag, use:
adapter = new SimpleCursorAdapter(this, R.layout.item_row,
cursor, new String[] {"Emp_Name"}, new int[] R.id.txtEmployee}) {
#Override
public View getView (int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
view.setTag(someValue);
return view;
}
};
You can use setTag() and getTag().
One way to do this would be to have your ListAdapter inflate a layout instead of a TextView for each item of the list. Then you can have other (invisible) fields hidden in the layout.
The xml might look like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="#+id/visible_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Visible text"/>
<TextView android:id="#+id/hidden_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hidden value"
android:visibility="gone"/>
</LinearLayout>