Android Example Add border to Views and change Checkbox graphic

Discussion in 'Tutorials & Examples' started by stevel05, Jan 6, 2014.

  1. stevel05

    stevel05 Expert Licensed User

    Here are a couple of routines that may come in handy.

    The first adds a background to a view which can have a fill color, rounded corners and a border color. This is useful for picking out views against a background where they may otherwise not be too visible.

    If you want a decorative border then it would be better to use a dedicated graphic, but this will have some uses. And you haven't got to find a graphic.


    Code:
    'Add a border to a view. Adds Fillcolor, StrokeColor(Border color), rx,ry (rounded corners) SWidth(Border width)
    'and padding which is only applied to Labels
    Sub SetBorderDrawable (V As View, FillColor As Int, StrokeColor As Int, rx As Float, ry As Float, SWidth As Float, Padding As Int)

        
    Dim BM As Bitmap
        
    Dim BMD As BitmapDrawable
        
    Dim Cnv As Canvas
        
    'We need to draw on the bitmap with a canvas
        BM.InitializeMutable(V.Width,V.Height)
        Cnv.Initialize2(BM)
        
    'Sizing Variables need to be floats to enable the constructor to be found.
        Dim l,t,r,b As Float
        l = 
    0
        t = 
    0
        r = V.Width
        b = V.Height
        
    'Needs a RectF (Float) object not just a Rect
        Dim rect1 As JavaObject
        rect1.InitializeNewInstance(
    "android.graphics.RectF",Array As Object(l,t,r,b))
        
    'Create a Paint.Style object
        Dim PS As JavaObject
        PS.InitializeStatic(
    "android.graphics.Paint.Style")
        
    'Create and setup a Paint object
        Dim Paint,Paint1 As JavaObject
        
    Paint.InitializeNewInstance("android.graphics.Paint",Null)
        
    Paint.RunMethod("setStrokeWidth",Array As Object(SWidth))
        
    Paint.RunMethod("setColor",Array As Object(StrokeColor))
        
    Paint.RunMethod("setStyle",Array As Object(PS.GetField("STROKE")))
        
    Paint.RunMethod("setAntiAlias",Array As Object(True))

        Paint1.InitializeNewInstance(
    "android.graphics.Paint",Null)
        Paint1.RunMethod(
    "setColor",Array As Object(FillColor))
        Paint1.RunMethod(
    "setAntiAlias",Array As Object(True))
        Paint1.RunMethod(
    "setStyle",Array As Object(PS.GetField("FILL")))

        
    'Get the canvas object from the wrapper
        Dim CnvJO As JavaObject = Cnv
        CnvJO = CnvJO.GetField(
    "canvas")
        
    'Draw the filled round rect on the bitmap using the canvas
        CnvJO.RunMethod("drawRoundRect",Array As Object(rect1,rx,ry,Paint1))
        
    'Draw the border round rect on the bitmap using the canvas
        CnvJO.RunMethod("drawRoundRect",Array As Object(rect1,rx,ry,Paint))
        
    'Cast the Bitmap to a BitmapDrawable
        BMD.Initialize(BM)
        
    'Add padding if needed and requested
        If Padding <> -1 AND GetType(V) = "android.widget.TextView" Then
            
    Dim VJO As JavaObject = V
            VJO.RunMethod(
    "setPadding",Array As Object(Padding,Padding,Padding,Padding))
        
    End If
        
    'Add the BitmapDrawable to the view
        V.Background = BMD
    End Sub
    The second routine allows changing the graphic for a checkbox, on some backgrounds it's difficult to see the checkbox in default color. You can change the size and color of the tickbox.

    In addition you can specify a text character and color to use as the check and if you pass "Fill", the checked state will be the box filled with the TickColor.

    It would be fairly straight forward to change the routine to use a graphic instead of a character if you prefer or change the shape of the checkbox for a circle or star graphic maybe.

    Code:
    'Change the size and color of a Checkbox graphic. Set the tick character and color, as well as the box size and color
    'and padding (distance from the box to the edge of the graphic) and a disabled fill color
    'Pass "Fill" as the TickChar to fill the box with TickColor when selected.
    Sub SetCBDrawable(CB As CheckBox,BoxColor As Int,BoxWidth As Int,TickColor As Int,TickChar As String,DisabledColor As Int,Size As Int,Padding As Int)
        
    Dim SLD As StateListDrawable
        SLD.Initialize

        
    Dim BMEnabled,BMChecked,BMDisabled As Bitmap
        BMEnabled.InitializeMutable(Size,Size)
        BMChecked.InitializeMutable(Size,Size)
        BMDisabled.InitializeMutable(Size,Size)
        
    'Draw Enabled State
        Dim CNV As Canvas
        CNV.Initialize2(BMEnabled)
        
    Dim Rect1 As Rect
        Rect1.Initialize(Padding ,Padding ,Size - Padding ,Size - Padding)
        CNV.DrawRect(Rect1,BoxColor,
    False,BoxWidth)
        
    Dim Enabled,Checked,Disabled As BitmapDrawable
        Enabled.Initialize(BMEnabled)
        
    'Draw Selected state
        Dim CNV1 As Canvas
        CNV1.Initialize2(BMChecked)
        
    If TickChar = "Fill" Then
            CNV1.DrawRect(Rect1,TickColor,
    True,BoxWidth)
            CNV1.DrawRect(Rect1,BoxColor,
    False,BoxWidth)
        
    Else
            CNV1.DrawRect(Rect1,BoxColor,
    False,BoxWidth)
            
    'Start small and find the largest font that allows the tick to fit in the box
            Dim FontSize As Int = 6
            
    Do While CNV.MeasureStringHeight(TickChar,Typeface.DEFAULT,FontSize) < Size - (BoxWidth * 2) - (Padding * 2)
                FontSize = FontSize + 
    1
            
    Loop
            FontSize = FontSize - 
    1
            
    'Draw the TickChar centered in the box
            CNV1.DrawText(TickChar,Size/2,(Size + CNV.MeasureStringHeight(TickChar,Typeface.DEFAULT,FontSize))/2,Typeface.DEFAULT,FontSize,TickColor,"CENTER")
        
    End If
        Checked.Initialize(BMChecked)
        
    'Draw disabled State
        Dim CNV2 As Canvas
        CNV2.Initialize2(BMDisabled)
        CNV2.DrawRect(Rect1,DisabledColor,
    True,BoxWidth)
        CNV2.DrawRect(Rect1,BoxColor,
    False,BoxWidth)
        Disabled.Initialize(BMDisabled)

        
    'Add to the StateList Drawable
        SLD.AddState(SLD.State_Disabled,Disabled)
        SLD.AddState(SLD.State_Checked,Checked)
        SLD.AddState(SLD.State_Enabled,Enabled)
        SLD.AddCatchAllState(Enabled)
        
    'Add SLD to the Checkbox
        Dim JO As JavaObject = CB
        JO.RunMethod(
    "setButtonDrawable",Array As Object(SLD))
    End Sub
    Both are used in the example app attached, which are a bit extreme but you'll get the idea.

    Both require the JavaObject Library

    I hope you find them useful.

    Tags: Border Drawable CheckBox Image Graphic
     

    Attached Files:

    Last edited: Mar 29, 2014
    fredo, Humberto, koaunglay and 13 others like this.
  2. notedop

    notedop Member Licensed User

    Nice, would you also be able to do something similar with radiobuttons? I really do not like the standard rb and would like to customize it as much as possible,
     
  3. stevel05

    stevel05 Expert Licensed User

    Sorry I didn't reply sooner, I missed your post.

    Radiobutton is based on a StateListDrawable the same as Checkbox, so you can used the same code. Just change the type of CB to View or Radiobutton in the signature and you can pass a Radiobutton.

    You can then change the drawing elements as you please.
     
    notedop likes this.
  4. notedop

    notedop Member Licensed User

    No worries :), I will try this tonight when I get home. Sounds promising already! :-D
     
  5. StillLearning

    StillLearning Member Licensed User

    Thank you, works great to enhance the checkboxs
     
  6. Derek Jee

    Derek Jee Active Member Licensed User

    Hello.. I have added your sample code to my app and have got it drawing my checkboxes well.. I am having trouble though with my checkboxes which need to be checked and disabled. It does not show the box as checked when the activity shows.. Can you advise if the current code allows you to set the checkbox to be checked and disabled..

    Thank you..
     
  7. stevel05

    stevel05 Expert Licensed User

    It's changing the graphic on a standard checkbox, so setting Checkbox1.Checked = True on startup (preferably after setting the graphic) should work.
     
  8. Derek Jee

    Derek Jee Active Member Licensed User

    Hi Steve

    Thanks for responding. I can get it to check on startup if the value is false but I want some of my values to be true AND disabled.. This is what I am writing..

    Code:
    SetCBDrawable(chk2,Colors.DarkGray,2Dip,Colors.Blue,Chr(10004),Colors.LightGray,60Dip,2dip)
    chk2.Checked = 
    True
    chk2.Enabled = 
    False
    I have also placed the checked and disabled properties before drawing the box to no avail..

    I am wondering if it is just redrawing after I set the state or am I setting the value in the wrong place? It does seem that setting it disabled is unchecking it..

    Thank you,

    Derek.
     
  9. luisftv

    luisftv Member Licensed User

    Thank you for those two routines steve05.

    How would you go on putting a border on a check-box that uses a bitmap (png, jpg, etc.) and control it's size?

    Also, how do you set the corner ratio for drawables and bitmaps using your code?


    Specially for buttons using bitmaps, the corner ration and the border?

    I attached here your example with the check box already using a png... but I cannot set a border unless the button becomes a drawable, and I don't want it a drawable. I want the nice png image as background.

    Thanks.
     

    Attached Files:

  10. stevel05

    stevel05 Expert Licensed User

    The border is drawn on the background. If you are using an image as a background, then the border would need to be part of that image.
     
  11. luisftv

    luisftv Member Licensed User

    Thanks steve05.

    I hope in the near feature B4A can add that option instead of having to draw it on the image. The disadvantage of doing it to the image is that in Android TVs, the border would be on all buttons using images, therefore, it is the same as not having the border. But, if the image is given a border only when it comes into focus, then you can tell where the cursor is location on those Android TV or phones using a D-Pad. For now, only buttons with drawables (using colors, not images) can be given a border when they come into focus... bummer... I'll figure something in the mean time.

    Thanks again.
     
  12. MaFu

    MaFu Well-Known Member Licensed User

    Also with images. Use one bitmapDrawable for normal state and another for focused state.
     
  13. luisftv

    luisftv Member Licensed User

    Mafu,

    Thanks for the suggestion... I'm happy to report that I had figured that one out long ago... see here.

    It's just that adjusting the "Focus" image and adding a border to the image itself is not as convenient and time saving as adding it with code, just like you do with gradient images.

    But, I know Erel will figure something out in the near future... he always does.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice