2015-12-06 3 views
-1

В основном я пытаюсь скрыть и показать текст в строке списка, когда я нажимаю кнопку в строке списка. Я добавил onClick() для кнопки внутри метода getView(), а затем вызвал notifyDataSetChanged(). Но это не работает. Никаких изменений в видимости текста. Вот мой код Адаптера:notifyDatasetChanged не работает внутри метода getView() для пользовательского адаптера в Android

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.

+0

Нет смысла вызывать здесь 'notifyDataSetChanged();' для вашей цели –

+0

Можете ли вы рассказать, что еще я могу вызвать, чтобы обновить полный вид? –

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

} 

Это будет работать.

+0

Ты сделал мой день .. Он работает. Большое спасибо. –

+0

Wow..miracle: P –

+1

Большое спасибо, он отлично работает! @Песочные часы – rockstar

0

Создание экземпляра адаптера, например Adapter myAdapter = new Adapter, установите его в listview или recyclerviewlistview.setAdapter(mydapter) и например каждый раз, когда вы добавляете новые данные в его называют adapter.notifyDataSetChanged()

0

Переменная flag не контекстная объекта holder. Таким образом, flag всегда = false в вашем случае. Как насчет setVisibility(View.GONE) изначально? А затем setVisibility(View.VISIBLE) ТОЛЬКО при нажатии ivArrow.

+0

Я проверил, что falg не всегда является ложным. Когда я нажимаю кнопку «Развернуть», флаг становится истинным, и он переходит в состояние. –

+0

@ArindamMukherjee, Извините, теперь я вижу, что вы меняете значение флага. Но все же, я думаю, что это не правильная логика.Я предлагаю setVisibility (View.VISIBLE), когда пользователь нажимает на значок стрелки, как я сказал в своем сообщении. –

+0

Я уже пробовал это. Но это не работает. –

1

Вызов notifyDataSetChanged() вызывает ListView, чтобы перестроить все. Он удалит свои дочерние представления, вызовет getView() для всех элементов, которые видны, и таким образом вы будете перепроверять все данные для этих элементов.

Но ваши данные на самом деле не изменились. Вы ничего не изменили в списке вопросов, поэтому привязка данных снова бессмысленна. Вместо этого вы попытались что-то изменить в своем ViewHolder объекте, но нет гарантии, что convertView вы получите после notifyDataSetChanged() для того же положения, что и раньше, так что возможно, что у какого-то предмета было затронуто (или, возможно, вообще нет ?).

Попробуйте удалить звонок по номеру notifyDataSetChanged() с сайта OnClickListener. Изменение видимости должно привести к повторной компоновке иерархии представлений, но пока вы не сказали ListView, что данные были изменены, он должен содержать все свои текущие дочерние элементы.

+0

Я немного смущен после прочтения вашего ответа. Простите за это. Я понял, что notifyDataSetChanged() не имеет смысла, поскольку нет изменения данных. Я удалил его. Но все же он не работает. Я не понял эту часть: «Изменение видимости должно привести к повторной компоновке иерархии представлений, но пока вы не сказали ListView о том, что данные изменились, он должен содержать всех своих текущих детей». Не могли бы вы немного подробнее остановиться. –

+2

@ArindamMukherjee Когда вид изменяется с VISIBLE на GONE (или наоборот), он вызывает 'requestLayout()'. Android должен измерять, компоновать и рисовать иерархию представлений, чтобы показать новое состояние. ListView - это ViewGroup; у него есть дети, он их измеряет, выкладывает и рисует. Если вы вызываете notifyDataSetChanged, LIstView удаляет его дочерние элементы и строит новые (которые затем измеряются, выкладываются и рисуются). Я предлагаю не называть это, чтобы ListView мог измерять/компоновать/рисовать детей, которые у него уже есть, включая тех, кто изменил видимость. – Karakuri

+0

@ArindamMukherjee Возможно, стоит попробовать использовать RecyclerView вместо ListView. ListView был разработан для полного контроля над своими дочерними элементами, включая клики, и поэтому вы бы предоставили «OnItemClickListener». Предоставление некоторым под-регионам этих детей кликабельности всегда было немного причудливым. RecyclerView использует противоположный подход: в основном он ничего не делает, кроме утилизации, поэтому сами представления могут получать клики и делать более сложные вещи. – Karakuri

Смежные вопросы