1

我正在使用以下方法开发一个 android 应用程序:

  • Jetpack 生命周期 (ViewModel)
  • 喷气背包导航
  • 线圈(图像加载器)

我正在尝试自定义 BottomNavigationMenu。

但有一件事是非常困难的......

在此处输入图像描述

最后一个选项卡是带边框的用户个人资料图像。

如果用户的头像背景颜色是白色的,那么 ui 就很奇怪。所以我应该显示边界。

class MainActivity {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        initBottomNav(binding.bottomNav)
        vm.initProfileBottomIcon()
    }

    private fun initBottomNav(bottomNav: BottomNavigationView) {
        val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
        bottomNav.setupWithNavController(navHostFragment.navController)
        bottomNav.itemIconTintList = null

        vm.profileImgUrl.observe(this) { url ->
            bottomNav.menu.findItem(R.id.profileFragment).load(this, url) {
                transformations(CircleCropTransformation())
            }
        }
    }
}

此代码在 BottomNavigationMenu 上绘制配置文件图像。但不画边界。

当我在谷歌上搜索时,不支持带有边框的 CircleCrop(甚至 Glide)。

所以我尝试了下面的代码,但效果不佳..

vm.profileImg.observe(this) { imgBitmap ->
    val layerBorder = ResourcesCompat.getDrawable(resources, R.drawable.oval_trans_border1_red, null)
    val layerIcon = BitmapDrawable(Resources.getSystem(), imgBitmap)
    val layerDrawable = LayerDrawable(arrayOf(layerIcon, layerBorder))

    val bottomNavProfile = bottomNav.menu.findItem(R.id.profileFragment)
    val request = ImageRequest.Builder(this)
        .data(layerDrawable)
        .target {
            bottomNavProfile.icon = it
        }
        .apply {
            transformations(CircleCropTransformation())
        }
        .build()
    imageLoader.enqueue(request)
}

有人帮我吗?

4

1 回答 1

1

您可以编写自己的带有边框的转换,如下所示:

class BorderedCircleCropTransformation(
    private val borderSize: Float = 0f,
    @ColorInt private val borderColor: Int = Color.BLUE
) : Transformation {

    override fun key(): String = BorderedCircleCropTransformation::class.java.name

    override suspend fun transform(pool: BitmapPool, input: Bitmap, size: Size): Bitmap {
        val borderOffset = (borderSize * 2).toInt()
        val halfWidth = input.width / 2
        val halfHeight = input.height / 2
        val circleRadius = Math.min(halfWidth, halfHeight).toFloat()
        val newBitmap = Bitmap.createBitmap(
            input.width + borderOffset,
            input.height + borderOffset,
            Bitmap.Config.ARGB_8888
        )

        // Center coordinates of the image
        val centerX = halfWidth + borderSize
        val centerY = halfHeight + borderSize

        val paint = Paint()
        val canvas = Canvas(newBitmap).apply {
            // Set transparent initial area
            drawARGB(0, 0, 0, 0)
        }

        // Draw the transparent initial area
        paint.isAntiAlias = true
        paint.style = Paint.Style.FILL
        canvas.drawCircle(centerX, centerY, circleRadius, paint)

        // Draw the image
        paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        canvas.drawBitmap(input, borderSize, borderSize, paint)

        // Draw the createBitmapWithBorder
        paint.xfermode = null
        paint.style = Paint.Style.STROKE
        paint.color = borderColor
        paint.strokeWidth = borderSize
        canvas.drawCircle(centerX, centerY, circleRadius, paint)
        return newBitmap
    }

    override fun equals(other: Any?) = other is BorderedCircleCropTransformation

    override fun hashCode() = javaClass.hashCode()

    override fun toString() = "BorderedCircleCropTransformation()"

    private companion object {
        val XFERMODE = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
    }
}

internal val Bitmap.safeConfig: Bitmap.Config
    get() = config ?: Bitmap.Config.ARGB_8888

然后将它作为转换传递给线圈,它会画出你想要的东西。我使用此代码绘制边框。

于 2022-01-13T14:10:13.850 回答