Last active
August 29, 2015 14:02
-
-
Save jwill/6e10a96fb5cfde9dd3a3 to your computer and use it in GitHub Desktop.
t
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Knowing the standard widget library is nice, but as someone who was once accused as not so much recreating the wheel as hand machining my own nuts and bolts -- I know there are times when nothing in the toolchest will quite do the job. That’s when it’s time to dive in and build your own custom View from scratch. | |
We’re not including any custom Views in sunshine, but let’s take a look at how you *would* build one. | |
You start by creating a new Class for your view [draw] | |
If you’re building something from scratch rather than modifying an existing View, it should descend from either View itself [Draw]...or SurfaceView [Draw] | |
View offers a lightweight canvas-based approach, while SurfaceView is designed specifically to support UI elements that require rapid redraws and / or 3D graphics using something like openGL. It’s perfect for Views that display games or Videos. | |
The existing widget library Views are descended from View, so let’s take that approach [Circle View]. | |
The base View class draws [Draw] an empty, borderless 100x100 pixel box. | |
To change that we override the onMeasure handler [draw] to indicate the View’s size, | |
and onDraw [draw] to draw its content. | |
If your View should always be an empty 100 pixel square, you’re in luck! Otherwise, we need to do some work. Let’s start by setting its size. | |
onMeasure is called when your View’s parent is laying out it’s children. As you know, when you add a View to a layout, you can specify a specific height or width -- but in most cases you’ll want to match parent or wrap the content. | |
When a Views’s onMeasure is called by it’s parent layout, it asks: “How much space will you use?” | |
...And passes in how much space is available, and whether the View will be given exactly that much space, or at most that much space. | |
You can decode that like this: [Draw] to obtain the size and mode parameter for the height and width bounds respectively. | |
If the returned mode is exactly [draw], the View will be placed into an area of exactly that size. You’ll be passed that value if the layout has specified a specific size, or if the View has been asked to fill the parent. In either case, it’s best practice to simply return the value passed in, unless that value is below your View’s minimum size -- in which case you can return the minimum value and rely on the parent Layout to crop or scroll as necessary. | |
The other alternative is AT_MOST, indicating that your view can define it’s own size, up to the size given. This is typically the case for Views set to WRAP_CONTENT -- where the View should be as wide as it needs to be to display it’s content (but no wider!), all provided it still fits within the parent container. | |
Once you’ve determined the size of your control, you *must* call setMeasuredDimension -- passing in your values. If you don’t -- your app will crash as soon as your View is laid out. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment