Фон
У меня есть небольшое приложение для живых обоев, которое я хочу добавить для него, чтобы показать анимацию GIF.
Для этого я нашел различные решения. Существует решение показать анимацию GIF в представлении ( здесь), и есть даже решение для показа его в живых обоях ( здесь).
Тем не менее, для обоих из них я не могу найти, как хорошо подходить к содержанию анимации GIF в пространстве, которое у него есть, что означает любое из следующего:
- center-crop - подходит для 100% контейнера (в этом случае экран), обрезание по сторонам (сверху и снизу или слева и справа) при необходимости. Ничего не растягивает. Это означает, что контент кажется прекрасным, но не все это может быть показано.
- fit-center - растяжка, чтобы соответствовать ширине/высоте
- center-inside - устанавливается как оригинальный размер, центрируется и растягивается, чтобы соответствовать ширине/высоте, только если он слишком большой.
Эта проблема
Ни один из них не относится к ImageView, поэтому я не могу просто использовать атрибут scaleType.
Что я нашел
Существует решение, которое дает вам GifDrawable ( здесь), который вы можете использовать в ImageView, но в некоторых случаях кажется довольно медленным, и я не могу понять, как его использовать в LiveWallpaper, а затем подгонять.
Основной код обработки GIF LiveWallpaper как таковой ( здесь):
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
}
}
}
Основной код обработки анимации 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()
}
}
}
Вопросы
- Учитывая анимацию GIF, как я могу масштабировать ее по каждому из указанных способов?
- Возможно ли иметь одно решение для обоих случаев?
- Можно ли использовать библиотеку GifDrawable (или любую другую возможность для этого) для живых обоев вместо класса Movie? Если да, то как?
EDIT: узнав, как масштабироваться для 2-х видов, мне все равно нужно знать, как масштабироваться в соответствии с третьим типом, а также знать, почему он продолжает сбой после изменений ориентации и почему он не всегда показывает предварительный просмотр сразу,
Я также хотел бы знать, какой лучший способ показать анимацию GIF здесь, потому что в настоящее время я просто обновляю холст ~ 60 кадров в секунду (1000/60 ожидания между каждыми 2 кадрами) без учета того, что в файле.
Проект доступен здесь.