Сделайте карусель с помощью ViewFlipper или ViewPager - PullRequest
9 голосов
/ 05 декабря 2011

Поскольку GalleryView устарел, мы должны иммигрировать в некоторые альтернативные виджеты, в моем случае ViewFlipper - лучший, но я столкнулся с несколькими проблемами, как вы можете видеть на следующем скриншоте. Я разработал карусель ImageGallery сGalleryView:

enter image description here

С ViewFlipper все работает, как я ожидал, но я не могу реализовать две вещи:

1- ViewFlipper всегда показывает один элемент;однако мне нужно отобразить три элемента (или даже больше) одновременно.

2- ViewFlipper - это не сенсорный виджет, и это не то, что я хочу!


Как FlávioFaria упомянул о ViewPager в следующем посте, это тоже отличный случай, но я не могу передать ему свою анимацию масштабирования!

Я сделал все с помощью ViewPager, теперь он работает отлично, но я пропустил одну функцию, и это прокрутка бесконечности!

Добавил мойPagerAdapter класс

public class CarouselAdapter extends PagerAdapter  
{  
    private Context mContext;
    private ImageLoader imageLoader;
    private String[] bannerUri;

    public CarouselAdapter (Context c, String[] bannerArray) 
    { 
        this.mContext = c; 
        this.bannerUri = bannerArray;
        // Setup image loader
        this.imageLoader = ImageLoader.getInstance();
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(c)
            .threadPoolSize(2) 
            .memoryCache(new WeakMemoryCache())
            .discCacheFileNameGenerator(new Md5FileNameGenerator())
            .build();
        this.imageLoader.init(config);
    } 

    @Override
    public Object instantiateItem(ViewGroup container, int position)
    {
        if (position >= bannerUri.length) 
            position %= bannerUri.length;

        ImageView i = new ImageView(mContext);
        displayImage(i, bannerUri[position]);
        i.setScaleType(ScaleType.FIT_XY); 
        container.addView(i);
        return i;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) 
    {
        container.removeView((View)object);
    }

    @Override
    public int getCount() 
    {
        return Integer.MAX_VALUE;
    }

    @Override
    public boolean isViewFromObject(View view, Object object)
    {
         return (view == object);
    }

    private void displayImage(final ImageView mImage, String ImageUri)
    {
        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
            .showStubImage(R.drawable.border)
            .showImageForEmptyUri(R.drawable.border)
            .imageScaleType(ImageScaleType.EXACTLY)
            .bitmapConfig(Bitmap.Config.RGB_565)
            .resetViewBeforeLoading()
            .cacheOnDisc() 
            .displayer(new FadeInBitmapDisplayer(740))
            .build();

        imageLoader.loadImage(ImageUri, defaultOptions, new SimpleImageLoadingListener() 
        {
            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage)
            {
                mImage.setImageDrawable(new BitmapDrawable(mContext.getResources()
                        , getDesiredBitmap(loadedImage, 12)));
            }
        });
    }

    private Bitmap getDesiredBitmap(Bitmap originalImage, int roundValue)
    {
        // Create required bitmaps
        Bitmap shadowBitmap = BitmapFactory.decodeResource(mContext.getResources()
                , R.drawable.samsungapps_thumb_shadow);
        Bitmap outputBitmap = Bitmap.createBitmap(originalImage.getWidth()
                , originalImage.getHeight() + 80, Bitmap.Config.ARGB_8888);
        // Create canvas and pass bitmap to it 
        Canvas mCanvas = new Canvas(outputBitmap);
        // And finally draw the shaodw
        mCanvas.drawBitmap(Bitmap.createScaledBitmap(shadowBitmap, originalImage.getWidth()
                , (int)(shadowBitmap.getHeight() / 2.3), false), 0, originalImage.getHeight(), null);

        mCanvas.drawBitmap(originalImage, 0, 0, null);

        return outputBitmap;
    }
}

Есть идеи о том, как выполнить эти две вещи?

Ответы [ 3 ]

2 голосов
/ 20 апреля 2013

после просмотра вашего кода я обнаружил, что CarouselAdapter ведет себя круговой (бесконечной прокруткой) частью кода, которая вызывает: -

@Override
    public int getCount() 
    {
        return Integer.MAX_VALUE;
    }

и

@Override
    public Object instantiateItem(ViewGroup container, int position)
    {
        if (position >= bannerUri.length) 
            position %= bannerUri.length;
       .
       . 
       .
    }

Однако вы делаете

        ImageView i = new ImageView(mContext);
        displayImage(i, bannerUri[position]);
        i.setScaleType(ScaleType.FIT_XY); 
        container.addView(i);
        return i;

в instantiateItem, поэтому для каждой страницы в ViewPager вы выделяете память для ImageView, и из-за этого ViewPager не хватает памяти.ViewPager имеет метод public void setOffscreenPageLimit (int limit), который ограничивает объем памяти, выделяемый путем уничтожения свободных страниц в иерархии представления. См. Ниже в документации Android

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

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

Вам следуетДержите этот предел на низком уровне, особенно если ваши страницы имеют сложные макеты.Этот параметр по умолчанию равен 1.

Как уже упоминалось выше, если не указать какое-либо значение для него, он будет использовать значение по умолчанию 1, а ViewPager уничтожит пустые страницы из иерархии представления.Поэтому вам нужно передать ему оптимизированное значение в соответствии с вашими требованиями к памяти (количество изображений и средний размер изображения), которое решит проблему нехватки памяти.

1 голос
/ 18 апреля 2013

Хорошо, вот что вы можете сделать:

  1. Используйте горизонтальное представление списка ( пример здесь )

  2. Убедитесь, что каждый элемент занимает около 1/3 ширины экрана. Может быть, немного больше.

  3. Для привязки центрального элемента обрабатывайте события касания, чтобы он плавно переходил к среднему элементу, например, как показано в примере samsung " круговой пусковой механизм ".

  4. Для получения более причудливых эффектов измените свойства размера / местоположения видов так же, как в примере, о котором я писал на # 3.

1 голос
/ 18 апреля 2013

Рассмотрите возможность использования ViewPager с несколькими страницами:

http://commonsware.com/blog/2012/08/20/multiple-view-viewpager-options.html

...