OS X Cocoa Auto Layout жасырын элементтері

Мен жаңа Auto Layout a> Lion-де, өйткені бұл өте жақсы көрінеді. Бірақ мен қалай жасауға болатыны туралы жақсы ақпарат таба алмаймын. Мысалға:

Менің екі жапсырма бар:

+----------------+
| +------------+ |
| + label 1    | |
| +------------+ |
|                |
| +------------+ |
| | label 2    | |
| +------------+ |
+----------------+

бірақ алғашқы жапсырма әрдайым мазмұнмен толтырылмайды, кейде ол үшін ешқандай мазмұн жоқ. Маған не істеу керек, бұл жапсырманы автоматты түрде көрсету 2, онда 1 жапсырмасы мазмұн болған кезде болады.

+----------------+
| +------------+ |
| + label 2    | |
| +------------+ |
|                |
|                |
|                |
|                |
+----------------+

Автокөлікпен автоматты түрде жұмыс істеу үшін қандай шектеулер қосылуға тура келеді? Мен барлық нәрселерді кодтайтынымды түсінемін, бірақ менің шамамен 30-ға жуық осындай жапсырмалар мен суреттер мен әртүрлі стильдер мен пішіндердің батырмалары бар, олардың бәрі қосымша болып табылады және мен автоматты түрде өте жақсы жұмыс істей алатын кезде код желілерін қосқым келмейді .

Егер ол жұмыс істемесе, онда мен WebView-ді ғана қолданамын және оны HTML және CSS-мен жасаймын.

29
Кесте тек қана төменнен жоғары болса, көмектеседі, бірақ кейбір заттар солдан оңға қарай және басқалардың және заттардың орнын алуға тиіс. Бірақ идея жаман емес деп санаймын.
қосылды автор Jeena, көзі
Мен автоматты түрде орналасу мүмкіндігі бар-жоғын білмеймін, бірақ шын мәнінде кесте болып табылатын нәрсе сияқты көрінеді.
қосылды автор user557219, көзі

8 жауаптар

Бұл автоматты түрде орналасу мүмкіндігі бар, бірақ ол жақсы түрде таралмайды.

Мысалға, мысалы, А белгісін және B белгісін (немесе түймені немесе шын мәнінде кез келген нәрсені) атап өтіңіз. Алдымен A үшін шолудың жоғарғы шектеуін қосу арқылы бастаңыз. Сонда A және B арасындағы тік аралық шектеулер. Бұл қалыпты жағдай. Егер сіз А нүктесін осы кезде алып тастасаңыз, онда B белгісіз орналасуы болады. Егер сіз оны жасырып тастасаңыз, ол әлі де этикеткалар арасындағы бос орынды қамтитын кеңістікке ие болады.

Содан кейін B-дан басқа шегінуді үстіңгі қатардың жоғарғы жағына қосу керек. Басымдықты басқаларға қарағанда төмен деп өзгертіңіз (900 деп айтыңыз), содан кейін оны тұрақты (немесе басқа да кіші мән) стандартты етіп орнатыңыз. Енді, A-ны қарап шығудан алшақтаған кезде, төменгі басымдылыққа шектеу басталады және B-ні жоғарғы жағына қарай тартып шығарады. Қиындықтар келесідей көрінеді:

Interface Builder screenshot

Мәселе сізге жапсырмалардың ұзын тізімімен жасауға тырысқанда келеді.

24
қосылды
Бұл ұсынылған іс үшін таза шешім. Көптеген этикеткалар үшін бұл кодты көбейту оңай. IB «жақын көршімізге» сілтеме жасаған кезде, «Жаңа шектеу қосу» редакторында қалқымалы терезедегі шешімді ұсынады. Егер бұл шынында да болса, ол қораптан шығатын еді. Менің ойымша, бұл мәселе олар өте ерте («неигбор»), және сіз мұны форматындағы форматында көре аласыз.
қосылды автор Chris Conover, көзі
Бұл жұмыстың екінші бөлігі қалай? Егер B-дан басқа шектеуді қоссаңыз, ол басымдыққа қарамастан әрдайым іске қосылмайды ма?
қосылды автор kevinl, көзі
nevermind, мен бұл нақты логиканы жұмыс істемей тұрған сценарийде қолдануға тырыстым: Менде A, B, C батырмалары бар. Мен B-ні алып тастаймын және C-ді орындауға келеді.
қосылды автор kevinl, көзі

