web-dev-qa-db-ja.com

NSViewをすべてのNSViewsの前面に移動する方法

スーパービューがあり、2つのサブビューがあります。これらのサブビューは重複しています。

メニューからビューを選択するたびに、対応するビューが正面ビューになり、アクションを処理する必要があります。つまり、最前面のサブビューである必要があります。

acceptsFirstResponderはすべての作業をうまく辞任します。ただし、マウスダウンイベントは、設定された一番上のサブビューに送信されます。

よろしく、ダナ

32
Dhanaraj

これを実現するもう1つの方法は、もう少し明確で簡潔です。

[viewToBeMadeForemost removeFromSuperview];
[self addSubview:viewToBeMadeForemost positioned:NSWindowAbove relativeTo:nil];

このメソッドのドキュメントによれば、relativeTo:nilを使用すると、ビューはそのすべての兄弟の上(またはNSWindowBelowの下)に追加されます。

37
Adam Preble

別の方法は、NSViewのsortSubviewsUsingFunction:context:メソッドを使用して、好みに合わせて兄弟ビューのコレクションを並べ替えることです。たとえば、比較関数を定義します。

static NSComparisonResult myCustomViewAboveSiblingViewsComparator( NSView * view1, NSView * view2, void * context )
{    
    if ([view1 isKindOfClass:[MyCustomView class]])    
        return NSOrderedDescending;    
    else if ([view2 isKindOfClass:[MyCustomView class]])    
        return NSOrderedAscending;    

    return NSOrderedSame;
}

次に、カスタムビューがすべての兄弟ビューの上に留まるようにする場合は、次のメッセージをカスタムビューのスーパービューに送信します。

[[myCustomView superview] sortSubviewsUsingFunction:myCustomViewAboveSiblingViewsComparator context:NULL];

または、このコードをスーパービュー自体に移動し、代わりにメッセージsortSubviewsUsingFunction:context:selfに送信することもできます。

15
Dalmazio

同等のUIViewメソッドを模倣するSwift 4カテゴリで@Dalmazioの回答を使用すると、次のようになります。

extension NSView {

    func bringSubviewToFront(_ view: NSView) {
            var theView = view
            self.sortSubviews({(viewA,viewB,rawPointer) in
                let view = rawPointer?.load(as: NSView.self)

                switch view {
                case viewA:
                    return ComparisonResult.orderedDescending
                case viewB:
                    return ComparisonResult.orderedAscending
                default:
                    return ComparisonResult.orderedSame
                }
            }, context: &theView)
    }

}

したがって、subViewcontainerViewで前面に表示するには

containerView.bringSubviewToFront(subView)

ビューを削除して再度追加するソリューションとは異なり、これにより制約が変更されません。

6
Confused Vorlon

RemoveFromSuperViewを呼び出さずにこれを機能させることができました

// pop to top
[self addSubview:viewToBeMadeForemost positioned:NSWindowAbove relativeTo:nil];
4
user511037

ビューを再度追加するだけでこれを実現できます。別のインスタンスは作成されません。

[self addSubview:viewToBeMadeForemost];

このコード行が実行される前後のサブビューの数をログに記録できます。

1
Alfredo Campos

以下のコードは正常に動作するはずです。

    NSMutableArray *subvies = [NSMutableArray arrayWithArray:[self subviews]];//Get all subviews..

    [viewToBeMadeForemost retain]; //Retain the view to be made top view..

    [subvies removeObject:viewToBeMadeForemost];//remove it from array

    [subvies addObject:viewToBeMadeForemost];//add as last item

    [self setSubviews:subvies];//set the new array..
1
Dhanaraj

ビューを前面に移動するには、ビューをsubviews配列の最後の要素として配置する必要があります。これがSwift 3.0ソリューションです:

func bringChildToFrontWith(viewIdentifier: Int) {
    var subViewArray = self.subviews // Apple docs recommend copying subViews array before operating on it, as it "can be changed at any time"
    for ix in 0 ..< subViewArray.count {
        if let childView = subViewArray[ix] as? MyViewSubClass {
            if childView.myViewSubClassIdentifier == viewIdentifier {
                let topItem = subViewArray[ix];
                subViewArray.remove(at: ix)
                subViewArray.append(topItem)
                self.contentView.subviews = subViewArray
            }
        }
    }
}
0
Jason McClinsey