아이폰어플개발정보2010. 10. 12. 06:36
pickerview동적으로 사이즈등 변경하기

UIPickerView, which presents a slot-machine-like list of options. Unfortunately, this view isn’t particularly easy to use, as its default presentation takes up quite a bit of screen real-estate, and it’s not obvious how to resize it. Today, I’d like to talk about how to tame this view.

Things That Just Ain’t So

When I was Googling for tips on how to control the size ofUIPickerViews, I repeatedly came across the following pieces of advice:

  • Pass in a small CGRect to initWithFrame
  • Make the UIPickerView a subview of another UIView, and then resize the outer view

Neither technique worked for me. (OS 2.2.1)

Affine Transformations

Semi-buried in the UIView class is the astonishingly usefultransform property, which performs arbitrary affine transformations on the view. This lets you do a lot of neat tricks, including scaling theUIPickerView.

Example

Here are the header and implementation files for a PickerDemo class, which is a view controller that manages a view containing aUIPickerView. (I nest the UIPickerView inside another UIView s.t. the PickerDemo controller can be pushed onto a Navigation Controller, with which I was playing when I pulled together this demo.)

 

This yields a simple, 3-reel UIPickerView, where each reel contains choices from 0 to 9. No (meaningful) CGRect is given for either theUIPickerView or its enclosing UIView; the former always assumes its default size, while the latter receives its geometry from the (not shown here) Navigation Controller. The result may be seen to the right.

Scaling

Lets try adding a simple scalingCGAffineTransform, by recoding the loadView function as follows:

This nicely scales down the UIPickerView. Unfortunately, the transform is applied to the center of the view, not the upper-left corner, which probably isn’t what one wants. (At least, it’s not what I want.) 

Composites

 
To do a scale relative to the UL corner, we’ll need to execute three transforms:
  • Move the UL corner to the origin
  • Scale relative to the origin
  • Move the origin to the UL corner
 
We can call these three transformations T0, S0, and T1, and since Cocoa/Core Graphics uses row vectors, we will compose them into a single transformation C with this formula:
  • C = T0*S0*T1
 
A re-written loadView incorporating this transform would look like this:
This yields the desired result. 

Digression

 
To be honest, I’m not really happy with the technique I used above to compute the translation offsets; the documentation states that:

The origin of the transform is the value of the center property, or the layer’s anchorPoint property if it was changed. (Use the layer property to get the underlying Core Animation layer object.)

 
The center property is given in the co-ordinate system of the view’s superview; I’m not familiar with the details of the anchorPointproperty. In the code above, I sort of hand-wave over all of this, and just assume that the origin of the transform will end up in the middle of the bounds rectangle, which is given in the view’s coordinate system. That seems to be true in this case, and might be true in the general case, but it is a hand-wave, and I thought it only fair to point it out.
Reading over that, I’m not sure it clarified anything, but let’s move on.

Brevity

 
You can compress the transformation composition code quite a bit:
Note that the transformations are assembled “backwards” in this idiom; the “innermost” or “first” transformation appears on the “outside” of the expression (its arguments appear last, on the right). Essentially, these functions take an existing transform and prepend a newly defined one to its left. 
You can download the final header and implementation files, if you’re interested in them.
Share and Enjoy:
Posted by 오늘마감

댓글을 달아 주세요