写在前面:
临近年底,也刚好有时间整理最新我的Github上的一些 Demo,这一年中也使用过不少第三方 SDK,对于 Bindings Liabrary 的转化也有一定心得体会,其实对于 Binding 的难易程度很大程度上跟 Framework 团队的代码质量相关,这里我会介绍一个使用率很广的一个 MJRefresh,同时也会分享Binding的过程。
已经有上百个 App 用到了 MJRefresh (只列出了其中一部分 App ):
Set Binding Library
Sharpie Bind
这里一般我们使用的方法有两种,这两种方法在之前的博客中都有介绍,如果不清楚的话可以查看一下:
- 手动使用类库转化工具转换
- 使用CocoaPods自动转换
Bindings Library的错误处理
首先我们需要处理ApiDefinition.cs
文件中的错误,这些错误一般都只会有几类,挨个解决就好了:
nint, nuint
类型错误
一般 nint 需要转换为 C# 的类型,我这里把它转换成 ulong/long 就基本上完事了[Verify(MethodToProperty)]
标签
这个标签是因为在OC是一个静态方法,C#会帮你转换成属性,遇到含有类似这种标签的错误,你可以删除/注释掉它。还有一些提示出错的如BaseType不用理,这个只是编辑器不支持这个标签,不影响项目编译和运行。
-
cannot declare instance members in a static class
这一类问题都是由于扩展的方法不能被识别一起的,需要把每个属性的get/set通过方法描述解决,这里我们拿一个例子来说,原始转化好的代码如下:
// @property (nonatomic, strong) MJRefreshHeader * mj_header;
[Export ("mj_header", ArgumentSemantic.Strong)]
MJRefreshHeader Mj_header { get; set; }
// @property (nonatomic, strong) MJRefreshFooter * mj_footer;
[Export ("mj_footer", ArgumentSemantic.Strong)]
MJRefreshFooter Mj_footer { get; set; }
修改后的代码如下:
// @property (nonatomic, strong) MJRefreshHeader * mj_header;
[Export("header")]
MJRefreshHeader Header();
[Export("setHeader:")]
void SetHeader(MJRefreshHeader header);
// @property (nonatomic, strong) MJRefreshFooter * mj_footer;
[Export("footer")]
MJRefreshFooter Footer();
[Export("setFooter:")]
void SetFooter(MJRefreshFooter header);
- 指针
在C#中是没有指针概念的,但 Objective-C 有 ,转换的时候有时候不会消除 *,这个时候你只需要把 * 去掉
一般最初的错误提示有这么几种,但是这些并不是绝对的,有些库转化后也会出现 类名大小错误、重分类定义、缺少系统库引用 等错误,像这些错误一般我们通过手动修改,注释,添加系统库引用即可。
使用 MJRefresh
在我们完成Binding Library的项目之后呢,我们可以开始实现相应的功能了,这里我们将使用 MJRefresh 来自定义 TableView的下拉刷新动画,这里我们通过每次上拉或下拉刷新来改变 Count 的值:
- 设置默认的 MJRefresh Header 和 Footer 样式:
table = new UITableView();
table.Frame = new CoreGraphics.CGRect(0, 40, UIScreen.MainScreen.Bounds.Width, UIScreen.MainScreen.Bounds.Height - 64 - 40);
table.DataSource = new TableDataSource(this);
table.Delegate = new TableDelegate(this);
this.View.AddSubview(table);
MJRefreshNormalHeader header = new MJRefreshNormalHeader();
table.SetHeader(header);
MJRefreshAutoNormalFooter footer = new MJRefreshAutoNormalFooter();
table.SetFooter(footer);
header.RefreshingBlock = async () => {
await Task.Delay(2000);
InvokeOnMainThread(() => {
footer.Hidden = true;
this.Count += 12;
table.ReloadData();
table.Header().EndRefreshing();
footer.Hidden = false;
});
};
header.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle), "MJRefreshHeaderIdleText"), MJRefreshState.Idle);
header.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle), "MJRefreshHeaderPullingText"), MJRefreshState.Pulling);
header.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle), "MJRefreshHeaderRefreshingText"), MJRefreshState.Refreshing);
header.AutomaticallyChangeAlpha = true;
footer.RefreshingBlock = async () => {
await Task.Delay(2000);
InvokeOnMainThread(() => {
footer.Hidden = true;
this.Count += 5;
table.ReloadData();
table.Footer().EndRefreshing();
footer.Hidden = false;
});
};
footer.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle), "MJRefreshAutoFooterIdleText"), MJRefreshState.Idle);
footer.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle), "MJRefreshAutoFooterRefreshingText"), MJRefreshState.Refreshing);
footer.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle), "MJRefreshAutoFooterNoMoreDataText"), MJRefreshState.NoMoreData);
table.Header().BeginRefreshing();
- 同时我们需要设置 TableView 的 Delegate 和 DataSource,这里我们将 Count 的值设置为 TableView 的行数:
public class TableDelegate : UITableViewDelegate
{
private ViewController _vc;
public TableDelegate(ViewController vc)
{
_vc = vc;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
_vc.NavigationController.PushViewController(new MJTableViewController(), true);
}
}
public class TableDataSource : UITableViewDataSource
{
private ViewController _vc;
public TableDataSource(ViewController vc)
{
_vc = vc;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell("testcell");
if (cell == null)
cell = new UITableViewCell(UITableViewCellStyle.Default, "testcell");
if(indexPath.Row % 2 != 0)
cell.TextLabel.Text = "push";
else
cell.TextLabel.Text = "modal";
return cell;
}
public override nint RowsInSection(UITableView tableView, nint section)
{
return _vc.Count;
}
}
- 同样我们可以自定义 Header 和 Footer 的样式,这里我们设置 Header 为一个自定义的 Gif 动画显示效果,同时添加模式请求头文字:
MJChiBaoZiHeader header = new MJChiBaoZiHeader();
this.TableView.SetHeader(header);
MJRefreshAutoNormalFooter footer = new MJRefreshAutoNormalFooter();
this.TableView.SetFooter(footer);
header.RefreshingBlock = async () => {
await Task.Delay(2000);
InvokeOnMainThread(() => {
footer.Hidden = true;
this.Count += 12;
this.TableView.ReloadData();
this.TableView.Header().EndRefreshing();
footer.Hidden = false;
});
};
header.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle),"MJRefreshHeaderIdleText"), MJRefreshState.Idle);
header.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle), "MJRefreshHeaderPullingText"), MJRefreshState.Pulling);
header.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle), "MJRefreshHeaderRefreshingText"), MJRefreshState.Refreshing);
header.AutomaticallyChangeAlpha = true;
footer.RefreshingBlock = async () => {
await Task.Delay(2000);
InvokeOnMainThread(() => {
footer.Hidden = true;
this.Count += 5;
this.TableView.ReloadData();
this.TableView.Footer().EndRefreshing();
footer.Hidden = false;
});
};
footer.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle), "MJRefreshAutoFooterIdleText"), MJRefreshState.Idle);
footer.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle), "MJRefreshAutoFooterRefreshingText"), MJRefreshState.Refreshing);
footer.SetTitle(NSBundle_MJRefresh.Mj_localizedStringForKey(NSBundle_MJRefresh.Mj_refreshBundle(NSBundle.MainBundle), "MJRefreshAutoFooterNoMoreDataText"), MJRefreshState.NoMoreData);
this.TableView.Header().BeginRefreshing();
- 这里的 MJChiBaoZiHeader 继承自 MJRefreshGifHeader,我们只需要设置不同状态下显示的静态图片就能达到 Gif 的效果:
using System;
using MJRefresh;
using UIKit;
using Foundation;
using System.Collections.Generic;
namespace Test_MJRefresh.DIY
{
public class MJChiBaoZiHeader : MJRefreshGifHeader
{
public override void Prepare()
{
base.Prepare();
NSMutableArray refreshImages = new NSMutableArray();
for (int i = 1; i < 3;i++)
{
UIImage image = new UIImage($"dropdown_loading_0{i}");
refreshImages.Add(image);
}
this.SetImages(refreshImages, MJRefreshState.Pulling);
this.SetImages(refreshImages , MJRefreshState.Refreshing);
}
}
}
完整 Demo 可以访问 项目地址
或者直接添加 Xamarin.iOS.MJRefresh Nuget 到项目中进行使用。
到这里Xamarin.iOS MJRefresh集成的介绍就完成了,希望能对您有所帮助。