适配器 onClickListener 没有在应该触发的时候触发,或者正确更新视图
Adapter onClickListener not firing when it should, or updating View correctly
求助!这是有效的,但没有版本控制。
评分按钮正在更新一个 TextView 从被点击的按钮向下几行,并且 Android 我为解决问题而输入的 Studio 日志甚至没有记录按钮已被点击。
整个事情都在横向发展,问题是'为什么点击 plusButton 和 minusButton 会在我想要更新内容的 'active' 行下方的几行中更新一个 TextView。
这是一张图片,我点了4次小熊,它更新了Player 4的得分TextView,wth?
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;
}
}
您的直接问题是整个适配器只有一个 ScoreHolder
对象。创建了多个视图,但由于它们都使用相同的支架,所有 OnClickListeners
将更改最后创建的列表行的 TextView
。
大多数 AdapterViews
,包括 ListView
,都使用 Views
的池来存储他们的项目。 convertView
参数最有可能是 null
前几次 getView
被调用,当池已满时,您将开始接收非空对象作为 converView
s .
TL;DR:您有多个列表项 Views
共享一个 ScoreHolder
对象。
尽量不要将其作为适配器的字段
public ScoreHolder holder = new ScoreHolder();
而且我认为你这样做的原因是因为你无法从 onClick 方法中获得对 holder 的引用,并且 IDE 试图使 holder 有效地最终化,但那不是这是可能的,因为您需要将 holder 分配给两个不同的事物,因此您只需将 holder 移动到一个字段即可。
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);
如果这不起作用(不记得三元是否对最终变量起作用),那么你可以将两个按钮的标签也设置为持有者,然后在两个点击监听器中获取持有者v
中的 onClick 方法
求助!这是有效的,但没有版本控制。
评分按钮正在更新一个 TextView 从被点击的按钮向下几行,并且 Android 我为解决问题而输入的 Studio 日志甚至没有记录按钮已被点击。
整个事情都在横向发展,问题是'为什么点击 plusButton 和 minusButton 会在我想要更新内容的 'active' 行下方的几行中更新一个 TextView。
这是一张图片,我点了4次小熊,它更新了Player 4的得分TextView,wth?
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;
}
}
您的直接问题是整个适配器只有一个 ScoreHolder
对象。创建了多个视图,但由于它们都使用相同的支架,所有 OnClickListeners
将更改最后创建的列表行的 TextView
。
大多数 AdapterViews
,包括 ListView
,都使用 Views
的池来存储他们的项目。 convertView
参数最有可能是 null
前几次 getView
被调用,当池已满时,您将开始接收非空对象作为 converView
s .
TL;DR:您有多个列表项 Views
共享一个 ScoreHolder
对象。
尽量不要将其作为适配器的字段
public ScoreHolder holder = new ScoreHolder();
而且我认为你这样做的原因是因为你无法从 onClick 方法中获得对 holder 的引用,并且 IDE 试图使 holder 有效地最终化,但那不是这是可能的,因为您需要将 holder 分配给两个不同的事物,因此您只需将 holder 移动到一个字段即可。
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);
如果这不起作用(不记得三元是否对最终变量起作用),那么你可以将两个按钮的标签也设置为持有者,然后在两个点击监听器中获取持有者v