1

IB のインスペクターに似たレイアウトが必要です。複数の展開可能なセクションがあり、それらはすべてスクロールビューに含まれています。

拡張可能なセクションが 1 つだけ必要な場合、私はすでにそこにいます: 拡張可能なセクションを NSBox に配置し、ボックスとその上のすべてのものに上部支柱を付けますが、下部支柱はありません。ストラット。次に、ボックスを表示/非表示にし、スクロールビューのドキュメント ビューのフレーム サイズを調整するように、開閉用三角形のアクションを設定します。

しかし、複数のボックスのストラットを設定する方法はないようです。開閉用三角形を閉じると隙間が残るか、ボックスが互いに重なり合っています。

私は NSOutlineView を見ましたが、それはテーブルです。コンボボックスやボタンなどのサブビューを持つことはできません。(または、カスタム セルを作成すれば、まだ行っていないことを実行できるかもしれませんが、それらはフル機能のレイアウトには適していないと思います。)

誰かが私を正しい方向に向けることができますか?

4

2 に答える 2

2

他の誰かがこの設計上の課題に遭遇した場合に備えて、思いついた IBAction を投稿します。

このスキームは、通常の反転されていないビューを使用します。つまり、原点は左下隅にあります。docSize を変更すると、上部にスペースが追加または削除されます。

単一の開示三角形の場合、一部のコントロールには上部ストラットが必要で、一部のコントロールには下部ストラットが必要ですが、このスキームでは、すべてのコントロールに上部ストラットと下部ストラットの両方が必要です。そうしないと、自動的に調整され、すべてが台無しになります。

最後に述べたように、一番下まで完全にスクロールすると、かなりの課題が伴います。しかし、それは別の章です…</p>

/**
 Action called upon clicking a disclosure triangle.
 Hides or discloses the box associated with the disclosure triangle.
 */
- (IBAction) discloseBox:(id)sender {

// Determine which box is governed by this disclosure triangle.
NSBox *boxTarget;
switch ([sender tag]) {
    case kDT_Source:
        boxTarget = self.boxSourceInfo;
        break;
    case kDT_Tweak:
        boxTarget = self.boxTweak;
        break;
    case kDT_Series:
        boxTarget = self.boxSeries;
        break;
    case kDT_Abbrevs:
        boxTarget = self.boxAbbreviations;
        break;
    case kDT_Flag:
        boxTarget = self.boxFlaggingAndComments;
        break;
    default:
        break;
}

// Get size info on the content with and without the box.
NSView *docView = [self.svEditorMain documentView];
NSSize docSize = [docView frame].size;
CGFloat fHeightChange = [boxTarget frame].size.height;

// Before actually changing the content size, record what point is currently at the top of the window.
CGFloat dropFromTop_preChange = [self getCurrentDropFromTop];

// If the state is now on, make the box visible.
// If the state is now off, hide the box and make the height change negative.
switch ([sender state]) {
    case NSOnState:
        [boxTarget setHidden:NO];
        break;
    case NSOffState:
        [boxTarget setHidden:YES];
        fHeightChange *= -1;
        break;
    default:
        break;
}
// Use the height change to prepare the adjusted docSize, but don't apply it yet.
NSSize adjustedDocSize = NSMakeSize(docSize.width, (docSize.height + fHeightChange));

// Make sure the adjustees array is populated.
[self populateVerticalAdjusteesArray];

// If the height change is positive, expand the content size before adjusting the origins, so that the origins will have space to move up into. (Space will be added at top.)
if (fHeightChange > 0)
    [docView setFrameSize:adjustedDocSize];

// Get the current, pre-change Y origin of the target box.
CGFloat boxOriginY_preChange = [boxTarget frame].origin.y;
// Loop through the adjustees, adjusting their height.
NSControl *control;
CGFloat originX;
CGFloat originY;

for (NSUInteger ui = 0; ui < [self.carrVerticalAdjustees count]; ++ui) {
    control = [self.carrVerticalAdjustees objectAtIndex:ui];
    originY = [control frame].origin.y;
    // Adjust all controls that are above the origin Y of the target box (but do nothing to the target box itself).
    // Since coordinate system places origin at lower left corner, higher numbers are higher controls.
    if (originY > boxOriginY_preChange) {
        originX = [control frame].origin.x; // get originX just so you can assemble a new NSPoint
        originY += fHeightChange; 
        [control setFrameOrigin:NSMakePoint(originX, originY)];
    }
    // Since the array was assembled in order from top down, once a member is encountered whose origin is below the target's, we're done.
    else 
        break;
}

// If the height change is negative, contract the content size only now, after the origins have all been safely adjusted downwards. (Space will be removed at top.)
if (fHeightChange < 0)
    [docView setFrameSize:adjustedDocSize];

// Left to its own devices, the scroller will maintain the old distance from the bottom, so whatever is under the cursor will jump up or down. To prevent this, scroll the content to maintain the old distance from the TOP, as recorded above.
// (This won't work if user is already scrolled to the bottom and then collapses a box. The only way to maintain the scroll position then would be to add blank space at the bottom, which would require moving  the origin of all the content up. And then you would want to reverse those changes as soon as the blank space scrolled back out of view, which would require adding some trackers and monitoring NSViewBoundsDidChangeNotification.)
[self scrollMainTo:dropFromTop_preChange];  

}

于 2011-03-25T13:40:19.093 に答える
0

InspectorKitをチェックしてください。ただし、Xcode 4 を使用している場合は、IBPlugins がサポートされなくなったため、コードで InspectorKit を使用する必要があることに注意してください (また、Interface Builder プラグインの便利なドラッグ アンド ドロップを使用しないでください)。

于 2011-03-23T16:14:58.823 に答える