适配器onClickListener何时不应触发,或正确更新View

时间:2016-10-13 12:39:21

标签: android adapter android-arrayadapter

帮助!这是有效的,但没有版本控制。

评分按钮正在从单击的一行向下更新TextView几行,而我输入问题解决的Android Studio日志甚至没有注册按钮被击中。

整个事情是侧面的,问题是“为什么点击plusButton和minusButton会在”活动“的几行中更新一个TextView。我希望更新内容的行。

这是一张照片,我已经点了4次熊,它更新了玩家4的得分TextView,是吗? enter image description here

package com.basketball.dating;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;

/**
 * {@link ScoreBoardAdapter} is an {@link ArrayAdapter} that can provide the layout for each list item
 * based on a data source, which is a list of {@link ScoreBoard} objects.
 */
public class ScoreBoardAdapter extends ArrayAdapter<ScoreBoard>  {

    /** Resource ID for the background color for this list of words */
    private int mColorResourceId;

    final String TAG = "ScoreBoardAdapter";
    public ScoreHolder holder = new ScoreHolder();

    /**
     * Create a new {@link ScoreBoardAdapter} object.
     *
     * @param context is the current context (i.e. Activity) that the adapter is being created in.
     * @param scoreBoards is the list of {@link ScoreBoard}s to be displayed.
     */
    public ScoreBoardAdapter(Context context, ArrayList<ScoreBoard> scoreBoards) {
        super(context, 0, scoreBoards);
        //mColorResourceId = new ContextCompat().getColor(getContext(), R.color.colorAccent);
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        // Check if an existing view is being reused, otherwise inflate the view
        View listItemView = convertView;
        //ScoreHolder holder = new ScoreHolder();

        if (listItemView == null) {
            listItemView = LayoutInflater.from(getContext()).inflate(
                    R.layout.list_item, parent, false);
            // now stuff all the row's views into a ScoreHolder object
            holder.plusButton = (TextView) listItemView.findViewById(R.id.plusButton);
            holder.minusButton = (TextView) listItemView.findViewById(R.id.minusButton);
            holder.scoreTextView = (TextView) listItemView.findViewById(R.id.score_text_view);

            // now attach these details to the row, so it 'remembers' they're there
            listItemView.setTag(holder);
        }
        else {
            Log.wtf("ScoreBoardADAPTER", "NOT_NULL ROW");
            holder = (ScoreHolder) listItemView.getTag();
        }
        holder.plusButton.setOnClickListener(new View.OnClickListener() {
            //private int pos = position;
            public void onClick(View v) {
                //TextView mPlusButton = (TextView) v;
                Log.wtf(TAG, "hit increment " + position);
                int score = Integer.parseInt((String) holder.scoreTextView.getText());
                if (score < 99) {
                    holder.scoreTextView.setText(String.valueOf(score + 1));
                }
            }
        });
        holder.minusButton.setOnClickListener(new View.OnClickListener() {
            //private int pos = position;
            public void onClick(View v) {
                //TextView mMinusButton = (TextView) v;
                int score = Integer.parseInt((String) holder.scoreTextView.getText());
                holder.scoreTextView.setText(String.valueOf(score - 1));
            }
        });

        // Get the {@link Word} object located at this position in the list
        ScoreBoard currentScoreBoard = getItem(position);

        // Find the TextView in the list_item.xml layout with the ID miwok_text_view.
        TextView playerNameTextView = (TextView) listItemView.findViewById(R.id.playerName);

        playerNameTextView.setText("Player " + String.valueOf(currentScoreBoard.getPlayerName()) );

        // Find the ImageView in the list_item.xml layout with the Avatar.
        ImageView imageView = (ImageView) listItemView.findViewById(R.id.playerAvatar);
        // display the provided image based on the resource ID
        imageView.setImageResource(currentScoreBoard.getAvatar());
        // Make sure the view is visible
        imageView.setVisibility(View.VISIBLE);

        // TODO adapt to colour the leaders gold, silver, bronze
//        // Set the theme color for the list item
//        View textContainer = listItemView.findViewById(R.id.text_container);
//        // Find the color that the resource ID maps to
//        int color = ContextCompat.getColor(getContext(), R.color.colorAccent);
//        // Set the background color of the text container View
//        textContainer.setBackgroundColor(color);

        // Return the whole list item layout so that it can be shown in the ListView.
        return listItemView;
    }

    /* need to be able to save an object of key textViews for each list item , or 'row' */
    static class ScoreHolder {
        TextView plusButton;
        TextView minusButton;
        TextView scoreTextView;
    }
}

2 个答案:

答案 0 :(得分:2)

尽量不要将其作为适配器的字段

public ScoreHolder holder = new ScoreHolder();

我认为你这样做的原因是因为你无法从onClick方法中获得对持有者的引用,并且IDE试图使持有者有效地最终,但这是不可能的,因为你需要将持有人分配给两个不同的东西,所以你只需将持有人移动到一个字段。

TL; DR尝试将其放回getView方法

View listItemView = convertView;
final ScoreHolder holder = listItemView == null ? new ScoreHolder() : listItemView.getTag();

    if (listItemView == null) {
        listItemView = LayoutInflater.from(getContext()).inflate(
                R.layout.list_item, parent, false);

如果这不起作用(不记得三元是否在最终变量上工作),那么你可以将两个按钮的标签设置为持有者,然后在两个点击监听器中获取持有者onClick方法来自v

答案 1 :(得分:0)

您的直接问题是整个适配器只有一个ScoreHolder对象。创建了多个视图,但由于它们都使用相同的持有者,所有OnClickListeners都将更改上次创建的列表行的TextView

大多数AdapterViews,包括ListView,会为其商品使用Views池。 convertView参数在调用null的前几次很可能是getView,当池已满时,您将开始接收非空对象converView s

TL; DR:您有多个列表项Views共享一个ScoreHolder对象。