在Android

时间:2015-12-06 06:34:52

标签: android listview baseadapter notifydatasetchanged

当我点击列表行中的按钮时,我基本上尝试隐藏并在列表行中显示文本。我在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。

4 个答案:

答案 0 :(得分:3)

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

} 

这会奏效。

答案 1 :(得分:1)

调用notifyDataSetChanged()会导致ListView重建所有内容。它将删除其子视图,为所有可见的项目调用getView(),因此您将重新绑定这些项目的所有数据。

但您的数据实际上并没有改变。您还没有修改问题列表中的任何内容,因此再次绑定数据毫无意义。相反,您尝试更改ViewHolder对象中的某些内容,但无法保证convertViewnotifyDataSetChanged()与{C}}之前的位置相同,因此它与#39;某些其他项目可能受到影响(或者根本没有?)。

尝试从notifyDataSetChanged()删除对OnClickListener的通话。可见性更改应该会导致视图层次结构的重新布局,但只要您没有告诉ListView数据已更改,它就应该保留所有当前的子级。

答案 2 :(得分:0)

创建适配器的实例,例如C/A,将其设置为Adapter myAdapter = new Adapterlistview,例如recyclerview,并且每次向其添加新数据时调用{{1 }}

答案 3 :(得分:0)

变量flag对对象holder不具有上下文敏感性。所以flag在你的情况下总是=假。最初setVisibility(View.GONE)怎么样?然后setVisibility(View.VISIBLE)仅在点击ivArrow时。