2013-08-08 4 views
0

У меня есть один список в моем приложении, он содержит две строки для задачи, а другой - для тревоги, даты, серьезности. Первоначально первая строка элемента списка отображается только для всего элемента списка, а вторая невидима. Когда я нажимаю на элемент списка вторую строку, отображаемую для этого элемента, а также нажимаю на другой элемент списка, в этот момент указанный элемент списка закрыл эту вторую строку. Его работа прекрасна для меня ... Моя проблема заключается в том, что я открываю один элемент списка, а затем прокручиваю список, а затем нажимаю на другой элемент списка, в то время выше не может быть закрыт, потому что указанный выше элемент списка будет chnaged.please любой один помочь мне, как решить эту проблему ...listview Получение нового экземпляра при прокрутке списка

int lastselectedPosition == -1 
    @Override 
    public void onItemClick(AdapterView<?> arg0, View view, int position, 
     long id) { 
     TextView textviewDate=(TextView)view.findViewById(R.id.taskTimeidDaytoDay); 
     selectedtaskDate=textviewDate.getText().toString().trim(); 
     if (lastselectedPosition == -1) { 
     Log.i(TAG,"Loopif:"+lastselectedPosition); 
     TextView twTaskTime = (TextView) view 
       .findViewById(R.id.taskTimeidDaytoDay); 
     TextView twSeverity = (TextView) view 
       .findViewById(R.id.severityidDaytoDay); 
     TextView twAlarm = (TextView) view 
       .findViewById(R.id.alarmidDaytoDay); 
     twAlarm.setVisibility(view.VISIBLE); 
     twSeverity.setVisibility(view.VISIBLE); 
     twTaskTime.setVisibility(view.VISIBLE); 
     lastselectedPosition = position; 
     lastSelectedItem = arg0.getChildAt(position); 
     } else { 
     // Log.i(TAG,"LoopElse:"+lastselectedPosition); 
     lastSelectedItem.findViewById(R.id.taskTimeidDaytoDay) 
       .setVisibility(lastSelectedItem.GONE); 
     lastSelectedItem.findViewById(R.id.severityidDaytoDay) 
       .setVisibility(lastSelectedItem.GONE); 
     lastSelectedItem.findViewById(R.id.alarmidDaytoDay).setVisibility(
       lastSelectedItem.GONE); 
     if (lastselectedPosition != position) { 
      view.findViewById(R.id.taskTimeidDaytoDay).setVisibility(
        view.VISIBLE); 
      view.findViewById(R.id.severityidDaytoDay).setVisibility(
        view.VISIBLE); 
      view.findViewById(R.id.alarmidDaytoDay).setVisibility(
        view.VISIBLE); 
      lastselectedPosition = position; 
      lastSelectedItem = arg0.getChildAt(position); 
     } else { 
      lastselectedPosition = -1; 
      lastSelectedItem = null; 
     } 
     } 

GetView():

@Override 
public View getView(int position, View view, ViewGroup parent) { 
    Log.i("XXXX", "Inside getView"); 
    final DaytoDayTaskGetterSetter objDaytoDaygetset=getItem(position); 
    TextView textviewTask; 
    TextView txtviewAlarm ,txtviewTaskTime ,txtviewSeverity; 
    Log.i(TAG,"InsideGetView:"+position); 
    LayoutInflater inflater=(LayoutInflater)context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); 
    if(view==null) 
    { 
     view=inflater.inflate(R.layout.daytodaylistlayout,null); 

     } 
     Log.i("XXXX", "before first test"); 
    textviewTask=(TextView)view.findViewById(R.id.tasknameidDaytoDay); 
    txtviewAlarm=(TextView)view.findViewById(R.id.alarmidDaytoDay); 
    txtviewSeverity=(TextView)view.findViewById(R.id.severityidDaytoDay); 
    txtviewTaskTime=(TextView)view.findViewById(R.id.taskTimeidDaytoDay); 
    return view; 
} 

enter image description here

enter image description here

Вначале я нажимаю элемент списка «gdfgdtet», он показывает еще одну строку, а затем я нажимаю на второй элемент списка «dfgsdgsd», в то время указанный выше элемент списка «gdfgdtet» закрыл вторую строку. Это нормальный вывод .Пожалуйста, если я открою элемент списка «gdfgdtet», а затем проведите по экрану список в это время, оба «gdfgdtet» «dfgsdgsd» будут открыты и разбиты ... потому что ссылка на один элемент списка изменилась, когда я прокручиваю, пожалуйста, как решить эту проблему ...

+1

Пожалуйста размещать логику, содержащуюся внутри GetView() 'метода' и после трассировки стека для авария. –

ответ

1

Вы должны обратить внимание на Tal Kanel's ответ и рассмотрим это как расширение для него. Его совет поможет вам в конечном итоге.

Добавить boolean поле для DaytoDayTaskGetterSetter класса A:

public class DaytoDayTaskGetterSetter { 

.... 
.... 
boolean open; 

    public DaytoDayTaskGetterSetter (.., .., boolean o) { 
     .... 
     .... 
     open = o; 
    } 

