Эквивалент iOS для Android View.GONE режим видимости


79

Я разрабатываю приложение для iOS, и я использую Storyboard с включенным AutoLayout. Один из моих контроллеров представления имеет набор из 4 кнопок, и в определенных обстоятельствах я бы хотел, чтобы первая исчезла.

Если я использую этот setHidden:TRUEметод, UIButton становится невидимым, но очевидно, что он занимает место в представлении, и в результате возникает «дыра», которую я не смог заполнить, заставляя оставшуюся UIButton плавать в верхней части основного представления.

В Android я бы просто использовал View.GONEвместо View.INVISIBLE, но в iOS я застрял с таким поведением, и я не хочу верить, что единственное решение - вручную (да, я имею в виду программно) переместить оставшиеся элементы вверх.

Я думал, что смогу сделать это, установив какое-то ограничение, чтобы сделать все таким же автоматическим, как в Android, но мне не повезло.

Может ли кто-нибудь указать мне правильное направление, прежде чем я выключу автопрокладку?

Я использую IB, но мне также нравится программировать.

ОБНОВИТЬ:

Установка высоты компонента на 0 тоже не помогает.

Я пробовал примерно так:

UIButton *b;
CGRect frameRect = b.frame;
frameRect.size.height = 0;
b.frame = frameRect;

Как насчет того, чтобы установить высоту кнопки на ноль?
cahn

Я пробовал примерно так: UIButton * b; CGRect frameRect = b.frame; frameRect.size.height = 0; b.frame = frameRect; Не повезло :(
elbuild

Я знаю, что это очень старый вопрос, но в отношении вашего обновления установка фрейма на 0 не поможет, если вы используете автоматическое размещение. Вы должны установить ограничение высоты
равным

Ответы:


40

Добавление ограничения (NSLayoutAttributeHeight), которое устанавливает высоту представления равным 0, сработало для меня:

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.captchaView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0]];

11
Быстрая версия:self.view.addConstraint(NSLayoutConstraint(item: self.captchaView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 0))
iStar

1
Это должен был быть ответ
Рик Ройд Абан

2
Что делать, если я не знаю фактической высоты желаемого вида (например, вид контейнера, отображаемый немного позже)?
А. Петров

Большое спасибо за отличный ответ! Кому-то может понадобиться. У меня ошибка Unable to simultaneously satisfy constraints. в то время как у меня уже были ограничения для просмотра. Я решаю это с помощью stackoverflow.com/a/38625419/1270901
Невин Чен

@iStar Я использовал тот же код, но он не работает ... stackoverflow.com/questions/45454992/…
Санджай Мангаролия 02

20

Все ответы на этот вопрос неэффективны. Лучший способ использовать метод setVisibility: Gone для Android в iOS - этоStackView сначала выбрать компоненты, затем в редакторе, встроить, просмотреть стек,

подключите новое представление стека с IBOutlet, затем:

скрыто:

UIView * firstView = self.svViewFontConfigure.arrangedSubviews[0];
        firstView.hidden = YES;

видимость:

UIView * firstView = self.svViewFontConfigure.arrangedSubviews[0];
        firstView.hidden = NO;

при использовании представления стека все ограничения будут сохранены!

Документ


На самом деле это действительно хорошее решение, но стоит отметить, что для него требуется iOS9 +.
user3533716

Я использовал ваше блестящее решение (+1 за вас, большое спасибо !!), но я подключил через IBOutlet напрямую представление, которое я хотел показать и скрыть, поэтому мне нужно набрать только одну строку кода! :)
Cristina De Rito

1
На самом деле это неверный ответ. Android View.GONE удаляет представление в пользовательском интерфейсе. Например, если вы установите View.GONE элемент, представления под этим видом будут сдвигаться вверх. Таким образом, ваше предложение просто скрывает представление, равное View.HIDE. Посмотрите на этот ответ: stackoverflow.com/questions/11556607/…
emin deniz

Я не искал на android api ... Но я мобильный разработчик, поэтому знаю механику ... В Android с логическим флагом вид может быть видимым или нет (Gone, Visible) Если он удаляется из пользовательского интерфейса, будет трудно добавьте еще раз ... но в ios, это в макете, но без пробелов .... Более того, есть официальное скрытое свойство ios, которое имеет место ... Скрытое свойство UIStackview,
такое

16

добавьте ограничение высоты для вашего представления следующим образом:введите описание изображения здесь

затем сделайте выход для ограничения высоты в вашем файле viewController следующим образом:введите описание изображения здесь

& затем в вашем методе viewDidLoad измените высоту ограничения на 0 следующим образом:

override func viewDidLoad() {
    super.viewDidLoad()
nsLcButtonHeight.constant = 0
}

1
постоянная высота отстой, я использую равную высоту и множитель, например, чтобы взять 25% родительского представления, любой пример для этого?
user924

8

Для достижения функциональности Androids.GONE на iOS необходимо использовать UIStackView. После этого спрячьте ребенка по положению. ( Документация по яблокам )

SWIFT 4:

let firstView = cell.rootStackView.arrangedSubviews[0]
    firstView.isHidden = true // first view gone

Это пример ячейки таблицы, просто поместите обе внутренности Stack viewи получите предмет для GONEребенка.

введите описание изображения здесь


6

Что вы можете сделать, так это сгруппировать свои представления в виде стека. Затем, когда вы скрываете определенный вид, остальные виды будут автоматически сдвинуты, чтобы заполнить пространство.

Вы можете проверить документацию Apple по просмотрам стека: https://developer.apple.com/reference/uikit/uistackview

или онлайн-руководства, такие как: https://www.appcoda.com/stack-views-intro/


1

1) Если ваши кнопки расположены вертикально, вы должны установить heightзначение 0, а в случае горизонтального расположения кнопок попробуйте установитьwidth значение 0 или вы можете установить оба значения в 0.

ИЛИ ЖЕ

2) вы можете попробовать этот подход, который устанавливает button2поверх button1:

- (void)viewDidLoad
{
[super viewDidLoad];

UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button1 setTitle:@"hello" forState:UIControlStateNormal];

UIButton *button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button2 setTitle:@"world" forState:UIControlStateNormal];

[button1 sizeToFit]; [button2 sizeToFit];
[button2 setFrame:CGRectMake(button1.frame.origin.x, button1.frame.origin.y, button2.frame.size.width, button2.frame.size.height)];

[self.view addSubview:button1];
[self.view addSubview:button2];

}


1

Этот вопрос довольно старый, но я обнаружил, что в шкафу устанавливаются дополнительные ограничения (так что представления вокруг "пропавшего" представления знают, что делать, если оно отсутствует)

A  which you want to be     A
|  after setting B to gone  |
B                           C
|                               
C                               
  1. Установите ограничение с более низким приоритетом (750) с C на A.
  2. Добавьте верхние и нижние ограничения B (или слева и справа, если вы хотите, чтобы ваше представление свернулось по горизонтали) в массив NSLayoutConstraint bConstraints . Сделайте это:
    1. Щелкните элемент управления и перетащите от ограничения к ViewController
    2. Изменить соединение с розетки на розетку.
    3. Ибо имя поставлю bConstraints.
    4. Нажмите "Подключиться". Это создаст @IBOutlet var bConstraints: [NSLayoutConstraint]!в вашем ViewController
    5. Чтобы добавить дополнительные ограничения: перетащите от ограничения в Storyboard к имени переменной @IBOutlet
  3. Затем спрячьте B

    B.hidden = true
    NSLayoutConstraint.deactivateConstraints(bConstraints)
    
  4. Показать

    B.hidden = false
    NSLayoutConstraint.activateConstraints(bConstraints)
    

Очевидно, что чем больше и больше у вас представлений, тем сложнее это становится, так как вам нужны дополнительные ограничения для каждого представления.


было бы более полезно, если бы вы объяснили, почему вы не можете реализовать
wyu

Второй момент. Но я работаю в Xamarin. До сих пор не нашел решения этой проблемы. Не знаю, как построить массив NSLayoutConstraint с ограничениями B. Я предполагаю, что это делается программно, было бы неплохо увидеть код для этого. Мне кажется, что ваш метод является наиболее разумным способом решения этой проблемы, однако его нелегко реализовать с помощью простого псевдокода
Густаво Байокки Коста

