Странная анимация в Галерее, когда у детей запрашивается инвалид - PullRequest
3 голосов
/ 16 декабря 2011

Это адаптер моей Галереи, на котором я отображаю ImageViews (большой палец страницы)

Я хочу загрузить изображения ASync (иногда это может происходить из сети), поэтому я сделал этот код:

    public View getView(int position, View convertView, ViewGroup parent) {
        final ImageView image = convertView != null ? convertView : new ImageView(getContext());

        final PageInfo page = getItem(position);

        image.setBackgroundColor(Color.WHITE);

        image.setLayoutParams(new Gallery.LayoutParams(96, 170));

        new AsyncTask<Void, Void, Bitmap>() {
            @Override
            protected Bitmap doInBackground(Void... arg0) {
                try {
                    File thumbnail = page.thumbnail();//Thumbnail download the image if not available
                    return BitmapFactory.decodeStream(new FileInputStream(thumbnail));
                } catch (ApplicationException e) {
                    return null;
                } catch (NetworkException e) {
                    return null;
                }
            }

            protected void onPostExecute(Bitmap result) {
                if (result == null)
                    return;

                image.setImageBitmap(result);
            };
        }.executeOnExecutor(executor);

        return image;
    }

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

Как мне этого избежать? Или я могу изменить изображение ImageView без запроса макета ViewGroup?

РЕДАКТИРОВАТЬ: Аналогичный вопрос о группах разработчиков Google http://code.google.com/p/android/issues/detail?id=15526

Ответы [ 6 ]

4 голосов
/ 16 декабря 2011

У виджета Галерея есть известная ошибка, из-за которой он всегда возвращает нулевой convertView.Это означает, что каждый раз, когда вызывается getView, вы создаете новый ImageView, который может вызывать возникшую проблему.

Существует галерея, созданная третьей стороной, которая исправляет ошибку утилизации, ищет в Интернете EcoGallery и вы можете найти способ ее реализации.Это заметно повысит производительность графики при прокрутке галереи.

3 голосов
/ 20 декабря 2011

Если вы не можете заставить его работать должным образом, я однажды сделал хак, который может помочь.

В конце вашего doInBackground(), перед тем как вы вернетесь, выполните:

int viewsOnScreen = 3;
while(viewsOnScreen >= 1){ //adapt the numbers so that they work with your gallery, this is for a gallery with one visible child.
    viewsOnScreen = getLastVisiblePosition() - getFirstVisiblePosition();
    SystemClock.sleep(100);
}

Это будет ожидать обновления изображения до тех пор, пока вы не отобразите только один вид (или любой другой номер, который вы укажете, смысл в том, что у вас нет частичных видов на экране ), что вызовет «скачок»пройти незамеченным.Если ваши проблемы также связаны с переходом на совершенно другую позицию в галерее, я рекомендую вам проверить, какой объект вы выбрали перед загрузкой, и после загрузки вы найдете, в каком положении находится этот объект, и вызвать setSelection() в эту позицию.

Но сначала попробуйте все другие решения ...

2 голосов
/ 03 февраля 2012

Если вы все еще не нашли решение, вот мое.

Вам нужна CustomGallery, которая по умолчанию составляет почти 1: 1 Android Gallery. Но вы не можете расширить галерею, вы должны скопировать весь исходный код в свой класс. Вам нужно будет сделать то же самое с классами CustomAbsSpinner и CustomAdapterView. Все это, чтобы изменить только одну строку кода ... В вашем классе CustomGallery измените метод onLayout () на этот:

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);

    /*
     * Remember that we are in layout to prevent more layout request from
     * being generated.
     */

    mInLayout = true;

    /*
     * Add if condition to avoid calling layout()  unnecessarily:
     * -when children calls onLayout after loading imageview
     */
    if(changed || mDataChanged)
        layout(0, false);
    mInLayout = false;
}

Это приведет к тому, что layout() вызывается только тогда, когда это действительно необходимо.

Была также другая известная ошибка в поведении галереи, которая вызывает скачки галереи на notifyDataSetChanged(). Если у вас также есть эта ошибка, просто закомментируйте одну строку в классе CustomAdapterView:

    @Override
    public void onChanged() {
        mDataChanged = true;
        mOldItemCount = mItemCount;
        mItemCount = getAdapter().getCount();

        // Detect the case where a cursor that was previously invalidated has
        // been repopulated with new data.
        if (CustomAdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
                && mOldItemCount == 0 && mItemCount > 0) {
            CustomAdapterView.this.onRestoreInstanceState(mInstanceState);
            mInstanceState = null;
        } else {
            rememberSyncState();
        }
        checkFocus();
        //comment this line to avoid gallery snap on notyfiDataSetChanged 
        //requestLayout();
    }

В любом случае, хорошая тема Маркос! Спасибо за то, что привели меня к решению. Если вам нужен источник пользовательских классов, дайте мне знать.

РЕДАКТИРОВАТЬ (автор Маркос Васконселос):

Существует множество стилей, которые нужно скопировать, чтобы получить исправление R для этих классов.

Для тех, кто ищет исходный код Android 2.2 (без папки res, если кто-то нашел его, пожалуйста, сообщите нам), это можно найти здесь: http://en.newinstance.it/2010/12/01/android-sdk-2-2_r2-sources/

Для более поздних версий API это можно сделать через SDK Manager, и он будет расположен в / sources / android-

1 голос
/ 21 декабря 2011

Вы можете использовать концепцию LazyList, которая извлекает изображение из Интернета и временно помещает его в локальный кеш, что косвенно приводит к плавной навигации по галерее, поскольку изображение сохраняется локально

вот ссылка https://github.com/thest1/LazyList или http://androidsnips.blogspot.com/2010/08/lazy-loading-of-images-in-list-view-in.html

1 голос
/ 20 декабря 2011

Работает ли это случайно, если вы (а) выполняете прокрутку очень медленно или (б) не перезапускаете convertView?

Я выхожу на конечность и думаю, что это так ...

Причина в том, что когда вы перезапускаете ImageView из предыдущего вызова getItem (), вы не отменяете связанный AsyncTask. У вас будет несколько задач, обновляющих один и тот же ImageView, что может быть описанным вами поведением.

0 голосов
/ 24 декабря 2011

Вы можете установить растровое изображение по умолчанию перед началом загрузки фактического изображения. Это гарантирует, что пустые представления не будут установлены с неправильными растровыми изображениями.

// load defaultBmp in constructor.

image.setBackgroundColor(Color.WHITE);

image.setLayoutParams(new Gallery.LayoutParams(96, 170));

image.setImageBitmap(defaultBmp); // set the default bitmap (could be white). 
// execute AsyncTask here.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...