UIPopoverController появляется не в том месте

Я потратил некоторое время на поиски ответа на этот вопрос, но пока ничего не нашел.

Я пытаюсь представить всплывающее окно с помощью кнопки в UIInputAccessoryView. UIBarButtonItem, из которого я хочу отображать всплывающее окно, имеет настраиваемый вид, поэтому я могу использовать изображение. Я создаю такую ​​кнопку:

 buttonImage=[UIImage imageNamed:@"tags.png"];
 aButton=[UIButton buttonWithType:UIButtonTypeCustom];
 [aButton setImage:buttonImage forState:UIControlStateNormal];
 aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
 UIBarButtonItem* compButton2=[[UIBarButtonItem alloc]initWithCustomView:aButton];
 [aButton addTarget:self action:@selector(tagIt:) forControlEvents:UIControlEventTouchUpInside];

Когда приходит время отображать всплывающее окно, я делаю это так:

CGRect tRect=[((UIButton*)sender) convertRect:((UIButton*)sender).frame toView:self.notePlainText];
NSLog(@"TagIt tRect: %f %f %f %f", tRect.origin.x, tRect.origin.y, tRect.size.width, tRect.size.height);
[self.popoverController presentPopoverFromRect:tRect inView:self.notePlainText permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

Но вот что я получаю:

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

Всплывающее окно выглядит нормально, но оно появляется поверх второй кнопки, хотя должно появиться поверх первой.

Итак, я нашел этот вопрос: UIBarButtonItem с настраиваемым изображением и без границы и я подумал: «а, возможно, будет лучше, если я представлю всплывающее окно из элемента barbutton, вместо того, чтобы делать это таким образом. Подклассы кода UIBarButtonItem, чтобы иметь кнопку с изображением, а не текстом, и правильно представлять элемент barbutton при вызове действия. Это позволило мне использовать ... presentPopoverFromBarButtonItem ...

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

Всплывающее окно с неправильной ориентацией

Наконец, я отмечу, что у меня есть другие элементы кнопок панели в другом месте программы, которых нет в UIInputAccessoryViews, которые появляются правильно и без проблем. Это только кажется происходящим из представления вспомогательного ввода.

Это только в: Скрытие и отображение клавиатуры, кажется, делает эту работу немного лучше. Глядя на данные кадра (CGRect) для кнопки, они не меняются между поворотами, если только они не скрыты и не возвращены. Это ошибка?

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

Большое Вам спасибо.


comment
Вы пробовали [UIPopoverController presentPopoverFromBarButtonItem:(UIBarButtonItem *)item permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated]? Желательно, если вы удерживаете кнопку панели.   -  person bshirley    schedule 09.07.2011
comment
@bshirley - да, я пробовал. вопрос, на который я ссылался выше подклассов uibarbuttonitem, чтобы упростить создание barbuttonitem с изображением вместо текста. Когда я сделал это и использовал ... popoverfrombarbuttonitem ... результатом было второе изображение выше, на котором всплывающее окно появилось в правильном положении, но было неправильно повернуто.   -  person Chris    schedule 09.07.2011


Ответы (6)


Итак, я получил это для работы с помощью следующего неуклюжего кода, хотя, если бы кто-нибудь мог сказать мне, почему я должен это делать (или почему я НЕ ДОЛЖЕН это делать), я был бы очень признателен.

CGRect r=((UIButton*)sender).frame;
CGRect tRect=[((UIButton*)sender) convertRect:((UIButton*)sender).frame toView:self.view];
tRect.origin.x=r.origin.x;

[self.popoverController presentPopoverFromRect:tRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
person Chris    schedule 09.07.2011
comment
Вы должны использовать свойство bounds вместо frame. convertRect:toView: преобразует прямоугольник из системы координат получателя в представление, переданное в toView:. frame представления находится в системе координат своего супервизора, а bounds находится в системе координат этого представления. - person Tobias Klüpfel; 02.11.2011
comment
или вы можете использовать [self.popoverController presentPopoverFromRect: [кадр отправителя] inView: self.view allowedArrowDirections: UIPopoverArrowDirectionDown animated: YES]; и все будет хорошо - person Dannie P; 05.02.2013

У меня была точно такая же проблема, когда всплывающее окно указывало на другое место в iOS 7, и благодаря ответу Криса я был наконец-то удалось увидеть согласованность между iOS 6 и iOS 7. Мне пришлось внести одну небольшую корректировку в код, заменив frame на bounds, чтобы он располагался там, где я ожидал.

CGRect r = [sender frame];
CGRect tRect = [sender convertRect:sender.bounds toView:self.view];
tRect.origin.x=r.origin.x;

[self.popoverController presentPopoverFromRect:tRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:NO];
person Korey Hinton    schedule 04.11.2013
comment
Отличное простое решение. Отлично работает в XCode 5.0! - person Droid Chris; 11.11.2013
comment
Есть ли причина, по которой вы не называете эту линию так? CGRect tRect=[sender convertRect:sender.bounds toView:self.view]; - person Evan R; 14.03.2014
comment
@EvanR хороший момент, здесь нет причин переводить его с id на UIButton, так как я все равно могу отправить ему любое сообщение - person Korey Hinton; 17.03.2014

Используйте 1_. Для этого убедитесь, что у вас есть ссылка на кнопку панели (либо сохранив ее в свойстве на контроллере представления, либо используя IBOutlet), а затем вызовите метод в всплывающем окне, которое вы хотите показать.

person Benjamin Mayo    schedule 08.07.2011
comment
Ага. Как я объяснил в своем вопросе и в своем комментарии выше, я попробовал это, и в результате получилось правильно расположенное, но неправильно повернутое всплывающее окно. Спасибо хоть. - person Chris; 09.07.2011
comment
Хм ... Вы разрешили какие-либо направления стрелок? Вид мог быть повернут, чтобы соответствовать указанному направлению стрелки? В противном случае это действительно странно. - person Benjamin Mayo; 10.07.2011

Я использовал тот же обходной путь в этом ответе; похоже, это проблема с iOS 4.3 (возможно, 4.x). Похоже, это исправлено в iOS 5.

person azsromej    schedule 04.11.2011

Попробуй это:

[self.popoverController presentPopoverFromRect:[sender bounds]
                    inView:sender
  permittedArrowDirections:UIPopoverArrowDirectionAny 
                  animated:YES];
person Shehbaz Khan    schedule 29.08.2013

Вы можете просто сместить эту точку:

if segue.identifier == "layersPopover"
{
    let vc = segue.destinationViewController
    let controller = vc.popoverPresentationController

    if controller != nil
    {
        controller?.delegate = self

        var rect = controller?.sourceRect
        rect?.offsetInPlace(dx: 19, dy: 0)
        controller?.sourceRect = rect!
    }
}
person AndrewK    schedule 20.04.2016