使用 convertView android 的多个 xml 视图
multiple xml views with convertView android
我正在尝试编写一个 ListView 适配器,它将根据我为其创建视图的数据属性传递基于多个 xml 文件之一的视图。我的代码工作正常,除非我尝试使用 convertView 来加快进程。无论我如何尝试使用它,我要么使我的程序崩溃,要么得到奇怪的输出。我理解 为什么 这对 convertView 来说是个问题,但我强烈怀疑我仍然可以完成这项工作。谁能告诉我如何修复我的代码?
(现在我使用 convertView 作为我 return 的视图的名称,即使我没有 'if (convertView==null)' 例程正常工作)
public class PaymentListFragment extends ListFragment {
private ArrayList<Payment> mPayments;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.payment_schedule_title);
mPayments = PaymentSchedule.get(getActivity()).getPayments();
PaymentAdapter adapter = new PaymentAdapter(mPayments);
setListAdapter(adapter);
}
private class PaymentAdapter extends ArrayAdapter<Payment> {
public PaymentAdapter(ArrayList<Payment> payments) {
super(getActivity(), 0, payments);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Payment p = mPayments.get(position);
//normal
//if (convertView == null) {
//cant work out how to use convertview conditional without screwing up project
//it would speed it up to fix this however
if (p.type == Payment.TYPE_START) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_start, null);
TextView remainDisplay =
(TextView) convertView.findViewById(R.id.remainDisplayStart);
remainDisplay.setText(p.getRemainString());
TextView paymentDate =
(TextView) convertView.findViewById(R.id.paymentDateStart);
paymentDate.setText(p.getDateString());
TextView paymentDisplay =
(TextView) convertView.findViewById(R.id.paymentDisplayStart);
paymentDisplay.setText(p.getDefaultPaymentString());
TextView aprDisplay =
(TextView) convertView.findViewById(R.id.aprDisplayStart);
aprDisplay.setText(p.getInterestRate() * 1200 + "%");
} else {
//if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_payment, null);
//}
TextView paymentDate =
(TextView) convertView.findViewById(R.id.paymentDate);
paymentDate.setText(p.getDateString());
TextView paymentDisplay =
(TextView) convertView.findViewById(R.id.paymentDisplay);
paymentDisplay.setText(p.getPaymentString());
TextView principalDisplay =
(TextView) convertView.findViewById(R.id.principalDisplay);
principalDisplay.setText(p.getPrincipalString());
TextView interestDisplay =
(TextView) convertView.findViewById(R.id.interestDisplay);
interestDisplay.setText(p.getInterestString());
TextView remainDisplay =
(TextView) convertView.findViewById(R.id.remainDisplay);
remainDisplay.setText(p.getRemainString());
}
//}
return convertView;
}
}
}
您可以使用以下技巧:
总是在您创建 convertView
时附加一个 标签 (setTag()
),指定 类型 布局(在您的情况下 R.layout.list_item_start
或 R.layout.list_item_payment
)。
当您检查 convertView != null
时,您还需要检查 convertView.getTag()
指定的类型是否与您正在更新的布局相同,以避免膨胀正常运行,因为:
- 如果 类型不同 您需要使用新的膨胀操作覆盖
convertView
,因为您需要创建正确的布局类型。
- 如果 类型相同 您可以简单地更新布局而无需膨胀操作
您还可以通过采用 ViewHolder pattern.
来改进整个代码
谢谢! Bonnyz 的建议奏效了。我添加了以下代码:
Payment p = mPayments.get(position);
if (convertView == null || convertView.getTag() != p.type) {
if(p.type == Payment.TYPE_START) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_start, null);
convertView.setTag(Payment.TYPE_START);
} else{
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_payment, null);
convertView.setTag(Payment.TYPE_PAYMENT);
}
}
我也将尝试使用 ViewHolder。我今天才知道。
public class CustomAdapter extends BaseAdapter {
String[] frName;
String[] lrName;
String[] myLocation;
Context context;
int[] imageId;
private static LayoutInflater inflater = null;
public CustomAdapter(MainActivity mainActivity, String[] fstName, String[] lstName, String[] location, int[] prgmImages) {
super();
context = mainActivity;
frName = fstName;
lrName = lstName;
myLocation = location;
imageId = prgmImages;
inflater = (LayoutInflater) context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return 12;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public class Holder {
TextView tv_frname, tv_lrname, tv_location, tv_fstname, tv_lstname;
ImageView img;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
Holder holder = new Holder();
if (position < frName.length) {
convertView = inflater.inflate(R.layout.myadapterdesin, null);
holder.tv_frname = (TextView) convertView.findViewById(R.id.frname);
holder.tv_lrname = (TextView) convertView.findViewById(R.id.lrname);
holder.tv_location = (TextView) convertView.findViewById(R.id.place);
holder.tv_frname.setText(frName[position]);
holder.tv_lrname.setText(lrName[position]);
holder.tv_location.setText(myLocation[position]);
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(context, "You Clicked " + position, Toast.LENGTH_SHORT).show();
}
});
return convertView;
} else if (position >= frName.length) {
convertView = inflater.inflate(R.layout.mylist, null);
holder.img = (ImageView) convertView.findViewById(R.id.img_view);
holder.tv_fstname = (TextView) convertView.findViewById(R.id.fstname);
holder.tv_lstname = (TextView) convertView.findViewById(R.id.lstname);
holder.tv_fstname.setText(frName[(position) - (frName.length)]);
holder.tv_lstname.setText(lrName[(position) - (frName.length)]);
holder.img.setImageResource(imageId[(position) - (frName.length)]);
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(context, "You Clicked " + position, Toast.LENGTH_SHORT).show();
}
});
return convertView;
}
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(context, "You Clicked " + position, Toast.LENGTH_SHORT).show();
}
});
return convertView;
}
}
我正在尝试编写一个 ListView 适配器,它将根据我为其创建视图的数据属性传递基于多个 xml 文件之一的视图。我的代码工作正常,除非我尝试使用 convertView 来加快进程。无论我如何尝试使用它,我要么使我的程序崩溃,要么得到奇怪的输出。我理解 为什么 这对 convertView 来说是个问题,但我强烈怀疑我仍然可以完成这项工作。谁能告诉我如何修复我的代码? (现在我使用 convertView 作为我 return 的视图的名称,即使我没有 'if (convertView==null)' 例程正常工作)
public class PaymentListFragment extends ListFragment {
private ArrayList<Payment> mPayments;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.payment_schedule_title);
mPayments = PaymentSchedule.get(getActivity()).getPayments();
PaymentAdapter adapter = new PaymentAdapter(mPayments);
setListAdapter(adapter);
}
private class PaymentAdapter extends ArrayAdapter<Payment> {
public PaymentAdapter(ArrayList<Payment> payments) {
super(getActivity(), 0, payments);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Payment p = mPayments.get(position);
//normal
//if (convertView == null) {
//cant work out how to use convertview conditional without screwing up project
//it would speed it up to fix this however
if (p.type == Payment.TYPE_START) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_start, null);
TextView remainDisplay =
(TextView) convertView.findViewById(R.id.remainDisplayStart);
remainDisplay.setText(p.getRemainString());
TextView paymentDate =
(TextView) convertView.findViewById(R.id.paymentDateStart);
paymentDate.setText(p.getDateString());
TextView paymentDisplay =
(TextView) convertView.findViewById(R.id.paymentDisplayStart);
paymentDisplay.setText(p.getDefaultPaymentString());
TextView aprDisplay =
(TextView) convertView.findViewById(R.id.aprDisplayStart);
aprDisplay.setText(p.getInterestRate() * 1200 + "%");
} else {
//if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_payment, null);
//}
TextView paymentDate =
(TextView) convertView.findViewById(R.id.paymentDate);
paymentDate.setText(p.getDateString());
TextView paymentDisplay =
(TextView) convertView.findViewById(R.id.paymentDisplay);
paymentDisplay.setText(p.getPaymentString());
TextView principalDisplay =
(TextView) convertView.findViewById(R.id.principalDisplay);
principalDisplay.setText(p.getPrincipalString());
TextView interestDisplay =
(TextView) convertView.findViewById(R.id.interestDisplay);
interestDisplay.setText(p.getInterestString());
TextView remainDisplay =
(TextView) convertView.findViewById(R.id.remainDisplay);
remainDisplay.setText(p.getRemainString());
}
//}
return convertView;
}
}
}
您可以使用以下技巧:
总是在您创建
convertView
时附加一个 标签 (setTag()
),指定 类型 布局(在您的情况下R.layout.list_item_start
或R.layout.list_item_payment
)。当您检查
convertView != null
时,您还需要检查convertView.getTag()
指定的类型是否与您正在更新的布局相同,以避免膨胀正常运行,因为:- 如果 类型不同 您需要使用新的膨胀操作覆盖
convertView
,因为您需要创建正确的布局类型。 - 如果 类型相同 您可以简单地更新布局而无需膨胀操作
- 如果 类型不同 您需要使用新的膨胀操作覆盖
您还可以通过采用 ViewHolder pattern.
来改进整个代码谢谢! Bonnyz 的建议奏效了。我添加了以下代码:
Payment p = mPayments.get(position);
if (convertView == null || convertView.getTag() != p.type) {
if(p.type == Payment.TYPE_START) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_start, null);
convertView.setTag(Payment.TYPE_START);
} else{
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_payment, null);
convertView.setTag(Payment.TYPE_PAYMENT);
}
}
我也将尝试使用 ViewHolder。我今天才知道。
public class CustomAdapter extends BaseAdapter {
String[] frName;
String[] lrName;
String[] myLocation;
Context context;
int[] imageId;
private static LayoutInflater inflater = null;
public CustomAdapter(MainActivity mainActivity, String[] fstName, String[] lstName, String[] location, int[] prgmImages) {
super();
context = mainActivity;
frName = fstName;
lrName = lstName;
myLocation = location;
imageId = prgmImages;
inflater = (LayoutInflater) context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return 12;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public class Holder {
TextView tv_frname, tv_lrname, tv_location, tv_fstname, tv_lstname;
ImageView img;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
Holder holder = new Holder();
if (position < frName.length) {
convertView = inflater.inflate(R.layout.myadapterdesin, null);
holder.tv_frname = (TextView) convertView.findViewById(R.id.frname);
holder.tv_lrname = (TextView) convertView.findViewById(R.id.lrname);
holder.tv_location = (TextView) convertView.findViewById(R.id.place);
holder.tv_frname.setText(frName[position]);
holder.tv_lrname.setText(lrName[position]);
holder.tv_location.setText(myLocation[position]);
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(context, "You Clicked " + position, Toast.LENGTH_SHORT).show();
}
});
return convertView;
} else if (position >= frName.length) {
convertView = inflater.inflate(R.layout.mylist, null);
holder.img = (ImageView) convertView.findViewById(R.id.img_view);
holder.tv_fstname = (TextView) convertView.findViewById(R.id.fstname);
holder.tv_lstname = (TextView) convertView.findViewById(R.id.lstname);
holder.tv_fstname.setText(frName[(position) - (frName.length)]);
holder.tv_lstname.setText(lrName[(position) - (frName.length)]);
holder.img.setImageResource(imageId[(position) - (frName.length)]);
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(context, "You Clicked " + position, Toast.LENGTH_SHORT).show();
}
});
return convertView;
}
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(context, "You Clicked " + position, Toast.LENGTH_SHORT).show();
}
});
return convertView;
}
}