我有NSScrollview
嵌套在另一个NSScrollview
内。如何使内部视图仅处理水平滚动?垂直滚动应移动外部视图。
目前我将scrollWheel:
事件从内部视图传递到外部视图,但速度非常慢。
答案 0 :(得分:6)
我也遇到了嵌套滚动视图的问题。内部滚动视图应水平滚动,外部应垂直滚动。
当处理来自魔术鼠标/触控板的滚动事件时,为每个手势选择一个滚动视图非常重要,否则当手指不能完全笔直移动时,您会看到奇怪的抖动。您还应该确保用两个手指点击触控板显示两个滚动条。
当处理来自强大鼠标或具有旧式滚轮的鼠标的传统滚动事件时,您必须为每个事件选择正确的滚动视图,因为事件中没有手势阶段信息。
这是我的内部滚动视图的子类,仅在Mountain Lion中进行测试:
@interface PGEHorizontalScrollView : NSScrollView {
BOOL currentScrollIsHorizontal;
}
@end
@implementation PGEHorizontalScrollView
-(void)scrollWheel:(NSEvent *)theEvent {
/* Ensure that both scrollbars are flashed when the user taps trackpad with two fingers */
if (theEvent.phase==NSEventPhaseMayBegin) {
[super scrollWheel:theEvent];
[[self nextResponder] scrollWheel:theEvent];
return;
}
/* Check the scroll direction only at the beginning of a gesture for modern scrolling devices */
/* Check every event for legacy scrolling devices */
if (theEvent.phase == NSEventPhaseBegan || (theEvent.phase==NSEventPhaseNone && theEvent.momentumPhase==NSEventPhaseNone)) {
currentScrollIsHorizontal = fabs(theEvent.scrollingDeltaX) > fabs(theEvent.scrollingDeltaY);
}
if ( currentScrollIsHorizontal ) {
[super scrollWheel:theEvent];
} else {
[[self nextResponder] scrollWheel:theEvent];
}
}
@end
我的实现并不总是正确地转发手势取消事件,但至少在10.8中这不会导致问题。
答案 1 :(得分:1)
这是我的NSScrollView的子类,可以满足您的要求。由于它只是传递事件,它不关心响应者链,它应该是高效的,好像它不是一个子类(或至少接近)
h file
#import <Cocoa/Cocoa.h>
@interface HorizontalScrollView : NSScrollView
@end
和m
@implementation HorizontalScrollView
- (void)scrollWheel:(NSEvent *)theEvent {
NSLog(@"%@", theEvent);
if(theEvent.deltaX !=0)
[super scrollWheel:theEvent];
else
[[self nextResponder] scrollWheel:theEvent];
}
@end
答案 2 :(得分:0)
快速4。
答案是Jakob上面的出色回答的翻译,其中添加了方向标记。
正如他在回答中的评论中所述,如果操作不正确,可能会产生一些细微的并发症。当简单地将所有scrollWheel()调用转发给下一个响应者时,我看到NSTrackingAreas无法正确更新以及NSTextView视图上的工具提示和光标样式未对齐的问题。
class ECGuidedScrollView: NSScrollView
{
enum ScrollDirection {
case vertical
case horizontal
}
private var currentScrollMatches: Bool = false
private var scrollDirection: ScrollDirection
init(withDirection direction: ScrollDirection) {
scrollDirection = direction
super.init(frame: NSRect.zero)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func scrollWheel(with event: NSEvent)
{
// Ensure that both scrollbars are flashed when the user taps trackpad with two fingers
if event.phase == .mayBegin {
super.scrollWheel(with: event)
nextResponder?.scrollWheel(with: event)
return
}
/*
Check the scroll direction only at the beginning of a gesture for modern scrolling devices
Check every event for legacy scrolling devices
*/
if event.phase == .began || (event.phase == [] && event.momentumPhase == [])
{
switch scrollDirection {
case .vertical:
currentScrollMatches = fabs(event.scrollingDeltaY) > fabs(event.scrollingDeltaX)
case .horizontal:
currentScrollMatches = fabs(event.scrollingDeltaX) > fabs(event.scrollingDeltaY)
}
}
if currentScrollMatches {
super.scrollWheel(with: event)
} else {
self.nextResponder?.scrollWheel(with: event)
}
}
}