notifyDatasetChanged 在 Android 中自定义适配器的 getView() 方法中不起作用
notifyDatasetChanged is not working inside the getView() method for Custom Adapter In Android
我基本上是在单击列表行中的按钮时尝试在列表行中隐藏和显示文本。我在 getView() 方法中为按钮添加了 onClick(),然后调用了 notifyDataSetChanged()。但它不起作用。文本可见性没有变化。这是我的自定义适配器代码:
public class ListAdapter extends BaseAdapter {
private Context context;
private List<String> mListQuestion = null;
private List<String> mListAnswer = null;
ViewHolder holder = null;
boolean flag = false;
public ListAdapter(Context context, List<String> question, List<String> answer ) {
this.mListQuestion = question;
this.mListAnswer = answer;
this.context = context;
}
@Override
public Object getItem(int position)
{
return mListQuestion.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getCount() {
return mListQuestion.size();
}
@Override
@SuppressWarnings("deprecation")
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_faq_item, null);
holder = new ViewHolder();
holder.tvQuestion = (TextView) convertView.findViewById(R.id.text);
holder.tvAns = (TextView) convertView.findViewById(R.id.anstext);
holder.ivArrow = (Button)convertView.findViewById(R.id.arrow_expand);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.tvQuestion.setText(mListQuestion.get(position));
holder.tvAns.setText(mListAnswer.get(position));
holder.ivArrow.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
if (flag == false)
{
Logger.d("arrow clicked when flag is false");
holder.tvAns.setVisibility(View.VISIBLE);
holder.ivArrow.setBackgroundResource(R.drawable.up_arrow);
flag = true;
}
else if (flag == true)
{
Logger.d("arrow clicked when flag is true");
holder.tvAns.setVisibility(View.GONE);
holder.ivArrow.setBackgroundResource(R.drawable.down_arrow);
flag = false;
}
notifyDataSetChanged();
}
});
return convertView;
}
static class ViewHolder {
TextView tvQuestion;
TextView tvAns;
Button ivArrow;
}
}
有人可以告诉我这里做错了什么吗?
提前致谢。
-Arindam.
创建适配器实例,例如 Adapter myAdapter = new Adapter
,将其设置为 listview
或 recyclerview
,例如 listview.setAdapter(mydapter)
,每次向其添加新数据时调用 adapter.notifyDataSetChanged()
变量 flag
对对象 holder
上下文不敏感。所以 flag
在你的情况下总是 = false 。 setVisibility(View.GONE)
一开始怎么样?然后 setVisibility(View.VISIBLE)
仅当 ivArrow 被点击时。
调用 notifyDataSetChanged()
导致 ListView
重建一切。它将删除其子视图,为所有可见的项目调用 getView()
,因此您将重新绑定这些项目的所有数据。
但是您的数据实际上并没有改变。您还没有修改问题列表中的任何内容,因此再次绑定数据是没有意义的。相反,您已尝试更改 ViewHolder
对象中的某些内容,但不能保证 notifyDataSetChanged()
之后获得的 convertView
与之前的位置相同,因此某些 其他项受到影响(或者可能none?)。
尝试从 OnClickListener
中删除对 notifyDataSetChanged()
的调用。可见性更改应该会导致视图层次结构的重新布局,但只要您没有告诉 ListView
数据已更改,它就应该保留其所有当前子项。
public class ListAdapter extends BaseAdapter {
private Context context;
private List<String> mListQuestion = null;
private List<String> mListAnswer = null;
ViewHolder holder = null;
private List<Boolean> textViewVisibileState;
public ListAdapter(Context context, List<String> question, List<String> answer ) {
this.mListQuestion = question;
this.mListAnswer = answer;
this.context = context;
this.textViewVisibileState=new ArrayList<>(Arrays.asList(new Boolean[getCount()]));
Collections.fill(this.textViewVisibileState,false);
}
@Override
public Object getItem(int position)
{
return mListQuestion.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getCount() {
return mListQuestion.size();
}
@Override
@SuppressWarnings("deprecation")
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_faq_item, null);
holder = new ViewHolder();
holder.tvQuestion = (TextView) convertView.findViewById(R.id.text);
holder.tvAns = (TextView) convertView.findViewById(R.id.anstext);
holder.ivArrow = (Button)convertView.findViewById(R.id.arrow_expand);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.tvQuestion.setText(mListQuestion.get(position));
holder.tvAns.setText(mListAnswer.get(position));
if(textViewVisibileState.get(position))
{
holder.tvAns.setVisibility(View.GONE);
holder.ivArrow.setBackgroundResource(R.drawable.down_arrow);
}
else
{
Logger.d("arrow clicked when flag is false");
holder.tvAns.setVisibility(View.VISIBLE);
holder.ivArrow.setBackgroundResource(R.drawable.up_arrow);
}
holder.ivArrow.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
if (textViewVisibileState.get(position))
{
textViewVisibileState.set(position,false);
}
else
{
textViewVisibileState.set(position,true);
}
notifyDataSetChanged();
}
});
return convertView;
}
static class ViewHolder {
TextView tvQuestion;
TextView tvAns;
Button ivArrow;
}
}
这会奏效。
我基本上是在单击列表行中的按钮时尝试在列表行中隐藏和显示文本。我在 getView() 方法中为按钮添加了 onClick(),然后调用了 notifyDataSetChanged()。但它不起作用。文本可见性没有变化。这是我的自定义适配器代码:
public class ListAdapter extends BaseAdapter {
private Context context;
private List<String> mListQuestion = null;
private List<String> mListAnswer = null;
ViewHolder holder = null;
boolean flag = false;
public ListAdapter(Context context, List<String> question, List<String> answer ) {
this.mListQuestion = question;
this.mListAnswer = answer;
this.context = context;
}
@Override
public Object getItem(int position)
{
return mListQuestion.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getCount() {
return mListQuestion.size();
}
@Override
@SuppressWarnings("deprecation")
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_faq_item, null);
holder = new ViewHolder();
holder.tvQuestion = (TextView) convertView.findViewById(R.id.text);
holder.tvAns = (TextView) convertView.findViewById(R.id.anstext);
holder.ivArrow = (Button)convertView.findViewById(R.id.arrow_expand);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.tvQuestion.setText(mListQuestion.get(position));
holder.tvAns.setText(mListAnswer.get(position));
holder.ivArrow.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
if (flag == false)
{
Logger.d("arrow clicked when flag is false");
holder.tvAns.setVisibility(View.VISIBLE);
holder.ivArrow.setBackgroundResource(R.drawable.up_arrow);
flag = true;
}
else if (flag == true)
{
Logger.d("arrow clicked when flag is true");
holder.tvAns.setVisibility(View.GONE);
holder.ivArrow.setBackgroundResource(R.drawable.down_arrow);
flag = false;
}
notifyDataSetChanged();
}
});
return convertView;
}
static class ViewHolder {
TextView tvQuestion;
TextView tvAns;
Button ivArrow;
}
}
有人可以告诉我这里做错了什么吗? 提前致谢。
-Arindam.
创建适配器实例,例如 Adapter myAdapter = new Adapter
,将其设置为 listview
或 recyclerview
,例如 listview.setAdapter(mydapter)
,每次向其添加新数据时调用 adapter.notifyDataSetChanged()
变量 flag
对对象 holder
上下文不敏感。所以 flag
在你的情况下总是 = false 。 setVisibility(View.GONE)
一开始怎么样?然后 setVisibility(View.VISIBLE)
仅当 ivArrow 被点击时。
调用 notifyDataSetChanged()
导致 ListView
重建一切。它将删除其子视图,为所有可见的项目调用 getView()
,因此您将重新绑定这些项目的所有数据。
但是您的数据实际上并没有改变。您还没有修改问题列表中的任何内容,因此再次绑定数据是没有意义的。相反,您已尝试更改 ViewHolder
对象中的某些内容,但不能保证 notifyDataSetChanged()
之后获得的 convertView
与之前的位置相同,因此某些 其他项受到影响(或者可能none?)。
尝试从 OnClickListener
中删除对 notifyDataSetChanged()
的调用。可见性更改应该会导致视图层次结构的重新布局,但只要您没有告诉 ListView
数据已更改,它就应该保留其所有当前子项。
public class ListAdapter extends BaseAdapter {
private Context context;
private List<String> mListQuestion = null;
private List<String> mListAnswer = null;
ViewHolder holder = null;
private List<Boolean> textViewVisibileState;
public ListAdapter(Context context, List<String> question, List<String> answer ) {
this.mListQuestion = question;
this.mListAnswer = answer;
this.context = context;
this.textViewVisibileState=new ArrayList<>(Arrays.asList(new Boolean[getCount()]));
Collections.fill(this.textViewVisibileState,false);
}
@Override
public Object getItem(int position)
{
return mListQuestion.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getCount() {
return mListQuestion.size();
}
@Override
@SuppressWarnings("deprecation")
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_faq_item, null);
holder = new ViewHolder();
holder.tvQuestion = (TextView) convertView.findViewById(R.id.text);
holder.tvAns = (TextView) convertView.findViewById(R.id.anstext);
holder.ivArrow = (Button)convertView.findViewById(R.id.arrow_expand);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.tvQuestion.setText(mListQuestion.get(position));
holder.tvAns.setText(mListAnswer.get(position));
if(textViewVisibileState.get(position))
{
holder.tvAns.setVisibility(View.GONE);
holder.ivArrow.setBackgroundResource(R.drawable.down_arrow);
}
else
{
Logger.d("arrow clicked when flag is false");
holder.tvAns.setVisibility(View.VISIBLE);
holder.ivArrow.setBackgroundResource(R.drawable.up_arrow);
}
holder.ivArrow.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
if (textViewVisibileState.get(position))
{
textViewVisibileState.set(position,false);
}
else
{
textViewVisibileState.set(position,true);
}
notifyDataSetChanged();
}
});
return convertView;
}
static class ViewHolder {
TextView tvQuestion;
TextView tvAns;
Button ivArrow;
}
}
这会奏效。