【问题标题】:Gif is not playing after shared element transition. Glide v 4.8.0共享元素转换后 Gif 不播放。滑翔 v 4.8.0
【发布时间】:2019-05-04 08:14:44
【问题描述】:

列表中正在播放 Gif。 但在共享元素转换后它会停止。

.diskCacheStrategy(DiskCacheStrategy.ALL)
 GlideApp.with(this)
                .load(arguments?.getString(EXTRA_IMAGE_URL))
                .onlyRetrieveFromCache(true)
                .listener(object : RequestListener<Drawable> {
                    override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                        startPostponedEnterTransition()
                        return false
                    }

                    override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                        startPostponedEnterTransition()
                        return false
                    }
                })
                .into(view.ivDialog)

【问题讨论】:

    标签: android kotlin android-animation android-transitions


    【解决方案1】:

    在我的情况下有效的丑陋黑客(在 Java 中抱歉):

    .listener(new RequestListener<Drawable>() {
            @Override
            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
              return false;
            }
    
            @Override
            public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
              if (resource instanceof GifDrawable){
                final Handler handler = new Handler();                
                handler.post(() -> resource.setVisible(true, true));
              }
              return false;
            }
          });
    

    【讨论】:

      【解决方案2】:

      如果您的所有图像都是 Gifs,那么只需添加 .asGif 并将您的 listener 替换为 GifDrawable,如下所示,

      GlideApp.with(this)
                      .load(arguments?.getString(EXTRA_IMAGE_URL))
                      .asGif()
                      .onlyRetrieveFromCache(true)
                      .listener(object : RequestListener<GifDrawable> {
                          override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<GifDrawable>?, isFirstResource: Boolean): Boolean {
                              startPostponedEnterTransition()
                              return false
                          }
      
                          override fun onResourceReady(resource: GifDrawable?, model: Any?, target: Target<GifDrawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                              startPostponedEnterTransition()
                              return false
                          }
                      })
                      .into(view.ivDialog)
      

      如果您的图片不只是 Gif,请仔细检查以下 2 个解决方案

      解决方案 1-

      通过设置

      确保您的Activity B半透明 Activity
      <item name="android:windowIsTranslucent">true</item>
      

      仅在您的Activity's Theme 中且仅当您的活动 A 是半透明的,否则请确保您的两个活动都是非半透明或半透明的。

      更新:2020 年 6 月

      解决方案 2-

      在您的活动的onCreate() 方法调用postponeEnterTransition() 之前设置您的内容并在Glide 的onLoadFailed()onResourceReady() 回调中调用startPostponedEnterTransition()

      override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
      
              postponeEnterTransition()
      
              setContentView(R.layout.activity_main)
      
               GlideApp.with(context)
              .load(myImageUrl)
              .transition(DrawableTransitionOptions.withCrossFade())
              .listener(object : RequestListener<Drawable> {
                  override fun onLoadFailed(
                      e: GlideException?,
                      model: Any?,
                      target: Target<Drawable>?,
                      isFirstResource: Boolean
                  ): Boolean {
                      setStartPostponedTransition(itemImage)
                      return false
                  }
      
                  override fun onResourceReady(
                      resource: Drawable?,
                      model: Any?,
                      target: Target<Drawable>?,
                      dataSource: DataSource?,
                      isFirstResource: Boolean
                  ): Boolean {
                      setStartPostponedTransition(itemImage)
                      return false
                  }
      
              })
              .into(itemImage)
      
      }
      

      注意,这个 setStartPostponedTransition() 是辅助函数,我们在 ImageView 的 onPreDraw() 回调中调用 startPostponedEnterTransition()

       private fun setStartPostponedTransition(image: ImageView) {
              image.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
                  override fun onPreDraw(): Boolean {
                      image.viewTreeObserver.removeOnPreDrawListener(this)
                      startPostponedEnterTransition()
                      return true
                  }
              })
          }
      

      现在您的 Gif 将在您的 ActivityB 中播放,同时从 ActivityA 过渡,一旦您的 ImageView 的布局被绘制到屏幕上。

      这个解决方案是一个疯狂的黑客!我希望它会有所帮助。

      使用解决方案 2,您就可以开始了!

      【讨论】:

      • 这在我的情况下不起作用。如果只有几张图片是 Gif 会怎样?
      • @YiyoCastillo 我已经更新了答案,请查看。
      【解决方案3】:

      看起来这是库中的一个问题,我们将不得不接受我们自己的自定义修复。在我的情况下,在不给用户造成任何障碍的情况下,我重新加载了 gif 并延迟了一段时间,以便它可以无缝运行。 (反正第一次会缓存图片,Glide会高效处理后续调用)

      imageView.loadImageIfAvailable(logoUrl)
      imageView.transitionName = imageTransitionName
                      handler = Handler()
                      runnable = Runnable {
                          imageView.loadImageIfAvailable(logoUrl)
                      } 
                      handler.postDelayed(runnable, 2000)
      

      loadImageIfAvailable 是我自己的扩展函数,用于使用 Glide 加载图像。

      fun ImageView.loadImageIfAvailable(url: String?) {
          url?.let {
              Glide.with(context)
                  .load(url)
                  .into(this)
          }
      }
      
      
      Note: Don't forget to unregister the handlers by calling removeCallbacks on onStop()    
      
      override fun onStop() {
          super.onStop()
          handler?.removeCallbacks(runnable)
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-02-04
        • 1970-01-01
        • 2015-08-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多