You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LayerDrawable无法显示4张图片仅显示一张的技术问题求助

Android中LayerDrawable仅显示单张图片的问题

我在Android开发中尝试用LayerDrawable显示4张图片,但始终只有一张能正常显示。以下是核心实现代码和布局文件:

核心代码

private fun getClusterIcon(cluster: Cluster<Store>): BitmapDescriptor? {
       
      val profilePhotos: MutableList<Drawable> =  ArrayList(4.coerceAtMost(cluster.size))

      for(store in cluster.items)
      {
          if (profilePhotos.size == 4) break;

                 Picasso.get().load(store.hauptBild).into(object : com.squareup.picasso.Target {
                     override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
                         val drawable: Drawable = BitmapDrawable(ctx.resources,bitmap);
                         drawable.setBounds(0, 0, width, height)
                         profilePhotos.add(drawable)
                     }

                     override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {}

                     override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}


                 })


      }

        val multiDrawable = LayerDrawable(profilePhotos.toTypedArray())
        multiDrawable.setBounds(0, 0, width, height)

        mClusterImageView!!.setImageDrawable(multiDrawable)
        val icon: Bitmap = mClusterIconGenerator.makeIcon(cluster.size.toString())
        return BitmapDescriptorFactory.fromBitmap(icon)

  }

布局文件(multi_profil.xml)

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:padding="2dp"
android:layout_width="@dimen/custom_profile_image"
android:layout_height="@dimen/custom_profile_image">

<ImageView
    android:id="@+id/image"
    android:scaleType="centerCrop"
    android:layout_width="@dimen/custom_profile_image"
    android:layout_height="@dimen/custom_profile_image"/>
  
<TextView
    android:id="@id/amu_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="@style/amu_Bubble.TextAppearance.Light"
    android:background="@android:color/black"
    android:paddingLeft="@dimen/custom_profile_padding"
    android:paddingRight="@dimen/custom_profile_padding"
    android:layout_gravity="center"
    android:alpha=".8"/>

</FrameLayout>

问题原因

  1. Picasso异步加载时序错误:into(Target)是异步操作,循环结束后立刻创建LayerDrawable时,profilePhotos列表大概率还没加载完所有图片,导致LayerDrawable中Drawable数量不足。
  2. Drawable边界重叠:所有Drawable的bounds都设置为(0, 0, width, height),四张图完全重叠,视觉上只能看到最上层的一张。

解决方案

1. 处理异步加载时序

用CountDownLatch等待所有图片加载完成后再创建LayerDrawable,同时避免主线程阻塞:

private fun getClusterIcon(cluster: Cluster<Store>) {
    val maxCount = 4.coerceAtMost(cluster.size)
    val profilePhotos: MutableList<Drawable> = ArrayList(maxCount)
    val latch = CountDownLatch(maxCount)

    for(store in cluster.items) {
        if (profilePhotos.size == maxCount) break

        Picasso.get().load(store.hauptBild).into(object : com.squareup.picasso.Target {
            override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
                bitmap?.let {
                    val drawable = BitmapDrawable(ctx.resources, it)
                    profilePhotos.add(drawable)
                }
                latch.countDown()
            }

            override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {
                latch.countDown()
            }

            override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}
        })
    }

    Thread {
        try {
            latch.await()
            ctx.runOnUiThread {
                if (profilePhotos.isEmpty()) return@runOnUiThread
                
                val multiDrawable = LayerDrawable(profilePhotos.toTypedArray())
                multiDrawable.setBounds(0, 0, width, height)
                
                // 分区域设置每张图的边界,避免重叠
                val halfW = width / 2
                val halfH = height / 2
                profilePhotos.forEachIndexed { index, _ ->
                    val drawable = multiDrawable.getDrawable(index)
                    when(index) {
                        0 -> drawable.setBounds(0, 0, halfW, halfH)
                        1 -> drawable.setBounds(halfW, 0, width, halfH)
                        2 -> drawable.setBounds(0, halfH, halfW, height)
                        3 -> drawable.setBounds(halfW, halfH, width, height)
                    }
                }

                mClusterImageView!!.setImageDrawable(multiDrawable)
                val icon = mClusterIconGenerator.makeIcon(cluster.size.toString())
                // 这里可通过回调或LiveData传递生成的BitmapDescriptor
            }
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
    }.start()
}

2. 调整返回逻辑

原方法直接返回BitmapDescriptor会因异步加载未完成返回空值,建议改用回调接口或LiveData传递最终结果,替代直接返回值的方式。

内容的提问来源于stack exchange,提问作者Captai-N

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 20:52:05