Android如何实现图片屏幕滑动?

15

我正在开发一个非常基本的android图库,它可以显示相机文件夹中的最后一张照片,用户可以向左滑动查看前一张。

我使用了ViewPager和PagerAdapter实现了这个功能,并使用sampleSize缩放图像。我的问题是,实现效率远不如默认的图库应用程序,每次滑动图片都需要等待大约200毫秒才能加载下一张。所以,我的想法在如何实现它方面并没有起到作用。

有什么方法可以高效地完成这个任务,如果可能,还可以允许稍后进行缩放吗?


这看起来很有前途,但我不知道如何将其与文件一起实现,而不是使用drawables。http://www.androidviews.net/2012/11/photoview/


编辑:

我成功地使用photoview(一个被修改过的viewpager)提高了速度,但是将文件路径转换为位图或drawable却需要太长时间。

我已经尝试了dilix和iDroid Explorer建议的这两种方法:

// Method A
Drawable d = Drawable.createFromPath(imagePath);
imageView.setImageDrawable(d);

// Method B
Bitmap myBitmap = BitmapFactory.decodeFile(imagePath);
imageView.setImageBitmap(myBitmap);

但是两者都会产生错误位图太大,无法上传到纹理。我需要尽快将图像传递给imageView并绕过此错误,或许可以获得更好的速度。目前我正在缩放图像并将它们转换为drawable,但效率并不高。


您可以使用画廊 (Gallery),链接如下:http://developer.android.com/reference/android/widget/Gallery.html - Jaiprakash Soni
你必须知道,你所注意到的延迟是由于文件轮询引起的!因此,如果你注意到androidviews.net非常快,记住它使用的是可绘制对象而不是图像文件! - Sherif elKhatib
4个回答

3

1
我刚刚测试了一下,它运行得很好。但是我一直在研究代码,没有看到任何用图像文件代替可绘制对象实现的方法。我将开始检查是否可以将其与我的实现结合使用,但我不认为这会起作用。 - lisovaccaro
我正在使用photoview实现,结合imageView.setImageDrawable(GetDrawable(imagePath, 150, 150));将SD卡文件路径转换为可绘制的图像。然而这种方法仍然相当低效。也许有一种方法可以直接使用文件路径来设置view.setImage?(无需转换) - lisovaccaro
这引导我走上了正确的道路。我必须想办法实现懒加载图片,如果可能的话,还要考虑如何更改viewpager动画。 - lisovaccaro
你知道如何禁用捏合打开/关闭缩放吗? - VansFannel

1

我不确定你是否得到了正确的解决方案。但是如果您想使用您提供的链接继续进行自己的实现,则:

http://www.androidviews.net/2012/11/photoview/   //this link is given in your question

您可以查看this SO,了解如何将文件路径转换为可绘制对象。现在,您已经获取了指定文件的可绘制对象,并在给定的链接上实现。

我认为该链接会很好地发挥作用。

请随意发表评论。


我刚试了一下你的方法(文件路径到位图和文件路径到可绘制对象),但两者都返回相同的错误:W/OpenGLRenderer(20913): Bitmap too large to be uploaded into a texture - lisovaccaro
目前我正在使用photoview,结合一个在使用位图之前对其进行缩放的函数。但我认为这个函数并不是很高效,我需要更快地将文件加载到imageview中。 - lisovaccaro
图片是从互联网上来的吗? - Shreyash Mahajan
没有,这些图片来自 SD 卡。 - lisovaccaro

1

1)

这看起来很有前途,但我不知道如何将其与文件实现而不是可绘制物一起使用http://www.androidviews.net/2012/11/photoview/

您必须在适配器中存储文件链接而不是可绘制列表,然后加载它。

2) 但我可以想象,与可绘制物相比,文件不会那么高效,因为要从SD卡中解析文件。

我认为您可以通过同时加载几个图像(压缩)来节省时间,并且当您划过到另一个图像时,您已经拥有了该图像和内存,而在刷卡时,您可以开始在内存中加载其他图像。

在浏览画廊时,您可能不需要加载图像,并且在几乎停止后再加载它。

这是主要问题:内存消耗与性能之间的平衡。

更新

我认为最好的方法是探索谷歌画廊的现有代码,而不是自己探索:https://github.com/CyanogenMod/android_packages_apps_Gallery

当我查看时,他们会存储缓存(几乎就像我所说的加载多个位图),并且仅存储调整大小的图像-似乎很有效。

也许我误解了你的第一个观点,我在我的适配器中有一个文件列表,但是我必须将它们转换为可绘制对象,因为我不知道其他添加到图像视图的方法,所以我会做这样的事情(imageView.setImageDrawable(GetDrawable(imagePath, 150, 150));)。有没有一种方法可以在不进行此转换的情况下显示图像?这可能会节省很多资源。 - lisovaccaro
你可以加载位图(压缩的,例如一次可以加载3个 - 当前、上一个和下一个),并像这样将该位图加载到视图中:https://dev59.com/x2855IYBdhLWcg3wuG0M - dilix
我刚刚尝试了另一个问题中的实现,但是出现了错误:Bitmap too large to be uploaded into a texture (2560x1920, max=2048x2048)。看起来很接近了。这与压缩有关吗?我不知道如何加载它们压缩过的,你知道如何绕过这个错误吗? - lisovaccaro
我还不能确定,但如果这个方法可行的话,我就不必将图像转换为可绘制对象,也许可以节省几毫秒的时间。顺便说一下,我认为ViewPager会自动预加载相邻屏幕,因此我可能已经同时加载了3张图片。 - lisovaccaro
"位图太大,无法上传到纹理中(2560x1920,最大=2048x2048)" - 您的设备屏幕对于这样的分辨率来说太小了 - 调整位图大小将更有效:https://dev59.com/BG445IYBdhLWcg3we6V9 顺便提醒一下,请回收您的位图以避免内存泄漏。 - dilix
这只是一个建议,如果我没有帮到你,很抱歉。然后你可以检查谷歌应用的现有代码(请查看更新的答案)。 - dilix

1
请参考官方文档,其中有一个很好的示例,可以有效地向您介绍如何使用 ViewPager。您应该使用已加载的图像的缓存,并在 UI 线程之外加载图像。您还希望将图像缩放到显示所需的最小尺寸(通常是 2 的幂 - 请注意,图像不总是按照您要求的大小进行缩放!)ViewPager 还会在后台加载图像,以准备下一张幻灯片,这是使用 setOffScreenPageLimit 方法设置的(默认值通常很好,我认为是 2)。

https://developer.android.com/training/displaying-bitmaps/index.html


起初我认为这个例子很糟糕,但它确实允许快速滑动。不过启动需要很长时间。我会看看能否实现它。 - lisovaccaro
我一直在尝试动态加载图像文件,但似乎不可能将它们放在最终和静态的imageUrls中。请检查我尝试过的,也许您可以找到解决方案:http://pastebin.com/raw.php?i=LDAwU7Mx - lisovaccaro
你是不是想调用 pathsList、imageList?由于 imageUrls 是一个 final 变量,所以你只能赋值一次。你可以使用 public final static String[] imageUrls = imageList.toArray(new String[imageList.size()]) - ndw

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