Android List with Image - How to implement - android

I'm looking for a clear way to establish the XML resource for a list of strings with an image attached to it.
Should I use attributes? What is the best practice?

list_layout.xml
<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/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
row_layout.xml
<?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/row_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView android:id="#+id/row_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
In onCreate()
setContentView(R.layout.list_layout);
ListView lv = (ListView) findViewById(R.id.list);
List<ListRow> list = new ArrayList<ListRow>();
for ( loop through your data ) {
list.add(new ListRow("text", R.drawable.image));
}
YourAdapter adapter = new YourAdapter(this, list);
lv.setAdapter(adapter);
The classes
class ListRow {
private String text;
private int resource;
public ListRow(String text, int resource) {
super();
this.text = text;
this.resource = resource;
}
public int getText() {
return text;
}
public int getResource() {
return resource;
}
}
class YourAdapter extends BaseAdapter implements OnClickListener {
private Context context;
private List<ListRow> theList;
public YourAdapter (Context context, List<ListRow> theList) {
this.context = context;
this.theList = theList;
}
public View getView(int position, View convertView, ViewGroup viewGroup) {
ListRow row = theList.get(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_layout, null);
}
TextView tv = (TextView) convertView.findViewById(R.id.row_text);
tv.setText(row.getText());
ImageView iv = (ImageView) convertView.findViewById(R.id.row_image);
iv.setBackgroundResource(row.getResource());
return convertView;
}
#Override
public void onClick(DialogInterface dialog, int which) {
}
}

Related

ListView of images not working

