I have added a custom cell as follows for stepper progress. UI perspective, it looks what I want, but I could not able to figure out how I could able to determine whether or not button has been clicked.
I have inspired via https://github.com/yenbekbay/AYStepperView, but this one has PageViewController which I could not able to add it in the tableCell.
#import "StepperProgressTableViewCell.h"
#import "AYStepperView.h"
static CGFloat const kFormStepperViewHeight = 80;
#interface StepperProgressTableViewCell ()
#property (nonatomic) AYStepperView *stepperView;
#property (nonatomic) NSUInteger currentIndex;
#property (nonatomic) NSUInteger currentStep;
#end
#implementation StepperProgressTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
[self setUpViews];
self.currentIndex = 0;
self.currentStep = 0;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
#pragma mark Private
- (void)setUpViews {
self.stepperView = [[AYStepperView alloc]initWithFrame:CGRectMake(0, 40 , self.frame.size.width, kFormStepperViewHeight)
titles:#[NSLocalizedString(#"Start", nil),
NSLocalizedString(#"Cooking", nil),
NSLocalizedString(#"Ready", nil)]];
self.stepperView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
self.stepperView.userInteractionEnabled = YES;
[self addSubview:self.stepperView];
self.containerView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.stepperView.frame), CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds) - CGRectGetMaxY(self.stepperView.frame))];
[self addSubview:self.containerView];
}
#end
AYStepperView.m
#import "AYStepperView.h"
#import <pop/POP.h>
static UIEdgeInsets const kStepperViewPadding = {
15, 0, 15, 0
};
static CGFloat const kStepperLabelsSpacing = 10;
static CGFloat const kStepperPipeHeight = 5;
#interface AYStepperView ()
#property (nonatomic) UIView *pipeView;
#property (nonatomic) UIView *labelsView;
#property (nonatomic) UIView *pipeBackgroundView;
#property (nonatomic) UIView *pipeFillView;
#property (nonatomic) NSMutableArray *stepLabels;
#end
#implementation AYStepperView
#pragma mark Initialization
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titles {
self = [super initWithFrame:frame];
if (!self) {
return nil;
}
_titles = titles;
self.backgroundColor = [UIColor colorWithRed:0.98f green:0.98f blue:0.98f alpha:1];
self.tintColor = [UIColor colorWithRed:0.2f green:0.29f blue:0.37f alpha:1];
self.pipeView = [[UIView alloc] initWithFrame:CGRectMake(kStepperViewPadding.left, kStepperViewPadding.top, CGRectGetWidth(self.bounds) - kStepperViewPadding.left - kStepperViewPadding.right, CGRectGetHeight(self.bounds) / 2 - kStepperViewPadding.top)];
[self addSubview:self.pipeView];
self.labelsView = [[UIView alloc] initWithFrame:CGRectMake(kStepperViewPadding.left, CGRectGetMaxY(self.pipeView.frame) + kStepperViewPadding.top, CGRectGetWidth(self.bounds) - kStepperViewPadding.left - kStepperViewPadding.right, CGRectGetHeight(self.bounds) / 2 - kStepperViewPadding.top - kStepperViewPadding.bottom)];
[self addSubview:self.labelsView];
self.pipeBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, (CGRectGetHeight(self.pipeView.bounds) - kStepperPipeHeight) / 2, CGRectGetWidth(self.pipeView.bounds), kStepperPipeHeight)];
self.pipeBackgroundView.backgroundColor = [UIColor lightGrayColor];
[self.pipeView addSubview:self.pipeBackgroundView];
CGRect pipeFillViewFrame = self.pipeBackgroundView.frame;
pipeFillViewFrame.size.width = 0;
self.pipeFillView = [[UIView alloc] initWithFrame:pipeFillViewFrame];
self.pipeFillView.backgroundColor = self.tintColor;
[self.pipeView addSubview:self.pipeFillView];
_stepButtons = [NSMutableArray new];
_stepLabels = [NSMutableArray new];
for (NSUInteger i = 0; i < titles.count; i++) {
UIButton *stepButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, CGRectGetHeight(self.pipeView.bounds), CGRectGetHeight(self.pipeView.bounds))];
stepButton.center = CGPointMake(CGRectGetWidth(self.pipeView.bounds) * (i + 0.5f) / titles.count, stepButton.center.y);
stepButton.clipsToBounds = YES;
stepButton.tag = i;
stepButton.layer.cornerRadius = CGRectGetHeight(stepButton.bounds) / 2;
stepButton.backgroundColor = [UIColor lightGrayColor];
[self.pipeView addSubview:stepButton];
[self.stepButtons addObject:stepButton];
UILabel *stepLabel = [UILabel new];
stepLabel.font = [UIFont systemFontOfSize:[UIFont smallSystemFontSize]];
stepLabel.textColor = self.tintColor;
stepLabel.textAlignment = NSTextAlignmentCenter;
stepLabel.text = titles[i];
stepLabel.numberOfLines = 0;
stepLabel.frame = (CGRect) {
stepLabel.frame.origin, [stepLabel sizeThatFits:CGSizeMake(CGRectGetWidth(self.pipeView.bounds) / titles.count - kStepperLabelsSpacing, 0)]
};
stepLabel.center = CGPointMake(CGRectGetWidth(self.labelsView.bounds) * (i + 0.5f) / titles.count, CGRectGetHeight(self.labelsView.bounds) / 2);
[self.labelsView addSubview:stepLabel];
[self.stepLabels addObject:stepLabel];
}
_currentStepIndex = 0;
[self completeStepAtIndex:0 until:1 completionBlock:nil];
return self;
}
#pragma mark Public
- (void)updateCurrentStepIndex:(NSUInteger)currentStepIndex completionBlock:(void (^)())completionBlock {
if (currentStepIndex >= self.titles.count || currentStepIndex == self.currentStepIndex) {
if (completionBlock) {
completionBlock();
}
} else {
NSUInteger previousStepIndex = self.currentStepIndex;
_currentStepIndex = currentStepIndex;
if ((NSInteger)currentStepIndex - (NSInteger)previousStepIndex > 0) {
[self completeStepAtIndex:previousStepIndex + 1 until:currentStepIndex + 1 completionBlock:completionBlock];
} else {
[self uncompleteStepAtIndex:previousStepIndex until:currentStepIndex - 1 completionBlock:completionBlock];
}
}
}
#pragma mark Setters
- (void)setTintColor:(UIColor *)tintColor {
_tintColor = tintColor;
self.pipeFillView.backgroundColor = tintColor;
for (UILabel *label in self.stepLabels) {
label.textColor = tintColor;
}
[self.stepButtons[self.currentStepIndex] setBackgroundColor:tintColor];
}
#pragma mark Private
- (void)completeStepAtIndex:(NSUInteger)index until:(NSUInteger)until completionBlock:(void (^)())completionBlock {
if (index == until) {
if (completionBlock) {
completionBlock();
}
} else {
[UIView animateWithDuration:0.2f animations:^{
CGRect pipeFillViewFrame = self.pipeFillView.frame;
NSLog(#"%lu, %lu",until, index);
if(index == _titles.count - 1)
{
pipeFillViewFrame.size.width = CGRectGetWidth(self.pipeBackgroundView.bounds) * (index + 1.0f) / self.titles.count;
}
else
{
pipeFillViewFrame.size.width = CGRectGetWidth(self.pipeBackgroundView.bounds) * (index + 0.5f) / self.titles.count;
}
self.pipeFillView.frame = pipeFillViewFrame;
} completion:^(BOOL finishedWidthAnimation) {
[self completeStepAtIndex:index + 1 until:until completionBlock:completionBlock];
UIView *stepButton = self.stepButtons[index];
stepButton.backgroundColor = self.tintColor;
POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY];
scaleAnimation.velocity = [NSValue valueWithCGSize:CGSizeMake(3.f, 3.f)];
scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.f, 1.f)];
scaleAnimation.springBounciness = 5.f;
[stepButton.layer pop_addAnimation:scaleAnimation forKey:#"scaleAnimation"];
}];
}
}
- (void)uncompleteStepAtIndex:(NSUInteger)index until:(NSUInteger)until completionBlock:(void (^)())completionBlock {
if (index == until) {
if (completionBlock) {
completionBlock();
}
} else {
if (index > until + 1) {
UIView *stepButton = self.stepButtons[index];
stepButton.backgroundColor = [UIColor lightGrayColor];
POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY];
scaleAnimation.velocity = [NSValue valueWithCGSize:CGSizeMake(3.f, 3.f)];
scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.f, 1.f)];
scaleAnimation.springBounciness = 5.f;
[stepButton.layer pop_addAnimation:scaleAnimation forKey:#"scaleAnimation"];
}
[UIView animateWithDuration:0.2f animations:^{
CGRect pipeFillViewFrame = self.pipeFillView.frame;
pipeFillViewFrame.size.width = CGRectGetWidth(self.pipeBackgroundView.bounds) * (index + 0.5f) / self.titles.count;
self.pipeFillView.frame = pipeFillViewFrame;
} completion:^(BOOL finishedWidthAnimation) {
[self uncompleteStepAtIndex:index - 1 until:until completionBlock:completionBlock];
}];
}
}
#end
If you want to catch events from a cell to the view controller, the simplest way is to create a protocol and set the view controller as the cell's delegate. I'm sure there are many similar questions here that can help you like this one for example.
Related
I need to write a scanner on the ios/react-native app. Before this project has used another scanner, but that now doesn't work. I have UIView and UIViewController. In the built app, the camera is showing, but when I aim the camera on the barcode, nothing happens, captureResult does not call. So I am new to IOS and don't know how to fix it.
MyView.h
#import <UIKit/UIView.h>
#import <ZXingObjC/ZXingObjC.h>
#import <React/RCTComponent.h>
#import "MyViewController.h"
#interface MyView: UIView <ZXCaptureDelegate>
#property (nonatomic, strong) MyViewController *scannerController;
#property (nonatomic, copy) RCTBubblingEventBlock onClose;
#property (nonatomic, copy) RCTBubblingEventBlock onCaptureVin;
#property (nonatomic, copy) RCTBubblingEventBlock onEnterVinManuallyPress;
#end
MyView.m
#import "MyView.h"
#import "MyViewController.h"
#import <UIKit/UIKit.h>
#import <AVKit/AVKit.h>
#import <sys/utsname.h>
UIColor *fillColor;
UIButton *flashButton;
#implementation MyView
int additionalHeightIphoneX = 34;
//===============//
// INITIALIZE SDK
//===============//
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
self.scannerController = [[MyViewController alloc] initWithNibName: nil bundle: nil];
[self.scannerController.capture setDelegate: self];
[self.scannerController.capture start];
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self.subviews makeObjectsPerformSelector: #selector(removeFromSuperview)];
[self addSubview:self.scannerController.view];
self.scannerController.view.frame = self.bounds;
fillColor = [UIColor colorWithRed:29/255.0f green:41/255.0f blue:50/255.0f alpha:0.8];
[self createHeader];
[self createTarget];
[self createManualVinEntryButton];
[self createCancelButton];
}
- (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result {
UILabel* label = [[UILabel alloc] init];
label.font = [UIFont systemFontOfSize:36];
label.text = result.text;
label.textColor = [UIColor yellowColor];
label.backgroundColor =
[[UIColor blackColor] colorWithAlphaComponent:0.5];
[label sizeToFit];
label.center = CGPointMake(self.bounds.size.width/2,
self.bounds.size.height/2);
[self addSubview:label];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelegate:label];
[UIView setAnimationDidStopSelector:#selector(removeFromSuperview)];
label.alpha = 0;
[UIView commitAnimations];
[self sendVinCode: result.text]
}
//========================//
// REACT CALLBACK FUNCTION
//========================//
- (void) sendVinCode: (NSString *)code {
if (!self.onCaptureVin) {
return;
}
self.onCaptureVin(#{#"vin": code});
}
- (void) cancelVinScan {
if (!self.onClose) {
return;
}
self.onClose(#{});
}
- (void) requestManualVinEntry {
if (!self.onEnterVinManuallyPress) {
return;
}
self.onEnterVinManuallyPress(#{});
}
//================//
// BUTTON HANDLERS
//================//
- (void) manualVinEntryButtonHandler:(UIButton *)button {
[self requestManualVinEntry];
}
- (void) cancelButtonHandler:(UIButton *)button {
[self cancelVinScan];
}
//==========//
// CUSTOM UI
//==========//
- (void) createHeader {
UIView *headerContainer = [[UIView alloc] init];
headerContainer.translatesAutoresizingMaskIntoConstraints = NO;
[headerContainer setBackgroundColor: [UIColor colorWithWhite:1 alpha:0.7]];
UILabel *scanVinMessage = [[UILabel alloc] initWithFrame:CGRectMake(22.2, 18.0, 183.5, 21)];
[scanVinMessage setText:#"Scan VIN"];
[scanVinMessage setTextAlignment:NSTextAlignmentCenter];
[scanVinMessage setTextColor:[UIColor darkGrayColor]];
[scanVinMessage setBackgroundColor:[UIColor clearColor]];
[scanVinMessage setFont:[UIFont systemFontOfSize:17]];
[scanVinMessage setCenter:CGPointMake(self.frame.size.width / 2, 27.5)];
[headerContainer addSubview:scanVinMessage];
[self addSubview:headerContainer];
// [headerContainer.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:0.0].active = YES;
// [headerContainer.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:0.0].active = YES;
// [headerContainer.heightAnchor constraintEqualToConstant:55.0].active = YES;
}
- (void) createTarget {
UIView *scanLine = [[UIView alloc] init];
scanLine.translatesAutoresizingMaskIntoConstraints = NO;
[scanLine setBackgroundColor:[UIColor redColor]];
[self addSubview:scanLine];
// [scanLine.centerYAnchor constraintEqualToAnchor:self.centerYAnchor].active = YES;
// [scanLine.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:25.0].active = YES;
// [scanLine.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-25.0].active = YES;
// [scanLine.heightAnchor constraintEqualToConstant:4.0].active = YES;
UIView *topLeftTop = [[UIView alloc] init];
topLeftTop.translatesAutoresizingMaskIntoConstraints = NO;
[topLeftTop setBackgroundColor:[UIColor redColor]];
[self addSubview:topLeftTop];
// [topLeftTop.bottomAnchor constraintEqualToAnchor:self.centerYAnchor constant:-34.0].active = YES;
// [topLeftTop.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:15.0].active = YES;
// [topLeftTop.heightAnchor constraintEqualToConstant:4.0].active = YES;
// [topLeftTop.widthAnchor constraintEqualToConstant:24.0].active = YES;
UIView *topLeftLeft = [[UIView alloc] init];
topLeftLeft.translatesAutoresizingMaskIntoConstraints = NO;
[topLeftLeft setBackgroundColor:[UIColor redColor]];
[self addSubview:topLeftLeft];
// [topLeftLeft.bottomAnchor constraintEqualToAnchor:self.centerYAnchor constant:-14.0].active = YES;
// [topLeftLeft.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:15.0].active = YES;
// [topLeftLeft.heightAnchor constraintEqualToConstant:20.0].active = YES;
// [topLeftLeft.widthAnchor constraintEqualToConstant:4.0].active = YES;
UIView *topRightTop = [[UIView alloc] init];
topRightTop.translatesAutoresizingMaskIntoConstraints = NO;
[topRightTop setBackgroundColor:[UIColor redColor]];
[self addSubview:topRightTop];
// [topRightTop.bottomAnchor constraintEqualToAnchor:self.centerYAnchor constant:-34.0].active = YES;
// [topRightTop.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-15.0].active = YES;
// [topRightTop.heightAnchor constraintEqualToConstant:4.0].active = YES;
// [topRightTop.widthAnchor constraintEqualToConstant:24.0].active = YES;
UIView *topRightRight = [[UIView alloc] init];
topRightRight.translatesAutoresizingMaskIntoConstraints = NO;
[topRightRight setBackgroundColor:[UIColor redColor]];
[self addSubview:topRightRight];
// [topRightRight.bottomAnchor constraintEqualToAnchor:self.centerYAnchor constant:-14.0].active = YES;
// [topRightRight.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-15.0].active = YES;
// [topRightRight.heightAnchor constraintEqualToConstant:20.0].active = YES;
// [topRightRight.widthAnchor constraintEqualToConstant:4.0].active = YES;
UIView *bottomLeftBottom = [[UIView alloc] init];
bottomLeftBottom.translatesAutoresizingMaskIntoConstraints = NO;
[bottomLeftBottom setBackgroundColor:[UIColor redColor]];
[self addSubview:bottomLeftBottom];
// [bottomLeftBottom.topAnchor constraintEqualToAnchor:self.centerYAnchor constant:34.0].active = YES;
// [bottomLeftBottom.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:15.0].active = YES;
// [bottomLeftBottom.heightAnchor constraintEqualToConstant:4.0].active = YES;
// [bottomLeftBottom.widthAnchor constraintEqualToConstant:24.0].active = YES;
UIView *bottomLeftLeft = [[UIView alloc] init];
bottomLeftLeft.translatesAutoresizingMaskIntoConstraints = NO;
[bottomLeftLeft setBackgroundColor:[UIColor redColor]];
[self addSubview:bottomLeftLeft];
// [bottomLeftLeft.topAnchor constraintEqualToAnchor:self.centerYAnchor constant:14.0].active = YES;
// [bottomLeftLeft.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:15.0].active = YES;
// [bottomLeftLeft.heightAnchor constraintEqualToConstant:20.0].active = YES;
// [bottomLeftLeft.widthAnchor constraintEqualToConstant:4.0].active = YES;
UIView *bottomRightBottom = [[UIView alloc] init];
bottomRightBottom.translatesAutoresizingMaskIntoConstraints = NO;
[bottomRightBottom setBackgroundColor:[UIColor redColor]];
[self addSubview:bottomRightBottom];
// [bottomRightBottom.topAnchor constraintEqualToAnchor:self.centerYAnchor constant:34.0].active = YES;
// [bottomRightBottom.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-15.0].active = YES;
// [bottomRightBottom.heightAnchor constraintEqualToConstant:4.0].active = YES;
// [bottomRightBottom.widthAnchor constraintEqualToConstant:24.0].active = YES;
UIView *bottomRightRight = [[UIView alloc] init];
bottomRightRight.translatesAutoresizingMaskIntoConstraints = NO;
[bottomRightRight setBackgroundColor:[UIColor redColor]];
[self addSubview:bottomRightRight];
// [bottomRightRight.topAnchor constraintEqualToAnchor:self.centerYAnchor constant:14.0].active = YES;
// [bottomRightRight.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-15.0].active = YES;
// [bottomRightRight.heightAnchor constraintEqualToConstant:24.0].active = YES;
// [bottomRightRight.widthAnchor constraintEqualToConstant:4.0].active = YES;
}
- (void) createCancelButton {
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
UIButton *cancelButton = [[UIButton alloc] init];
[cancelButton addTarget:self action:#selector(cancelButtonHandler:) forControlEvents:UIControlEventTouchUpInside];
float buttonSize = 43.0;
float margin = 20.0;
[cancelButton setFrame:CGRectMake(screenWidth - buttonSize - margin, screenHeight - buttonSize - margin, buttonSize, buttonSize)];
[cancelButton setBackgroundImage:[UIImage imageNamed:#"vin-scan-cancel"]
forState:UIControlStateNormal];
[self addSubview:cancelButton];
}
- (void) createManualVinEntryButton {
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
UIButton *manualVinEntryButton = [[UIButton alloc] init];
[manualVinEntryButton addTarget:self action:#selector(manualVinEntryButtonHandler:) forControlEvents:UIControlEventTouchUpInside];
[manualVinEntryButton setTitle:#"Enter VIN Manually" forState:UIControlStateNormal];
[manualVinEntryButton sizeToFit];
float buttonHeight = 43.0;
float margin = 20.0;
[manualVinEntryButton setFrame:CGRectMake(margin, screenHeight - buttonHeight - margin, 200, buttonHeight)];
[manualVinEntryButton setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
[[manualVinEntryButton layer] setCornerRadius:21];
[[manualVinEntryButton layer]setBackgroundColor: [[UIColor colorWithWhite:1 alpha:.7] CGColor]];
[self addSubview:manualVinEntryButton];
}
//========//
// UTILITY
//========//
- (BOOL) isIphoneX {
struct utsname systemInfo;
uname(&systemInfo);
NSString* deviceModel = [NSString stringWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];
return [deviceModel isEqualToString:#"iPhone10,3"] ||
[deviceModel isEqualToString:#"iPhone10,6"] ||
[deviceModel isEqualToString:#"iPhone11,2"] ||
[deviceModel isEqualToString:#"iPhone11,8"] ||
[deviceModel isEqualToString:#"iPhone11,4"] ||
[deviceModel isEqualToString:#"iPhone12,1"] ||
[deviceModel isEqualToString:#"iPhone12,3"] ||
[deviceModel isEqualToString:#"iPhone12,5"] ||
[deviceModel isEqualToString:#"iPad8,5"];
};
- (void)applyOrientation {
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
float scanRectRotation;
float captureRotation;
switch (orientation) {
case UIInterfaceOrientationPortrait:
captureRotation = 0;
scanRectRotation = 90;
break;
case UIInterfaceOrientationLandscapeLeft:
captureRotation = 90;
scanRectRotation = 180;
break;
case UIInterfaceOrientationLandscapeRight:
captureRotation = 270;
scanRectRotation = 0;
break;
case UIInterfaceOrientationPortraitUpsideDown:
captureRotation = 180;
scanRectRotation = 270;
break;
default:
captureRotation = 0;
scanRectRotation = 90;
break;
}
self.scannerController.capture.layer.frame = self.frame;
CGAffineTransform transform = CGAffineTransformMakeRotation((CGFloat) (captureRotation / 180 * M_PI));
[self.scannerController.capture setTransform:transform];
[self.scannerController.capture setRotation:scanRectRotation];
[self.scannerController applyRectOfInterest:orientation];
}
#end
MyViewController.h
#import <UIKit/UIViewController.h>
#import <ZXingObjC/ZXingObjC.h>
#interface MyViewController: UIViewController
#property (nonatomic, strong) ZXCapture *capture;
#property (nonatomic, weak) IBOutlet UIView *scanRectView;
#property (nonatomic, weak) IBOutlet UILabel *decodedLabel;
#property (nonatomic) BOOL scanning;
#property (nonatomic) BOOL isFirstApplyOrientation;
#property (nonatomic) CGAffineTransform _captureSizeTransform;
- (void)applyRectOfInterest:(UIInterfaceOrientation)orientation;
#end
MyViewController.m
#import "MyViewController.h"
#interface MyViewController()
#end
#implementation MyViewController
//===============//
// INITIALIZE SDK
//===============//
- (instancetype)init {
self = [super init];
if (self) {
// Custom initialization
self.capture = [[ZXCapture alloc] init];
self.capture.sessionPreset = AVCaptureSessionPreset1920x1080;
self.capture.camera = self.capture.back;
self.capture.focusMode = AVCaptureFocusModeContinuousAutoFocus;
self.scanning = NO;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// self.capture = [[ZXCapture alloc] init];
// self.capture.sessionPreset = AVCaptureSessionPreset1920x1080;
// self.capture.camera = self.capture.back;
// self.capture.focusMode = AVCaptureFocusModeContinuousAutoFocus;
// self.scanning = YES;
// [self.capture start];
[self.view.layer addSublayer:self.capture.layer];
// [self.view bringSubviewToFront:self.scanRectView];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (self.isFirstApplyOrientation) return;
self.isFirstApplyOrientation = YES;
[self applyOrientation];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
//========//
// CLEANUP
//========//
- (void)dealloc {
[self.capture.layer removeFromSuperlayer];
}
//=======================//
// ROTATION AND TRANSFORM
//=======================//
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
- (BOOL)shouldAutorotate {
return YES;
}
- (void)applyRectOfInterest:(UIInterfaceOrientation)orientation {
CGFloat scaleVideoX, scaleVideoY;
CGFloat videoSizeX, videoSizeY;
CGRect transformedVideoRect = self.scanRectView.frame;
if([self.capture.sessionPreset isEqualToString:AVCaptureSessionPreset1920x1080]) {
videoSizeX = 1080;
videoSizeY = 1920;
} else {
videoSizeX = 720;
videoSizeY = 1280;
}
if(UIInterfaceOrientationIsPortrait(orientation)) {
scaleVideoX = self.capture.layer.frame.size.width / videoSizeX;
scaleVideoY = self.capture.layer.frame.size.height / videoSizeY;
// Convert CGPoint under portrait mode to map with orientation of image
// because the image will be cropped before rotate
// reference: https://github.com/TheLevelUp/ZXingObjC/issues/222
CGFloat realX = transformedVideoRect.origin.y;
CGFloat realY = self.capture.layer.frame.size.width - transformedVideoRect.size.width - transformedVideoRect.origin.x;
CGFloat realWidth = transformedVideoRect.size.height;
CGFloat realHeight = transformedVideoRect.size.width;
transformedVideoRect = CGRectMake(realX, realY, realWidth, realHeight);
} else {
scaleVideoX = self.capture.layer.frame.size.width / videoSizeY;
scaleVideoY = self.capture.layer.frame.size.height / videoSizeX;
}
// _captureSizeTransform = CGAffineTransformMakeScale(1.0/scaleVideoX, 1.0/scaleVideoY);
self.capture.scanRect = CGRectApplyAffineTransform(transformedVideoRect, CGAffineTransformMakeScale(1.0/scaleVideoX, 1.0/scaleVideoY));
}
//========//
// UTILITY
//========//
- (NSString *)barcodeFormatToString:(ZXBarcodeFormat)format {
switch (format) {
case kBarcodeFormatAztec:
return #"Aztec";
case kBarcodeFormatCodabar:
return #"CODABAR";
case kBarcodeFormatCode39:
return #"Code 39";
case kBarcodeFormatCode93:
return #"Code 93";
case kBarcodeFormatCode128:
return #"Code 128";
case kBarcodeFormatDataMatrix:
return #"Data Matrix";
case kBarcodeFormatEan8:
return #"EAN-8";
case kBarcodeFormatEan13:
return #"EAN-13";
case kBarcodeFormatITF:
return #"ITF";
case kBarcodeFormatPDF417:
return #"PDF417";
case kBarcodeFormatQRCode:
return #"QR Code";
case kBarcodeFormatRSS14:
return #"RSS 14";
case kBarcodeFormatRSSExpanded:
return #"RSS Expanded";
case kBarcodeFormatUPCA:
return #"UPCA";
case kBarcodeFormatUPCE:
return #"UPCE";
case kBarcodeFormatUPCEANExtension:
return #"UPC/EAN extension";
default:
return #"Unknown";
}
}
- (void)captureCameraIsReady:(ZXCapture *)capture {
self.scanning = YES;
}
- (void)applyOrientation {
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
float scanRectRotation;
float captureRotation;
switch (orientation) {
case UIInterfaceOrientationPortrait:
captureRotation = 0;
scanRectRotation = 90;
break;
case UIInterfaceOrientationLandscapeLeft:
captureRotation = 90;
scanRectRotation = 180;
break;
case UIInterfaceOrientationLandscapeRight:
captureRotation = 270;
scanRectRotation = 0;
break;
case UIInterfaceOrientationPortraitUpsideDown:
captureRotation = 180;
scanRectRotation = 270;
break;
default:
captureRotation = 0;
scanRectRotation = 90;
break;
}
self.capture.layer.frame = self.view.frame;
CGAffineTransform transform = CGAffineTransformMakeRotation((CGFloat) (captureRotation / 180 * M_PI));
[self.capture setTransform:transform];
[self.capture setRotation:scanRectRotation];
[self applyRectOfInterest:orientation];
}
#end
How to get the black blocks disappear?
And after the rotation, the black blocks disappear.
AppDelegate Source File:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *viewController = [mainStoryBoard instantiateViewControllerWithIdentifier:#"ViewController"];
self.window.rootViewController = viewController;
bar = [KodUserCenterBar instance];
[self.window makeKeyAndVisible];
return YES;
}
Header File:
#interface KodUserCenterBar : UIWindow
/**获取单例
*/
+ (instancetype)instance;
/**显示工具栏
*/
+ (void)show;
/**隐藏工具栏
*/
+ (void)hide;
/**显示功能视图
*/
+ (void)showFunctionView;
/**隐藏功能视图
*/
+ (void)hideFunctionView;
#end
Source File:
#define WIDTH self.frame.size.width
#define HEIGHT self.frame.size.height
#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height
#define kBarWidth 200
#define kBarImageViewTag 100
#define kBarItemGap 5
#define degreesToRadian(x) (M_PI * (x) / 180.0)
#interface KodUserCenterBarFunctionItemObject : NSObject
#property (nonatomic, copy) NSString *title;
#property (nonatomic, assign) NSUInteger indexOfTabBar;
#property (nonatomic, copy) NSString *imageName;
+ (instancetype)objectWithTitle:(NSString *)title indexOfTabBar:(NSUInteger)index imageName:(NSString *)imageName;
#end
#implementation KodUserCenterBarFunctionItemObject
+ (instancetype)objectWithTitle:(NSString *)title indexOfTabBar:(NSUInteger)index imageName:(NSString *)imageName
{
KodUserCenterBarFunctionItemObject *obj = [KodUserCenterBarFunctionItemObject new];
if (obj) {
obj.title = title;
obj.indexOfTabBar = index;
obj.imageName = imageName;
}
return obj;
}
#end
#interface KodUserCenterBar()
{
UIPanGestureRecognizer *pan;
UIViewController *_rootVC;
}
#property (nonatomic, copy) NSArray *itemsOfBar;
#property (nonatomic, assign) CGFloat initWidth;
#property (atomic, strong) UIButton *button;
#end
static KodUserCenterBar *static_instance = nil;
static BOOL isShowMenu = NO;
#implementation KodUserCenterBar
+ (instancetype)instance
{
if (static_instance == nil) {
static_instance = [KodUserCenterBar new];
[static_instance addTopButton];
}
return static_instance;
}
+ (void)show
{
[KodUserCenterBar instance].hidden = NO;
}
+ (void)hide
{
[KodUserCenterBar instance].hidden = YES;
}
+ (void)showFunctionView
{
if (!isShowMenu) {
[[KodUserCenterBar instance] clickBar:nil];
}
}
+ (void)hideFunctionView
{
if (isShowMenu) {
[[KodUserCenterBar instance] clickBar:nil];
}
}
- (instancetype)init
{
if (self = [super init]) {
self.backgroundColor = [UIColor clearColor];
self.windowLevel = UIWindowLevelAlert;
self.userInteractionEnabled = YES;
[self makeKeyAndVisible];
self.sd_x = 0;
self.sd_center_y = [UIScreen mainScreen].bounds.size.height / 2;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(onDeviceOrientationChange) name:UIDeviceOrientationDidChangeNotification object:nil];
}
return self;
}
- (NSArray *)itemsOfBar
{
if (_itemsOfBar == nil) {
KodUserCenterBarFunctionItemObject *item1 = [KodUserCenterBarFunctionItemObject objectWithTitle:#"个人中心" indexOfTabBar:0 imageName:#"tb3_toolbaruser"];
KodUserCenterBarFunctionItemObject *item2 = [KodUserCenterBarFunctionItemObject objectWithTitle:#"游戏礼包" indexOfTabBar:1 imageName:#"tb3_toolbargame"];
KodUserCenterBarFunctionItemObject *item3 = [KodUserCenterBarFunctionItemObject objectWithTitle:#"系统公告" indexOfTabBar:2 imageName:#"tb3_toolbarmsg"];
KodUserCenterBarFunctionItemObject *item4 = [KodUserCenterBarFunctionItemObject objectWithTitle:#"游戏论坛" indexOfTabBar:3 imageName:#"tb3_toolbarbbs"];
NSArray *data = #[item1, item2, item3, item4];
_itemsOfBar = [NSArray arrayWithArray:data];
}
return _itemsOfBar;
}
- (void)onDeviceOrientationChange
{
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
if (orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown) {
NSLog(#"is portrait");
NSLog(#"width = %f, height = %f", kScreenWidth, kScreenHeight);
[self adjustWindowPosition];
self.sd_center_y = kScreenHeight / 2;
}
else if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight) {
NSLog(#"is landscape");
NSLog(#"width = %f, height = %f", kScreenWidth, kScreenHeight);
[self adjustWindowPosition];
self.sd_center_y = kScreenHeight / 2;
}
}
- (void)addTopButton
{
pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(dragBar:)];
pan.delaysTouchesBegan = NO;
[self addGestureRecognizer:pan];
UIViewController *vc = [[KodBasicViewController alloc] init];
vc.view.backgroundColor = [UIColor clearColor];
self.rootViewController = vc;
CGSize size = [UIImage imageNamed:#"tb3_assi_nor"].size;
self.sd_width = size.width;
self.sd_height = size.height;
self.initWidth = size.width;
_button = [[UIButton alloc] init];
[_button setBackgroundImage:[UIImage imageNamed:#"tb3_assi_nor"] forState:UIControlStateNormal];
[_button setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateHighlighted];
[_button setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateSelected];
_button.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
[_button addTarget:self action:#selector(clickBar:) forControlEvents:UIControlEventTouchUpInside];
_button.userInteractionEnabled = YES;
_button.selected = NO;
[_button becomeFirstResponder];
[vc.view addSubview:_button];
}
- (void)clickBar:(id)button
{
NSTimeInterval interval = 0.2;
__weak typeof(_button) weakButton = _button;
isShowMenu = !isShowMenu;
pan.enabled = !isShowMenu;
if (self.sd_center_x > kScreenWidth / 2) {
[UIView animateWithDuration:interval animations:^{
self.sd_x = kScreenWidth;
} completion:^(BOOL finished) {
if (isShowMenu) {
self.sd_width = kBarWidth + self.initWidth;
_button.sd_right_x = self.sd_width;
UIImage *image = [UIImage imageNamed:#"tb3_assi_bor_right"];
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(1, 30, 1, 0)];
UIImageView *rightImageView = [[UIImageView alloc] initWithImage:image];
rightImageView.image = image;
rightImageView.sd_width = kBarWidth;
rightImageView.sd_right_x = _button.sd_x;
rightImageView.sd_center_y = _button.sd_center_y;
rightImageView.tag = kBarImageViewTag;
rightImageView.userInteractionEnabled = YES;
[self.rootViewController.view addSubview:rightImageView];
self.sd_x = kScreenWidth;
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_right"] forState:UIControlStateNormal];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_pre_right"] forState:UIControlStateSelected];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_pre_right"] forState:UIControlStateHighlighted];
[self addFunctionItems:NO];
}
else {
self.sd_width = self.initWidth;
_button.sd_right_x = self.sd_width;
UIView *contentView = [self.rootViewController.view viewWithTag:kBarImageViewTag];
[contentView removeFromSuperview];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_nor"] forState:UIControlStateNormal];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateSelected];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateHighlighted];
}
[UIView animateWithDuration:interval animations:^{
self.sd_right_x = kScreenWidth;
}];
}];
}
else {
[UIView animateWithDuration:interval animations:^{
self.sd_right_x = 0;
} completion:^(BOOL finished) {
if (isShowMenu) {
self.sd_width = kBarWidth + self.initWidth;
UIImage *image = [UIImage imageNamed:#"tb3_assi_bor_left"];
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(1, 0, 1, 30)];
UIImageView *leftImageView = [[UIImageView alloc] initWithImage:image];
leftImageView.image = image;
leftImageView.sd_width = kBarWidth;
leftImageView.sd_x = _button.sd_right_x;
leftImageView.sd_center_y = _button.sd_center_y;
leftImageView.tag = kBarImageViewTag;
leftImageView.userInteractionEnabled = YES;
[self.rootViewController.view addSubview:leftImageView];
self.sd_right_x = 0;
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_left"] forState:UIControlStateNormal];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_pre_left"] forState:UIControlStateSelected];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_act_pre_left"] forState:UIControlStateHighlighted];
[self addFunctionItems:YES];
}
else {
self.sd_width = self.initWidth;
UIView *contentView = [self.rootViewController.view viewWithTag:kBarImageViewTag];
[contentView removeFromSuperview];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_nor"] forState:UIControlStateNormal];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateSelected];
[weakButton setBackgroundImage:[UIImage imageNamed:#"tb3_assi_pre"] forState:UIControlStateHighlighted];
}
[UIView animateWithDuration:interval animations:^{
self.sd_x = 0;
}];
}];
}
}
- (void)addFunctionItems:(BOOL)isLeft
{
UIView *bgView = [self.rootViewController.view viewWithTag:kBarImageViewTag];
if (bgView) {
[self.itemsOfBar enumerateObjectsUsingBlock:^(KodUserCenterBarFunctionItemObject *obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([bgView viewWithTag:idx] == nil) {
KodFrameTabBarItem *item = [[KodFrameTabBarItem alloc] init];
item.tag = idx;
item.title = obj.title;
item.imageName = obj.imageName;
item.sd_width = (bgView.sd_width - _itemsOfBar.count * kBarItemGap - 10) / _itemsOfBar.count;
item.sd_height = bgView.sd_height;
item.sd_center_y = bgView.sd_height / 2;
item.sd_center_x = kBarItemGap + idx * (item.sd_width + kBarItemGap) + item.sd_width / 2;
item.sd_center_x += isLeft ? 0 : item.sd_width / 4;
[item addTarget:self action:#selector(clickItem:) forControlEvents:UIControlEventTouchUpInside];
[bgView addSubview:item];
}
}];
}
}
- (void)clickItem:(id)sender
{
[KodNavigationView showWithIndex:0];
[[UIApplication sharedApplication].keyWindow addSubview:[KodNavigationView instance]];
}
- (void)adjustWindowPosition
{
if (self.sd_center_x < kScreenWidth / 2) {
self.sd_x = 0;
}
else {
self.sd_right_x = kScreenWidth;
}
}
- (void)dragBar:(UIPanGestureRecognizer *)p
{
CGPoint panPoint = [p locationInView:[[UIApplication sharedApplication] keyWindow]];
if (p.state == UIGestureRecognizerStateBegan) {
if (_button) {
_button.selected = YES;
}
}
else if(p.state == UIGestureRecognizerStateChanged) {
self.center = CGPointMake(panPoint.x, panPoint.y);
if (panPoint.x < WIDTH / 2) {
self.sd_x = 0;
}
else if (panPoint.x > kScreenWidth - WIDTH / 2) {
self.sd_right_x = kScreenWidth;
}
if (panPoint.y < HEIGHT / 2) {
self.sd_y = 0;
}
else if (panPoint.y > kScreenHeight - HEIGHT / 2) {
self.sd_bottom_y = kScreenHeight;
}
}
else if(p.state == UIGestureRecognizerStateEnded) {
if(panPoint.x <= kScreenWidth / 2) {
[UIView animateWithDuration:0.2 animations:^{
self.sd_x = 0;
} completion:nil];
}
else {
[UIView animateWithDuration:0.2 animations:^{
self.sd_right_x = kScreenWidth;
} completion:nil];
}
if (_button) {
_button.selected = NO;
}
}
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#end
Root ViewController
Source File Of Root ViewController:
#interface KodBasicViewController ()
#end
#implementation KodBasicViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
UIWindow *window = self.view.window;
[window bringSubviewToFront:window.rootViewController.view];
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
UIWindow *window = self.view.window;
[window bringSubviewToFront:window.rootViewController.view];
}
#end
Here is my solution to this problem:
window.layer.masksToBounds = true
It's the default background colour of UIWindow instance, and while your root view is doing rotation, those uncovered parts will be shown as black block as you said.
You can just set your desired background colour for your window (or make your root view's frame big enough to cover whole window while doing rotation, not recommended):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
[self.window setBackgroundColor:[UIColor lightGrayColor]];
[self.window makeKeyAndVisible];
return YES;
}
I have a pickerview that is getting its information from a separate AFPickerView file. I'm getting the error "Implicit conversion of 'int' to 'UIColor*' is disallowed with ARC". Any suggestions on an easy fix for this?
Here is the code that it effects:
[visibleViews minusSet:recycledViews];
// add missing pages
for (int index = firstNeededViewIndex; index <= lastNeededViewIndex; index++)
{
if (![self isDisplayingViewForIndex:index])
{
UILabel *label = (UILabel *)[self dequeueRecycledView];
if (label == nil)
{
label = [[UILabel alloc] initWithFrame:CGRectMake(_rowIndent, 0, self.frame.size.width - _rowIndent, 39.0)];
label.backgroundColor = [UIColor clearColor];
label.font = self.rowFont;
label.textColor = RGBACOLOR(0.0, 0.0, 0.0, 0.75);
}
[self configureView:label atIndex:index];
[contentView addSubview:label];
[visibleViews addObject:label];
}
}
}
Here is the full code:
#import "AFPickerView.h"
#implementation AFPickerView
#pragma mark - Synthesization
#synthesize dataSource;
#synthesize delegate;
#synthesize selectedRow = currentRow;
#synthesize rowFont = _rowFont;
#synthesize rowIndent = _rowIndent;
#pragma mark - Custom getters/setters
- (void)setSelectedRow:(int)selectedRow
{
if (selectedRow >= rowsCount)
return;
currentRow = selectedRow;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * currentRow) animated:NO];
}
- (void)setRowFont:(UIFont *)rowFont
{
_rowFont = rowFont;
for (UILabel *aLabel in visibleViews)
{
aLabel.font = _rowFont;
}
for (UILabel *aLabel in recycledViews)
{
aLabel.font = _rowFont;
}
}
- (void)setRowIndent:(CGFloat)rowIndent
{
_rowIndent = rowIndent;
for (UILabel *aLabel in visibleViews)
{
CGRect frame = aLabel.frame;
frame.origin.x = _rowIndent;
frame.size.width = self.frame.size.width - _rowIndent;
aLabel.frame = frame;
}
for (UILabel *aLabel in recycledViews)
{
CGRect frame = aLabel.frame;
frame.origin.x = _rowIndent;
frame.size.width = self.frame.size.width - _rowIndent;
aLabel.frame = frame;
}
}
#pragma mark - Initialization
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// setup
[self setup];
// backgound
UIImageView *bacground = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"pickerBackground.png"]];
[self addSubview:bacground];
// content
contentView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, frame.size.width, frame.size.height)];
contentView.showsHorizontalScrollIndicator = NO;
contentView.showsVerticalScrollIndicator = NO;
contentView.delegate = self;
[self addSubview:contentView];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTap:)];
[contentView addGestureRecognizer:tapRecognizer];
// shadows
UIImageView *shadows = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"pickerShadows.png"]];
[self addSubview:shadows];
// glass
UIImage *glassImage = [UIImage imageNamed:#"pickerGlass.png"];
glassImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 76.0, glassImage.size.width, glassImage.size.height)];
glassImageView.image = glassImage;
[self addSubview:glassImageView];
}
return self;
}
- (void)setup
{
_rowFont = [UIFont boldSystemFontOfSize:24.0];
_rowIndent = 30.0;
currentRow = 0;
rowsCount = 0;
visibleViews = [[NSMutableSet alloc] init];
recycledViews = [[NSMutableSet alloc] init];
}
#pragma mark - Buisness
- (void)reloadData
{
// empry views
currentRow = 0;
rowsCount = 0;
for (UIView *aView in visibleViews)
[aView removeFromSuperview];
for (UIView *aView in recycledViews)
[aView removeFromSuperview];
visibleViews = [[NSMutableSet alloc] init];
recycledViews = [[NSMutableSet alloc] init];
rowsCount = [dataSource numberOfRowsInPickerView:self];
[contentView setContentOffset:CGPointMake(0.0, 0.0) animated:NO];
contentView.contentSize = CGSizeMake(contentView.frame.size.width, 39.0 * rowsCount + 4 * 39.0);
[self tileViews];
}
- (void)determineCurrentRow
{
CGFloat delta = contentView.contentOffset.y;
int position = round(delta / 39.0);
currentRow = position;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * position) animated:YES];
[delegate pickerView:self didSelectRow:currentRow];
}
- (void)didTap:(id)sender
{
UITapGestureRecognizer *tapRecognizer = (UITapGestureRecognizer *)sender;
CGPoint point = [tapRecognizer locationInView:self];
int steps = floor(point.y / 39) - 2;
[self makeSteps:steps];
}
- (void)makeSteps:(int)steps
{
if (steps == 0 || steps > 2 || steps < -2)
return;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * currentRow) animated:NO];
int newRow = currentRow + steps;
if (newRow < 0 || newRow >= rowsCount)
{
if (steps == -2)
[self makeSteps:-1];
else if (steps == 2)
[self makeSteps:1];
return;
}
currentRow = currentRow + steps;
[contentView setContentOffset:CGPointMake(0.0, 39.0 * currentRow) animated:YES];
[delegate pickerView:self didSelectRow:currentRow];
}
#pragma mark - recycle queue
- (UIView *)dequeueRecycledView
{
UIView *aView = [recycledViews anyObject];
if (aView)
[recycledViews removeObject:aView];
return aView;
}
- (BOOL)isDisplayingViewForIndex:(NSUInteger)index
{
BOOL foundPage = NO;
for (UIView *aView in visibleViews)
{
int viewIndex = aView.frame.origin.y / 39.0 - 2;
if (viewIndex == index)
{
foundPage = YES;
break;
}
}
return foundPage;
}
- (void)tileViews
{
// Calculate which pages are visible
CGRect visibleBounds = contentView.bounds;
int firstNeededViewIndex = floorf(CGRectGetMinY(visibleBounds) / 39.0) - 2;
int lastNeededViewIndex = floorf((CGRectGetMaxY(visibleBounds) / 39.0)) - 2;
firstNeededViewIndex = MAX(firstNeededViewIndex, 0);
lastNeededViewIndex = MIN(lastNeededViewIndex, rowsCount - 1);
// Recycle no-longer-visible pages
for (UIView *aView in visibleViews)
{
int viewIndex = aView.frame.origin.y / 39 - 2;
if (viewIndex < firstNeededViewIndex || viewIndex > lastNeededViewIndex)
{
[recycledViews addObject:aView];
[aView removeFromSuperview];
}
}
[visibleViews minusSet:recycledViews];
// add missing pages
for (int index = firstNeededViewIndex; index <= lastNeededViewIndex; index++)
{
if (![self isDisplayingViewForIndex:index])
{
UILabel *label = (UILabel *)[self dequeueRecycledView];
if (label == nil)
{
label = [[UILabel alloc] initWithFrame:CGRectMake(_rowIndent, 0, self.frame.size.width - _rowIndent, 39.0)];
label.backgroundColor = [UIColor clearColor];
label.font = self.rowFont;
label.textColor = RGBACOLOR(0.0, 0.0, 0.0, 0.75);
}
[self configureView:label atIndex:index];
[contentView addSubview:label];
[visibleViews addObject:label];
}
}
}
- (void)configureView:(UIView *)view atIndex:(NSUInteger)index
{
UILabel *label = (UILabel *)view;
label.text = [dataSource pickerView:self titleForRow:index];
CGRect frame = label.frame;
frame.origin.y = 39.0 * index + 78.0;
label.frame = frame;
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self tileViews];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate)
[self determineCurrentRow];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self determineCurrentRow];
}
#end
This should work with ARC. Replace RGBACOLOR with colorWithRed:green:blue:alpha
label.textColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.75f];
I'm trying to make another custom view available at rood VC's viewdidload.
MSHView *customTextView = [[MSHView alloc] initWithFrame:self.view.bounds];
customTextView.textView.text = #"abc";
[customTextView layoutSubviews];
[self.view addSubview:customTextView];
MSHView Header file:
#property(nonatomic, strong) UITextView * textView;
#property (nonatomic, strong) UIImageView* translucentIV;
MSHView implementaion file:
-(UIImageView*) translucentIV {
if(!_translucentIV) {
_translucentIV.frame = self.frame;
//NSLog(#"frame for translucent IV, %#", _translucentIV.frame);
_translucentIV.backgroundColor = [UIColor whiteColor];
_translucentIV.alpha = 0.5;
}
return _translucentIV;
}
-(UITextView* ) textView{
if(!_textView){
/*
float height = self.bounds.size.height - 5;
float width = self.bounds.size.width - 5;
_textView.frame = CGRectMake(5,5,width,height);
_textView.text = #"test text";
*/
NSLog(#"textview property being initialized");
}
return _textView;
}
-(void)layoutSubviews {
self.textView.frame = self.frame;
self.translucentIV.backgroundColor = [UIColor whiteColor];
self.alpha = 0.5;
NSString *abc = #"abc";
self.textView.text = [NSString stringWithFormat:#"%#",abc];
NSLog(#"layout subview being called");
}
-(void) setTextView:(UITextView *)textView {
if(textView != _textView) {
_textView = textView;
_textView.text = #"setter method called";
}
}
Still cannot see the textview from MSHView. I think I'm not doing properties properly. any help or explanation?
Thanks in advance.
You are not creating the UIImageView and UITextView.
Try something more like:
-(UIImageView*) translucentIV {
if(!_translucentIV) {
_translucentIV = [[UIImageView alloc] initWithFrame:self.frame];
//NSLog(#"frame for translucent IV, %#", _translucentIV.frame);
_translucentIV.backgroundColor = [UIColor whiteColor];
_translucentIV.alpha = 0.5;
}
return _translucentIV;
}
-(UITextView *)textView {
if(!_textView) {
float height = self.bounds.size.height - 5;
float width = self.bounds.size.width - 5;
_textView = [[UITextView alloc] initWithFrame:CGRectMake(5,5,width,height)];
}
return _textView;
}
You'll also want to add them to the parent view somewhere.
I want to publish tutorial about how to easily create an UIScrollView on http://www.xprogress.com/ and I just want to check with you guys if the code is alright before I publish anything. Any help will be appreciated and I'll put your name / website on the bottom of the article :)
Thanks a lot :)
Ondrej
header file:
///
/// IGUIScrollViewImage.h
///
/// IGUILibrary
///
/// Created by Ondrej Rafaj on 7.4.10.
///
/// Copyright 2010 Home. All rights reserved.
///
/// #todo enable margin and center the image to the middle of the view
/**
<b>Examples:</b>
<i>This is just a short example how to use this class</i>
<pre>
- (NSArray *)getImages {
NSMutableArray *arr = [[[NSMutableArray alloc] init] autorelease];
[arr addObject:[UIImage imageNamed:#"image-1.jpg"]];
[arr addObject:[UIImage imageNamed:#"image-2.png"]];
[arr addObject:[UIImage imageNamed:#"image-3.png"]];
[arr addObject:[UIImage imageNamed:#"image-4.jpg"]];
return (NSArray *)arr;
}
- (void)viewDidLoad {
IGUIScrollViewImage *svimage = [[IGUIScrollViewImage alloc] init];
[svimage setSizeFromScrollView:self.scrView]; // takes size of the scroll view you've already placed on stage via Interface Builder
// or
//[svimage setWidth:320 andHeight:240]; // half screen
[svimage enablePositionMemory]; // enables position (pagination) memory for this scroll view
// or
//[svimage enablePositionMemoryWithIdentifier:#"myIdentifier"]; if you have more instances of this scroll view in your application
[svimage enablePageControlOnBottom];
// or
//[svimage enablePageControlOnTop];
[self.myUIView addSubview:[svimage get]]; // and place it on the stage :)
[super viewDidLoad];
}
</pre>
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface IGUIScrollViewImage : NSObject <UIScrollViewDelegate> {
UIScrollView *scrollView;
UIPageControl *pageControl;
CGRect rectScrollView;
CGRect rectPageControl;
int scrollWidth;
int scrollHeight;
NSArray *contentArray;
UIColor *bcgColor;
BOOL pageControlEnabledTop;
BOOL pageControlEnabledBottom;
BOOL rememberPosition;
NSString *positionIdentifier;
}
#property (nonatomic, retain) UIScrollView *scrollView;
- (int)getScrollViewWidth;
- (void)setWidth:(int)width andHeight:(int)height;
- (void)setSizeFromScrollView:(UIScrollView *)scView;
- (void)setBackGroudColor:(UIColor *)color;
- (void)setContentArray:(NSArray *)images;
- (void)enablePageControlOnTop;
- (void)enablePageControlOnBottom;
- (void)enablePositionMemory;
- (void)enablePositionMemoryWithIdentifier:(NSString *)identifier;
- (UIScrollView *)getWithPosition:(int)page;
- (UIScrollView *)getWithPositionMemoryIdentifier:(NSString *)identifier;
- (UIScrollView *)get;
#end
And the implementation file:
//
// IGUIScrollViewImage.m
// IGUILibrary
//
// Created by Ondrej Rafaj on 7.4.10.
// Copyright 2010 Home. All rights reserved.
//
#import "IGUIScrollViewImage.h"
#define kIGUIScrollViewImagePageIdentifier #"kIGUIScrollViewImagePageIdentifier"
#define kIGUIScrollViewImageDefaultPageIdentifier #"Default"
#implementation IGUIScrollViewImage
#synthesize scrollView;
- (int)getScrollViewWidth {
return ([contentArray count] * scrollWidth);
}
- (void)setWidth:(int)width andHeight:(int)height {
scrollWidth = width;
scrollHeight = height;
if (!width || !height) rectScrollView = [[UIScreen mainScreen] applicationFrame];
else rectScrollView = CGRectMake(0, 0, width, height);
}
- (void)setSizeFromScrollView:(UIScrollView *)scView {
scrollWidth = scView.frame.size.width;
scrollHeight = scView.frame.size.height;
rectScrollView = CGRectMake(0, 0, scrollWidth, scrollHeight);
}
- (void)setContentArray:(NSArray *)images {
contentArray = images;
}
- (void)setBackGroudColor:(UIColor *)color {
bcgColor = color;
}
- (void)enablePageControlOnTop {
pageControlEnabledTop = YES;
}
- (void)enablePageControlOnBottom {
pageControlEnabledBottom = YES;
}
- (void)enablePositionMemoryWithIdentifier:(NSString *)identifier {
rememberPosition = YES;
if (!identifier) identifier = kIGUIScrollViewImageDefaultPageIdentifier;
positionIdentifier = identifier;
}
- (void)enablePositionMemory {
[self enablePositionMemoryWithIdentifier:nil];
}
- (UIScrollView *)getWithPosition:(int)page {
if (!contentArray) {
contentArray = [[[NSArray alloc] init] autorelease];
}
if (page > [contentArray count]) page = 0;
if (!scrollWidth || !scrollHeight) {
rectScrollView = [[UIScreen mainScreen] applicationFrame];
scrollWidth = rectScrollView.size.width;
scrollHeight = rectScrollView.size.height;
}
rectScrollView = CGRectMake(0, 0, scrollWidth, scrollHeight);
self.scrollView = [[UIScrollView alloc] initWithFrame:rectScrollView];
self.scrollView.contentSize = CGSizeMake([self getScrollViewWidth], scrollHeight);
if (!bcgColor) bcgColor = [UIColor blackColor];
self.scrollView.backgroundColor = bcgColor;
self.scrollView.alwaysBounceHorizontal = YES;
self.scrollView.contentOffset = CGPointMake(page * scrollWidth, 0);
self.scrollView.pagingEnabled = YES;
UIImageView *imageView;
UIView *main = [[[UIView alloc] initWithFrame:rectScrollView] autorelease];
int i = 0;
for (UIImage *img in contentArray) {
imageView = [[UIImageView alloc] initWithImage:img];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
imageView.backgroundColor = [UIColor blackColor];
float ratio = img.size.width/rectScrollView.size.width;
CGRect imageFrame = CGRectMake(i, 0, rectScrollView.size.width, (img.size.height / ratio));
imageView.frame = imageFrame;
[self.scrollView addSubview:imageView];
i += scrollWidth;
}
[imageView release];
[main addSubview:scrollView];
if (pageControlEnabledTop) {
rectPageControl = CGRectMake(0, 5, scrollWidth, 15);
}
else if (pageControlEnabledBottom) {
rectPageControl = CGRectMake(0, (scrollHeight - 25), scrollWidth, 15);
}
if (pageControlEnabledTop || pageControlEnabledBottom) {
pageControl = [[[UIPageControl alloc] initWithFrame:rectPageControl] autorelease];
pageControl.numberOfPages = [contentArray count];
pageControl.currentPage = page;
[main addSubview:pageControl];
}
if (pageControlEnabledTop || pageControlEnabledBottom || rememberPosition) self.scrollView.delegate = self;
//if (margin) [margin release];
return (UIScrollView *)main;
}
- (UIScrollView *)get {
return [self getWithPosition:0];
}
- (UIScrollView *)getWithPositionMemoryIdentifier:(NSString *)identifier {
[self enablePositionMemoryWithIdentifier:identifier];
return [self getWithPosition:[[[NSUserDefaults alloc] objectForKey:[NSString stringWithFormat:#"%#%#", kIGUIScrollViewImagePageIdentifier, positionIdentifier]] intValue]];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sv {
int page = sv.contentOffset.x / sv.frame.size.width;
pageControl.currentPage = page;
if (rememberPosition) {
[[NSUserDefaults alloc] setObject:[NSString stringWithFormat:#"%d", page] forKey:[NSString stringWithFormat:#"%#%#", kIGUIScrollViewImagePageIdentifier, positionIdentifier]];
}
}
- (void)dealloc {
[scrollView release];
[super dealloc];
}
#end
Just a quick glance. You alloc UIImageView multiple times in
-(UIScrollView*)getWithPosition:(int)page and release it only once:
for (UIImage *img in contentArray) {
imageView = [[UIImageView alloc] initWithImage:img];
// ...
}
[imageView release];