Android - задержка кликов в ListView

голоса
17

У меня есть следующая структура в моем приложении:

FragmentActivity с ViewPagerхолдингом несколько фрагментов управляются с FragmentStatePagerAdapterпомощью compativility пакета с Android 2.1

Каждый фрагмент содержит ListView. Каждый элемент в ListViewимеет LinearLayoutс двух TextViewsи а Button. LinearLayoutИ кнопка есть onClickListeners(отдельно). При нажатии на LinearLayoutстартах другой Activity. Я заметил , что поведение щелчков очень непоследовательно: иногда действие выполняется немедленно , но очень часто задерживаются , а иногда она просто игнорируется независимо от того , сколько раз я нажимаю. Это становится еще более странным , потому что я могу нажать и действие будет выполняться только тогда , когда я начала прокрутки списка. Я пробовал различные комбинации setFocusable(false)и , setSelectable(true)но это , кажется, не имеет никакого значения. Есть идеи? Я буду рад предоставить более подробную информацию.

Задан 11/01/2012 в 07:27
источник пользователем
На других языках...                            


6 ответов

голоса
9

У меня была аналогичная проблема, и это заняло у меня 2 дня, чтобы отладить и решить. У меня есть ListAdapter, который создает несколько TextViews в LinearLayout для каждого элемента списка. Каждый TextView имеет собственный OnClickListener, потому что мне нужно обрабатывать щелчки по каждому пункту.

Когда я изменил реализацию, так что я повторно использовать Соображения OnClickListener перестал работать правильно. На 4.4.2 большинство кликов работал, но иногда не было никакой реакции, пока я не прокручиваются в списке. На 2.3 первые щелчки не будет работать, а затем все клики, где обрабатываются в пакете.

В моем частном случае, я создал все View в Java коде и не раздувая ресурсы. И критическая точка была, что я установить LayoutParams на LinearLayout даже когда повторно вид (это, кажется, более безопасным, то при условии, что повторно используемый вид имеет правильные параметры макета). Когда я не установить LayoutParams при повторном использовании все работает отлично! Вот критический код:

public View getView(int position, View convertView, ViewGroup parent) {
    LinearLayout tapeLine = null;
    if (convertView != null && convertView instanceof LinearLayout && ((LinearLayout)convertView).getChildCount() == 4) tapeLine = (LinearLayout) convertView; // Reuse view
    else tapeLine = new LinearLayout(activity);
    if (convertView == null) { // Don't set LayoutParams when reusing view
        ViewGroup.LayoutParams tapeLineLayoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        tapeLine.setLayoutParams(tapeLineLayoutParams);
    }
    ScrollingTape scrollingTape = calculatorHolder.getCalculator().getScrollingTape();
    int tapeWidthPx = parent.getWidth();
    TapeLineTextSizeInfo tapeLineTextSizeInfo = calculatorHolder.getTapeLineTextSizeHelper().createTapeLineTextSizeInfo(tapeWidthPx);
    ScrollingTapeLine line = scrollingTape.getLine(position);
    tapeLine.setOrientation(LinearLayout.HORIZONTAL);
    int tapeBackgroundColor = getBackgroundColor(line);
    tapeLine.setBackgroundColor(tapeBackgroundColor);
    addColumnViews(tapeLine, line, tapeLineTextSizeInfo);
    tapeLine.setTag(R.id.scrollingtapeadapter_viewtag_position, position);
    tapeLine.setOnLongClickListener(longClickListener);
    tapeLine.setOnClickListener(remainClickListener);
    return tapeLine;
}

Каковы предпосылки для такого странного поведения списке? Я сделал немного отладки и исследования в Android источников. Когда андроид обновления вид есть два важных шага onMeasure и OnLayout. Метод GetView из ListAdapter не только призван сделать вид, но и ранее во время onMeasure. В этом последнем случае создается представление, но он еще не зарегистрирован в цепи событий для обработки события нажатия.

Когда представление, которое было создано для onMeasure повторно используется позже, чтобы быть acutally обращено на экран, он должен быть регистр с Android системы для обработки события нажатия. Для этого частного случая Android develepers сделал что-то, что можно было бы рассматривать как грязного хака. Специальный флаг в LayoutParams используется для принятия решения о том, что вид должен быть зарегистрирован в изменении событий.

Теперь моя проблема: при сбросе LayoutParams также, когда точка зрения повторного использования, этот флаг был всегда сброшен. Поэтому Android система не будет регистрировать вид и события не прийти до конца.

резюмировать: когда resusing представления в GetView о наличии ListAdapter не перезаписывать LayoutParams, потому что они держат внутреннюю информацию андроида системы.

Ответил 03/05/2014 в 15:15
источник пользователем

голоса
4

Я столкнулся с той же проблемой, но в моем случае решение не держать ссылки на мнения, что вызвало проблемы с кэшированием зрения управления ListView. После правильного осуществления getView()способа с использованием converView, исчезли все странное поведение с потерей / неожиданными вызовами щелчка.

Ответил 23/03/2012 в 13:36
источник пользователем

голоса
3

В случае, если кто-нибудь задавался вопросом, как я решил эту проблему. В основном я должен был упростить свои макеты. Кажется, что, когда у вас есть сложные вложенные структуры события могут занять слишком много времени, чтобы пузырь, и если вы начинаете список прокрутки в том же время события могут вызвать неправильное действие. Я обрезается макеты, переключаясь на RelativeLayout как можно больше, и, казалось, чтобы помочь много

Ответил 07/02/2012 в 02:26
источник пользователем

голоса
1

Не уверен, если это помогает любому, но у меня была аналогичная проблема, а не с TableLayout. Эти решения не исправить мою проблему.

Для меня проблема была: android:animateLayoutChanges="true"

Удаление это позволило мои щелчки кнопки в пределах моих TableLayout строк работать должным образом. Я должен был затем анимировать свои взгляды вручную, вместо того, чтобы полагаться на вышеуказанную собственность.

Ответил 17/04/2015 в 22:25
источник пользователем

голоса
1

То , что сработало для меня было Назначив OnItemClickListenerна ListViewсчет setOnItemClickListener, а не OnClickListenerк отдельным элементам списка. Очевидно , что кнопка все еще нуждается в своей собственной OnClickListener, но я не проверял этот сценарий.

Ответил 11/08/2012 в 10:50
источник пользователем

голоса
-1

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

Ответил 11/01/2012 в 07:38
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more