I'm trying to customize ListView to show a list of images so i wrote the following code but unfortunately its not working.
layout/menu.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="match_parent" android:background="#drawable/menu_bg">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/name"
android:layout_gravity="center"/>
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/menu_list"
android:layout_gravity="center"
android:layout_marginTop="60sp"></ListView>
</LinearLayout>
layout/menu_item.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="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/item"/>
</LinearLayout>
Menu.java
public class Menu extends Activity{
private int[] items = {R.drawable.res_opt, R.drawable.new_game_opt, R.drawable.score_opt, R.drawable.exit_opt};
ListView list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menu);
list = (ListView) findViewById(R.id.menu_list);
list.setAdapter(new MenuAdapter(Menu.this, items));
}
}
MenuAdapter.java
public class MenuAdapter extends ArrayAdapter{
private int[] items;
private Context context;
public MenuAdapter(Context context, int[] items) {
super(context, R.layout.menu_item);
this.context = context;
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//make sure we have a view to work with
View itemView = convertView;
if(itemView == null)
{
LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
itemView = inflater.inflate(R.layout.menu_item,null, true);
}
//Find the object to work with
int id = items[position];
//Fill the view
ImageView item = (ImageView) itemView.findViewById(R.id.item);
item.setImageResource(id);
return itemView;
}
}
Add view holder class to your code, as its incomplete.
public class ViewHolder{
public ImageView iv;
}
Now, your code will look like this:
ViewHolder mViewHolder = new ViewHolder();
if(itemView == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
itemView = inflater.inflate(R.layout.menu_item,null, null);
mViewHolder.iv = (ImageView) itemView.findViewById(R.id.item);
itemView.setTag(mViewHolder);
}else{
mViewHolder = (ViewHolder) itemView.getTag();
}
//Find the object to work with
int id = items[position];
//Fill the view
mViewHolder.iv.setImageResource(id);
Also, you have missed adding size for you ListView adapter.
Hope, this could help you.
You need to use another super constuctor of ArrayAdapter.
public class MenuAdapter extends ArrayAdapter<Integer>{
private Integer[] items;
private Context context;
public MenuAdapter(Context context, Integer[] items) {
super(context, R.layout.menu_item, items);
this.context = context;
this.items = items;
}
Edited
Also fix this line
itemView = inflater.inflate(R.layout.menu_item,parent, false);

Custom Listview with Buttons as Item OnItemClickListener wi

I want to make a custom ListView with buttons as Items. Now I'm using the OnItemClickListener and for each click, a toast message comes up, but it only comes up, if i press out of the buttons, but in the ListView(see picture)
How can I do it, that the toast comes, if i press on the buttons, not out of them.
Adaptercode:
public class MainListAdapter extends ArrayAdapter<Games> {
Context context;
int layoutResourceId;
Games data[] = null;
public MainListAdapter(Context context, int layoutResourceId, Games[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
View row = convertView;
ListHolder holder = null;
if(row == null){
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ListHolder();
holder.btn = (Button)row.findViewById(R.id.listViewButton);
row.setTag(holder);
}else{
holder = (ListHolder)row.getTag();
}
Games games = data[position];
holder.btn.setText(games.name);
return row;
}
static class ListHolder {
Button btn;
}
}
In the Acitivty:
MainListAdapter adapter = new MainListAdapter(this, R.layout.listview_item_row, games_data);
listView1 = (ListView)findViewById(R.id.listView1);
final View header = (View)getLayoutInflater().inflate(R.layout.listview_newgame_row, null);
listView1.addHeaderView(header);
listView1.setAdapter(adapter);
listView1.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Toast.makeText(getApplicationContext(), "clicked", Toast.LENGTH_LONG).show();
}
});
listview_item_row.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:orientation="vertical" >
<Button
android:id="#+id/listViewButton"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:focusable="false"
android:background="#drawable/button" />
IN your Adupter class make two objects for button.
And setonclicklistner for the buttons in adupter view
E.g.
vi = inflater.inflate(R.layout.list_row_contact, null);
LinearLayout ll_adpt_main = (LinearLayout)vi.findViewById(R.id.ll_adpt_main);
TextView name = (TextView) vi.findViewById(R.id.name);
TextView discription = (TextView) vi.findViewById(R.id.number);
ImageView iv = (ImageView)vi.findViewById(R.id.iv);
iv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
}
});
return vi;
}
Make a separate onclicklistener for buttons. OnItemclicklistener is for a list item.
Firstly you have to create an xml layout like this.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
Then create an adapter class:
class MyAdapter extends ArrayAdapter<View.OnClickListener> {
public MyAdapter(Context context, int textViewResourceId, View.OnClickListener[] objects) {
super(context, textViewResourceId, objects);
}
public MyAdapter(Context context, int resource, int textViewResourceId, List<View.OnClickListener> objects) {
super(context, resource, textViewResourceId, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.event_layout, null);
Button b = (Button) convertView.findViewById(R.id.btn);
View.OnClickListener l = getItem(position);
b.setOnClickListener(l);
return convertView;
}
}
The layout of the activity should be like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LayoutActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".YourActivityName" >
<Button
android:id="#+id/btnHeader1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<Button
android:id="#+id/btnHeader2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ListView
android:id="#+id/your_list"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
Now to set list items:
ListView list = (ListView)findViewById(R.id.your_list);
View.OnClickListener[] listeners = ....;
MyAdapter adapter = new MyAdapter(context, R.layout.your_list_layout_adapter, listeners);
list.setAdapter(adapter);
I hope to have satisfied all your requests :)

My ListView is still slow after using ViewHolder

I'm using listview with customized list item layout.Also i'm using ViewHolder on my list view but the performance of list view is still very slow.How to solve this?
Here is my Activity.java
public class FilemanagerActivity extends Activity {
private ListView list;
private TextView status;
private String[] list_items;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_filemanager);
//Initialization
list=(ListView)findViewById(R.id.list);
///Function to List a dirs from that dir
listFiles("/");
list.setItemsCanFocus(false);
CustomAdapter adapter=new CustomAdapter(this, R.layout.list_filemanager, list_items);
list.setAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.filemanager, menu);
return true;
}
// CustomAdapter
private class CustomAdapter extends ArrayAdapter<String> {
String[] values;
int layout,img_dir;
LayoutInflater lf;
public CustomAdapter(Context context, int resource, String[] objects) {
super(context, resource, objects);
values = objects;
layout = resource;
lf= getLayoutInflater();
img_dir=R.drawable.device_mobile;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewholder;
if(convertView==null)
{
convertView = lf.inflate(layout, parent, false);
viewholder=new ViewHolder();
viewholder.checkbox=(CheckBox)convertView.findViewById(R.id.list_checkbox);
viewholder.txt = (TextView) convertView.findViewById(R.id.list_txt);
//viewholder.img = (ImageView) convertView.findViewById(R.id.list_img);
convertView.setTag(viewholder);
}
else
{
viewholder=(ViewHolder) convertView.getTag();
}
viewholder.txt.setText(values[position]);
//viewholder.img.setImageResource(img_dir);
viewholder.checkbox.setChecked(true);
return convertView;
}
}
//View Holder
public class ViewHolder
{
public TextView txt;
public ImageView img;
public CheckBox checkbox;
}
}
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"
tools:context=".FilemanagerActivity"
android:orientation="vertical">
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/list"
android:focusable="false"
></ListView>
</LinearLayout>
List item Layout:
<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:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textAppearance="#android:style/TextAppearance.Large"
android:id="#+id/list_txt"
android:layout_weight="0.2"
/>
<CheckBox
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/list_checkbox"
android:layout_weight="0.8"
/>
</LinearLayout>
Is there any performance error in my code?

