3

I'm struggling with assigning my listview row more than one textview. I want my row to have one textview for a person's name, one for address and one for age - but I'm not succeeding in doing so.

If someone could provide me with a simple example, that would be great.

Thanks!

Here's my custom ArrayAdapter

    import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class MyAdapter extends BaseAdapter {
    private LayoutInflater mInflater = null;
    private ArrayList<Invoice> peopleList;

    private final class ViewHolder {
        TextView kidLabel;
        TextView restLabel;
        TextView fristLabel;
        TextView amountLabel;
    }

    private ViewHolder mHolder = null;

    public MyAdapter(Context context) {
        Context mContext = context;
        mInflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        return peopleList.size();
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            mHolder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.row, null);
            convertView.setTag(mHolder);
        } else {
            mHolder = (ViewHolder) convertView.getTag();
        }

        mHolder.kidLabel = (TextView) convertView.findViewById(R.id.kidLabel);
        mHolder.kidLabel.setText(peopleList.get(position).getKID());

        mHolder.fristLabel = (TextView) convertView
                .findViewById(R.id.fristLabel);
        mHolder.fristLabel.setText(peopleList.get(position).getDueDate());

        mHolder.restLabel = (TextView) convertView.findViewById(R.id.restLabel);
        mHolder.restLabel.setText(peopleList.get(position).getDueAmount());

        mHolder.amountLabel = (TextView) convertView
                .findViewById(R.id.amountLabel);
        mHolder.amountLabel.setText(peopleList.get(position).getDueAmount());

        return convertView;
    }
}

And Here's my custom row xml:

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/RelativeLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="fill_parent"
        android:layout_height="45dip"
        android:src="@drawable/cellback" android:scaleType="fitXY"/>

    <TextView
        android:id="@+id/kidLabel"
        android:layout_width="160dip"
        android:layout_height="25dip"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:textSize="13dip" android:textColor="#333"/>

    <TextView
        android:id="@+id/fristLabel"
        android:layout_width="160dip"
        android:layout_height="20dip"
        android:layout_marginTop="25dip"
        android:textSize="11dip" android:textColor="#999"/>

    <TextView
        android:id="@+id/amountLabel"
        android:layout_width="160dip"
        android:layout_height="25dip"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:textSize="13dip" android:layout_marginLeft="160dip" android:gravity="right" android:textColor="#333"/>

    <TextView
        android:id="@+id/restLabel"
        android:layout_width="160dip"
        android:layout_height="20dip"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:textSize="11dip" android:layout_marginLeft="160dip" android:layout_marginTop="25dip" android:gravity="right" android:textColor="#999"/>

</RelativeLayout>
2

2 Answers 2

9

First,you should create a xml to describe what your list cell likes,called cell.xml,for example:

 <?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="wrap_content"
    android:orientation="vertical" android:background="@color/spink">

    <TextView
        android:id="@+id/name_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Name"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/address_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Address"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</LinearLayout>

Second,create a adapter.It helps your listview to show data:

public class MyAdapter extends BaseAdapter {
private LayoutInflater mInflater = null;
private ArrayList<People> peopleList;

private final class ViewHolder {
TextView nameTextView;
TextView addressTextView;
}

private ViewHolder mHolder = null;

public MyAdapter(Context context) {
mContext = context;
mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
return peopleList.size();
}

@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
mHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.cell, null);           
convertView.setTag(mHolder);
} else {
mHolder = (ViewHolder)convertView.getTag(); 
}

mHolder.nameTextView (TextView)convertView.findViewById(R.id.name_textView);
mHolder.nameTextView.setText(peopleList.get(position).getName());
mHolder.addressTextView = (TextView)convertView.findViewById(R.id.address_textView);
mHolder.addressTextView.setText(peopleList.get(position).getAddress());

return convertView;
}
}

Finally,when you want to show the data,do this in your activity:

listView.setAdapter(new MyAdapter());