Я не использовал Xamarin. В XCode это делается следующим образом: щелкните, удерживая клавишу Ctrl, и перетащите от ограничения к ViewController (это похоже на то, как вы создаете IBOutlet в xcode). В появившемся всплывающем окне (похоже на i.stack.imgur.com/JegLK.png ) измените раскрывающееся меню «Соединение» с Outletна Outlet Collection. Для дополнительных ограничений перетащите ctrl прямо к имени переменной. Я могу загрузить снимки позже сегодня (примерно через 8 часов)
вю,

поэтому массив NSLayoutConstraint - это коллекция выходов, здесь немного потерялись, ха-ха,
спасибо, что нашли

да, я обновлю ответ, чтобы он был более понятным. Итак, решение работает для вас?
wyu

0

Как показали мои исследования, даже AutoLayout не может вам помочь. Вы должны вручную заменить представления, на которые влияет необязательный показанный компонент (в моем случае, все представления в нижней части необязательного представления, но вы, я уверен, вы можете адаптировать это для обработки всех кнопок справа от необязательной кнопки ):

- (IBAction)toggleOptionalView:(id)sender {
    if (!_expanded) {
        self.optionalView.frame = CGRectMake(self.optionalView.frame.origin.x, self.optionalView.frame.origin.y, self.optionalView.frame.size.width, _optionalHeight);
        self.bottomView.frame = CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y+_optionalHeight, self.bottomView.frame.size.width, self.bottomView.frame.size.height);
        _expanded = YES;
    } else {
        self.optionalView.frame = CGRectMake(self.optionalView.frame.origin.x, self.optionalView.frame.origin.y, self.optionalView.frame.size.width, 0);
        self.bottomView.frame = CGRectMake(self.bottomView.frame.origin.x, self.bottomView.frame.origin.y-_optionalHeight, self.bottomView.frame.size.width, self.bottomView.frame.size.height);
        _expanded = NO;

    }
}

Рекомендуется не указывать жестко высоту / ширину дополнительных компонентов, иначе ваш код ломается каждый раз, когда вы редактируете XIB / Storyboard. У меня есть поле float _optionalHeight, которое я установил в viewDidLoad, поэтому оно всегда актуально.


0

Вы также можете очистить страницу или, по крайней мере, определенные ячейки страницы и переопределить все это. Это быстро и хорошо работает. Я не писал код, но нашел его в уже существующем проекте, над которым я работаю. Создание ManagementTableSectionи ManagementTableCellклассы для управления все это. Извините, я не могу предоставить более точный код.


0

Основываясь на ответе Дениз, вот решение с использованием ограничений в Swift

Например: если у вас есть 3 вида, A_view B_view и C_view, выровненные по вертикали в указанном порядке, и вы хотите «Скрыть» B, а также отрегулировать разницу, добавьте ограничение.

B_view.removeFromSuperView()
var constr = NSLayoutConstraint(item: C_view, 
                                attribute: NSLayoutAttribute.Top, 
                                relatedBy: NSLayoutRelation.Equal, 
                                toItem: A_view, 
                                attribute: NSLayoutAttribute.Bottom,
                                multiplier: 1,
                                constant: 20)
view.addConstraint(constr)

Константа - это (в данном случае) расстояние по вертикали между C_view и A_view


0

Я добавил новое свойство в пользовательскую реализацию UIView под названием «visible», которое, если установлено значение false, добавляет ограничение для свертывания представления (я добавил только ограничение ширины, поскольку мой список горизонтальный, но лучшим способом может быть добавление ограничение высоты также 0).

var visible:Bool = true{
        didSet{
            if(visible){
                clipsToBounds = false;
                removeConstraint(hideConstraint!)
            }else{
                clipsToBounds = true
                addConstraint(hideConstraint!)
            }
        }
    }

Вам нужно инициализировать ограничение нулевой ширины в представлении и добавить его как поле:

private var hideConstraint:NSLayoutConstraint?


func someInitFunction(){
    hideConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 0.0)
    ...
}

-3

setHidden: TRUE / FALSE - ближайший эквивалент Android View.GONE / VISIBLE.

Вид не обязательно занимает место, если его не видно!

Я сделал ComboBox-Alike с ListView, лежащим поверх других представлений. Я виден только при выборе:

введите описание изображения здесь


вы забыли, что в android у нас также есть view.invisible ... view.gone не похож на setHidden ... его view.invisible похож на setHidden
Nav
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.