我终于为 iOS 和 Android 创建了一个最低限度的解决方案。
共享项目
首先,让我们看看共享代码。App
为了在共享类和特定于平台的代码之间轻松交互,我们将静态存储Instance
在public static App
:
public static App Instance;
此外,我们将显示一个Image
,稍后将填充内容。所以我们创建一个成员:
readonly Image image = new Image();
在App
构造函数中,我们存储Instance
并创建页面内容,这是一个简单button
的前面提到的image
:
public App()
{
Instance = this;
var button = new Button {
Text = "Snap!",
Command = new Command(o => ShouldTakePicture()),
};
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
button,
image,
},
},
};
}
按钮的单击处理程序调用事件ShouldTakePicture
。它是一个公共成员,平台特定的代码部分将在稍后分配给它。
public event Action ShouldTakePicture = () => {};
最后,我们提供了一个公共方法来显示捕获的图像:
public void ShowImage(string filepath)
{
image.Source = ImageSource.FromFile(filepath);
}
安卓项目
在 Android 上,我们修改MainActivity
. 首先,我们为捕获的图像文件定义一个路径:
static readonly File file = new File(Environment.GetExternalStoragePublicDirectory(Environment.DirectoryPictures), "tmp.jpg");
最后,我们可以使用createdOnCreate
的 static并分配一个匿名事件处理程序,它将启动一个新的用于捕获图像:Instance
App
Intent
App.Instance.ShouldTakePicture += () => {
var intent = new Intent(MediaStore.ActionImageCapture);
intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(file));
StartActivityForResult(intent, 0);
};
最后但同样重要的是,我们的活动必须对生成的图像做出反应。它只会将其文件路径推送到共享ShowImage
方法。
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
App.Instance.ShowImage(file.Path);
}
就是这样!只是不要忘记在“AndroidManifest.xml”中设置“Camera”和“WriteExternalStorage”权限!
iOS 项目
对于 iOS 实现,我们创建了一个自定义渲染器。因此,我们添加一个新文件“CustomContentPageRenderer”,并在 using 语句之后添加相应的程序集属性:
[assembly:ExportRenderer(typeof(ContentPage), typeof(CustomContentPageRenderer))]
CustomContentPageRenderer
继承自PageRenderer
:
public class CustomContentPageRenderer: PageRenderer
{
...
}
我们重写该ViewDidAppear
方法并添加以下部分。
创建一个引用相机的新图像选择器控制器:
var imagePicker = new UIImagePickerController { SourceType = UIImagePickerControllerSourceType.Camera };
一旦ShouldTakePicture
引发事件,就呈现图像选择器控制器:
App.Instance.ShouldTakePicture += () => PresentViewController(imagePicker, true, null);
拍照后保存到MyDocuments
文件夹,调用共享ShowImage
方法:
imagePicker.FinishedPickingMedia += (sender, e) => {
var filepath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "tmp.png");
var image = (UIImage)e.Info.ObjectForKey(new NSString("UIImagePickerControllerOriginalImage"));
InvokeOnMainThread(() => {
image.AsPNG().Save(filepath, false);
App.Instance.ShowImage(filepath);
});
DismissViewController(true, null);
};
最后,我们需要处理取消图像拍摄过程:
imagePicker.Canceled += (sender, e) => DismissViewController(true, null);