In iOS 11 searchBar hides when scrolling tableView if we set to hide. how can I hide searchBar, navigationBar and tabBar when scrolling collectionView up ? And unhide them all when scrolling down ? Thanks for your help...
Subclass UIScrollViewDelegate in your UIViewController (i.e. class ViewController: UIViewController, UIScrollViewDelegate { codes... })
Implement scrollViewDidScroll Delegate method
func scrollViewDidScroll(scrollView: UIScrollView) {
let pan = scrollView.panGestureRecognizer
let velocity = pan.velocityInView(scrollView).y
if velocity < -5 {
self.navigationController?.setNavigationBarHidden(true, animated: true)
self.navigationController?.setToolbarHidden(true, animated: true)
} else if velocity > 5 {
self.navigationController?.setNavigationBarHidden(false, animated: true)
self.navigationController?.setToolbarHidden(false, animated: true)
}
}
Translating KTang's accepted answer to Objective-C:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
UIPanGestureRecognizer *pan = scrollView.panGestureRecognizer;
CGFloat velocity = [pan velocityInView:scrollView].y;
if (velocity < -5) {
[self.navigationController setNavigationBarHidden:YES animated:YES];
[self.navigationController setToolbarHidden:YES animated:YES];
} else if (velocity > 5) {
[self.navigationController setNavigationBarHidden:YES animated:YES];
[self.navigationController setToolbarHidden:YES animated:YES];
}
}
Related
My layout has two views See the pic:
pic 1
View1 is fullscreen, view2 framed in red bounds is a sublayer of view1. Both views are transparent and do nothing yet but camera broadcast. The code is:
import UIKit
import Foundation
import AVFoundation
class CameraView: UIView {
override class var layerClass: AnyClass {
get {
return AVCaptureVideoPreviewLayer.self
}
}
override var layer: AVCaptureVideoPreviewLayer {
get {
return super.layer as! AVCaptureVideoPreviewLayer
}
}
}
class SceneViewController: ARSceneViewController,
AVCaptureMetadataOutputObjectsDelegate {
var testFrameView: UIView?
var cameraView: CameraView!
override func loadView() {
super.loadView()
cameraView = CameraView()
testFrameView = cameraView
}
override func viewDidLoad() {
super.viewDidLoad()
if let testFrameView = testFrameView {
testFrameView.layer.borderColor = UIColor.red.cgColor
testFrameView.layer.borderWidth = 2
testFrameView.layer.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
view.addSubview(testFrameView)
view.bringSubview(toFront: testFrameView)
}
}
}
testFrameView is my view2. Now I want my testFrameView to capture something. That's why class CameraView was created. I add input like this:
import UIKit
import Foundation
import AVFoundation
class CameraView: UIView {
override class var layerClass: AnyClass {
get {
return AVCaptureVideoPreviewLayer.self
}
}
override var layer: AVCaptureVideoPreviewLayer {
get {
return super.layer as! AVCaptureVideoPreviewLayer
}
}
}
class SceneViewController: ARSceneViewController,
AVCaptureMetadataOutputObjectsDelegate {
var testFrameView: UIView?
var cameraView: CameraView!
///////////////// NEW /////////////////
let session = AVCaptureSession()
let sessionQueue = DispatchQueue(label: AVCaptureSession.self.description(), attributes: [], target: nil)
///////////////// NEW /////////////////
override func loadView() {
super.loadView()
cameraView = CameraView()
testFrameView = cameraView
}
override func viewDidLoad() {
super.viewDidLoad()
if let testFrameView = testFrameView {
testFrameView.layer.borderColor = UIColor.red.cgColor
testFrameView.layer.borderWidth = 2
testFrameView.layer.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
view.addSubview(testFrameView)
view.bringSubview(toFront: testFrameView)
}
}
///////////////// NEW /////////////////
session.beginConfiguration()
let videoDevice = AVCaptureDevice.default(for: .video)
if (videoDevice != nil) {
let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice!)
if (videoDeviceInput != nil) {
if (session.canAddInput(videoDeviceInput!)) {
session.addInput(videoDeviceInput!)
}
}
}
session.commitConfiguration()
cameraView.layer.session = session
///////////////// NEW /////////////////
}
Now view2 (aka testFrameView or CameraView) is ok, but view1 gets blocked with white screen like this:
pic 2
The question is: why view1 gets blocked when I run capture session using view2. How to avoid it?
I'm working on a weird issue right now. My Apps Deployment Target is set to iOS6, so I want to support both iOS6 and iOS7.
I just have a simple UITableView, in which the user can select the preferred notification sound.
The code for - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CheckmarkCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[cell setTintColor:[UIColor redColor]];
if (indexPath.section == 0){
cell.textLabel.text = [_availableSounds objectAtIndex:indexPath.row];
if (indexPath.row == _checkedSoundIndexPath.row) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
else {
// Unrelated, another settings cell
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
return cell;
}
My - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath looks like the following:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section != 0) {
return;
}
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[[self.tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
if (_checkedSoundIndexPath != indexPath) {
[[self.tableView cellForRowAtIndexPath:_checkedSoundIndexPath] setAccessoryType:UITableViewCellAccessoryNone];
}
_checkedSoundIndexPath = indexPath;
}
The problem is that an iOS7 iPhone won't show the checkmark as expected. Running the same code on an iOS6 iPhone works as expected. I tried to insert [cell setTintColor:[UIColor redColor]]; but without any luck. Even if I remove all AccessoryType related code and add the checkmark in my storyboard nothing appears. See screenshots below (first is iOS6 and second is iOS5).
Does anyone have an idea ? Or is it a bug in iOS7 ?
Thanks in advance !
Edit:
Even if I make a new simple UITableViewController, with just 5 cells with the Accessory set to UITableViewAccessoryTypeCheckmark, the Checkmarks won't appear on iOS7.
I had a similar problem and I solved this issues changing the tint color of the uitableview
I changed the tintcolot of uitable by InterfaceBuilder to Default color
or
tableView.tintColor = [UIColor blackColor];
I had the exact same problem as you are for a long time.
In my case I implemented some appearance tweaks. And one of them was
[[UIView appearance] setTintColor:[UIColor whiteColor]];
Try to find in your project global things like that.
In my application it working perfect,check it
//take it in .h file mutable arSelectedRows;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
//Do anything you want for cell here
if([arSelectedRows containsObject:indexPath]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[arSelectedRows addObject:indexPath];
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
[arSelectedRows removeObject:indexPath];
}
NSLog(#"id are here :%#",arSelectedIDs);
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
may be ,it will helpful.
No, There is No Problem with UITableViewCellAccessoryCheckmark in iOS 7,Make sure you have implemented correct logic for it.
I think the problem is with your checksoundIndexpath, please check whether it has a correct indexpath, Or First check with hardcoded indexpath.
you are not initializing the checksoundindxpath.
Also I noticed you are not assigning the selected row indexpath to _checkSoundIndexpath, Only you are checking if both indexpaths(current indexpaths and _checksoundindexpath) are equal, But if they are different then you should assign the selected indedxpath to _checksound indexpath.
I can solve this problem by set tint color for Cell
It didnt show because cell tint in white ,and cell selectionstyle is none
cell.tintColor = [UIColor blackColor];
if(cell.selected){
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}else{
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
I would rather reload tableview (preferably only the affected rows - using reloadRowsAtIndexPaths) after settings appropriate data in didSelectRowAtIndexPath: method.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Other logic..
[tableView deselectRowAtIndexPath:indexPath animated:NO]; // Would like to look for an alternative method to avoid this refresh??
NSMutableArray *reloadArray = [NSMutableArray arrayWithCapacity:2];
[reloadArray addObject:indexPath];
[reloadArray addObject:_checkedSoundIndexPath];
self.checkedSoundIndexPath = indexPath; // Should set this before reload
[tableView reloadRowsAtIndexPaths:reloadArray withRowAnimation:UITableViewRowAnimationAutomatic];
}
And, most importantly, add these lines in cellForRowAtIndexPath: method -
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// All your other code for this section followed by these lines...
if([_checkedSoundIndexPath compare:indexPath] == NSOrderedSame) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
// Other sections code
return cell;
}
I know the original question uses a simple UITableViewCell but this might work for someone else with a custom table view cell.
I have a custom UITableViewCell subclass. I tried everything but the checkmark won't show. Eventually I realised that I overrode layoutSubviews but forgot to call [super layoutSubviews]. Which meant the checkmark would not show correctly.
- (void)layoutSubviews
{
[super layoutSubviews];
//...custom layout here
}
I have a unique viewController for landscape mode, the problem is that when I segue to the landscape view controller (modal segue) the iAD disapears and it seems to stop receiving delegate methods as well. Only when I tap the tab bar to go to another view and then back again does it show again
- (void)orientationChanged:(NSNotification *)notification
{
NSLog(#"orientation changed");
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView && isThisView)
{
//[self.view bringSubviewToFront:self.backgroundImageView];
[self performSegueWithIdentifier:#"DisplayLandscapeView" sender:self];
isShowingLandscapeView = YES;
}
else if (deviceOrientation == UIDeviceOrientationPortrait && isShowingLandscapeView)
{
[self dismissViewControllerAnimated:YES completion:nil];
isShowingLandscapeView = NO;
self.bannerView.hidden = NO;
//[self.view sendSubviewToBack:self.backgroundImageView];
}
}
I have a UITableViewCell with an UICollectionView inside it. My custom UITableViewCell is responsible for the datasource and methods for the UICollectionView. All works perfectly except when I add some logging to the cellForItemAtIndexPath I see that all UICollectionViewCells will be loaded at once. So there goes my lazy/delayed loading when scrolling down.
Here is my logging in the custom UITableViewCell
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Loading cell: %i", indexPath.row);
}
The tableViewCell height is automaticaly calculated based on the items the UICollectioNView needs to handle. So in the tableview method of my ViewController:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//return dynamically the height based on the items to show in the collectionview.
}
So I guess this is my problem and reason why it doesn't do lazy loading. Is there an easy fix for this ? Or is this the way:
Source: http://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell
By this the lazy loading will only be handled by the UITableView and not the UICollectionView.
Here is the full code of my custom UITableViewCell, but as you will see this is really nothing special.
#implementation PeopleJoinedThisPlaceCell
#synthesize people = _people;
- (void)awakeFromNib
{
collectionView.delegate = self;
collectionView.dataSource = self;
collectionView.backgroundColor = [UIColor clearColor];
}
- (void)setPeople:(NSArray *)people
{
_people = people;
[collectionView reloadData];
}
#pragma mark - CollectionViewController delegate methods
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
if(_people == NULL) return 0;
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
if(_people == NULL) return 0;
return _people.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView_ cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Loading cell: %i", indexPath.row);
ImageCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"People" forIndexPath:indexPath];
PFObject *userPlace = [_people objectAtIndex:indexPath.row];
PFUser *user = [userPlace objectForKey:UserClassName];
[cell.BackgroundImageView setImage:[UIImage imageNamed:#"photo-big-bg"]];
[cell.ImageLoader startAnimating];
[[UserPhotos sharedInstance] getCachedSmallPhotoForUser:user withBlock:^(UIImage *image, NSError *error) {
[cell.ImageView setImage:image];
[cell.ImageLoader stopAnimating];
}];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView_ didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
PFObject *userPlace = [_people objectAtIndex:indexPath.row];
[_delegate gotoUserProfile:userPlace];
}
#end
Code works fine until I changed UIViewController with tableView to UICollectionViewController.
Now all cells shows same image, sometimes it flipping to nil.
However textLabels are OK.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TourGridCell";
TourGridCell *cell = (TourGridCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
Guide *guideRecord = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.titleLabel.text = [guideRecord.name uppercaseString];
cell.titleLabel.backgroundColor = [UIColor clearColor];
if ([guideRecord.sights count] > 0) {
if ([[guideRecord.sights objectAtIndex:0]valueForKey:#"thumbnail"]) {
cell.imageView.image = [UIImage drawImage:[[guideRecord.sights objectAtIndex:0]valueForKey:#"thumbnail"] inImage:[UIImage imageNamed:#"MultiplePhotos"] inRect:CGRectMake(11, 11, 63, 63)];
}else {
cell.imageView.image = [UIImage imageNamed:#"placeholder2"];
}
NSMutableString *sightsSummary = [NSMutableString stringWithCapacity:[guideRecord.sights count]];
for (Sight *sight in guideRecord.sights) {
if ([sight.name length]) {
if ([sightsSummary length]) {
[sightsSummary appendString:#", "];
}
[sightsSummary appendString:sight.name];
}
}
if ([sightsSummary length]) {
[sightsSummary appendString:#"."];
}
cell.sightsTextLabel.text = sightsSummary;
cell.detailTextLabel.text = [NSString stringWithFormat:NSLocalizedString(#"%i", nil) , [guideRecord.sights count]];
cell.detailTextLabel.hidden = NO;
// cell.textLabel.alpha = 0.7;
NSPredicate *enabledSightPredicate = [NSPredicate predicateWithFormat:#"notify == YES"];
NSArray *sightsEnabled = [[[guideRecord.sights array] filteredArrayUsingPredicate:enabledSightPredicate]mutableCopy];
NSPredicate *visitedSightPredicate = [NSPredicate predicateWithFormat:#"visited == YES"];
NSArray *sightsVisited = [[[guideRecord.sights array] filteredArrayUsingPredicate:visitedSightPredicate]mutableCopy];
if ([sightsEnabled count] > 0)
{
NSLog(#"green_badge");
cell.notifyIV.image = [UIImage imageNamed:#"green_badge"];
}
else if (sightsVisited.count == 0) {
NSLog(#"new_badge");
cell.notifyIV.image = [UIImage imageNamed:#"new_badge"];
}
else
{
cell.notifyIV.image = nil;
}
}
else {
cell.notifyIV.hidden = YES;
// cell.textLabel.textColor = RGB(0, 50, 140);
cell.detailTextLabel.hidden = YES;
cell.sightsTextLabel.text = nil;
}
return cell;
}
Cell set up in storyboard,
// TourGridCell.h
#import <UIKit/UIKit.h>
#interface TourGridCell : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UILabel *titleLabel;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UIImageView *notifyIV;
#property (weak, nonatomic) IBOutlet UILabel *textLabel;
#property (weak, nonatomic) IBOutlet UILabel *detailTextLabel;
#property (weak, nonatomic) IBOutlet UILabel *sightsTextLabel;
#end
#import "TourGridCell.h"
#implementation TourGridCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
you may need to provide some more data for it to be possible for others to work out what the problem is. I take it you have checked that at the different times this is called the conditions are being triggered so different images are actually being instantiated and added to your UICollectionViewCell? Also I take it you are aware a UICollectionViewCell doesn't have an image property so you will need to add a property in it's subclass (if you want easy access to the view without the overhead of retrieving it using it's tag ID) and ensure the view is added as a subview ?
I think, given the symptoms you have described, such a problem can occur if you are not adding your sub-views to the UICollectionViewCell's contentView. Apple's collection views have all manner of optimisations to ensure high performance and only the subviews of the UICollectionViewCell's content view (which is itself a sub-view of UICollectionViewCell) will be consistently drawn as you expect.
Though based on what you have provided, I can't be definitive as to if this is the cause of the problem.
#implementation UICollectionViewCellSubView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_imageView = [[UIImageView alloc] initWithFrame:frame];
[self.contentView addSubview:_imageView];
}
return self;
}
- (void)prepareForReuse
{
[super prepareForReuse];
// ensure you do appropriate things
// here for when the cells are recycled
// ...
}
#end
Solution is to nullify image each time in cellForItemAtIndexPath:
cell.imageView.image = nil;
if you are doing custom drawing in your cell, you will need to inform the cell to 'redraw' itself when a cell has been 'reused'. This is perhaps easiest done by implementing the prepareForReuse method in your UICollectionViewCell subclass.
- (void)prepareForReuse {
[super prepareForReuse];
[self setNeedsDisplay];
}
Technically, we probably don't need to include [super prepareForReuse] as the documentation suggests 'The default implementation of this method does nothing'. However, it is good practice, and who knows if Apple will change the default implementation of prepareForReuse in the future.