    .... 
    .... 

    public boolean shouldOpen() { 
     return open; 
    } 

    public void setOpen(boolean o) { 
     open = o; 
    } 
} 

В вашем getView(), проверить, если объект имеет свой набор open значения:

DaytoDayTaskGetterSetter obj = (DaytoDayTaskGetterSetter) getItem(position); 

if (obj.shouldOpen()) { 
    // Set visibility to true for the items 
} else { 
    // Set visibility to false for the items 
} 

В списке нажмёх, траверс списка и установить open для всех элементов списка. Используйте position для извлечения DaytoDayTaskGetterSetter и установить его open к истинным:

@Override 
public void onItemClick(AdapterView<?> arg0, View view, int position, long id) { 

    for (DaytoDayTaskGetterSetter obj : listContainingObjects) { 
     obj.setOpen(false); 
    } 

    DaytoDayTaskGetterSetter clickedItem = (DaytoDayTaskGetterSetter) 
               yourAdapter.getItem(position); 
    clickedItem.setOpen(true); 

    yourAdapter.notifyDataSetChanged(); 
} 

Edit 1:

@Override 
public void onItemClick(AdapterView<?> arg0, View view, int position, long id) { 

    DaytoDayTaskGetterSetter clickedItem = (DaytoDayTaskGetterSetter) 
               yourAdapter.getItem(position); 

    if (clickedItem.shouldOpen()) { 
     clickedItem.setOpen(false); 
    } else { 

     for (DaytoDayTaskGetterSetter obj : listContainingObjects) { 
      obj.setOpen(false); 
     } 

     clickedItem.setOpen(true); 
    } 

    yourAdapter.notifyDataSetChanged(); 
} 
+0

ki понять, если я снова нажму на открываемый элемент, он будет определенно закрыт, но вышеуказанное кодирование будет открыто тем же самым пунктом – Satheesh

+0

@Satheesh. См. Редактировать 1 выше. В любой момент времени будет видно не более одного вида. Если щелкнуть элемент (кто в настоящее время не отображается), его представление будет видимым. Если щелкнуть элемент (кто сейчас отображается в данный момент), его видимость будет переключена. – Vikram

+0

Большое спасибо vikram – Satheesh

4

Я постараюсь предоставить вам хороший ответ, что объясняет, почему у вас возникли эти проблемы, но общая идея состоит в том, что вы должны увидеть это видео - http://www.youtube.com/watch?v=wDBM6wVEO70

риала ase возьмите мои слова любезно - вы, кажется, не понимаете, что такое механизм утилизации, и я настоятельно рекомендую вам посмотреть полное видео, с которым я связал вас, и узнать больше об этом.

В общем, конкретная проблема в вашем коде заключается в том, что вы держите ссылку на элемент списка (lastSelectedItem), а затем пытаетесь использовать его при условии, что он все еще представляет один и тот же элемент списка. это неверно. на этом этапе (после прокрутки) представление уже было переработано для представления другого элемента в списке (на основе реализации адаптера).

listView число детей не размер адаптера.getCount() !!!!!!!! номер

ListViews х лет Чайлдс = количества видимых элементов списка на экране + 1 + заголовки + колонтитулы

допустят у вас есть 5 первые пункты видны на экране, то вы прокручиваете вниз. когда вы видите элемент 7, на самом деле вы видите тот же экземпляр представления, который использовался для отображения первого элемента списка и был переработан. getView вызывет на этом этапе с помощью convertView! = Null и положение в адаптере, чтобы вы могли повторно использовать элемент, добавив новые значения, такие как другой текст/изображение в один и тот же экземпляр.

Этот механизм обеспечивает возможность отображения списка «бесконечных «количество элементов в списке и удерживание в памяти только нескольких видов просмотров. представьте, что у вас есть список из 5000 элементов в списке, и каждый из них имеет другой экземпляр представления - вы получите исключение outOfMemory за секунду!

полное объяснение об этом было бы трудно записать в контексте ответа stackoverflow. это слишком долго пытаюсь объяснить одну из самых важных и сложных компонентов пользовательского интерфейса в Android, но это ссылка будет хорошее начало:

http://www.youtube.com/watch?v=wDBM6wVEO70

How ListView's recycling mechanism works

http://mobile.cs.fsu.edu/the-nuance-of-android-listview-recycling-for-n00bs/

если вы находятся в «быстром» исправлении для вашей конкретной проблемы, решение будет:

провести в структуре данных представляет ваш список дополнительное поле, указывающее, находится ли оно в «закрытом» или «открытом состоянии». когда элемент был нажат - смените данные и нажмите notifyDatasetChanged(). внутри getView() проверки, если элемент открыт или закрыть и заселить его accordinly

, кстати - это не только «быстрое решение» решение, но и то, что нужно делать в любом случае

+0

k Я понимаю, как решить эту проблему, пожалуйста, дайте мне решение – Satheesh

+0

@Satheesh: Я обновил свой ответ. теперь он предоставляет вам «быстрое исправление» solutin. –

+0

k i выведет мою функцию getview(), где я изменю положение ... – Satheesh