Android Tutorial [Arguably] Better Ninepatch

Hi guys. I write here hoping to help a few people.

Recently I started a project that makes heavy use of user personalization. I had bad experiences with nine patches in the past, even though I use illustrator [exclusively] for my graphics. The "patching" is done at insane zoom, pixel perfect and still... as I like to say, no dice.

Things that suffer the most are the subtle ones, borders a few pixels thick, round corners, stuff like that. Not counting the fact that applying a patch on a smaller view than the .9.png's dimensions will turn that view's background into a big pile of crap.

So, my solution is this:
Marry the 9patching with the svg library.

So, we need :

B4X:
Sub test(p As Panel, amount As Int )
    Dim rect0,rect1,rect2,rect3,rect4,rect5,rect6,rect7,rectfill As Rect
    Dim vect,vect2 As SVG
   
    cvs.Initialize(p)
    rect0.Initialize(amount * 1dip,0,p.Width - amount * 1dip,amount * 1dip)
    rect1.Initialize(p.Width - amount * 1dip,0,p.Width,amount * 1dip)
    rect2.Initialize(p.Width - amount * 1dip,amount * 1dip,p.Width,p.Height - amount * 1dip)
    rect3.Initialize(p.width - amount * 1dip, p.Height - amount * 1dip, p.Width, p.height)
    rect4.Initialize(amount * 1dip,p.Height - amount * 1dip, p.Width - amount * 1dip, p.Height)
    rect5.Initialize(0, p.Height - amount * 1dip, amount * 1dip,p.Height)
    rect6.Initialize(0,amount * 1dip,amount * 1dip,p.Height - amount * 1dip)
    rect7.Initialize(0,0,amount * 1dip,amount * 1dip)
'    rectfill.Initialize(amount * 1dip,amount * 1dip,p.Width - amount * 1dip,p.Height - amount * 1dip)
   
    vect.Initialize(File.DirAssets, "0.svg")
    vect.DrawPicture(cvs,rect0)
   
    vect.Initialize(File.DirAssets, "1.svg")
    vect.DrawPicture(cvs,rect1)
   
    vect2.Initialize(File.DirAssets, "2.svg")
    vect2.DrawPicture(cvs,rect2)
   
    vect.Initialize(File.DirAssets, "3.svg")
    vect.DrawPicture(cvs,rect3)

    vect.Initialize(File.DirAssets, "4.svg")
    vect.DrawPicture(cvs,rect4)
   
    vect.Initialize(File.DirAssets, "5.svg")
    vect.DrawPicture(cvs,rect5)

    vect.Initialize(File.DirAssets, "6.svg")
    vect.DrawPicture(cvs, rect6)
   
    vect.Initialize(File.DirAssets, "7.svg")
    vect.DrawPicture(cvs,rect7)
   
'    vect.Initialize(File.DirAssets, "bg_mid.svg")
'    vect.DrawPicture(cvs,rectfill)
   
    bmp = cvs.Bitmap
End Sub

And we put it on a panel p1 with

B4X:
test(p1, 10)

Now, this example shows a basic example of a button with black stroke and a fine "shine".
Capture.PNG


The actual panel, in this example, is painted on the "sides". The center "patch" is a gradient generated within b4a.

The up side:

You can change how the button looks within b4a by changing the panel's fill gradient. :D

And, as you can see, the bottom of this sub sports this line:

B4X:
bmp = cvs.Bitmap

This is useful because vectors eat up resources. I did a test with 20 buttons. It was slow as hell.

But, if you have 4-5 groups of buttons, you run this sub for each group, once, store the bitmap and reuse it.

I feel it has potential. Especially because it stretches perfectly inwards, there's no more need for patching outside of your editor of choice and because it scales perfectly, you can totally use it from ldpi to xxxhdpi.

And you can "mix and match"
Design 4 square corners, 4 round ones and you can mix them as you please.

From there on, you can create a circle with the corners, or a square, or a button like in this image, with rounded corners, or one with left "square" corners and right "round corners" and so on.


Untitled-4.png
All these buttons were generated with the same 8 resources.​


Now, I'm a noob. If you have a better way to do this... would you mind letting me know? Thank you!
 
Top