Xamarin.iOS 自定义按钮选择器

最近项目中做了一个标题栏中的按钮选择器,原生的UISegmentedControl 无法达到项目效果,效果如下图:


如果只针对项目写一个不难,可是如果以后遇到了还需要针对项目再去写一个,于是我打算把他写的活一些,最终决定用Builder模式来完成它,以前做android原生的时候就用Builder模式构建了一些组合view,但是我尝试着用java的方式去Builder的时候发现行不通,这次是Xamarin的项目,语言是C#,于是我又去学习了一下C#的Builder模式(浅显的理解很简单)。

哦,差点忘了介绍,项目的框架是MvvmCross,不理解的同学去他的官网看看,很良心的!

最终计划了一下这个工作分为三步走(典型的面向过程,哈哈)。



第一步:将这些可以看见的属性,或者随时可以变的属性抽象出来。

using System;
using UIKit;

namespace RuilaiGrow.iOS
{
    /// <summary>
    /// 多按钮圆角view构建抽象类
    /// by ge
    /// </summary>
    abstract class BuilderTopSelectedTitle
    {
        public abstract void setTitles(string[] titles);
        public abstract void setTextSize(nfloat size);
        public abstract void setCornerRadius(nfloat radius);
        public abstract void setHeight(nfloat height);
        public abstract void setWidth(nfloat width);
        public abstract void setNormalTextColor(UIColor color);
        public abstract void setSelectedTextColor(UIColor color);
        public abstract void setViewBackground(UIColor background);
        public abstract void setItemNormal(UIColor corlor);
        public abstract void setItemSelected(UIColor selected);
        public abstract UIView create();
    }
}


项目比较紧张,可能这些属性还是不够,或者说想的不到位,以后慢慢添加和优化。


第二步:创建实现类,构建需要的控件。

经过一番研究,最外层(也就是最终创建返回给界面的)是一个UIView,中间的按钮用UIButton来代替,原因是:经过查阅资料,和尝试,发现UIButton是将UILable于UIImageView封装的结果,采用懒加载的方式,用谁初始化谁,感觉很棒不用我自己造轮子了(以前一直做android原生,对iOS不是很了解,大家见笑)。下面是实现类的代码,注视挺全的了,直接复制粘贴了(懒懒懒)。

using System;
using System.Drawing;
using RuilaiGrow.iOS.Common;
using UIKit;

namespace RuilaiGrow.iOS
{
    /// <summary>
    /// 知识库主页标题切换控制器
    /// </summary>
    class KnowledgeTitleControl : BuilderTopSelectedTitle
    {
        public KnowledgeTitleControl()
        {
            
        }

