这是我在stackoverflow中的第一个问题。 如果我做错了,请纠正我。 所以......我们走了:
我正在尝试在ArrayAdapter中创建一个Button的onClickListener,它在同一布局中更改TextView的文本。但是发生的事情是:当我单击Button时,它会更改多个TextView的文本。 它是这样的:如果我按下列表中的第一个按钮,它会改变5h,9th,13th的文本.....为什么会发生这种情况?
我想要一个onClickListener来更改位于samelayout上的TextView的文本。
PS:当我说“按钮”时,它实际上是一个“ImageView”
适配器的代码:
public class ProductAdapter extends ArrayAdapter<Produtc> {
public ProductAdapter (Context context, ArrayList<Product> products) {
super(context, 0, products);
}
@Override
public View getView (final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
final Product product = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.layout_sliders, parent, false);
viewHolder = new ViewHolder();
viewHolder.textViewProductIndex = (TextView) convertView.findViewById(R.id.textViewIndex);
viewHolder.textViewProductName = (TextView) convertView.findViewById(R.id.textViewProductName);
viewHolder.textViewQuantity = (TextView) convertView.findViewById(R.id.textViewQuantity);
viewHolder.imageViewADD = (ImageView) convertView.findViewById(R.id.buttonAdd);
viewHolder.imageViewFILL = (ImageView) convertView.findViewById(R.id.buttonFill);
viewHolder.imageViewCheck = (ImageView) convertView.findViewById(R.id.buttonCheck);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
if (produto != null) {
viewHolder.textViewProductIndex.setText(product.getProductIndex());
viewHolder.textViewProductName.setText(product.getProductName());
viewHolder.imageViewADD.setTag(position);
viewHolder.imageViewFILL.setTag(position);
viewHolder.imageViewCheck.setTag(position);
viewHolder.textViewProductIndex.setTag(position);
viewHolder.textViewProductName.setTag(position);
viewHolder.textViewQuantity.setTag(position);
viewHolder.imageViewADD.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewHolder.textViewQuantity.setText("TESTING");
}
});
}
return convertView;
}
class ViewHolder {
private TextView textViewProductIndex;
private TextView textViewProductName;
private TextView textViewQuantity;
private ImageView imageViewADD;
private ImageView imageViewFILL;
private ImageView imageViewCheck;
}}
其他疑问:
- 我真的要传递setTag()?
- 我应该在ListView的onItemClickListener上的setApdapter之后处理clickListeners吗?
答案 0 :(得分:1)
你在这里提出了三个问题。让我试着用这种方式解释一下。
A)关于视图的可重用性。
假设您的阵列中有100x产品。但是,在任何时间点屏幕上只显示5x产品。所以listview只会夸大5x布局。滚动时会重复使用它们(注意,通过忽略缓存机制来简化这一点)。
如果您将第一个产品的“第一个视图”上的颜色设置为橙色,会发生什么。当第6个产品重新使用仍然是橙色的“第一视图”时。
您需要为所有100x产品设置一个属性布尔值,这样您就可以在每次进入视图时根据该属性设置视图的颜色。
B)setTag是可选的。但是如果你看到问题C)的答案就很有用。
C)通常有两种方法可以为列表视图设置onclick。 - 第一种方法是每次出现时都设置onclick到EACH视图。因此,如果您从第一个产品滚动到第100个产品,您将设置100次。然后,当您向上滚动时,您需要为每个视图创建一个onclick(),因为它们会在您滚动时被覆盖。
第二种方法是创建共享点击器。你可以将它设置到每个视图中。因此,实际上只有一个侦听器实例
final OnClickListener listener = new OnClickListener() {
void onClick(View view) {
Product product = (Product)view.getTag();
// do somethign
}
}
试试这个
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
public class ProductAdapter extends ArrayAdapter<Product> {
private final LayoutInflater inflater;
private Context mContext;
private ArrayList<Product> mProducts;
final String[] switch = new String[2] { "on", "off" };
public ProductAdapter(Context context, ArrayList<Product> products) {
super(context, 0, products);
this.mContext = context;
this.mProducts = products;
inflater = mContext.getLayoutInflater();
}
public class ViewHolder {
private final TextView textViewProductIndex;
private final TextView textViewProductName;
private final TextView textViewQuantity;
private final ImageView imageViewADD;
private final ImageView imageViewFILL;
private final ImageView imageViewCheck;
private byte selected = 0;
public ViewHolder(View view) {
this.mTextViewProductIndex = (TextView) v.findViewById(R.id.textViewIndex);
this.mTextViewProductName = (TextView) v.findViewById(R.id.textViewProductName);
this.mTextViewQuantity = (TextView) v.findViewById(R.id.textViewQuantity);
this.mImageViewADD = (ImageView) v.findViewById(R.id.buttonAdd);
this.mImageViewFILL = (ImageView) v.findViewById(R.id.buttonFill);
this.mImageViewCheck = (ImageView) v.findViewById(R.id.buttonCheck);
view.setTag(this);
}
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.layout_sliders, parent);
new ViewHolder(convertView);
}
final ViewHolder holder = (ViewHolder) convertView.getTag();
holder.textViewProductIndex.setText(mProducts.get(position).getProductIndex());
holder.textViewProductName.setText(mProducts.get(position).getProductName());
holder.imageViewADD.setOnClickListener(listener);
holder.mTextViewQuantity(switch[holder.selected]);
return convertView;
}
final OnClickListener listener = new OnClickListener() {
void onClick(View view) {
final ViewHolder holder = (ViewHolder) convertView.getTag();
holder.selected ^= 1;
holder.mTextViewQuantity.setText(switch[holder.selected]);
}
}
}
另一种方法是在listview的ItemClickListener中进行设置。然而,与上述第二种方式相比,其灵活性较低。
希望这有帮助
答案 1 :(得分:0)
欢迎使用StackOverflow!
这是因为列表视图正在重用视图以提高性能。所以第1,第5,第9视图实际上是相同的。执行viewHolder = (ViewHolder) convertView.getTag();
时,您将重用现有视图而不是创建新视图,这有利于提高性能。您还在避免findViewById
来电。
要解决您的问题,您应该在每次getView()调用时设置quantity
文本。像viewHolder.textViewQuantity.setText(product.getQuantity())
这样的东西。这将覆盖当前文本。
对于setTag
,它用于存储具有View的任意对象,以便您以后可以获取它。这用于实现ViewHolder模式,但也有其他用途。您不需要在视图持有者的每个属性上调用setTag,只需要convertView.setTag(viewHolder);
。
答案 2 :(得分:0)
我会这样做:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class ProductAdapter extends ArrayAdapter<Product> {
private Context mContext;
private ArrayList<Product> mProducts;
public ProductAdapter(Context context, ArrayList<Product> products) {
super(context, 0, products);
this.mContext = context;
this.mProducts = products;
}
public class ViewHolder {
private final TextView textViewProductIndex;
private final TextView textViewProductName;
private final TextView textViewQuantity;
private final ImageView imageViewADD;
private final ImageView imageViewFILL;
private final ImageView imageViewCheck;
public ViewHolder(View v, final int position) {
this.mTextViewProductIndex = (TextView) v.findViewById(R.id.textViewIndex);
this.mTextViewProductName = (TextView) v.findViewById(R.id.textViewProductName);
this.mTextViewQuantity = (TextView) v.findViewById(R.id.textViewQuantity);
this.mImageViewADD = (ImageView) v.findViewById(R.id.buttonAdd);
this.mImageViewFILL = (ImageView) v.findViewById(R.id.buttonFill);
this.mImageViewCheck = (ImageView) v.findViewById(R.id.buttonCheck);
}
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = mContext.getLayoutInflater();
rowView = inflater.inflate(R.layout.layout_sliders, parent);
ViewHolder viewHolder = new ViewHolder(rowView, position);
rowView.setTag(viewHolder);
}
final ViewHolder holder = (ViewHolder) rowView.getTag();
holder.textViewProductIndex.setText(mProducts.get(position).getProductIndex());
holder.textViewProductName.setText(mProducts.get(position).getProductName());
holder.textViewQuantity.setText(mProducts.get(position).getQuantity());
holder.imageViewADD.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.textViewQuantity.setText("TESTING");
}
});
return rowView;
}
}