选择一个已经被选中的段

本文关键字:一个 选择 | 更新日期: 2023-09-27 18:15:27

我试图使用UISegmentedControl来控制表的排序顺序,特别是我想在已经选择的段上注册一个tap(以逆我的排序)。因此,每当任何段被点击时,我都试图引发UIControlEvent.ValueChanged事件。

我已经从UISegmentedControl中重写了SelectedSegment,并且在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的。

选择一个已经被选中的段

您提供的问题链接的最后一个答案包含了最好的(工作良好)答案(我支持它,你也应该;-)。

注意:从评论来看,前面的答案(可能)适用于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);
        }
    }

提供的链接对于iOS7有很好的答案,但是使用Objective C/Swift,特别是当当前选择的段再次被按下时取消选择。

这是c#版本需要使用TouchesEnded事件而不是TouchesBegan。使用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 void,但当我意识到这是iOS7及以上版本所需要的时,我将名称更改为TouchesEnded。仍然没有工作,直到我意识到我必须改变这一行:

base.TouchesEnded(touches, evt);

如果你从TouchesBegan转换为TouchesEnded不要忘记修改这个