MonoTouch:UISegmentedControl选择已选择的片段

时间:2011-11-21 03:07:04

标签: c# iphone ios xamarin.ios uisegmentedcontrol

我正在尝试使用UISegmentedControl来控制我的表的排序顺序,特别是我想在已经选择的段上注册一个点击(以反转我的排序)。因此,我会尝试在点击任何细分时引发UIControlEvent.ValueChanged事件。

我已从SelectedSegment覆盖了UISegmentedControl并且正在使用此自定义类作为xcode中的元素,但是,当点击Segment控件时,似乎没有调用此代码(It <虽然= S)加载视图时调用strong> 。

[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 register taps on selected segment提出,但问题是针对ObjC而且这个问题适用于C#/ Monotouch。

2 个答案:

答案 0 :(得分:2)

你提供的问题link的最后一个答案包含最好的(工作良好)答案(我赞成它,你也应该;-)。

注意:从评论看来,以前的答案似乎(可能)在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);
        }
    }

答案 1 :(得分:0)

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

这是需要使用TouchesEnded事件而不是TouchesBegan的C#版本。使用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无效,但当我意识到iOS7及以上版本需要的时候,我将名称更改为TouchesEnded。在我意识到我还必须改变这条线之前,仍然没有工作:

base.TouchesEnded(touches, evt);

如果您从TouchesBegan转换为TouchesEnded,请不要忘记更改。