UILabel ішкі сыныбын жасыру

Бір қарапайым шешім UILabel-нің тек қана субклассы және ішкі мазмұнын өзгерту болып табылады.

@implementation WBSCollapsingLabel

- (CGSize)intrinsicContentSize
{
    if (self.isHidden) {
        return CGSizeMake(UIViewNoIntrinsicMetric, 0.0f);
    } else {
        return [super intrinsicContentSize];
    }
}

- (void)setHidden:(BOOL)hidden
{
    [super setHidden:hidden];

    [self updateConstraintsIfNeeded];
    [self layoutIfNeeded];
}

@end
10
қосылды
Жақсы ... үлкен сұрақ. Жалпы айтқанда, автоматты түрде орналасу тақырыбы SO-де жақсы қамтылмаған. Мен сондай-ақ, көптеген адамдар жай ғана шектеулерге шығып, биіктіктен айырылғанын ойлаймын. Кіші сыныптар да аздап тітіркендіреді.
қосылды автор Cameron Lowell Palmer, көзі
Жағдайда H: | - (8) - [view1] - (12) - [hidden1] - (8) - | Иә ... Сіз дұрыссыз, бірақ бұл кадрлармен болғанда бірдей мәселе. Көру арасындағы аралықтың орындалуын қамтамасыз етуіңіз керек, бірақ бұл бөлек мәселе!
қосылды автор Cameron Lowell Palmer, көзі
Бұл тәсілмен мәселе, ол әдетте сіздің көзқарастарыңыздың айналасында орналасқан шегін ескермейді.
қосылды автор tcurdt, көзі
updateConstraintsForSubtreeIfNeeded үшін NSViewNoInstrinsicMetric , updateConstraintsIfNeeded дегенге UIViewNoIntrinsicMetric дегенді қосыңыз, және layoutIfNeeded дегенге арналған layoutSubtreeIfNeeded және ол шебер сияқты жұмыс істейді. Рақмет сізге!
қосылды автор bithavoc, көзі
Бұл шын мәнінде қарапайым, талғампаздық жолына ұқсайды. Мен шын мәнінде жұмыс істейтін болса, неге ол жоғары дауыс берілмегенін білемін?
қосылды автор software evolved, көзі

Бұл санат автоматты түрде орналасуды шектеулі көріністерді шынымен жеңілдейді:

https://github.com/depth42/AutolayoutExtensions

Мен оны жобаға қосып, жақсы жұмыс істедім.

4
қосылды
Мен бұл жобаны менің жобамда қолдануға тырысамын, бірақ менің жаңа координатым PWHidingMasterView менің жобамдағы көріністер үшін Xcodeде пайда болмайды. Үлгі жобаны ашқан кезде, розетка бар. Мен жобадан және үлгісінен өзгеше екенін біле алмаймын. Кез келген кеңестер?
қосылды автор Ricardo Sanchez-Saez, көзі

Мен мұны осылай жасай алатын деп ойлаймын. Егер сіз 2-белгіге арналған орналасуды жапсырма 1-ден қашықтықтан шектеуге негізделсе де, 1 мазмұнға ие болмаған кезде нөлдік биіктікке авто-тасалауды жапсырған болсаңыз да, 2 белгісі сол қашықтықты төмендетеді, яғни:

+----------------+
| +------------+ |
| + label 1    | |
| +------------+ |
|        ^       |
|        ^       !
| +------------+ |
| | label 2    | |
| +------------+ |
+----------------+

Autolayout distance қашықтығы қайда? - Егер 1-белгі 1 жолдың бос болғанда нөлдік биіктікке айналуды білсе, сіз әлі де аласың:

+----------------+
| +------------+ |
|        ^       |
|        ^       !
| +------------+ |
| | label 2    | |
| +------------+ |
+----------------+

