MonoTouch: UISegmentedControl Выберите сегмент, который уже выбран

Я пытаюсь использовать UISegmentedControl для управления порядком сортировки моей таблицы, в частности, я хочу зарегистрировать нажатие на уже выбранный сегмент (чтобы инвертировать мою сортировку). Таким образом, я пытаюсь вызвать событие UIControlEvent.ValueChanged при каждом касании любого сегмента.

Я переопределил SelectedSegment из UISegmentedControl и использую этот настраиваемый класс для своего элемента в xcode, однако похоже, что этот код не вызывается при нажатии элемента управления «Сегмент» (он вызывается, когда представление загружается хотя = S).

[Register("ReselectableSegment")]
public class ReselectableSegment : UISegmentedControl
{
    static Selector selInit       = new Selector("init");  

    [Export("init")]  
    public ReselectableSegment()  
        : base(NSObjectFlag.Empty)  
    {  
        Handle = Messaging.IntPtr_objc_msgSend(this.Handle,  
            selInit.Handle);  
    }  

    public ReselectableSegment (IntPtr handle) : base(handle){}

    public override int SelectedSegment
    {
        [Export ("SelectedSegment:")]
        set { 
            if(this.SelectedSegment == value)
                this.SendActionForControlEvents(UIControlEvent.ValueChanged);

            base.SelectedSegment = value;
        }
    }
}

Этот вопрос задавался ранее по адресу: Регистр UISegmentedControl нажимает на выбранный сегмент, однако этот вопрос для ObjC, и этот вопрос для C # / Monotouch.


person Symmetry    schedule 21.11.2011    source источник


Ответы (2)


Последний ответ на вопрос ссылка, который вы предоставили, содержит лучшее (хорошо работает) ответ (я поддержал его, вы тоже должны ;-).

примечание: из комментариев похоже, что предыдущие ответы (возможно) работали на iOS4, но не на iOS5.

Вот код, который сделает то, что вы ищете. Я использовал RectangleF .ctor для его тестирования, возможно, вам придется добавить свой собственный .ctor, если вы используете что-то еще (но это не так сложно, как ваш исходный код, например, для создания подкласса не нужен селектор).

    class MyUISegmentedControl : UISegmentedControl {

        public MyUISegmentedControl (RectangleF r) : base (r) {}

        public override void TouchesBegan (NSSet touches, UIEvent evt)
        {
            int current = SelectedSegment;
            base.TouchesBegan (touches, evt);
            if (current == SelectedSegment)
                SendActionForControlEvents (UIControlEvent.ValueChanged);
        }
    }
person poupou    schedule 21.11.2011
comment
Спасибо, poupou. Извини, что мне потребовалось так много времени, чтобы пометить это как ответ, я отвлекся и занялся другими делами. Ваш ответ очень помог! - person Symmetry; 20.12.2011
comment
Примечание для себя ... последний ответ на вопрос ссылка неоднозначен и является движущейся целью. Лучше давать ссылку на ответ, а не на вопрос. - person Travelling Man; 09.06.2017

Приведенные ссылки имеют хорошие ответы для iOS7, но с использованием Objective C / Swift и, в частности, для отмены выбора сегмента при повторном нажатии текущего выбранного сегмента.

Вот версия C #, в которой вместо TouchesBegan необходимо использовать событие TouchesEnded. Использование TouchesBegan дважды вызвало для меня событие UISegmentedControl.ValueChanged, что привело к неправильному поведению.

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

 class OptionalSegmentedControl : UISegmentedControl
{


    public override void TouchesEnded(NSSet touches, UIEvent evt)
    {

        // Getting touch information to work out whether segment has been pressed, then dragged off to cancel the event
        // Comment these lines out if you don't care about handling this
        CGPoint locationPoint = ((UITouch)touches.AnyObject).LocationInView(this);
        CGPoint viewPoint = this.ConvertPointFromView(locationPoint, this);

        // Save the selected segment first
        nint current = this.SelectedSegment;

        // then fire the event
        base.TouchesEnded(touches, evt);


        // Check if the touch point is still on the control when the touch has ended, 
        // as well as comparing the current and new selected segment values 
        // and then fire the ValueChanged event if the same segment is pressed


        // Use this line and comment the second if statement if you don't care about handling click and drag to cancel the event 
        //if (current == this.SelectedSegment)
        if ((this.PointInside(viewPoint, evt)) && (current == this.SelectedSegment))
        {
            this.SelectedSegment = -1;
            SendActionForControlEvents(UIControlEvent.ValueChanged);
        }
    }


}

Затем в событии ValueChanged вы делаете то, что вам нужно сделать с UISegmentedControl:

            // cell.SegmentedControl for me was a UISegmented control in a UITableViewCell
            cell.SegmentedControl.ValueChanged += (s, e) =>
            {
                OptionalSegmentedControl osc = (OptionalSegmentedControl)s;

               // continue with your code logic.....

            };

Следует отметить, что я начал с пустоты TouchesBegan, но затем изменил имя на TouchesEnded, когда понял, что это то, что нужно для iOS7 и выше. Все еще не работало, пока я не понял, что мне также нужно изменить строку:

base.TouchesEnded(touches, evt);

Так что не забудьте изменить это, если вы конвертируете из TouchesBegan в TouchesEnded.

person Tahari    schedule 12.02.2017