通过按下同一适配器中的按钮更改ArrayAdapter内的TextView文本

时间:2015-07-07 19:35:42

标签: android android-arrayadapter clicklistener

这是我在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吗?

3 个答案:

答案 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;
    }
}