我正在制作一个绘图的项目。
我不使用axml,因为我在一个名为filledpolygon的类中绘制并在MainActivity中调用该函数。我只想在我的项目中截取屏幕截图。有没有任何基本功能,我可以在onCreate方法中调用它?因此,当程序运行时,它将自动截取屏幕截图。除了Xamarin平台,我找到了答案。
答案 0 :(得分:0)
在您的视图中,您可以运行以下代码,该代码将截取屏幕截图。我之前没有尝试在OnCreate()
中运行它,因此您可能需要对其进行测试以确保视图已完全呈现。
*修改:根据this post,您可能无法在OnCreate()
中运行此代码,因此您需要找到更好的地方。我无法弄清楚用户在他发布的链接中指的是什么帖子。
*编辑#2:刚发现Compress()
未考虑质量参数(下面列为0
),因为PNG无损,但如果您将格式更改为JPEG例如,您可能想要调高质量参数,因为您的图像看起来像垃圾。
public byte[] SaveImage() {
DrawingCacheEnabled = true; //Enable cache for the next method below
Bitmap bitmap = GetDrawingCache(true); //Gets the image from the cache
byte[] bitmapData;
using(MemoryStream stream = new MemoryStream()) {
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
bitmapData = stream.ToArray();
}
return bitmapData;
}
答案 1 :(得分:0)
由于不推荐使用Android 28 DrawingCacheEnabled
,因此如果不使用它,我们将迫使视图在自定义画布上重绘,这会导致自定义控件和渲染器出现伪像,并且屏幕截图版本可能与我们在屏幕上看到的有所不同
在简单情况下仍可使用的旧代码是:
public byte[] CaptureScreenshot()
{
var rootView =
Xamarin.Essentials.Platform.CurrentActivity.Window.DecorView.RootView;
rootView.DrawingCacheEnabled = true;
using (var screenshot = Bitmap.CreateBitmap(
rootView.Width,
rootView.Height,
Bitmap.Config.Argb8888))
{
var canvas = new Canvas(screenshot);
rootView.Draw(canvas);
using (var stream = new MemoryStream())
{
screenshot.Compress(Bitmap.CompressFormat.Png, 90, stream);
return stream.ToArray();
}
}
rootView.DrawingCacheEnabled = false;
}
DrawingCacheEnabled
过时的警告使我们重定向到使用PixelCopy
。此方法与回调一起起作用,因此同步使用它可以提供一些帮助:
用法:
public byte[] CaptureScreenshot()
{
using var helper = new ScreenshotHelper(
Xamarin.Essentials.Platform.CurrentActivity.Window.DecorView.RootView,
Xamarin.Essentials.Platform.CurrentActivity);
byte[] buffer = null;
bool wait = true;
Task.Run(async () =>
{
helper.Capture((Bitmap bitmap) =>
{
try
{
if (!helper.Error)
{
using (var stream = new MemoryStream())
{
bitmap.Compress(Bitmap.CompressFormat.Png, 90, stream);
buffer = stream.ToArray();
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
wait = false;
}
});
}).ConfigureAwait(false);
while (wait)
{
Task.Delay(10).Wait();
}
return buffer;
}
助手:
public class ScreenshotHelper : Java.Lang.Object, PixelCopy.IOnPixelCopyFinishedListener
{
public void OnPixelCopyFinished(int copyResult)
{
var stop = true;
if (copyResult == (int) PixelCopyResult.Success)
{
Error = false;
//todo CallbackGotScreenshot();
_callback(_bitmap);
}
else
{
Error = true;
}
_callback(_bitmap);
}
public bool Error { get; protected set; }
public ScreenshotHelper(Android.Views.View view, Activity activity)
{
_view = view;
_activity = activity;
_bitmap = Bitmap.CreateBitmap(
_view.Width,
_view.Height,
Bitmap.Config.Argb8888);
}
// Starts a background thread and its {@link Handler}.
private void StartBackgroundThread()
{
_BackgroundThread = new HandlerThread("ScreeshotMakerBackground");
_BackgroundThread.Start();
_BackgroundHandler = new Handler(_BackgroundThread.Looper);
}
// Stops the background thread and its {@link Handler}.
private void StopBackgroundThread()
{
try
{
_BackgroundThread.QuitSafely();
_BackgroundThread.Join();
_BackgroundThread = null;
_BackgroundHandler = null;
}
catch (Exception e)
{
//e.PrintStackTrace();
}
}
public void Capture(Action<Bitmap> callback)
{
//var locationOfViewInWindow = new int[2];
//_view.GetLocationInWindow(locationOfViewInWindow);
_callback = callback;
try
{
StartBackgroundThread();
//todo could create-use background handler
PixelCopy.Request(_activity.Window, _bitmap, this,
_BackgroundHandler);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
Task.Run(StopBackgroundThread);
}
}
private Android.Views.View _view;
private Activity _activity;
private Bitmap _bitmap;
private HandlerThread _BackgroundThread;
private Handler _BackgroundHandler;
private Action<Bitmap> _callback;
public new void Dispose()
{
_bitmap?.Dispose();
_bitmap= null;
_activity = null;
_view = null;
_callback = null;
base.Dispose();
}
}