How can we tile a vector image?

后端 未结 5 721
眼角桃花
眼角桃花 2021-02-12 21:02

With the support library now fully supporting vector images, I\'m trying to switch to vector images as much as I can in my app. An issue I\'m running into is that it seems impos

5条回答
  •  北荒
    北荒 (楼主)
    2021-02-12 21:15

    I'd like to put a full solution that doesn't require the support library hidden class, written in Kotlin, based on what was suggested in one of the answers (here) :

    DrawableWrapper.kt

    open class DrawableWrapper(drawable: Drawable) : Drawable(), Drawable.Callback {
        var wrappedDrawable: Drawable = drawable
            set(drawable) {
                field.callback = null
                field = drawable
                drawable.callback = this
            }
    
        override fun draw(canvas: Canvas) = wrappedDrawable.draw(canvas)
    
        override fun onBoundsChange(bounds: Rect) {
            wrappedDrawable.bounds = bounds
        }
    
        override fun setChangingConfigurations(configs: Int) {
            wrappedDrawable.changingConfigurations = configs
        }
    
        override fun getChangingConfigurations() = wrappedDrawable.changingConfigurations
    
        override fun setDither(dither: Boolean) = wrappedDrawable.setDither(dither)
    
        override fun setFilterBitmap(filter: Boolean) {
            wrappedDrawable.isFilterBitmap = filter
        }
    
        override fun setAlpha(alpha: Int) {
            wrappedDrawable.alpha = alpha
        }
    
        override fun setColorFilter(cf: ColorFilter?) {
            wrappedDrawable.colorFilter = cf
        }
    
        override fun isStateful() = wrappedDrawable.isStateful
    
        override fun setState(stateSet: IntArray) = wrappedDrawable.setState(stateSet)
    
        override fun getState() = wrappedDrawable.state
    
    
        override fun jumpToCurrentState() = DrawableCompat.jumpToCurrentState(wrappedDrawable)
    
        override fun getCurrent() = wrappedDrawable.current
    
        override fun setVisible(visible: Boolean, restart: Boolean) = super.setVisible(visible, restart) || wrappedDrawable.setVisible(visible, restart)
    
        override fun getOpacity() = wrappedDrawable.opacity
    
        override fun getTransparentRegion() = wrappedDrawable.transparentRegion
    
        override fun getIntrinsicWidth() = wrappedDrawable.intrinsicWidth
    
        override fun getIntrinsicHeight() = wrappedDrawable.intrinsicHeight
    
        override fun getMinimumWidth() = wrappedDrawable.minimumWidth
    
        override fun getMinimumHeight() = wrappedDrawable.minimumHeight
    
        override fun getPadding(padding: Rect) = wrappedDrawable.getPadding(padding)
    
        override fun invalidateDrawable(who: Drawable) = invalidateSelf()
    
        override fun scheduleDrawable(who: Drawable, what: Runnable, `when`: Long) = scheduleSelf(what, `when`)
    
        override fun unscheduleDrawable(who: Drawable, what: Runnable) = unscheduleSelf(what)
    
        override fun onLevelChange(level: Int) = wrappedDrawable.setLevel(level)
    
        override fun setAutoMirrored(mirrored: Boolean) = DrawableCompat.setAutoMirrored(wrappedDrawable, mirrored)
    
        override fun isAutoMirrored() = DrawableCompat.isAutoMirrored(wrappedDrawable)
    
        override fun setTint(tint: Int) = DrawableCompat.setTint(wrappedDrawable, tint)
    
        override fun setTintList(tint: ColorStateList?) = DrawableCompat.setTintList(wrappedDrawable, tint)
    
        override fun setTintMode(tintMode: PorterDuff.Mode) = DrawableCompat.setTintMode(wrappedDrawable, tintMode)
    
        override fun setHotspot(x: Float, y: Float) = DrawableCompat.setHotspot(wrappedDrawable, x, y)
    
        override fun setHotspotBounds(left: Int, top: Int, right: Int, bottom: Int) = DrawableCompat.setHotspotBounds(wrappedDrawable, left, top, right, bottom)
    }
    

    TilingDrawable.kt

    class TilingDrawable(drawable: Drawable) : DrawableWrapper(drawable) {
        private var callbackEnabled = true
    
        override fun draw(canvas: Canvas) {
            callbackEnabled = false
            val bounds = bounds
            val width = wrappedDrawable.intrinsicWidth
            val height = wrappedDrawable.intrinsicHeight
            var x = bounds.left
            while (x < bounds.right + width - 1) {
                var y = bounds.top
                while (y < bounds.bottom + height - 1) {
                    wrappedDrawable.setBounds(x, y, x + width, y + height)
                    wrappedDrawable.draw(canvas)
                    y += height
                }
                x += width
            }
            callbackEnabled = true
        }
    
        override fun onBoundsChange(bounds: Rect) {}
    
        override fun invalidateDrawable(who: Drawable) {
            if (callbackEnabled)
                super.invalidateDrawable(who)
        }
    
        override fun scheduleDrawable(who: Drawable, what: Runnable, `when`: Long) {
            if (callbackEnabled)
                super.scheduleDrawable(who, what, `when`)
        }
    
        override fun unscheduleDrawable(who: Drawable, what: Runnable) {
            if (callbackEnabled)
                super.unscheduleDrawable(who, what)
        }
    }
    

    Sample usage:

    yourView.background = TilingDrawable(AppCompatResources.getDrawable(this, R.drawable.your_drawable)!!)
    

提交回复
热议问题