hope it helps you.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! I'm leaning towards this anser, but when I try to assign the adapter to the listView like so: ListView infoTable = (ListView) this.findViewById(R.id.list); MyAdapter ad = new MyAdapter(getBaseContext()); infoTable.setAdapter(ad); The app crashes with no clear error message...
turns out it was the peopleList being empty that crashed the app. So this is answered. Thanks!
2

You need to create a custom listview layout and a custom array adapter (I have also created a custom class to work with the layout).

An example of this is:

Custom class that works with the custom listview layout:

package id10778734.sceresini.week4.exercise3.views;

import id10778734.sceresini.week4.exercise3.R;
import id10778734.sceresini.week4.exercise3.Constants;
import id10778734.sceresini.week4.exercise3.tasks.Task;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class TaskListItem extends LinearLayout {
    private Task mTask;
    private ImageView mEmailImageView;
    private ImageView mPriorityImageView;
    private TextView mTaskNameTextView;
    private TextView mTaskResponsibleTextView;
    private ImageView mDeleteImageView;

    public TaskListItem (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onFinishInflate() {
        super.onFinishInflate();
        mEmailImageView = (ImageView) findViewById(R.id.list_row_layout_email_button);
        mPriorityImageView = (ImageView) findViewById(R.id.list_row_layout_priority_icon);
        mTaskNameTextView = (TextView) findViewById(R.id.list_row_layout_task_name);
        mTaskResponsibleTextView = (TextView) findViewById(R.id.list_row_layout_responsible);
        mDeleteImageView = (ImageView) findViewById(R.id.list_row_layout_delete_button);

    }

    public void setTask (Task task) {
        mTask = task;
        mEmailImageView.setTag(task);

        switch (task.getPriority()) {
        case Constants.LOW: 
                            mPriorityImageView.setImageResource(R.drawable.low);
                            break;
        case Constants.MEDIUM: 
                            mPriorityImageView.setImageResource(R.drawable.medium);
                            break;
        case Constants.HIGH:
                            mPriorityImageView.setImageResource(R.drawable.high);
                            break;
        }

        mTaskNameTextView.setText(task.getName());
        mTaskResponsibleTextView.setText(task.getResponsible());
        mDeleteImageView.setTag(task);
    }

    public Task getTask () {
        return mTask;
    }

    public ImageView getDeleteImageView () {
        return mDeleteImageView;
    }

    public ImageView getEmailImageView () {
        return mEmailImageView;
    }
}

the custom layout xml file:

<?xml version="1.0" encoding="UTF-8"?>
<id10778734.sceresini.week4.exercise3.views.TaskListItem 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="5dip" >

    <ImageView
        android:id="@+id/list_row_layout_email_button"
        android:layout_width="36dip"
        android:layout_height="36dip"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="4dip"
        android:layout_marginRight="5dip"
        android:contentDescription="@string/list_row_email_icon_description"
        android:src="@android:drawable/ic_dialog_email" />

    <ImageView
        android:id="@+id/list_row_layout_priority_icon"
        android:layout_width="24dip"
        android:layout_height="24dip"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="4dip"
        android:layout_marginRight="10dip"
        android:contentDescription="@string/view_task_priority_icon_description" />

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical" >

        <TextView
            android:id="@+id/list_row_layout_task_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@+id/list_row_layout_responsible"
            android:paddingRight="5dip"
            android:textAppearance="@style/list_row_task_name" />

        <TextView
            android:id="@id/list_row_layout_responsible"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toLeftOf="@+id/list_row_layout_delete_button"
            android:maxWidth="100dip"
            android:textAppearance="@style/list_row_task_responsible" />

        <ImageView
            android:id="@id/list_row_layout_delete_button"
            android:layout_width="36dip"
            android:layout_height="36dip"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginLeft="5dip"
            android:layout_marginRight="5dip"
            android:contentDescription="@string/delete_task_icon_description"
            android:src="@drawable/task_delete" />
    </RelativeLayout>

</id10778734.sceresini.week4.exercise3.views.TaskListItem>

And the custom array adapter:

package id10778734.sceresini.week4.exercise3;

import id10778734.sceresini.week4.exercise3.R;
import id10778734.sceresini.week4.exercise3.tasks.Task;
import id10778734.sceresini.week4.exercise3.views.TaskListItem;

import java.util.ArrayList;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

public class TaskListAdapter extends BaseAdapter
{

    private ArrayList<Task> mTasks;
    private Context mContext;
    private AlertDialog unsavedChangesDialog;
    private TaskManagerApplication mApp;

    public TaskListAdapter(Context context, ArrayList<Task> tasks) {
        super();
        mApp = (TaskManagerApplication) context.getApplicationContext();
        mContext = context;
        mTasks = tasks;
    }

    @Override
    public int getCount()
    {
        return mTasks.size();
    }

    @Override
    public Task getItem(int position)
    {
        return (null == mTasks) ? null : mTasks.get(position);
    }

    @Override
    public long getItemId(int position)
    {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        TaskListItem tli;

        if (null == convertView)
        {
            tli = (TaskListItem) View.inflate(mContext, R.layout.list_row_layout, null);
        } else
        {
            tli = (TaskListItem) convertView;
        }

        tli.setTask(mTasks.get(position));

        tli.getEmailImageView().setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v)
            {
                emailTask(v);
            }
        });

        tli.getDeleteImageView().setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v)
            {
                deleteTask(v);
            }
        });

        return tli;
    }

    /**
     * deleteTask() prompts the user with an alert dialog and presents them with
     * the option to continue with the delete request or to cancel the request.
     * Upon confirmation, the selected Task object which is retrieved from the
     * deleteTaskIcon tag, will be removed from the list of currentTasks.
     * 
     * @param v
     */
    protected void deleteTask(View v)
    {
        final Task t = (Task) v.getTag();
        String alertMessage = String.format(mContext.getString(R.string.delete_task_message), t.getName());

        unsavedChangesDialog = new AlertDialog.Builder(mContext).setTitle(R.string.delete_task_title).setMessage(alertMessage)
        // Delete the task and refresh the adapter.
                .setPositiveButton(R.string.delete_task_delete, new AlertDialog.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface arg0, int arg1)
                    {
                        // Remove task from array list
                        mTasks.remove(t);

                        // Remove task from Database
                        mApp.deleteTask(t);

                        // Display toast message stating the task was deleted
                        mApp.displayToast(Constants.TASK_DELETED);

                        // Update listView with modified adapter
                        forceReload();
                    }
                })
                // Cancel the delete request and do nothing.
                .setNegativeButton(R.string.delete_task_cancel, new AlertDialog.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface arg0, int arg1)
                    {
                        unsavedChangesDialog.cancel();
                    }
                }).create();

        unsavedChangesDialog.show();
    }

    /**
     * emailTask() populates the selected task into an intent which allows the
     * user to select a client to send the task. This is formatted for email
     * clients.
     * 
     * @param v
     */
    protected void emailTask(View v)
    {
        // Retrieve the task that is allocated to this RowView
        final Task t = (Task) v.getTag();

        // Instantiate the intent that will be used to call the email client
        Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);

        // Variables/Arrays to hold email attributes
        String[] emailRecipients = { mContext.getString(R.string.email_task_to_email) };
        String emailType = mContext.getString(R.string.email_task_type);
        String emailTitle = mContext.getString(R.string.email_task_title);
        String emailSubject = String.format(mContext.getString(R.string.email_task_subject), t.getName());
        String emailMessage = String.format(mContext.getString(R.string.email_task_message), t.getResponsible(), t.getName(), mContext.getString(t.getPriorityStringId()));

        // Add the email attributes to the intent
        emailIntent.setType(emailType);
        emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, emailRecipients);
        emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, emailSubject);
        emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, emailMessage);

        // Start intent
        mContext.startActivity(Intent.createChooser(emailIntent, emailTitle));
    }

    /**
     * Refreshes the ListView with the modified dataset.
     */
    public void forceReload()
    {
        notifyDataSetChanged();
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.