Maybe it is possible by creating your NSLayoutConstraint manually. You could make the second attribute be the height of label 1, make the constant zero, and then carefully work out what the multiplier would be to make the distance be what you want based on a multiple of the non-zero label height.

Бірақ мұның бәрін жасай отырып, автоматты түрде автоматты түрде өлшенген NSLabel субклассы кодталған, көрнекі тілдің орнына шектеу нысанын қолмен жасаған және NSLayoutConstraint өз қалауынан тыс жерде орналасқан.

Егер жапсырма 1 жолы бос болса, 2 жапсырмасының рамкасын өзгертіп, жақсы боларсыз деп ойлаймын!

2
қосылды
0-ге тұрақты орнатусыз интерфейстің құрастырушысында кез-келген тікелей опция бар ма?
қосылды автор user2223516, көзі

Міне, интерфейстің құрастырушысын емес, бұл бағдарламаны қалай өңдегенімді мысалға келтіремін. Қысқаша; Мен қосылсам, көрініс қосылады, содан кейін мен бармаған кезде тік шектеулерді қосып, субвидео бойынша қайталанады.

Қарастырылып отырған пікірлер осы уақытқа дейін инициализацияланғанын ескеріңіз.

/*
  Begin Auto Layout
*/
NSMutableArray *constraints = [NSMutableArray array];
NSMutableDictionary *views = [[NSMutableDictionary alloc] init];


/*
  Label One
*/
if (enableLabelOne) {
    [contentView addSubview:self.labelOne];

    self.labelOne.translatesAutoresizingMaskIntoConstraints = NO;

    [views setObject:self.labelOne
              forKey:@"_labelOne"];

    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_labelOne(44)]"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:views]];

    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_labelOne]-|"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:views]];
}

/*
    Label Two
*/
if (enableLabelTwo) {
    [contentView addSubview:self.labelTwo];

    self.labelTwo.translatesAutoresizingMaskIntoConstraints = NO;

    [views setObject:self.labelTwo
              forKey:@"_labelTwo"];

    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_labelTwo(44)]"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:views]];
}

[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_labelTwo]-|"
                                                                         options:0
                                                                         metrics:nil
                                                                           views:views]];

/*
  Dynamically add vertical spacing constraints to subviews
*/
NSArray *subviews = [contentView subviews];

if ([subviews count] > 0) {
    UIView *firstView = [subviews objectAtIndex:0];
    UIView *secondView = nil;
    UIView *lastView = [subviews lastObject];

    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[firstView]"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:NSDictionaryOfVariableBindings(firstView)]];

    for (int i = 1; i < [subviews count]; i++) {
        secondView = [subviews objectAtIndex:i];
        [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[firstView]-10-[secondView]"
                                                                                 options:0
                                                                                 metrics:nil
                                                                                   views:NSDictionaryOfVariableBindings(firstView, secondView)]];
        firstView = secondView;
    }

    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[lastView]-|"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:NSDictionaryOfVariableBindings(lastView)]];
}


[self addConstraints:constraints];

Мен тек lastView шектеуін орнатамын, себебі бұл код UIScrollView ішіндегі нәрсеге бейімделді.

Мен оны бастапқыда бұл Stack Overflow жауапына сүйеніп, өзімнің қажеттіліктеріме сай өзгертті.

1
қосылды

Мен де мұны жақсы жағынан көрдім. Давидтің бөліміне ұқсас. Міне, ол кодта жұмыс істейді. Мен жалпы шолуды және оның барлық субвидеоларын, тіпті әрқашан көрсетіле алмайтындарды жасағанмын. Мен «code: V: | - [_ btn] сияқты көптеген шектеулерді қосылдым. Осы шектеудің соңында көріп тұрғандай, шолудың төменгі жағында сілтеме жоқ. Содан кейін екі көзқарас үшін екі шектеулі массивтерді жасадым, ал мен үшін айырмашылық «Қосымша параметрлер» үшбұрышының ашылуы болып табылады. Содан кейін үшбұрыштың күйіне байланысты басылғанда, мен шектеу мен субвойларды алып тастаймын. Мысалы, мынаны қосқым келеді:

