2017-02-10 10:52:35 geanwen 阅读数 1879

今天写一篇条形码扫描的文章,使用的是ZXing。

实现非常简单,下面一起来看一下步骤。


首先在项目中导入包:



接下来直接可以使用了:

直接在你的ViewController中声明变量:

MobileBarcodeScanner scanner;
初始化变量:
scanner = new MobileBarcodeScanner(this.NavigationController);
下面的代码是在一个按钮点击事件中调用扫码的:
Btn.TouchUpInside += async (sender, e) =>
			{

				// ZXing
				scanner.UseCustomOverlay = false;

				// 底部两个按钮文字
				scanner.FlashButtonText = "识别";
				scanner.CancelButtonText = "取消";

				// 方框上,下方文字提示
				scanner.TopText = "请将条形码对准方框内";
				scanner.BottomText = "确认后按下右下角识别按钮";

				//Start scanning
				var result = await scanner.Scan();

				// 处理结果
				HandleScanResult(result);

			};

下面是对结果简单的处理:

void HandleScanResult(ZXing.Result result)
		{
			string msg = "";

			if (result != null && !string.IsNullOrEmpty(result.Text))
				msg = "扫描结果: " + result.Text;
			else
				msg = "你取消了!";

			this.InvokeOnMainThread(() =>
			{
				var av = new UIAlertView("Barcode Result", msg, null, "OK", null);
				av.Show();
			});
		}

最后贴一张扫描的效果图





差点忘了,添加摄像头的权限:Privacy - Photo Library Usage Description。


上面实现的扫描条形码呢,需要我们手动点击识别按钮来识别,下面将调用的代码稍微改动一下,添加一个三秒延时自动识别:

Btn.TouchUpInside += (sender, e) =>
			{

				// ZXing
				scanner.UseCustomOverlay = false;

				// 底部两个按钮文字
				scanner.FlashButtonText = "识别";
				scanner.CancelButtonText = "取消";

				// 方框上,下方文字提示
				scanner.TopText = "请将条形码对准方框内";
				scanner.BottomText = "确认后按下右下角识别按钮";

				// 延时三秒自动扫秒
				var opt = new MobileBarcodeScanningOptions();
				opt.DelayBetweenContinuousScans = 3000;

				scanner.ScanContinuously(opt, HandleScanResult);
			};

好了,这样子调用即可达到自动识别的效果。

写完了后遇到一个坑,如上面截图,公司给的条形码都是纸质打印的,当时刚写完后一直扫不上,于是开始怀疑ZXing性能的问题了。

后来换了几个条形码都没有问题。

最后在仔细看了看纸质的条形码打印的质量有问题。

大家遇到扫不上的时候先检查一下条形码有没有问题。


2016-12-22 11:01:46 geanwen 阅读数 1254

前些天写的博客,自定义了一个组合view,由于对c#的事件机制不了解,所以view中的按钮回调Controller的方式我选择了开发Android时常使用的接口回调。在同事指出问题后我查阅了一些资料,看了几本书中c#委托机制的资料。最后封装了一下委托事件总线,java慢慢也在模仿这种委托机制。

下面贴出封装的类以及使用方法。

先贴出封装的委托机制的类:

using System;
namespace RuilaiGrow.iOS
{
	/// <summary>
	/// 委托事件总线 基类
	/// by ge
	/// </summary>
	public class EventBus : EventArgs
	{
		public EventBus(string bus)
		{
			this.Bus = bus;
		}

		public string Bus { get; set; }
	}

	public class EventBusDealer {
		public event EventHandler<EventBus> NewBusInfo;

		public void NewBus(object sender, string bus) {
			RaiseNewBusInfo(sender, bus);
		}

		protected void RaiseNewBusInfo(object sender, string bus)
		{
			EventHandler<EventBus> newBusInfo = NewBusInfo;
			if (newBusInfo != null) {
				newBusInfo(sender, new EventBus(bus));
			}
		}
}

}


在贴出使用方法,举例子,场景:假如现在在我自定义的view中有一个按钮,在他的点击事件中回调到界面几个数据。

第一步,在自定义的view中实例化封装的话委托事件对象:

		//委托事件
		public EventBusDealer eventBus = new EventBusDealer();
在点击事件中:

Button.TouchUpInside += (sender, e) =>
					{
						eventBus.NewBus(_list[index], "");
					};

在界面Controller中使用view找到委托事件的对象并绑定事件:

ListView.eventBus.NewBusInfo += (object sender, EventBus e) => { 
				//事件发送到这里
			};

上面我封装的EventBus(Android我一直使用的就是EventBus,所以从情怀的角度起名叫这个,不要误导大家。我自己写iOS的demo时候,程序的icon一直用的是Android的小机器人图标,哈哈哈)发送的第二个参数是String,可以自行修改达到自己的需求。






2016-12-05 16:49:07 geanwen 阅读数 2115

项目中的一个界面,用到了弹出窗口,当我拿到效果图的时候突然发现,iOS的弹出窗口我只做过最基本的警告视图。上个周末自己在家尝试了用警告视图来完成这个,结果发现没办法达到这个效果。最后打电话请教以前iOS原生开发的同事整理了一条思路进行尝试。

