다음과 같은 사용자 지정 뒤로 버튼을 설정하는 iOS 7 앱이 있습니다.
UIImage *backButtonImage = [UIImage imageNamed:@"back-button"];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setImage:backButtonImage forState:UIControlStateNormal];
backButton.frame = CGRectMake(0, 0, 20, 20);
[backButton addTarget:self
action:@selector(popViewController)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
viewController.navigationItem.leftBarButtonItem = backBarButtonItem;
그러나 이렇게하면 iOS 7 “왼쪽에서 오른쪽으로 스 와이프”동작이 비활성화되어 이전 컨트롤러로 이동합니다. 사용자 정의 버튼을 설정하고이 제스처를 계속 활성화 할 수있는 방법을 아는 사람이 있습니까?
편집 : 대신 viewController.navigationItem.backBarButtonItem을 설정하려고했지만 내 사용자 지정 이미지가 표시되지 않는 것 같습니다.
답변
중요 :
이것은 해킹입니다. 이 답변을 살펴 보는 것이 좋습니다 .
leftBarButtonItem
나를 위해 일한 것을 할당 한 후 다음 라인을 호출하십시오 .
self.navigationController.interactivePopGestureRecognizer.delegate = self;
편집 :init
메서드
에서 호출하면 작동하지 않습니다 . in viewDidLoad
또는 유사한 메서드를 호출해야합니다 .
답변
가능한 경우 UINavigationBar의 backIndicatorImage 및 backIndicatorTransitionMaskImage 속성을 사용합니다. UIAppearanceProxy에서이를 설정하면 애플리케이션에서 동작을 쉽게 수정할 수 있습니다. 주름은 ios 7에서만 설정할 수 있지만 어쨌든 ios 7에서만 팝 제스처를 사용할 수 있기 때문에 효과가 있습니다. 일반적인 iOS 6 스타일은 그대로 유지할 수 있습니다.
UINavigationBar* appearanceNavigationBar = [UINavigationBar appearance];
//the appearanceProxy returns NO, so ask the class directly
if ([[UINavigationBar class] instancesRespondToSelector:@selector(setBackIndicatorImage:)])
{
appearanceNavigationBar.backIndicatorImage = [UIImage imageNamed:@"back"];
appearanceNavigationBar.backIndicatorTransitionMaskImage = [UIImage imageNamed:@"back"];
//sets back button color
appearanceNavigationBar.tintColor = [UIColor whiteColor];
}else{
//do ios 6 customization
}
interactivePopGestureRecognizer의 델리게이트를 조작하려고하면 많은 문제가 발생합니다.
답변
UINavigationController를 하위 클래스로 만드는 이 솔루션 http://keighl.com/post/ios7-interactive-pop-gesture-custom-back-button/ 을 보았습니다 . 컨트롤러가 제자리에 놓이기 전에 스 와이프하는 경우를 처리하므로 더 나은 솔루션으로 충돌이 발생합니다.
이 외에도 루트 뷰 컨트롤러에서 스 와이프를 수행하면 (하나를 누른 후 다시 뒤로) UI가 응답하지 않는 것으로 나타났습니다 (위의 답변에서도 동일한 문제).
따라서 서브 클래 싱 된 UINavigationController의 코드는 다음과 같아야합니다.
@implementation NavigationController
- (void)viewDidLoad {
[super viewDidLoad];
__weak NavigationController *weakSelf = self;
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.delegate = weakSelf;
self.delegate = weakSelf;
}
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
// Hijack the push method to disable the gesture
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.interactivePopGestureRecognizer.enabled = NO;
}
[super pushViewController:viewController animated:animated];
}
#pragma mark - UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animate {
// Enable the gesture again once the new controller is shown
self.interactivePopGestureRecognizer.enabled = ([self respondsToSelector:@selector(interactivePopGestureRecognizer)] && [self.viewControllers count] > 1);
}
@end
답변
나는 사용한다
[[UINavigationBar appearance] setBackIndicatorImage:[UIImage imageNamed:@"nav_back.png"]];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"nav_back.png"]];
[UIBarButtonItem.appearance setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -64) forBarMetrics:UIBarMetricsDefault];
답변
또한 뒤로 버튼을 숨기고 사용자 정의 leftBarItem으로 바꿉니다.
푸시 작업 후 interactivePopGestureRecognizer 대리자를 제거하면 나를 위해 일했습니다.
[self.navigationController pushViewController:vcToPush animated:YES];
// Enabling iOS 7 screen-edge-pan-gesture for pop action
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
답변
navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
이것은 http://stuartkhall.com/posts/ios-7-development-tips-tricks-hacks 에서 왔지만 몇 가지 버그가 발생합니다.
- 화면의 왼쪽 가장자리에서 스 와이프 할 때 다른 viewController를 navigationController에 밀어 넣습니다.
- 또는 topViewController가 navigationController에서 팝업 될 때 화면의 왼쪽 가장자리에서 안으로 스 와이프합니다.
예를 들어 navigationController의 rootViewController가 표시되면 화면 왼쪽 가장자리에서 안쪽으로 스 와이프하고 무언가를 탭 (빠르게)하여 다른 ViewController를 navigationController로 푸시 한 다음
- rootViewController는 터치 이벤트에 응답하지 않습니다.
- anotherViewController는 표시되지 않습니다.
- 화면 가장자리에서 다시 스 와이프하면 anotherViewController가 표시됩니다.
- 사용자 정의 뒤로 버튼을 탭하여 anotherViewController를 팝업하고 충돌합니다!
따라서 다음 과 같이 UIGestureRecognizerDelegate
메소드를 구현해야합니다 self.navigationController.interactivePopGestureRecognizer.delegate
.
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer == navigationController.interactivePopGestureRecognizer) {
return !navigationController.<#TODO: isPushAnimating#> && [navigationController.viewControllers count] > 1;
}
return YES;
}
답변
다음은 Nick H247의 답변의 swift3 버전입니다.
class NavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
if responds(to: #selector(getter: interactivePopGestureRecognizer)) {
interactivePopGestureRecognizer?.delegate = self
delegate = self
}
}
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
if responds(to: #selector(getter: interactivePopGestureRecognizer)) {
interactivePopGestureRecognizer?.isEnabled = false
}
super.pushViewController(viewController, animated: animated)
}
}
extension NavigationController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
interactivePopGestureRecognizer?.isEnabled = (responds(to: #selector(getter: interactivePopGestureRecognizer)) && viewControllers.count > 1)
}
}
extension NavigationController: UIGestureRecognizerDelegate {}