[self.backgroundView removeConstraints:self.lessOptionsConstraints];
[self.backgroundView addSubview:self.nameField];
[self.backgroundView addConstraints:self.moreOptionsConstraints];

Мен алып тастаған шектеулер, V: [_ btn] - | секілді түйіннің төменгі жағындағы түймені байланыстырды. Мен қосқан шектеулер V: [_ btn] - [_ nameField] - | сияқты көрінеді, себебі бұл шектеу жаңа көріністі оның үстіндегі түпнұсқа көрінісі мен төменгі сюжетдің биіктігі.

0
қосылды

Бұл мәселені жүйелі түрде шешіңіз. Менде бірқатар бірнеше түймешіктер бар, және мен кез-келген уақытта оларды жасыруды шешуі мүмкін.

enter image description here

Пайдаланылатын Картография олардың кез-келгеніне hidden өзгерген сайын оларды ауыстыру үшін.

let buttons = self.buttons!.filter { button in
    return !button.hidden
}

constrain(buttons, replace: self.constraintGroup) { buttons in
    let superview = buttons.first!.superview!

    buttons.first!.left == superview.left

    for var i = 1; i < buttons.count; i++ {
        buttons[i].left == buttons[i-1].right + 10
    }

    buttons.last!.right == superview.right
}
0
қосылды

Мен мұны тағы бір жол таптым. Бұл әдіс кез келген жерде қолданылуы мүмкін, масштабтау проблемалары жоқ; және шеттерін де өңдейді. Және сіз үшін 3-ші партиялық заттардың қажеті жоқ.

Алдымен, осы орналасуды қолданбаңыз:

V:|-?-[Label1]-10-[Label2]-10-|
H:|-?-[Label1]-?-|
H:|-20-[Label2]-20-|

Оны орнына пайдаланыңыз:

("|" is the real (outer) container)
V:|-?-[Label1]-0-[Label2HideableMarginContainer]-0-|
H:|-?-[Label1]-?-|
H:|-0-[Label2HideableMarginContainer]-0-|

("|" is Label2HideableMarginContainer)
V:|-10-[Label2]-10-|
H:|-20-[Label2]-20-|

Енді біз не істедік? Label2 орналасу кезінде тікелей қолданылмайды; ол Margin-Container ішіне орналастырылған. Бұл контейнер Label2 proxy ретінде пайдаланылады, орналасудағы 0 шеттерімен. Нақты шеттер Margin-Container ішінен ішіне қойылады.

Енді біз Label2 -ті жасыра аламыз:

  • Жасырын параметрін YES параметріне орнату

ЖӘНЕ

  • Disabling the Top, Bottom, Leading ЖӘНЕ Trailing constraints. So seek them out, than set Active to NO on them. This will cause the Margin-Container to have a Frame Size of (0,0); because it does have subview(s); but there aren't any (active) layout constraints which anchors those subviews to it.

Maybe a bit complex, but you only have to develop it once. All the logic can be put into a separate place, ЖӘНЕ be reused every time you need to hide smg.

Міне, C# Xamarin коды Margin-Container көрінісінің ішкі жиектеріне ішкі көріністі (суреттерді) анкерлейтін шектеулерді қалай іздеу керек:

public List SubConstraints { get; private set; }

private void ReadSubContraints()
{
    var constraints = View.Constraints;//View: the Margin-Container NSView
    if(constraints?.Any() ?? false)
    {
        SubConstraints = constraints.Where((NSLayoutConstraint c) => {
            var predicate = 
                c.FirstAttribute == NSLayoutAttribute.Top ||
                c.FirstAttribute == NSLayoutAttribute.Bottom ||
                c.FirstAttribute == NSLayoutAttribute.Leading ||
                c.FirstAttribute == NSLayoutAttribute.Trailing;
            predicate &= ViewЖӘНЕSubviews.Contains(c.FirstItem);//ViewЖӘНЕSubviews: The View ЖӘНЕ View.Subviews
            predicate &= ViewЖӘНЕSubviews.Contains(c.SecondItem);
            return predicate;
        }).ToList();
    }
}
0
қосылды