安卓自定义列表视图行

3
我正在努力为我的列表视图行分配多个文本视图。我希望我的行有一个用于人名,一个用于地址和一个用于年龄的文本视图 - 但我没有成功做到这一点。
如果有人能为我提供一个简单的示例,那就太好了。
谢谢!
这是我的自定义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;
    }
}

以下是我的自定义行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>

展示一些代码。你尝试过什么? - Th0rndike
3
有许多重复的内容,尝试使用“listview自定义布局”的第一个搜索结果是SO(stackoverflow)网站的这篇文章:http://stackoverflow.com/questions/5649872/listview-custom-layout。 - Bondax
2个回答

9
首先,您需要创建一个XML文件来描述列表单元格的样式,称为cell.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="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>

第二步,创建一个适配器。它可以帮助你的列表视图显示数据:
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;
}
}

最后,在您的活动中想要展示数据时,执行以下操作:

listView.setAdapter(new MyAdapter());

希望这能对您有所帮助。


谢谢!我倾向于这个答案,但是当我尝试将适配器分配给listView时: ListView infoTable = (ListView) this.findViewById(R.id.list); MyAdapter ad = new MyAdapter(getBaseContext()); infoTable.setAdapter(ad);应用程序崩溃,并没有明确的错误消息... - PinkFloydRocks
原来是peopleList为空导致了应用程序崩溃。问题已解决,谢谢! - PinkFloydRocks

2
你需要创建一个自定义的列表视图布局和自定义的数组适配器(我也创建了一个与布局一起使用的自定义类)。
例如:
与自定义列表视图布局一起使用的自定义类:
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;
    }
}

自定义布局的xml文件:

<?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>

还有自定义数组适配器:

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();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接