List image is empty

i'm having some trouble with my code app: i'm trying to display in an activity a list of image taken from an array but when i try to execute the app i've an empty list without error in debug. Can anyone help me? Here is my activity:
String [] vett;
ListView list;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_techpuno);
list=(ListView)findViewById(android.R.id.list);
Intent intent = getIntent();
vett=intent.getExtras().getStringArray("nomeImmagine");
for(int i = 0;i<vett.length;i++){
Log.d("test", vett[i]);}
//list.setListAdapter(new AdapterTecniche(this, vett));
list.setAdapter(new AdapterTecniche(this, R.layout.activity_techp,vett));
}
And here it is the adapter:
public class AdapterTecniche extends ArrayAdapter<String> {
private final int resource;
private final String[] img;
public ImageLoader imageLoader;
LayoutInflater inflater;
public AdapterTecniche(Context context,int resource, String[]img) {
// your code
super(context, R.layout.activity_techpuno);
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.context = context;
this.resource=resource;
this.img=img;
imageLoader=new ImageLoader(getContext().getApplicationContext());
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
View rowView = convertView;
if(rowView == null) {
Log.d("errore","Immagini non presenti");
rowView = inflater.inflate(R.layout.immagini, parent, false);
viewHolder=new ViewHolder();
viewHolder.imageView=(ImageView) rowView.findViewById(R.id.list_image);
rowView.setTag(viewHolder);
}
else
{
viewHolder=(ViewHolder)rowView.getTag();
}
if(img==null){
Log.d("errore","Immagini non presenti");
}else{
int resourceId = context.getResources().getIdentifier(img[position],"drawable", context.getPackageName());
for(int i=0;i<img.length;i++){
Log.d("err", img[i]);
}
imageLoader.DisplayImage(resourceId, viewHolder.imageView);
}
return rowView;
}
static class ViewHolder {
ImageView imageView;
}
}
Immagini.xml (each image layout)
<LinearLayout 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/list_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_gravity="center_horizontal" />
</LinearLayout>
And Activity layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#android:id/list" />
</LinearLayout>
setContentView(R.layout.activity_techpuno);
should be before
list=(ListView)findViewById(R.id.listView);
Because Activity firstly need to have binded/inflated layout, after that you can "find" your views from it.
Edit
Use ArrayAdapter(Context context, int resource, T[] objects) constructor to give objects to it.
Or override getCount() because your adapter have no idea how many items he got.

Can't find TextView in recursive custom Listview adapter

