Skip to content

Instantly share code, notes, and snippets.

@mswolters
Created March 17, 2016 12:07
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save mswolters/9ffbdf01478e36194f8f to your computer and use it in GitHub Desktop.
Save mswolters/9ffbdf01478e36194f8f to your computer and use it in GitHub Desktop.
TilingDrawable
public class TilingDrawable extends android.support.v7.graphics.drawable.DrawableWrapper {
private boolean callbackEnabled = true;
public TilingDrawable(Drawable drawable) {
super(drawable);
}
@Override
public void draw(Canvas canvas) {
callbackEnabled = false;
Rect bounds = getBounds();
Drawable wrappedDrawable = getWrappedDrawable();
int width = wrappedDrawable.getIntrinsicWidth();
int height = wrappedDrawable.getIntrinsicHeight();
for (int x = bounds.left; x < bounds.right + width - 1; x+= width) {
for (int y = bounds.top; y < bounds.bottom + height - 1; y += height) {
wrappedDrawable.setBounds(x, y, x + width, y + height);
wrappedDrawable.draw(canvas);
}
}
callbackEnabled = true;
}
@Override
protected void onBoundsChange(Rect bounds) {
}
/**
* {@inheritDoc}
*/
public void invalidateDrawable(Drawable who) {
if (callbackEnabled) {
super.invalidateDrawable(who);
}
}
/**
* {@inheritDoc}
*/
public void scheduleDrawable(Drawable who, Runnable what, long when) {
if (callbackEnabled) {
super.scheduleDrawable(who, what, when);
}
}
/**
* {@inheritDoc}
*/
public void unscheduleDrawable(Drawable who, Runnable what) {
if (callbackEnabled) {
super.unscheduleDrawable(who, what);
}
}
}
@Miha-x64
Copy link

Miha-x64 commented Mar 9, 2017

Thank you for sharing, that's very useful!
I've also added

    @Override
    public int getMinimumWidth() {
        return 0;
    }
    @Override
    public int getMinimumHeight() {
        return 0;
    }

, so wrapped drawable's size won't affect view's size.

@Abushawish
Copy link

Abushawish commented May 23, 2017

I'm having an issue, the super() in the constructor warns

DrawableWrapper can only be called from within the same library group (groupId=com.android.support)

Similarly the getWrappedDrawable() in the draw(Canvas canvas) states

DrawableWrapper.getWappedDrawable can only be called from within the same library group (groupId=com.android.support)

Tried my Google-Fu, but very little results are online. Any help you can offer?

@mswolters
Copy link
Author

It seems an @RestrictTo annotation was added to the class in the support library, so I think the only solution would be to copy the entire source of DrawableWrapper and subclass that.

@nikiforov-org
Copy link

Could you write a constructor for this class for tiling layout, simple "get started"?

@antaki93
Copy link

antaki93 commented Nov 24, 2017

Is it a correct example of use? At least, it work… :)
Drawable drawable = ContextCompat.getDrawable(this, R.drawable.my_drawable_resource); TilingDrawable tDraw = new TilingDrawable(drawable); tDraw.draw(new Canvas()); mRelativeLayout.setBackground(tDraw);

@AndroidDeveloperLB
Copy link

@antaki93 You can use this way on Kotlin:

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

BTW, here's the original code of the TilingDrawable, in Kotlin:


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)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment