I have a custom UIScrollView, and I add 5 imageView as its subviews.However, after I log its subviews array , it has 6 children!! I use storyboard to add the scrollview add drag its IBOutlet. I have no idea where the firstObject come from?
- (void)configViews {
NSInteger launchImageCount = 5;
CGFloat screenWidth = CGRectGetWidth([UIScreen mainScreen].bounds);
CGFloat screenHeight = CGRectGetHeight([UIScreen mainScreen].bounds);
self.scrollView.contentSize = CGSizeMake(screenWidth * launchImageCount, screenHeight);
self.scrollView.clipsToBounds =YES;
self.scrollView.pagingEnabled = YES;
self.scrollView.delegate = self;
self.scrollView.showsHorizontalScrollIndicator = NO;
for(int i = 0; i < launchImageCount; i++) {
NSString *imageName = [NSString stringWithFormat:#"B0%lu.jpg",(long)(i+1)];
CGRect rect = CGRectMake(screenWidth*i, 0, screenWidth, screenHeight);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:rect];
imageView.image = [UIImage imageNamed:imageName];
[self.scrollView addSubview:imageView];
}
NSLog(#"subviews :%#",self.scrollView.subviews);
self.pageControl.numberOfPages = launchImageCount;
}
Log:
2015-09-26 17:24:29.626 CustomTableView[60621:7911319] subviews :(
"<UIImageView: 0x7f9680f30760; frame = (234.5 118; 2.5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680f2f6c0>>",
"<UIImageView: 0x7f9680e25a30; frame = (0 0; 375 667); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680e19290>>",
"<UIImageView: 0x7f9680d5ab30; frame = (375 0; 375 667); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680d5a7b0>>",
"<UIImageView: 0x7f9680e26af0; frame = (750 0; 375 667); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680e26280>>",
"<UIImageView: 0x7f9680e2a450; frame = (1125 0; 375 667); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680e2a1b0>>",
"<UIImageView: 0x7f9680e2e1b0; frame = (1500 0; 375 667); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680e2df90>>"
)
The UIScrollView has two default UIImageView to show you your scroll bars.
You probably enabled a horizontal/vertical scroll indicator, and that is the reason you see this extra UIImageView child.
Related
When looking at the Apple "Mail" app, the fonts of the row actions is around 20% smaller than the default ones. How can I get the same font size in swift?
Here is the view hierarchy:
<UITableViewCellDeleteConfirmationView: 0x14ed4edf0; frame = (320 0; 254 77.5); clipsToBounds = YES; autoresize = H; layer = <CALayer: 0x170620340>>
| <_UITableViewCellActionButton: 0x14ed190f0; frame = (155 0; 99 77.5); opaque = NO; autoresize = H; layer = <CALayer: 0x170622a00>>
| | <UIButtonLabel: 0x14ed36920; frame = (15 28; 69 21.5); text = 'Delete'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x17029ce30>>
| <_UITableViewCellActionButton: 0x14ed50380; frame = (71.5 0; 83.5 77.5); opaque = NO; autoresize = H; layer = <CALayer: 0x170436ec0>>
| | <UIButtonLabel: 0x14ed45a50; frame = (15 28; 53.5 21.5); text = 'Edit'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x17009d4c0>>
| <_UITableViewCellActionButton: 0x14ed5a320; frame = (0 0; 71.5 77.5); opaque = NO; autoresize = H; layer = <CALayer: 0x170439940>>
| | <UIButtonLabel: 0x14ed422b0; frame = (15 28; 41.5 21.5); text = 'More'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x170296760>>
Can I access the UIButtonLabels somehow?
Tried so far:
I tried changing the appearance, but it seems not defined for this element.
Writing an extension for UILabel that changes font on layoutSubviews worked, but it also changed all other UILabels.
Objc code
+ (NSArray*)findAllButtonLabelFromCell:(UITableViewCell*)cell {
NSMutableArray* buttonLabels = [[NSMutableArray alloc]init];
[self addButtonLabelToArray:buttonLabels view:cell];
return buttonLabels;
}
+ (void)addButtonLabelToArray:(NSMutableArray*)arr view:(UIView*)view {
//For pass Apple examine
//contact the name in runtime
NSString* prefix = #"UIButton";
NSString* suffix = #"Label";
NSString* name = [prefix stringByAppendingString:suffix];
for (UIView* subView in view.subviews) {
if ([subView isKindOfClass:NSClassFromString(name)]) {
[arr addObject:subView];
}
[self addButtonLabelToArray:arr view:subView];
}
}
and you should access the return array elements with UILabel
I need a uisearchbar to be clear
I've tried all suggested methods - setting the background image to a clear one etc.
But - the UISearchbar always seems to have a frame - which can be set (using the image method) and an overlay with a tint (this is the portion of the search bar which is inset from the search bar boundaries) which always has the same height and a blackish tint -
I can not get rid of this tint using any of the searchbar or toolbar methods - is there a hack to make this clear - or strech it to all the corners of the UISearchbar???
Here is a snippet of the last incarnation I am trying - with no luck :(
self.searchBar = [[UISearchBar alloc] initWithFrame:searchBarBackground.bounds];
self.searchBar.placeholder = NSLocalizedString(#"Search", nil);
self.searchBar.searchBarStyle = UISearchBarStyleMinimal;
[searchBarBackground addSubview:self.searchBar];
self.searchBar.translucent = YES;
self.searchBar.backgroundImage = [UIImage new];
self.searchBar.scopeBarBackgroundImage = [UIImage new];
Adding a hierarchy dump of the search bar
<UISearchBar: 0x17f36340; frame = (0 0; 240 44); text = ''; opaque = NO; gestureRecognizers = <NSArray: 0x17f35e00>; layer = <CALayer: 0x17f36270>>
| <UIView: 0x17f36010; frame = (0 0; 240 44); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x17f35fe0>>
| | <UISearchBarBackground: 0x17f35bc0; frame = (0 0; 240 44); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x17f35ac0>>
| | | <_UIBackdropView: 0x17f317d0; frame = (0 0; 240 44); hidden = YES; opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <_UIBackdropViewLayer: 0x17f311e0>>
| | <UISearchBarTextField: 0x17f34e40; frame = (0 0; 0 0); text = ''; clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x17f34e10>>
| | | <_UISearchBarSearchFieldBackgroundView: 0x17f337c0; frame = (0 0; 0 0); autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x17f33900>>
| | | | <_UISearchBarSearchFieldBackgroundView: 0x17f32540; frame = (0 0; 0 0); hidden = YES; opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x17f32480>>
| | | | <_UISearchBarSearchFieldBackgroundView: 0x17f31e00; frame = (0 0; 0 0); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x17f31ea0>>
*
/
What a headache for something so trivial as setting the background of my UISearchbar to "white with alpha"! - This is how I was finally able to create the look I wanted. A "clear" UISearchbar ontop of a whitesh background
self.searchBar = [[UISearchBar alloc] initWithFrame:SearchBarFrame];
self.searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
UIView *whiteView = [[UIView alloc] initWithFrame:self.searchBar.bounds];
whiteView.backgroundColor = [UIColor colorWithWhite:1 alpha:0.5];
whiteView.layer.cornerRadius = 5;
[self.searchBar insertSubview:whiteView atIndex:0];
self.searchBar.placeholder = NSLocalizedString(#"Search", nil);
self.searchBar.searchBarStyle = UISearchBarStyleMinimal;
[self addSubview:self.searchBar];
self.searchBar.translucent = YES;
self.searchBar.backgroundImage = [UIImage new];
self.searchBar.scopeBarBackgroundImage = [UIImage new];
UIImage *clearImage = [UIImage imageWithColor:[UIColor clearColor] andSize:SearchBarFrame.size];
[self.searchBar setSearchFieldBackgroundImage:clearImage forState:UIControlStateNormal];
And the helper method
+ (UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize)size
{
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
rect.size = size;
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
For SWIFT:
Create a clear PNG background image
Set your UISearchBar style to default value
in your viewDidLoad or wherever you want it add this code:
yourSearchBar.setSearchFieldBackgroundImage(UIImage(named: "yourClearBackgroundImage"), forState: .Normal)
yourSearchBar.backgroundImage = UIImage()
I have a UIButton with a UITextView as it's subview. The UITextView has 1 layer which the border is colored and has a width of 1. When I archive the UIButton then unarchive it, the border color and the border width becomes nil. If I set the layer background color, it will stay the same when archived then unarchived, which makes this bug very confusing.
UIButton textButton = ...
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:textButton];
UIButton *textButton2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
The lldb debug output shows that the border color disappears
(lldb) po [[[textButton subviews] firstObject] layer] <CALayer:0x13445780; position = CGPoint (150 50); bounds = CGRect (0 0; 300 100); delegate = <UITextView: 0xdb20000; frame = (0 0; 300 100); text = ''; clipsToBounds = YES; autoresize = RM+BM; userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0x13446430>; layer = <CALayer: 0x13445780>; contentOffset: {0, 0}>; sublayers = (<_UITextTiledLayer: 0x13448e80>, <CALayer: 0x13445d90>); masksToBounds = YES; allowsGroupOpacity = YES; borderColor = <CGColor 0xc09b6d0> [<CGColorSpace 0xbf28210> (kCGColorSpaceDeviceRGB)] ( 0.378437 0.5 0.13035 1 ); backgroundColor = <CGColor 0xbed1e10> [<CGColorSpace 0xbe65e70> (kCGColorSpaceDeviceGray)] ( 0 0 ); borderWidth = 1>
(lldb) po [[[textButton2 subviews] firstObject] layer] <CALayer:0x13443fe0; position = CGPoint (150 50); bounds = CGRect (0 0; 300 100); delegate = <UITextView: 0xdb2aa00; frame = (0 0; 300 100); text = ''; clipsToBounds = YES; autoresize = RM+BM; userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0x13432ed0>; layer = <CALayer: 0x13443fe0>; contentOffset: {0, 0}>; sublayers = (<_UITextTiledLayer: 0x134447f0>, <CALayer: 0x13434740>); masksToBounds = YES; allowsGroupOpacity = YES; backgroundColor = <CGColor 0xbed1e10> [<CGColorSpace 0xbe65e70> (kCGColorSpaceDeviceGray)] ( 0 0 )>
Is there something special about the border color? Or is this really a bug?
I add objects in UIScrollView inside cycle FOR, but after the second interaction the index of subviews change.
When i create the ScrollView:
scroll.subviews :(
"<UIImageView: 0x147aeee0; frame = (1017 186; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x147aef50>>",
"<UIImageView: 0x147aefa0; frame = (1019 184; 5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x147af010>>"
)
After i have the cycle FOR with [scroll addSubview:btn];
First
scroll.subviews :(
"<UIImageView: 0x147aeee0; frame = (1017 186; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x147aef50>>",
"<UIImageView: 0x147aefa0; frame = (1019 184; 5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x147af010>>",
"<ContentButton: 0x13fdc610; baseClass = UIButton; frame = (15 10; 221 173); opaque = NO; tag = 1; layer = <CALayer: 0x1034cc00>>"
)
Second (change last object to index 0)
scroll.subviews :(
"<ContentButton: 0x13fdc610; baseClass = UIButton; frame = (15 10; 221 173); opaque = NO; tag = 1; layer = <CALayer: 0x1034cc00>>",
"<UIImageView: 0x147aefa0; frame = (1019 184; 5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x147af010>>",
"<UIImageView: 0x147aeee0; frame = (1017 186; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x147aef50>>",
"<ContentButton: 0x105ddf70; baseClass = UIButton; frame = (246 10; 221 173); opaque = NO; tag = 149; layer = <CALayer: 0x105523e0>>"
)
Third and so on, the object will add normally (in last index)
scroll.subviews :(
"<ContentButton: 0x13fdc610; baseClass = UIButton; frame = (15 10; 221 173); opaque = NO; tag = 1; layer = <CALayer: 0x1034cc00>>",
"<UIImageView: 0x147aefa0; frame = (1019 184; 5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x147af010>>",
"<UIImageView: 0x147aeee0; frame = (1017 186; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x147aef50>>",
"<ContentButton: 0x105ddf70; baseClass = UIButton; frame = (246 10; 221 173); opaque = NO; tag = 149; layer = <CALayer: 0x105523e0>>",
"<ContentButton: 0x13f1dc80; baseClass = UIButton; frame = (477 10; 221 173); opaque = NO; tag = 3; layer = <CALayer: 0x13f1dd20>>"
)
The problem is in the second interaction, so why the last object (ContentButton) was in the index 2 and change into index 0?
for (obj * objScroll in arrayChaObj)
{
// UIButton
ContentButton * btn = [[ContentButton alloc] initWithFrame:CGRectMake(btContentPosXChaObj,
10,
imgButtonScroll.size.width,
imgButtonScroll.size.height)];
btContentPosXChaObj += 10 + imgButtonScroll.size.width;
[scroll addSubview:btn];
NSLog(#"scroll.subviews :%#",scroll.subviews);
[scroll setContentSize:CGSizeMake(btContentPosXChaObj, imgButtonScroll.size.height+10)];
}
This is just a wild guess.
What happens when you call setContentSize: for the first time? Well, the two image views end up outside the content region. They won't be ever displayed.
I guess the scrollview then optimizes the order of subviews and puts the invisible ones to the end which can probably improve its clipping (redrawing) functionality.
Currently I don't have the time to check this and experiment but it's a reasonable explanation for me.
I just want to grab the button tag 1~ 5 in ScrollView, other data do not need to grasp
(void)layoutScrollImages
{
UIImageView *view = nil;
NSArray *subviews = [weekscroll subviews];
CGFloat curXLoc = 0;
for (view in subviews)
{
if ([view isKindOfClass:[UIImageView class]] && view.tag > 0)
{
NSLog(#"%d",view.tag);
CGRect frame = view.frame;
frame.origin = CGPointMake(curXLoc, 0);
view.frame = frame;
curXLoc += (wScrollObjWidth);
}
}
NSLog(#"subviews = %#",subviews);
[weekscroll setContentSize:CGSizeMake((wNumImages * wScrollObjWidth), [weekscroll bounds].size.height)];
}
subviews = (
"<UIImageView: 0x1ba330; frame = (313 61; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x1bac00>>",
"<UIImageView: 0x1bc900; frame = (315 59; 5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x1bdde0>>",
"<UIButton: 0x1bd380; frame = (0 1; 50 66); opaque = NO; layer = <CALayer: 0x1bd410>>",
"<UIButton: 0x1bd690; frame = (50 0; 50 66); opaque = NO; layer = <CALayer: 0x1bd720>>",
"<UIButton: 0x1bd9a0; frame = (100 0; 50 66); opaque = NO; layer = <CALayer: 0x1bda30>>",
"<UIButton: 0x1bc570; frame = (150 0; 50 66); opaque = NO; layer = <CALayer: 0x1bc600>>",
"<UIButton: 0x1beaa0; frame = (300 0; 50 66); opaque = NO; tag = 1; layer = <CALayer: 0x1beb30>>",
"<UIButton: 0x1bff40; frame = (350 0; 50 66); opaque = NO; tag = 2; layer = <CALayer: 0x1c0920>>",
"<UIButton: 0x1c0e60; frame = (400 0; 50 66); opaque = NO; tag = 3; layer = <CALayer: 0x1c0ef0>>",
"<UIButton: 0x1c1430; frame = (450 0; 50 66); opaque = NO; tag = 4; layer = <CALayer: 0x1c14c0>>",
"<UIButton: 0x1c1a00; frame = (500 0; 50 66); opaque = NO; tag = 5; layer = <CALayer: 0x1c1a90>>",
"<UIButton: 0x1cb340; frame = (1800 0; 50 66); opaque = NO; layer = <CALayer: 0x1cb3d0>>",
"
)UIImageView: 0x1ba330; frame = (313 61; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer =
As per printed log, only UIButtons are having tags and in sample code you are working on UIImageView, so use given code as per your requirement.
I have modified your code as below, just check it out.
for (id objView in subviews)
{
if ([objView isKindOfClass:[UIImageView class]])
{
UIImageView *imgView = (UIImageView*) objView;
if (imgView.tag > 0)
{
NSLog(#"%d",imgView.tag);
CGRect frame = imgView.frame;
frame.origin = CGPointMake(curXLoc, 0);
imgView.frame = frame;
curXLoc += (wScrollObjWidth);
}
}
}
Or if you want to grab only UIButtons,
for (UIButton *btnView in subviews)
{
if ([btnView isKindOfClass:[UIButton class]] && btnView.tag > 0)
{
NSLog(#"%d",btnView.tag);
CGRect frame = btnView.frame;
frame.origin = CGPointMake(curXLoc, 0);
btnView.frame = frame;
curXLoc += (wScrollObjWidth);
}
}
You want the button with tags greater than 0 right.. then why are you checking for [UIImageView class].. ?
your condition to find Buttons with tag greater than 0 should be :
if ([aView isKindOfClass:[UIButton class] && (aView.tag > 0)]) {
}