Search code examples
androidxmltexturesnine-patch

Apply 9patch and texture to button


I'm work on project where all buttons has paper-like background. Also buttons needs rounded corners and specific border. To make corners and borders I use nine patch. Here comes the problem! Using texture as background excludes nine patch btw nine patches can't stretch textures right way.

Is there any way to combine nine patch with texture? I tried to use layer-listand failed with it.

Update. Here is my nine-patch (scaled) enter image description here

And here is texture

enter image description here


Solution

  • After some research I made custom class that extends Button. This class can apply texture to 9patch buttons accordingly mask.

    public class TextureButton extends Button {
    
    private final static String TAG = TextureButton.class.getSimpleName();
    private BitmapDrawable texture;
    private NinePatchDrawable ninePatchDrawable;
    private Paint paint;
    
    
    public TextureButton(Context context) {
        super(context);
        init();
    }
    
    public TextureButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    
    public TextureButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    
    private void init() {
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pattern300);
        texture = new BitmapDrawable(getResources(), bitmap);
        texture.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        Bitmap bitmapMask = BitmapFactory.decodeResource(getResources(), R.drawable.btn_mask);
        ninePatchDrawable = new NinePatchDrawable(getResources(), bitmapMask, bitmapMask.getNinePatchChunk(), new Rect(0, 0, 0, 0), null);
        paint = new Paint();
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
        paint.setAntiAlias(true);
    }
    
    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);
        canvas.saveLayer(0, 0, getWidth(), getHeight(), paint, Canvas.ALL_SAVE_FLAG);
        texture.setBounds(0, 0, getWidth(), getHeight());
        texture.setAlpha(255);
        texture.draw(canvas);
        ninePatchDrawable.setBounds(0, 0, getWidth(), getHeight());
        ninePatchDrawable.draw(canvas);
        canvas.restore();
    }
    
    }
    

    As mask I use 9patch with white and transparent pixels.