I created this class called GeoArea, which is suppose to store "Geographical Area" that have children Geographical Areas, this is fairly strait foward:
public class GeoArea {
public String id;
public String name;
public List<GeoArea> subGeoAreas;
public GeoArea parentGeoArea;
public GeoArea(String id) {
this.id = id;
name = id;
subGeoAreas = new LinkedList<GeoArea>();
}
#Override
public String toString() {
return name;
}
}
I have created the following Layout to render it on Android, the idea here is to for each GeoArea to recursively render it self and then it's children GeoArea in a listView:
//layout_geo_area.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/txtGeoAreaName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:gravity="left"
android:text="Geo Area Name"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ListView
android:id="#+id/listViewChildGeoAreas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/txtGeoAreaName"
android:gravity="left" >
</ListView>
</RelativeLayout>
This is my adapter I created for GeoArea to be displayed in a listView:
public class AdapterGeoArea extends ArrayAdapter<GeoArea>{
private ArrayList<GeoArea> _myGeoArea;
private Context _myContext;
LayoutInflater _inflater;
public AdapterGeoArea(Context context, ArrayList<GeoArea> myGeoArea) {
super(context, 0, myGeoArea);
_myGeoArea = myGeoArea;
_inflater = LayoutInflater.from(context);
_myContext = context;
}
public int getCount() {
return _myGeoArea.size();
}
public View getView(int position, View convertView, ViewGroup parent) {
GeoAreaLayoutHolder holder;
if (convertView == null) {
convertView = _inflater.inflate(R.layout.layout_geo_area,parent,false);
holder = new GeoAreaLayoutHolder();
holder.txtGeoAreaName = (TextView)convertView.findViewById(R.id.txtGeoAreaName);
holder.txtGeoAreaName.setTag(convertView);
holder.listViewChildGeoAreas = (ListView)convertView.findViewById(R.id.listViewChildGeoAreas);
holder.listViewChildGeoAreas.setTag(convertView);
} else {
holder = (GeoAreaLayoutHolder) convertView.getTag();
}
GeoArea curGeoArea = _myGeoArea.get(position);
holder.txtGeoAreaName.setText(curGeoArea.name);
if(curGeoArea.subGeoAreas.size()>0){
ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
AdapterGeoArea adapter = new AdapterGeoArea(_myContext, testList);
for(GeoArea childGeoArea:curGeoArea.subGeoAreas){
testList.add(childGeoArea);
}
holder.listViewChildGeoAreas.setAdapter(adapter);
}
return convertView;
}
static class GeoAreaLayoutHolder {
public TextView txtGeoAreaName;
public ListView listViewChildGeoAreas;
}
}
And here is my Activity that I am using to set it all up:
public class ActivityGeoAreas extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_geo_area);
GeoArea.searchTerm = "Bar & Grill";
GeoArea torontoArea = new GeoArea("cityOfToronto");
ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
testList.add(torontoArea);
AdapterGeoArea adapter = new AdapterGeoArea(this, testList);
ListView lv = (ListView) findViewById(R.id.listViewChildGeoAreas);
lv.setAdapter(adapter);
}
}
When I try to run it, I get the error nullPointerException on the line:
holder.txtGeoAreaName.setText(curGeoArea.name);
What am I doing wrong?
You may want to check ExpandableListView may suit your needs better
http://developer.android.com/reference/android/widget/ExpandableListView.html
An example # http://www.androidhive.info/2013/07/android-expandable-list-view-tutorial/
Continuing from my previous answer to your question ( i though that solved your problem)
To display just name in your listview
list_row.xml // this is the layout with textview to be inflated in getView.
Each row will have textview
<?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" >
<TextView
android:id="#+id/textGeoArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="14dp"
android:text="Choose Area"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
layout_geo_area.xml // with only listview no textview
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/listViewChildGeoAreas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:gravity="left" >
</ListView>
</RelativeLayout>
Now your adapter class
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_row,parent,false);
// inflate list_row.xml with textview
holder = new ViewHolder();
holder.tv = (TextView)convertView.findViewById(R.id.textGeoArea);
holder.setTag(convertView);
}
else {
holder = (ViewHolder) convertView.getTag();
}
GeoArea curGeoArea = _myGeoArea.get(position);
holder.tv.setText(curGeoArea.name);
return convertView;
}
static class ViewHolder // use a view holder for smooth scrolling an performance
{
TextView tv;
}
You have a custom adapter.
public class AdapterGeoArea extends ArrayAdapter<GeoArea>{
Now you set the adapter to listview like below
AdapterGeoArea adapter = new AdapterGeoArea(this, testList);
ListView lv = (ListView) findViewById(R.id.listViewChildGeoAreas);
lv.setAdapter(adapter);
So why do you need the below. remove these
if(curGeoArea.subGeoAreas.size()>0){
ArrayList<GeoArea> testList = new ArrayList<GeoArea>();
AdapterGeoArea adapter = new AdapterGeoArea(_myContext, testList);
for(GeoArea childGeoArea:curGeoArea.subGeoAreas){
testList.add(childGeoArea);
}
holder.listViewChildGeoAreas.setAdapter(adapter);

Categories

Resources