本篇文章只记录达到这个效果的思路和主要的代码。

1.创建一个自定义的View,即新建一个类继承自UIView,这个最外层的总view长和宽就是屏幕的长和宽,内部包含了弹出窗口的view,并设置最外层的View的透明度为半透明(16进制颜色址前两位就是透明度)。


    

/// <summary>
    /// 自定义弹窗
    /// by ge
    /// </summary>
    public class PayAlertView : UIView
    {
        public PayAlertView(RectangleF viewFrame)
        {
            this.Frame = viewFrame;
        }

public override void LayoutSubviews()
        {
            base.LayoutSubviews();

//...省略构建view的代码...
    //设置view的背景半透明黑色
            this.BackgroundColor = MvxTouchColor.BlacAlpha;
        }


2.创建好这个自定义的View后,在ViewController中引入这个View:

/// <summary>
        /// 支付弹窗view
        /// </summary>
        private PayAlertView _dialogView = null;
        public PayAlertView DialogView
        {
            get
            {
                if (_dialogView == null) {
                    _dialogView = new PayAlertView(new RectangleF(0, 0,
                                                                  (float)UIScreen.MainScreen.Bounds.Width, 
                                                                  (float)UIScreen.MainScreen.Bounds.Height));
                }
                return _dialogView;
            }
        }



3.当点击界面上某一个按钮时,在他的委托点击事件中将自定义的View添加到Window中就可以了(判断弹窗是否添加过了,避免只能弹出一次):

    //按钮点击事件
                    payVipBtn.TouchUpInside += (sender, e) =>
                    {
                        if (DialogView.Hidden)
                            DialogView.Hidden = false;
                        else this.View.Window.AddSubview(DialogView);
                    };


4.隐藏弹窗。当我们需要关闭弹窗时直接隐藏就可以,再次点击按钮时就不用像


    //关闭弹窗
                    if (!DialogView.Hidden)
                        DialogView.Hidden = true;



思路记录到这里,如果哪里写错了,或者写法不太好请大家及时指出。进行优化

下面贴出,我的另一篇博客:给自定义弹窗加透明渐变动画。

http://blog.csdn.net/geanwen/article/details/54177841


2016-11-15 14:37:42 geanwen 阅读数 1681

最近项目中做了一个标题栏中的按钮选择器,原生的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);

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

搞定!!




2016-12-06 17:36:14 geanwen 阅读数 1397

今天遇到一个奇葩的BUG,当我写了一些控件Add到一个UIView中。

运行后,在界面上点击其中的控件没有问题,但是我点击UIView空白区域时,整个UIView都变透明了,包括其中的子控件也透明了。

我猜测应该是默认的选中效果。

第一种:针对UIView中控件不需要点击事件

给UIView添加一个空的点击事件,代码如下:

uiView.AddGestureRecognizer(new UIGestureRecognizer());

运行后发现果然点击空白不会透明了,但是其中的子控件的点击事件也被屏蔽掉了。

第二种:针对一个初始界面可以显示完全的情况

出现这个问题的原因就是继承了MvxDialogViewController这个基类。所以一种方式是继承的基类换成MvxViewController。另一种方式是,我们自己写的一些view添加到Root中显示,那么我们添加的这些View作为了MvxDialogViewController中的TableView的Cell出现。框架默认的选中的style是点击后变透明,所以出现了这个bug。

解决方法:在添加完Root后遍历每一个Cell,设置他们选中的style即可,如下:

public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            TableView.SeparatorStyle = UITableViewCellSeparatorStyle.None;
            Root = (RootElement)GetRoot();

            //循环去掉选中效果
            var cell = Root.TableView.VisibleCells[0];
            cell.SelectionStyle = UITableViewCellSelectionStyle.None;
            var cell1 = Root.TableView.VisibleCells[1];
            cell1.SelectionStyle = UITableViewCellSelectionStyle.None;
            var cell2 = Root.TableView.VisibleCells[2];
            cell2.SelectionStyle = UITableViewCellSelectionStyle.None;
        }

这种方式呢,从方法字面意思上可以理解出,去掉的是正在显示在界面内的View的点击效果。当我们界面足够长,初始的界面显示不完的时候,那么,下面的一些UIView的点击效果还是会透明。

第三种:针对界面足够长,也是醉好的一种解决方式

其实这篇博客一开始只有上面两种解决方式,在我开发一段时间之后,测试自己的界面时,用了上面第二种方式的界面,拉到最下面还是会出现点击透明的问题。于是经过再一次尝试,写出本解决方法。

上面提到了,继承了MvxDialogViewController后,我们添加到Root中的View作为一个Cell出现,即可以把MvxDialogViewController当成是一个UI tableView(其实他就是!因为继承了它以后要设置UITableViewStyle)。那么UITableView中有Select方法,可以设置选中的行,MvxDialogViewController肯定也有。于是试着找了一下,真的有。于是复写下面Select方法,回调点击的参数:

public override void Selected(Foundation.NSIndexPath indexPath)
		{
			base.Selected(indexPath);

			// 根据点击的indexPath去掉选中效果
			Root.TableView.CellAt(indexPath).SelectionStyle = UITableViewCellSelectionStyle.None;
		
		}

搞定!!






没有更多推荐了,返回首页