        //最外层总view
        UIView _thisView = null;
        public UIView ThisView
        {
            get
            {
                if (_thisView == null)
                {
                    //根据本view的宽与高来计算其实位置(目的最终添加到View的导航栏的时候可以居中显示)
                    nfloat startX = (UIScreen.MainScreen.Bounds.Width - _itemWid * _titles.Length) / 2;
                    nfloat startY = (EasyLayout.BarHeight - _viewHei) / 2;
                    _thisView = new UIView(new RectangleF((float)startX, (float)startY, (float(_itemWid * _titles.Length), (float)_viewHei));
                    _thisView.BackgroundColor = _viewBackground;
                }
                return _thisView;
            }
        }

        //标题数组
        private string[] _titles;

        //item数组
        private UIButton[] _itemBtns;

        //控件的高
        private nfloat _viewHei = 45;

        //item的宽
        private nfloat _itemWid = 70;

        //item正常时的颜色
        private UIColor _itemNormalBac = UIColor.Blue;

        //item选中时的颜色
        private UIColor _itemSeletedBac = UIColor.White;

        //文字正常的颜色
        private UIColor _textNormalColor = UIColor.Black;

        //文字选中时的颜色
        private UIColor _textSeletedColor = UIColor.Red;

        //设置本view的颜色
        private UIColor _viewBackground = UIColor.Blue;

        //文字的大小
        private nfloat _textSize = 15;

        //边框与按钮的圆角
        private nfloat _radius = 18;

        //按钮上次点击事件 默认0
        private int lastIndex = 0;

        /// <summary>
        /// 最终创建view
        /// </summary>
        public override UIView create()
        {
            ThisView.Layer.BorderWidth = 1;
            ThisView.Layer.BorderColor = MvxTouchColor.ShallowGrayOne.CGColor;
            ThisView.Layer.CornerRadius = _radius;

            _itemBtns = new UIButton[_titles.Length];

            //循环创建文字按钮并加入到总view中
            int lenght = _titles.Length;
            for (int i = 0; i < lenght; i++) {
                _itemBtns[i] = new UIButton();
                _itemBtns[i].Tag = i;
                _itemBtns[i].SetTitle(_titles[i], UIControlState.Normal);
                _itemBtns[i].SetTitleColor(_textNormalColor, UIControlState.Normal);
                _itemBtns[i].Layer.CornerRadius = _radius;
                _itemBtns[i].TitleLabel.Font = UIFont.SystemFontOfSize(_textSize);
//设置第一个按钮选中状态
                if (i == 0)
                {
                    _itemBtns[i].BackgroundColor = _itemSeletedBac;
                    _itemBtns[i].SetTitleColor(_textSeletedColor, UIControlState.Normal);
                }
            }

            ThisView.AddSubviews(_itemBtns);

            //循环设置view内部item之间约束
            for (int i = 0; i < lenght; i++) {
                if (i == 0)
                {
                    ThisView.ConstrainLayout(() =>
                                             _itemBtns[i].Frame.GetCenterY() == ThisView.Frame.GetCenterY()
                                             && _itemBtns[i].Frame.Width == _itemWid
                                             && _itemBtns[i].Frame.Height == ThisView.Frame.Height
                                             && _itemBtns[i].Frame.Left == ThisView.Frame.Left

                                             && ThisView.Frame.Bottom == _itemBtns[i].Frame.Bottom
                                        );
                }
                else { 
                    ThisView.ConstrainLayout(() =>
                                             _itemBtns[i].Frame.GetCenterY() == ThisView.Frame.GetCenterY()
                                             && _itemBtns[i].Frame.Left == _itemBtns[i - 1].Frame.Right
                                             && _itemBtns[i].Frame.Width == _itemWid
                                             && _itemBtns[i].Frame.Height == ThisView.Frame.Height
                                        );
                }
            }

            //按钮点击事件
            for (int i = 0; i < _titles.Length; i++) {
                _itemBtns[i].TouchUpInside += this.TouchBtn;
            }

            return ThisView;
        }

        //按钮点击处理
        private void TouchBtn(object sender, EventArgs e)
        {
            UIButton v = (UIKit.UIButton)sender;

            //如果和上次点的一样 return
            if (v.Tag == lastIndex)
                return;

            //清空上次点击view的状态
            _itemBtns[lastIndex].BackgroundColor = _itemNormalBac;
            _itemBtns[lastIndex].SetTitleColor(_textNormalColor, UIControlState.Normal);

            //设置本次点击的view的状态
            _itemBtns[v.Tag].BackgroundColor = _itemSeletedBac;
            _itemBtns[v.Tag].SetTitleColor(_textSeletedColor, UIControlState.Normal);

            //记录本次点击的位置
            lastIndex = (int)v.Tag;

            //回调点击位置
            if (_click != null) {
                _click.TitleBackIndex((int)v.Tag);
            }
        }

        /// <summary>
        /// 设置按钮正常时的状态颜色
        /// </summary>
        /// <param name="corlor">Corlor.</param>
        public override void setItemNormal(UIColor corlor)
        {
            this._itemNormalBac = corlor;
        }

        /// <summary>
        /// 设置item选中时的背景
        /// </summary>
        /// <param name="selected">Selected.</param>
        public override void setItemSelected(UIColor selected)
        {
            this._itemSeletedBac = selected;
        }

        /// <summary>
        /// 设置正常时的文字的颜色
        /// </summary>
        /// <param name="color">Color.</param>
        public override void setNormalTextColor(UIColor color)
        {
            this._textNormalColor = color;
        }

        /// <summary>
        /// 设置选中时文字的颜色
        /// </summary>
        /// <param name="color">Color.</param>
        public override void setSelectedTextColor(UIColor color)
        {
            this._textSeletedColor = color;
        }

        /// <summary>
        /// 设置item的文字
        /// </summary>
        /// <param name="titles">Titles.</param>
        public override void setTitles(string[] titles)
        {
            this._titles = titles;
        }

        /// <summary>
        /// 设置view的背景图片
        /// </summary>
        /// <param name="background">Background.</param>
        public override void setViewBackground(UIColor background)
        {
            this._viewBackground = background;
        }

        /// <summary>
        /// 设置item的宽
        /// </summary>
        /// <param name="width">Width.</param>
        public override void setWidth(nfloat width)
        {
            this._itemWid = width;
        }

        /// <summary>
        /// 设置本view的高
        /// </summary>
        /// <param name="height">Height.</param>
        public override void setHeight(nfloat height)
        {
            this._viewHei = height;
        }

        /// <summary>
        /// 设置边框的圆角与按钮的圆角
        /// </summary>
        /// <param name="radius">Radius.</param>
        public override void setCornerRadius(nfloat radius)
        {
            this._radius = radius;
        }

        /// <summary>
        /// 设置文字的大小
        /// </summary>
        /// <param name="size">Size.</param>
        public override void setTextSize(nfloat size)
        {
            this._textSize = size;
        }

        /// <summary>
        /// 点击view回调接口
        /// </summary>
        public interface ClickTitleControlItem {
            void TitleBackIndex(int index);
        }

        private ClickTitleControlItem _click;

        public void setClickTitleControlItem(ClickTitleControlItem click)
        {
            this._click = click;
        }
    
    }
}



上面就是实现类的全部内容,最后那个接口是这个view点击某个按钮时的回调,同事说我这是拿java的思想来写c#,搞得我去查了一下,打算把这个换成事件委托机制。

下面看一下第三步:使用

在Controller中直接定义一个UIView接收创建的view就可以:

       

 //头部导航栏的view
        UIView _topViewControl = null;
        public UIView TopViewControl { 
            get{
                if (_topViewControl == null) {
                    string[] s = new string[] {
                        "0-1岁", "1-3岁", "3-6岁"
                    };
                    KnowledgeTitleControl ctr = new KnowledgeTitleControl();
                    ctr.setWidth(85);
                    ctr.setHeight(EasyLayout.BarHeight - 10f);
                    ctr.setTitles(s);
                    ctr.setTextSize(15);
                    ctr.setCornerRadius(18);
                    ctr.setItemNormal(MvxTouchColor.DeepRed);
                    ctr.setViewBackground(MvxTouchColor.DeepRed);
                    ctr.setItemSelected(MvxTouchColor.White);
                    ctr.setNormalTextColor(MvxTouchColor.ShallowGrayOne);
                    ctr.setSelectedTextColor(MvxTouchColor.DeepRed);
                    ctr.setClickTitleControlItem(this);
                    _topViewControl = ctr.create();
                }
                return _topViewControl;
            }
        }



最后将view添加到导航栏就可以了:

ViewDidLoad()方法中:

//将头部控制器的uiview加入顶部导航栏
NavigationController.NavigationBar.AddSubview(TopViewControl);

按钮的个数是根据构造函数传入的数组决定的。

搞定!!




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值