安卓ViewPager卡顿问题

13

你好,我有一个ViewPager(使用FragmentStatePagerAdapter),其中有几个页面并带有一些PNG作为这些页面的背景。我已经遵循了在UI中显示位图的指南 (http://developer.android.com/training/displaying-bitmaps/display-bitmap.html) ,因此我已经在后台线程中缓存并设置图像可绘制对象。但是,当切换页面时仍然会出现一些延迟。在每个片段上,我只在onCreateView()方法中填充视图,所以我不知道可能导致这种延迟的原因。我该怎么做才能消除这种延迟/卡顿效果?

11个回答

52

我遇到了类似的问题。

我正在展示类似教程的页面。每个页面都是一个全屏的jpg图片。

一开始,我把这些图片放在 res/drawables 文件夹中。然而,在滑动ViewPager时非常卡顿。

然后我把这些jpg移动到 res/drawable-hdpi 文件夹中,卡顿问题解决了。

我认为根据文件夹对图片进行不同的优化。因此我们不能把所有内容都放在res/drawable文件夹中。


这正是我的问题,你的答案为我解决了它。我把所有全尺寸背景图片放在xhdpi文件夹中,现在非常流畅。 :) - Amyth
1
你是怎么想到这个方法的?我差点以为“可能是因为图片太大导致内存占用过多”,但我按照你说的做了,结果就奏效了。我把我的图片放在了xhdpi文件夹里,这是否意味着具有hdpi/mdpi/xxhdpi/xxxhdpi分辨率的手机也能显示我的背景图片? - Alex

19

您可以尝试使用viewPager.setOffScreenLimit(size)方法,将其设置为页面数量。这样可以在滑动时加载所有片段,并避免重新加载它们。


只需要做一个小修正,应该是 viewPager.setOffscreenLimit(size)。虽然这个方法对我有效,还是感谢你! - Andrew Steinmetz
请注意,如果您的页面上有许多高分辨率图像或者您有许多页面,这可能很快导致 OutOfMemoryError - ubuntudroid

6

为消除卡顿:

1)如果图片是静态的,请将图片放在res/drawable-hdpi中。如果图片是从URL下载的,则使用后台线程加载图片。

2)通过此方法设置页面的屏幕限制:viewPager.setOffScreenLimit(size)。借助这个方法,View Pager可以缓存你所设定数目的最小屏幕,默认为1。

3)您可以使用FragmentPagerAdapterFragmentStatePagerAdapter以获得更好的性能。


4

我解决了这个问题,通过将图片移动到drawable-nodpi文件夹中,这样可以禁用所有DPI的缩放。如果将图片移动到hdpi / xhdpi文件夹中,只有当用户使用具有该屏幕密度的设备时才会禁用缩放。


2
我按照 Coderek 的回答,将它移动到不同的res/drawable-hdpi文件夹中。在我的项目中,drawable-xxxhdpi效果最好。

1
我的解决方案是在页面切换时预加载图片,以避免延迟。
final Drawable[] images = new Drawable[3];
for(int i=0; i<3; i++){
    int position = i+1;
    images[i] = getResources().getDrawable(getResources().getIdentifier("image"+position, "drawable", getPackageName()));
 }

然后:

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            imageSwitcher.setImageDrawable(images[position]);
        }

        @Override
        public void onPageScrollStateChanged(int state) {
        }
    });

尽管代码受到赞赏,但它应该始终有相应的解释。这并不需要很长,但是这是期望的。 - peterh

1

我知道这是一个旧问题,但最近我遇到了它并发现了一个不同的问题。如果有人看到这篇文章,我想分享一下。

我的碎片都只是很大的ImageView持有者,并滚动通过UX / UI团队给我的图像。然而,每当下一张或上一张图片是不同大小,例如(1200 x 1200)转变为(1200 x 1300),那么滑动会出现延迟,但其他图片则没有问题。

分辨率在正确的文件夹中。我进行了实验,并发现如果将所有图像裁剪成相同的大小,就没有延迟问题。但是,这不符合我的需求,因为我需要不同大小的图像。

所以我改用Glide将图像异步加载到位,而不是直接设置drawable,这样效果非常好。因此,如果其他人也遇到了这个问题,可能只需要切换到使用Glide异步加载,而不是直接设置图像。


1
在 @coderek 的基础上,我似乎通过获取特定密度下未缩放的位图来解决了这个问题。
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resource, opts);

((ImageView) view).setImageBitmap(bitmap);

xxhdpi设备上使用来自drawable文件夹的图像会导致分配多达8倍的内存!

P.S.:

你可以对可绘制对象进行降采样,如果分辨率过大:
opts.inSampleSize = 2;

0

以上的解决方案在我的情况下都没有奏效!

我发现了一个库,它可以解决这个问题,并且还包含了一些有趣的功能。在这里查看它吧!

试试这个:

在gradle中

compile 'com.ToxicBakery.viewpager.transforms:view-pager-transforms:1.2.32@aar'

onCreate

viewPager.setPageTransformer(true, new DefaultTransformer());

通过更改第二个参数,您可以获得一些非标准效果,尽管并非所有效果都能正常工作。


0

我也遇到了类似的问题,在我的情况下,滞后是由于布局的背景图片太大造成的。我只需调整图片大小,滑动卡顿问题就解决了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接