Виджет галереи Android "джиттер" / "прыжки" / странное поведение - PullRequest
2 голосов
/ 21 января 2012

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

Я использую пользовательский Adapter для виджета Gallery, и я надуваю пользовательский макет для каждого элемента в Gallery в этом Adapter. Вы можете увидеть код для Adapter и макеты ниже. Виджет Gallery в настоящее время не использует Views, поэтому я не использую трюки ViewHolder и т. Д.

Проблема

Проблема в том, что я испытываю "скачки" в виджете Gallery, когда он работает на экранах планшетов, но он отлично работает на мобильных телефонах. Я использую разные макеты для обоих типов устройств и знаю, что они используются правильно - я достаточно тщательно это проверил.

Что я пробовал

  • Изменение ширины / высоты макета элемента Gallery - без изменений. Но если я установлю цвет фона, он появится.
  • Попытка удалить интервал Gallery, но из-за этого Gallery элементы перекрывают друг друга
  • Убедился, что Adapter работает и загружается правильная раскладка
  • Убедитесь, что я не изменяю настройки Adapter в коде
  • Очистка проекта

Видео примеры выпуска

Два устройства используют один и тот же пакет приложений с одной и той же кодовой базой, единственное отличие состоит в макетах, как показано ниже.

НЕ РАБОТАЕТ - На планшете (Acer Iconia A500 - 10 дюймов, 1280 x 800, мдд): http://www.youtube.com/watch?v=vN2d61_Ojsc

РАБОТА - на мобильном телефоне (Samsung Galaxy Nexus - 4,7 дюйма, 720 x 1280, xhdpi): http://www.youtube.com/watch?v=j8s-JfwWofo

Код - Галерея адаптера

public class ImageAdapter extends BaseAdapter {

        LayoutInflater inflater;

        public ImageAdapter() {
            inflater = (LayoutInflater) Main.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        public int getCount() {
            return coverFileNames.size();
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {

            convertView = (ImageView) inflater.inflate(R.layout.main_large_img, null);

            ((ImageView) convertView).setImageBitmap(coverFileNames.get(position));

            return convertView;
        }

    }

Код - Основная раскладка

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:alwaysDrawnWithCache="true"
    android:animationCache="true"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/txtMainTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingBottom="0sp"
        android:paddingLeft="30sp"
        android:paddingTop="20sp"
        android:shadowColor="#000000"
        android:shadowDx="1.0"
        android:shadowDy="1.0"
        android:shadowRadius="1.0"
        android:text="@string/mainMyMoviesTitle"
        android:textAppearance="?android:attr/textAppearanceLarge" >
    </TextView>

    <TextView
        android:id="@+id/txtNumberofMovies"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="30sp"
        android:shadowColor="#000000"
        android:shadowDx="1.0"
        android:shadowDy="1.0"
        android:shadowRadius="1.0"
        android:text="@string/mainNumberofMovies"
        android:textAppearance="?android:attr/textAppearanceSmall" >
    </TextView>

    <Gallery
        android:id="@+id/gallery1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        android:spacing="20dp"
        android:unselectedAlpha="1.0" >
    </Gallery>

</LinearLayout>

Код - Расположение элементов галереи (планшет, layout-xlarge-land-mdpi)

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainLargeImg"
    android:layout_width="374dp"
    android:layout_height="600dp"
    android:layout_marginLeft="0dp"
    android:layout_marginRight="0dp"
    android:maxHeight="600dp"
    android:maxWidth="374dp"
    android:minHeight="600dp"
    android:minWidth="374dp"
    android:scaleType="fitXY"
    android:src="@drawable/noposterxl" />

Код - Расположение элементов галереи (телефон, layout-normal-port-xhdpi)

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainLargeImg"
    android:layout_width="188dp"
    android:layout_height="300dp"
    android:layout_marginLeft="0dp"
    android:layout_marginRight="0dp"
    android:maxHeight="300dp"
    android:maxWidth="188dp"
    android:src="@drawable/noposterxl" />

PS. Рассматриваемое приложение - Mizuu - на Маркете есть бесплатная версия, которую вы можете попробовать сами, чтобы увидеть проблему. Это происходит, когда вы проводите горизонтальную прокрутку, и следующее изображение вот-вот будет показано. Бесплатная версия в настоящее время только для планшетов.

Ответы [ 4 ]

3 голосов
/ 21 января 2012

Обнаружил, что это похоже на вашу проблему:

http://www.unwesen.de/2011/04/17/android-jittery-scrolling-gallery/

Исправление - переопределить эти два метода. Я не уверен, что это правильный путь:

private long mLastScrollEvent;

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
  long now = SystemClock.uptimeMillis();
  if (Math.abs(now - mLastScrollEvent) > 250) {
    super.onLayout(changed, l, t, r, b);
  }
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
    float distanceY)
{
  mLastScrollEvent = SystemClock.uptimeMillis();
  return super.onScroll(e1, e2, distanceX, distanceY);
}

У него есть хакерское исправление, предположим, вы могли бы попробовать.

Также подан отчет об ошибке:

http://code.google.com/p/android/issues/detail?id=16171

1 голос
/ 21 января 2012

Я в итоге решил использовать HorizontalListView от Devsmart вместо Gallery виджета.Это не совсем то же самое, и ему не хватает нескольких функций по сравнению с виджетом Gallery, но он идеально плавный, способен повторно использовать Views и не «прыгает» при прокрутке элементов.Кроме того, он не выровнен по центру, как виджет Gallery, что является еще одной вещью, которую я давно хотел.

Виджет HorizontalListView доступен здесь: https://github.com/dinocore1/DevsmartLib-Android

1 голос
/ 21 января 2012

Я не уверен, но поскольку этот переход происходит при вызове getView (), я думаю, что это связано с тем фактом, что Gallery некорректно перерабатывает представления. Однако, если это так, я не знаю, почему это будет работать лучше на телефоне, чем на планшете, но я подозреваю, что это связано либо с тем, что телефон имеет немного более быстрый процессор, либо с изображениями, которые использование в галерее может занять больше памяти на планшете, поскольку они могут быть больше на экране.

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

Кто-то исправил ошибку, из-за которой Галерея не перезагружалась, и выпустил ее под названием «EcoGallery», поэтому довольно сложно включить ее в свои проекты, потому что вам нужно вручную включить несколько файлов Java и несколько других. Ресурсы. Но если вы реализуете это и тестируете на планшете, я думаю, что это может помочь облегчить вашу проблему.

0 голосов
/ 14 марта 2012

Я только что узнал, что это ошибка в Android 3.x и что она исправлена ​​в Android 4.0 - что объясняет, почему он работает на Galaxy Nexus и почему он не работаетна моем Acer Iconia A500 на сотах.Я обновился до Transformer Prime, и он тоже работает безупречно.

Проблема сейчас в том, что пользователи на Android 3.x будут испытывать ошибку и обвиняют меня в этом, когда я не виноват...

...