gpt4 book ai didi

android - 如何在 View 和动态壁纸中适合 GIF 动画的内容?

转载 作者:IT老高 更新时间:2023-10-28 21:53:02 34 4
gpt4 key购买 nike

背景

我有一个小型动态壁纸应用,我想添加对它的支持以显示 GIF 动画。

为此,我找到了各种解决方案。有在 View 中显示 GIF 动画的解决方案(here),甚至还有在动态壁纸中显示的解决方案(here)。

但是,对于他们两个,我都找不到如何将 GIF 动画的内容很好地适应它所拥有的空间,这意味着以下任何一种:

  1. center-crop - 适合 100% 的容器(在本例中为屏幕),在需要时在侧面(顶部和底部或左侧和右侧)进行裁剪。不拉伸(stretch)任何东西。这意味着内容看起来不错,但可能不会全部显示。
  2. fit-center - 拉伸(stretch)以适应宽度/高度
  3. center-inside - 设置为原始大小,居中,只有在太大时才会拉伸(stretch)以适应宽度/高度。

问题

这些都不是关于 ImageView 的,所以我不能只使用 scaleType 属性。

我发现了什么

有一个解决方案可以为您提供 GifDrawable (here),您可以在 ImageView 中使用它,但在某些情况下它似乎很慢,我不知道如何在 LiveWallpaper 中使用它,然后适合它。

LiveWallpaper GIF 处理的主要代码如下(here):

class GIFWallpaperService : WallpaperService() {
override fun onCreateEngine(): WallpaperService.Engine {
val movie = Movie.decodeStream(resources.openRawResource(R.raw.cinemagraphs))
return GIFWallpaperEngine(movie)
}

private inner class GIFWallpaperEngine(private val movie: Movie) : WallpaperService.Engine() {
private val frameDuration = 20

private var holder: SurfaceHolder? = null
private var visible: Boolean = false
private val handler: Handler = Handler()
private val drawGIF = Runnable { draw() }

private fun draw() {
if (visible) {
val canvas = holder!!.lockCanvas()
canvas.save()
movie.draw(canvas, 0f, 0f)
canvas.restore()
holder!!.unlockCanvasAndPost(canvas)
movie.setTime((System.currentTimeMillis() % movie.duration()).toInt())

handler.removeCallbacks(drawGIF)
handler.postDelayed(drawGIF, frameDuration.toLong())
}
}

override fun onVisibilityChanged(visible: Boolean) {
this.visible = visible
if (visible)
handler.post(drawGIF)
else
handler.removeCallbacks(drawGIF)
}

override fun onDestroy() {
super.onDestroy()
handler.removeCallbacks(drawGIF)
}

override fun onCreate(surfaceHolder: SurfaceHolder) {
super.onCreate(surfaceHolder)
this.holder = surfaceHolder
}
}
}

View 中处理GIF动画的主要代码如下:

class CustomGifView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
private var gifMovie: Movie? = null
var movieWidth: Int = 0
var movieHeight: Int = 0
var movieDuration: Long = 0
var mMovieStart: Long = 0

init {
isFocusable = true
val gifInputStream = context.resources.openRawResource(R.raw.test)

gifMovie = Movie.decodeStream(gifInputStream)
movieWidth = gifMovie!!.width()
movieHeight = gifMovie!!.height()
movieDuration = gifMovie!!.duration().toLong()
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
setMeasuredDimension(movieWidth, movieHeight)
}

override fun onDraw(canvas: Canvas) {

val now = android.os.SystemClock.uptimeMillis()
if (mMovieStart == 0L) { // first time
mMovieStart = now
}
if (gifMovie != null) {
var dur = gifMovie!!.duration()
if (dur == 0) {
dur = 1000
}
val relTime = ((now - mMovieStart) % dur).toInt()
gifMovie!!.setTime(relTime)
gifMovie!!.draw(canvas, 0f, 0f)
invalidate()
}
}
}

问题

  1. 给定一个 GIF 动画,我如何以上述各种方式对其进行缩放?
  2. 是否可以为这两种情况提供一个解决方案?
  3. 是否可以将 GifDrawable 库(或任何其他可绘制对象)用于动态壁纸,而不是使用 Movie 类?如果有,怎么做?

编辑:在找到如何缩放 2 种之后,我仍然需要知道如何根据第三种类型进行缩放,并且还想知道为什么它在方向更改后一直崩溃,以及为什么它并不总是显示立即预览。

我还想知道在这里显示 GIF 动画的最佳方式是什么,因为目前我只是刷新 Canvas ~60fps(每 2 帧之间等待 1000/60),而不考虑文件中的内容。

项目可用here .

最佳答案

如果您有 Glide在您的项目中,您可以轻松加载 Gif,因为它为您的 ImageView 提供了绘图 GIF,并且支持许多缩放选项(如中心或给定宽度和...)。

Glide.with(context)
.load(imageUrl or resourceId)
.asGif()
.fitCenter() //or other scaling options as you like
.into(imageView);

关于android - 如何在 View 和动态壁纸中适合 GIF 动画的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49944661/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com