and*_*per 30 android animated-gif
我有一个小型动态壁纸应用程序,我想添加支持它来显示GIF动画.
为此,我找到了各种解决方案.有一种在视图(这里)中显示GIF动画的解决方案,甚至还有一个解决方案,可以在动态壁纸(这里)中显示它.
但是,对于它们两者,我无法找到如何在其所拥有的空间中很好地拟合GIF动画的内容,这意味着以下任何一种情况:
这些都不是关于ImageView的,所以我不能只使用scaleType属性.
有一个解决方案可以为你提供一个GifDrawable(这里),你可以在ImageView中使用它,但在某些情况下它似乎很慢,我无法弄清楚如何在LiveWallpaper中使用它然后适合它.
LiveWallpaper GIF处理的主要代码就是这样(这里):
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
在视图中处理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()
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:在找到如何缩放2种之后,我仍然需要知道如何根据第三种类型进行缩放,并且还想知道为什么它在方向改变后不断崩溃,以及为什么它不总是立即显示预览.
我也想知道在这里展示GIF动画的最佳方式是什么,因为目前我只刷新画布~60fps(每2帧之间等待1000/60),而不考虑文件中的内容.
项目可在此处获得.
如果您的项目中有Glide,您可以轻松加载Gif,因为它为您的ImageView提供绘图GIF并支持许多缩放选项(如中心或给定宽度和......).
Glide.with(context)
.load(imageUrl or resourceId)
.asGif()
.fitCenter() //or other scaling options as you like
.into(imageView);
Run Code Online (Sandbox Code Playgroud)
好吧,我想我知道如何扩展内容了。但不确定为什么应用程序有时在方向改变时仍然崩溃,以及为什么应用程序有时不立即显示预览。
项目可在此处获取。
对于center-inside,代码是:
private fun draw() {
if (!isVisible)
return
val canvas = holder!!.lockCanvas() ?: return
canvas.save()
//center-inside
val scale = Math.min(canvas.width.toFloat() / movie.width().toFloat(), canvas.height.toFloat() / movie.height().toFloat());
val x = (canvas.width.toFloat() / 2f) - (movie.width().toFloat() / 2f) * scale;
val y = (canvas.height.toFloat() / 2f) - (movie.height().toFloat() / 2f) * scale;
canvas.translate(x, y)
canvas.scale(scale, scale)
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())
}
Run Code Online (Sandbox Code Playgroud)
对于中心裁剪,代码是:
private fun draw() {
if (!isVisible)
return
val canvas = holder!!.lockCanvas() ?: return
canvas.save()
//center crop
val scale = Math.max(canvas.width.toFloat() / movie.width().toFloat(), canvas.height.toFloat() / movie.height().toFloat());
val x = (canvas.width.toFloat() / 2f) - (movie.width().toFloat() / 2f) * scale;
val y = (canvas.height.toFloat() / 2f) - (movie.height().toFloat() / 2f) * scale;
canvas.translate(x, y)
canvas.scale(scale, scale)
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())
}
Run Code Online (Sandbox Code Playgroud)
对于健身中心,我可以使用这个:
val canvasWidth = canvas.width.toFloat()
val canvasHeight = canvas.height.toFloat()
val bitmapWidth = curBitmap.width.toFloat()
val bitmapHeight = curBitmap.height.toFloat()
val scaleX = canvasWidth / bitmapWidth
val scaleY = canvasHeight / bitmapHeight
scale = if (scaleX * curBitmap.height > canvas.height) scaleY else scaleX
x = (canvasWidth / 2f) - (bitmapWidth / 2f) * scale
y = (canvasHeight / 2f) - (bitmapHeight / 2f) * scale
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
890 次 |
| 最近记录: |