For getting the temperature in a specific point, you need the X and Y position.
You can get the pixel position using the OnTouch event of View.IOnTouchListener, for example.
Example Code:
public bool OnTouch(View v, MotionEvent e)
{
Position_X = (int)e.GetX();
Position_Y = (int)e.GetY();
return true;
}
and OnFrameProcessed, your code would look like this:
public void OnFrameProcessed(RenderedImage renderedImage)
{
if (renderedImage.InvokeImageType() == RenderedImage.ImageType.ThermalRadiometricKelvinImage)
{
var step = renderedImage.Width();
var pixel = Position_X + (Position_Y * step);
var thermalPixels = renderedImage.ThermalPixelValues();
if (thermalPixels.Length < pixel)
{
pixel = thermalPixels.Length - 1;
}
//temperature in point
AvgPointTemperature = (thermalPixels[pixel] / 100.0) - 273.15;
}
}
I don't know if it's the best method, but it's the one I found.
Thanks.
Okey , this need Customizing a ContentPage to get X and Y from IOS or Android device.
Android:
public override bool OnTouchEvent(MotionEvent e)
{
Console.WriteLine("x->" + e.GetX() + "y->" + e.GetY());
return base.OnTouchEvent(e);
}
IOS:
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);
UITouch touch = (UITouch)touches.AnyObject;
CGPoint cp = touch.LocationInView(this.View);
Console.WriteLine("x->" + cp.X + "y->" + cp.Y);
}
Related
How can I implement a video recorder inside an application using xamarin forms?
You can use Xamarin.Plugin.Media. If it is not flexible enough for you, then you need to implement the video recorder using the native APIs. In which case you probably shouldn't be doing Xamarin.Forms at all, but if you insist that is the way.
Do you want to achieve the result like following GIF(Over 2M, SO cannot allow upload it )?
https://imgur.com/a/kpMl2ed
I achieve it in android by custom rendere. Here is code.
First of all, we should MediaRecorder to record the video.
public void startRecord(SurfaceView surfaceView)
{
Device.BeginInvokeOnMainThread(() => {
string path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/test.mp4";
recorder = new MediaRecorder();
//If you want to rotate the video screen, you can use following code
//Camera camera = Camera.Open();
//Camera.Parameters parameters = camera.GetParameters();
//parameters.SetPreviewSize(640, 480);
//parameters.SetPictureSize(640, 480);
//camera.SetParameters(parameters);
//camera.SetDisplayOrientation(90);
//camera.Unlock();
//recorder.SetCamera(camera);
recorder.SetVideoSource(VideoSource.Camera);
recorder.SetAudioSource(AudioSource.Mic);
recorder.SetOutputFormat(OutputFormat.Default);
recorder.SetVideoEncoder(VideoEncoder.Default);
recorder.SetAudioEncoder(AudioEncoder.Default);
recorder.SetOutputFile(path);
recorder.SetPreviewDisplay(surfaceView.Holder.Surface);
recorder.Prepare();
recorder.Start();
});
}
If you want to achieve the record the video inside the application, you should use custom renderer to view. Use SurfaceView to see the camera view.First of all. please create a CameraPreview
public sealed class CameraPreview : ViewGroup, ISurfaceHolderCallback
{
public SurfaceView surfaceView;
ISurfaceHolder holder;
Camera.Size previewSize;
IList<Camera.Size> supportedPreviewSizes;
Camera camera;
IWindowManager windowManager;
MediaRecorder recorder;
public bool IsPreviewing { get; set; }
public Camera Preview {
get { return camera; }
set {
camera = value;
if (camera != null) {
supportedPreviewSizes = Preview.GetParameters().SupportedPreviewSizes;
RequestLayout();
}
}
}
public CameraPreview (Context context)
: base (context)
{
surfaceView = new SurfaceView (context);
AddView (surfaceView);
windowManager = Context.GetSystemService (Context.WindowService).JavaCast<IWindowManager>();
IsPreviewing = false;
holder = surfaceView.Holder;
holder.AddCallback (this);
MessagingCenter.Subscribe<string>("111", "Hi", (expense) =>
{
startRecord(surfaceView);
});
MessagingCenter.Subscribe<string>("1112", "Hi2", (expense) =>
{
stopRecord(surfaceView);
});
}
private void stopRecord(SurfaceView surfaceView)
{
recorder.Stop();
recorder.Release();
}
public void startRecord(SurfaceView surfaceView)
{
Device.BeginInvokeOnMainThread(() => {
string path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/test.mp4";
recorder = new MediaRecorder();
//If you want to rotate the video screen, you can use following code
//Camera camera = Camera.Open();
//Camera.Parameters parameters = camera.GetParameters();
//parameters.SetPreviewSize(640, 480);
//parameters.SetPictureSize(640, 480);
//camera.SetParameters(parameters);
//camera.SetDisplayOrientation(90);
//camera.Unlock();
//recorder.SetCamera(camera);
recorder.SetVideoSource(VideoSource.Camera);
recorder.SetAudioSource(AudioSource.Mic);
recorder.SetOutputFormat(OutputFormat.Default);
recorder.SetVideoEncoder(VideoEncoder.Default);
recorder.SetAudioEncoder(AudioEncoder.Default);
recorder.SetOutputFile(path);
recorder.SetPreviewDisplay(surfaceView.Holder.Surface);
recorder.Prepare();
recorder.Start();
});
}
protected override void OnMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
int width = ResolveSize (SuggestedMinimumWidth, widthMeasureSpec);
int height = ResolveSize (SuggestedMinimumHeight, heightMeasureSpec);
SetMeasuredDimension (width, height);
if (supportedPreviewSizes != null) {
previewSize = GetOptimalPreviewSize (supportedPreviewSizes, width, height);
}
}
protected override void OnLayout (bool changed, int l, int t, int r, int b)
{
var msw = MeasureSpec.MakeMeasureSpec (r - l, MeasureSpecMode.Exactly);
var msh = MeasureSpec.MakeMeasureSpec (b - t, MeasureSpecMode.Exactly);
surfaceView.Measure (msw, msh);
surfaceView.Layout (0, 0, r - l, b - t);
}
public void SurfaceCreated (ISurfaceHolder holder)
{
try {
if (Preview != null) {
Preview.SetPreviewDisplay (holder);
}
} catch (Exception ex) {
System.Diagnostics.Debug.WriteLine (#" ERROR: ", ex.Message);
}
}
public void SurfaceDestroyed (ISurfaceHolder holder)
{
if (Preview != null) {
Preview.StopPreview ();
}
}
public void SurfaceChanged (ISurfaceHolder holder, Android.Graphics.Format format, int width, int height)
{
var parameters = Preview.GetParameters ();
parameters.SetPreviewSize (previewSize.Width, previewSize.Height);
RequestLayout ();
//If you want to rotate the video screen, you can use following code
//switch (windowManager.DefaultDisplay.Rotation) {
//case SurfaceOrientation.Rotation0:
// camera.SetDisplayOrientation (90);
// break;
//case SurfaceOrientation.Rotation90:
// camera.SetDisplayOrientation (0);
// break;
//case SurfaceOrientation.Rotation270:
// camera.SetDisplayOrientation (180);
// break;
//}
Preview.SetParameters (parameters);
Preview.StartPreview ();
IsPreviewing = true;
}
Camera.Size GetOptimalPreviewSize (IList<Camera.Size> sizes, int w, int h)
{
const double AspectTolerance = 0.1;
double targetRatio = (double)w / h;
if (sizes == null) {
return null;
}
Camera.Size optimalSize = null;
double minDiff = double.MaxValue;
int targetHeight = h;
foreach (Camera.Size size in sizes) {
double ratio = (double)size.Width / size.Height;
if (Math.Abs (ratio - targetRatio) > AspectTolerance)
continue;
if (Math.Abs (size.Height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.Abs (size.Height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = double.MaxValue;
foreach (Camera.Size size in sizes) {
if (Math.Abs (size.Height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.Abs (size.Height - targetHeight);
}
}
}
return optimalSize;
}
}
Then, Here is custom renderer.
[assembly: ExportRenderer(typeof(CustomRenderer.CameraPreview), typeof(CameraPreviewRenderer))]
namespace CustomRenderer.Droid
{
public class CameraPreviewRenderer : ViewRenderer
{
CameraPreview cameraPreview;
public CameraPreviewRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<CustomRenderer.CameraPreview> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// Unsubscribe
cameraPreview.Click -= OnCameraPreviewClicked;
}
if (e.NewElement != null)
{
if (Control == null)
{
cameraPreview = new CameraPreview(Context);
SetNativeControl(cameraPreview);
}
Control.Preview = Camera.Open((int)e.NewElement.Camera);
// Subscribe
cameraPreview.Click += OnCameraPreviewClicked;
}
}
void OnCameraPreviewClicked(object sender, EventArgs e)
{
if (cameraPreview.IsPreviewing)
{
cameraPreview.Preview.StopPreview();
cameraPreview.IsPreviewing = false;
}
else
{
cameraPreview.Preview.StartPreview();
cameraPreview.IsPreviewing = true;
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Control.Preview.Release();
}
base.Dispose(disposing);
}
}
}
If you want to know how to achieve Camera Preview in the IOS or UWP, you can refer to this link.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/view
Here is code in github.
https://github.com/851265601/FormsRecordVideoInside
Above way to achieve it, it a bit complexed. I suggest you to use the Xam.Plugin.Media to achieve it. Here is running GIF. it cannot see the video preview in the application, but you do not need to use custom renderer to achieve it just serveral lines code.
private async void PlayStopButtonText_Clicked(object sender, EventArgs e)
{
// throw new NotImplementedException();
var file = await CrossMedia.Current.TakeVideoAsync(new StoreVideoOptions
{
SaveToAlbum = true,Directory = "Sample"
});
//Get the public album path
if (file == null)
return;
await DisplayAlert("File Location", file.AlbumPath, "OK");
}
In the android, add the following permission.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Here is running GIF(Over 2M, SO cannot allow upload it ).
https://imgur.com/a/9WE4szZ
I am using Xamarin.Android to use inbuilt camera app to take a photo
but there are two missed things that I cant do and I have been googling them for long time:
I want to get a msg or popup (anything) after pressing the button to take a photo like "photo taken"
I want to let the user focus on any point of the camera - TAP TO FOCUS
async void TakePhotoButtonTapped(object sender, EventArgs e)
{
camera.StopPreview();
Android.Hardware.Camera.Parameters parameters = camera.GetParameters();
parameters.FocusMode = global::Android.Hardware.Camera.Parameters.FocusModeAuto;
camera.SetParameters(parameters);
var image = textureView.Bitmap;
try
{
var absolutePath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim).AbsolutePath;
var folderPath = absolutePath + "/Camera";
var filePath = System.IO.Path.Combine(folderPath, string.Format("photo_{0}.jpg", Guid.NewGuid()));
var fileStream = new FileStream(filePath, FileMode.Create);
await image.CompressAsync(Bitmap.CompressFormat.Jpeg, 92, fileStream);
fileStream.Close();
image.Recycle();
var intent = new Android.Content.Intent(Android.Content.Intent.ActionMediaScannerScanFile);
var file = new Java.IO.File(filePath);
var uri = Android.Net.Uri.FromFile(file);
intent.SetData(uri);
MainActivity.Instance.SendBroadcast(intent);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(#" ", ex.Message);
}
camera.StartPreview();
}
I tried this but not working:
public void OnAutoFocus(bool success, Android.Hardware.Camera camera)
{
var parameters = camera.GetParameters();
if (parameters.FocusMode != Android.Hardware.Camera.Parameters.FocusModeContinuousPicture)
{
parameters.FocusMode = Android.Hardware.Camera.Parameters.FocusModeContinuousPicture;
if (parameters.MaxNumFocusAreas > 0)
{
parameters.FocusAreas = null;
}
camera.SetParameters(parameters);
camera.StartPreview();
}
}
public bool OnTouch(Android.Views.View view, MotionEvent e)
{
if (camera != null)
{
var parameters = camera.GetParameters();
camera.CancelAutoFocus();
Rect focusRect = CalculateTapArea(e.GetX(), e.GetY(), 1f);
if (parameters.FocusMode != Android.Hardware.Camera.Parameters.FocusModeAuto)
{
parameters.FocusMode = Android.Hardware.Camera.Parameters.FocusModeAuto;
}
if (parameters.MaxNumFocusAreas > 0)
{
List<Area> mylist = new List<Area>();
mylist.Add(new Android.Hardware.Camera.Area(focusRect, 1000));
parameters.FocusAreas = mylist;
}
try
{
camera.CancelAutoFocus();
camera.SetParameters(parameters);
camera.StartPreview();
camera.AutoFocus(this);
}
catch (System.Exception ex)
{
Console.WriteLine(ex.ToString());
Console.Write(ex.StackTrace);
}
return true;
}
return false;
}
private Rect CalculateTapArea(object x, object y, float coefficient)
{
var focusAreaSize = 500;
int areaSize = Java.Lang.Float.ValueOf(focusAreaSize * coefficient).IntValue();
int left = clamp((int) x - areaSize / 2, 0, textureView.Width - areaSize);
int top = clamp((int) y - areaSize / 2, 0, textureView.Height - areaSize);
RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
Matrix.MapRect(rectF);
return new Rect((int) System.Math.Round(rectF.Left), (int) System.Math.Round(rectF.Top), (int) System.Math.Round(rectF.Right),
(int) System.Math.Round(rectF.Bottom));
}
private int clamp(int x, int min, int max)
{
if (x > max)
{
return max;
}
if (x < min)
{
return min;
}
return x;
}
For focusing the camera when touching the preview you will need to:
Add a touch event handler to listen for the user touching the preview
Get the X and Y coordinates from that touch event, which are usually in the event arguments
Create a rectangle to focus to tell the Android Camera where to focus and in which area
Set FocusAreas and MeteringAreas on Camera.Parameters from your rectangle
Set the new Camera.Parameters on the camera
Set a AutoFocus callback on the camera
When the callback triggers, remove the callback from the camera, and cancel auto focus
To notify the user about a picture being taken, you can use a Toast or create a area in your preview where you want to show such messages. It is entirely up to you how you want to notify the user.
I used following code to drag and drop Button in C# and it works like charm when my Form.RightToLeftLayout=False,
but
when I set RightToLeftLayout=True
it doesnt work and move the control in wrong direction!!!
public partial class Form1 : Form
{
int xPosition;
int yPosition;
bool isDraged;
public Form1()
{
InitializeComponent();
}
private void btnMoveable_MouseDown(object sender, MouseEventArgs e)
{
this.Cursor = Cursors.SizeAll;
xPosition = e.X;
yPosition = e.Y;
isDraged = true;
}
private void btnMoveable_MouseUp(object sender, MouseEventArgs e)
{
isDraged = false;
this.Cursor = Cursors.Default;
}
private void btnMoveable_MouseMove(object sender, MouseEventArgs e)
{
if (isDraged)
{
btnMoveable.Left = btnMoveable.Left + e.X - xPosition;
btnMoveable.Top = btnMoveable.Top + e.Y - yPosition;
}
}
}
Well, you're discovering how RightToLeft is implemented. Everything is still in their normal logical position but the coordinate system is mirror-imaged along the Y-axis. So movement along the X-axis is inverted. You'll need to accommodate that. Fix:
int dx = e.X - xPosition;
if (this.RightToLeft == RightToLeft.Yes) dx = -dx;
btnMoveable.Left = btnMoveable.Left + dx;
I am calling invalidate() which is calling onDraw(). The bitmap that I wish to show on the screen is not being displayed after running doInBackGround(). Can anyone help?
Here is what I have tested out so far.
When I place the same line of code
canvas.drawBitmap();
in onPreExecute() it works, but in onPostExecute() it does not display the expected results.
This is my code:
public class FloorAppActivity extends Activity {
private Context globalContext;
private Point displaySize;
private int displayWidth;
private int displayHeight;
private String floorID;
private String floorName;
private String floorGridNumStr;
private int floorGridNum;
private String floorNumStr;
private int positionX;
private int positionY;
private int XCoord;
private int YCoord;
private int ZCoord;
private float signalStr;
private Integer dBm;
private Bitmap floorPlan;
private Bitmap userMark;
private Bitmap redPin;
private FloorView floorView;
private Connection conn = null;
private Canvas canvas=null;
private int newScrollRectX=0;
private int newScrollRectY=0;
private Paint paint;
private boolean a = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
globalContext = this;
floorID = getIntent().getStringExtra("floorID");
floorName = getIntent().getStringExtra("floorName");
positionX = getIntent().getIntExtra("userPositionX",-1);
positionY = getIntent().getIntExtra("userPositionY",-1);
dBm = getIntent().getIntExtra("BestSignal", -1);
//Get the grid number
if(Integer.parseInt(floorName.substring(floorName.lastIndexOf("_")+1))<10)
floorGridNumStr = floorName.substring(8, 9);
else
floorGridNumStr = floorName.substring(8, 10);
floorGridNum = Integer.parseInt(floorGridNumStr);
floorNumStr = floorName.substring(5,7);
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
displaySize = new Point();
try {
// GetSize is not available in older models of Android
display.getSize(displaySize);
} catch (java.lang.NoSuchMethodError ignore) { // Older device
displaySize.x = display.getWidth();
displaySize.y = display.getHeight();
}
try {
InputStream source = getAssets().open(floorID);
floorPlan = BitmapFactory.decodeStream(source);
displayWidth = Math.min(displaySize.x, floorPlan.getWidth());
displayHeight = Math.min(displaySize.y, floorPlan.getHeight());
userMark = BitmapFactory.decodeResource(getResources(),R.drawable.star);
redPin = BitmapFactory.decodeResource(getResources(),R.drawable.redpin);
floorView = new FloorView(this);
setContentView(floorView);
}
catch (IOException e) {
MapServerAPI server = new MapServerAPI(globalContext,"Retrieving floor plan. Please wait...") {
#Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if (bitmap == null)
Toast.makeText(globalContext, "Error in retrieving floor plan!", Toast.LENGTH_LONG).show();
else {
floorPlan = bitmap;
displayWidth = Math.min(displaySize.x, floorPlan.getWidth());
displayHeight = Math.min(displaySize.x, floorPlan.getHeight());
userMark = BitmapFactory.decodeResource(getResources(),R.drawable.star);
redPin = BitmapFactory.decodeResource(getResources(),R.drawable.redpin);
floorView = new FloorView(globalContext);
setContentView(floorView);
}
}
};
server.execute(floorID);
}
}
#Override
public void onResume() {
super.onResume();
registerReceiver(broadcastReceiver,new IntentFilter("FingerPrint_LOCATION_UPDATE"));
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
}
// listen for user location change
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String result = intent.getStringExtra("location");
Toast.makeText(context,result,Toast.LENGTH_LONG).show();
String floorId = intent.getStringExtra("floorID");
floorName = intent.getStringExtra("name");
dBm = intent.getIntExtra("BestSignal", -1);
int userLocationX = intent.getIntExtra("userPositionX",-1);
int userLocationY = intent.getIntExtra("userPositionY",-1);
//Get the grid number
if(Integer.parseInt(floorName.substring(floorName.lastIndexOf("_")+1))<10)
floorGridNumStr = floorName.substring(8, 9);
else
floorGridNumStr = floorName.substring(8, 10);
floorGridNum = Integer.parseInt(floorGridNumStr);
floorNumStr = floorName.substring(5,7);
if(!floorId.equals(floorID)){
positionX = userLocationX;
positionY = userLocationY;
InputStream source=null;
try {
source = getAssets().open(floorID);
} catch (IOException e) {
}
floorPlan = BitmapFactory.decodeStream(source);
floorView.postInvalidate();
}
}
};
private class FloorView extends View {
private Rect displayRect; //rect we display to
private Rect scrollRect; //rect we scroll over our bitmap with
private int scrollRectX = 0; //current left location of scroll rect
private int scrollRectY = 0; //current top location of scroll rect
private float scrollByX = 0; //x amount to scroll by
private float scrollByY = 0; //y amount to scroll by
private float startX = 0; //track x from one ACTION_MOVE to the next
private float startY = 0; //track y from one ACTION_MOVE to the next
public FloorView(Context context) {
super(context);
// Destination rect for our main canvas draw. It never changes.
displayRect = new Rect(0, 0, displayWidth, displayHeight);
// Scroll rect: this will be used to 'scroll around' over the
// bitmap in memory.
if (positionX + displayWidth / 2 > floorPlan.getWidth())
scrollRectX = floorPlan.getWidth() - displayWidth;
else
scrollRectX = positionX - displayWidth / 2;
if (scrollRectX < 0)
scrollRectX = 0;
if (positionY + displayHeight / 2 > floorPlan.getHeight())
scrollRectY = floorPlan.getHeight() - displayHeight;
else
scrollRectY = positionY - displayHeight / 2;
if (scrollRectY < 0)
scrollRectY = 0;
scrollRect = new Rect(scrollRectX, scrollRectY, displayWidth, displayHeight);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Remember our initial down event location.
startX = event.getRawX();
startY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
float x = event.getRawX();
float y = event.getRawY();
// Calculate move update. This will happen many times
// during the course of a single movement gesture.
scrollByX = x - startX; //move update x increment
scrollByY = y - startY; //move update y increment
startX = x; //reset initial values to latest
startY = y;
invalidate(); //force a redraw
break;
}
return true; //done with this event so consume it
}
#Override
protected void onDraw(Canvas canvas1) {
canvas=canvas1;
// Our move updates are calculated in ACTION_MOVE in the opposite direction
// from how we want to move the scroll rect. Think of this as dragging to
// the left being the same as sliding the scroll rect to the right.
newScrollRectX = scrollRectX - (int)scrollByX;
newScrollRectY = scrollRectY - (int)scrollByY;
// Don't scroll off the left or right edges of the bitmap.
if (newScrollRectX < 0)
newScrollRectX = 0;
else if (newScrollRectX > (floorPlan.getWidth() - displayWidth))
newScrollRectX = (floorPlan.getWidth() - displayWidth);
// Don't scroll off the top or bottom edges of the bitmap.
if (newScrollRectY < 0)
newScrollRectY = 0;
else if (newScrollRectY > (floorPlan.getHeight() - displayHeight))
newScrollRectY = (floorPlan.getHeight() - displayHeight);
// We have our updated scroll rect coordinates, set them and draw.
scrollRect.set(newScrollRectX, newScrollRectY,
newScrollRectX + displayWidth, newScrollRectY + displayHeight);
paint = new Paint();
canvas.drawBitmap(floorPlan, scrollRect, displayRect, paint);
// Update user position
if (positionX >= newScrollRectX && positionX - newScrollRectX <= displayWidth
&& positionY >= newScrollRectY && positionY - newScrollRectY <= displayHeight)
canvas.drawBitmap(userMark,positionX-newScrollRectX-userMark.getWidth()/2,positionY-newScrollRectY-userMark.getHeight()/2,paint);
class AsyncTaskToConnect extends AsyncTask <Void, Void, Void>{
#Override
protected Void doInBackground(Void... cmd) {
// connect to database and retrieve values
return null;
}
#Override
protected void onPostExecute(Void v)
{//PE
if (positionX >= newScrollRectX && positionX - newScrollRectX <= displayWidth
&& positionY >= newScrollRectY && positionY - newScrollRectY <= displayHeight)
{
canvas.drawBitmap(redPin,480-newScrollRectX-userMark.getWidth()/2,90-newScrollRectY-userMark.getHeight()/2,paint);
}
//return null;
// Reset current scroll coordinates to reflect the latest updates,
// so we can repeat this update process.
scrollRectX = newScrollRectX;
scrollRectY = newScrollRectY;
}//PE
}
AsyncTaskToConnect[] asyncTaskC = null;
asyncTaskC = new AsyncTaskToConnect[1];
asyncTaskC[0] = new AsyncTaskToConnect();
asyncTaskC[0].executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// Cache our new dimensions; we'll need them for drawing.
displayWidth = Math.min(w, floorPlan.getWidth());
displayHeight = Math.min(h, floorPlan.getHeight());
// Destination rect for our main canvas draw.
displayRect = new Rect(0, 0, displayWidth, displayHeight);
// Scroll rect: this will be used to 'scroll around' over the
// bitmap in memory.
if (positionX + displayWidth / 2 > floorPlan.getWidth())
scrollRectX = floorPlan.getWidth() - displayWidth;
else
scrollRectX = positionX - displayWidth / 2;
if (scrollRectX < 0)
scrollRectX = 0;
if (positionY + displayHeight / 2 > floorPlan.getHeight())
scrollRectY = floorPlan.getHeight() - displayHeight;
else
scrollRectY = positionY - displayHeight / 2;
if (scrollRectY < 0)
scrollRectY = 0;
scrollRect = new Rect(scrollRectX, scrollRectY, displayWidth, displayHeight);
super.onSizeChanged(w, h, oldw, oldh);
}
}
}
P.S. This is my first time posting. Please pardon me if i make mistakes in my post. Thanks.
I think the problem is that you are storing the Canvas object passed into the onDraw method. The object may not be valid after the onDraw method has returned.
It looks like you are trying to prepare a Bitmap on a background thread and then draw it on screen when it has been prepared. The way you do it is - prepare the Bitmap and just call invalidate on the View in onPostExecute method. Then in the onDraw method, you can take that Bitmap object and draw it using canvas.drawBitmap
I am developing a Windows 8 app using WinJS. I am trying to get the touch coordinates for pinch and zoom. I have implemented the gesture manipulation handlers via Windows.UI.Input.GestureRecognizer. I am triggering my pinch and zoom logic when for the "manipulationupdated" event, event.delta.scale is not 1. When manipulation happens inside the "manipulationupdated" event object I find coordinates of only 1 position. How do I calculate both the finger touch coordinates from this information?
Also how do I know which touch coordinate the position belong to? I find the position repeated multiple times inside the event object - at event.position and event.detail[0].position
What I am trying to achieve is performing pinch and zoom in a chart(much like a map). Kindly help me out with these questions.
public class PZBehavior : Behavior
{
bool _isDragging;
bool _isPinching;
Point _ptPinchPositionStart;
private Image _imgZoom;
private ScaleTransform _scaleTransform;
private RotateTransform _rotateTransform;
private TranslateTransform _translateTransform;
private MatrixTransform _previousTransform;
private TransformGroup _parentGroup;
private TransformGroup _currentTransform;
protected override void OnAttached()
{
_imgZoom = AssociatedObject;
_imgZoom.RenderTransform = BuildTrasnformGroup();
var listener = GestureService.GetGestureListener(AssociatedObject);
listener.DragStarted += DragStarted;
listener.DragDelta += DragDelta;
listener.DragCompleted += DragCompleted;
listener.PinchStarted += PinchStarted;
listener.PinchDelta += PinchDelta;
listener.PinchCompleted += PinchCompleted;
}
private TransformGroup BuildTrasnformGroup()
{
_parentGroup = new TransformGroup();
_currentTransform = new TransformGroup();
_previousTransform = new MatrixTransform();
_scaleTransform = new ScaleTransform();
_rotateTransform = new RotateTransform();
_translateTransform = new TranslateTransform();
_currentTransform.Children.Add(_scaleTransform);
_currentTransform.Children.Add(_rotateTransform);
_currentTransform.Children.Add(_translateTransform);
_parentGroup.Children.Add(_previousTransform);
_parentGroup.Children.Add(_currentTransform);
return _parentGroup;
}
void PinchCompleted(object sender, PinchGestureEventArgs e)
{
if (_isPinching)
{
TransferTransforms();
_isPinching = false;
}
}
void PinchDelta(object sender, PinchGestureEventArgs e)
{
if (_isPinching)
{
// Set scaling
_scaleTransform.ScaleX = e.DistanceRatio;
_scaleTransform.ScaleY = e.DistanceRatio;
// Optionally set rotation
_rotateTransform.Angle = e.TotalAngleDelta;
// Set translation
Point ptPinchPosition = new Point(0,0);
_translateTransform.X = ptPinchPosition.X - _ptPinchPositionStart.X;
_translateTransform.Y = ptPinchPosition.Y - _ptPinchPositionStart.Y;
}
}
void PinchStarted(object sender, PinchStartedGestureEventArgs e)
{
_isPinching = e.OriginalSource == _imgZoom;
if (_isPinching)
{
// Set transform centers
Point ptPinchCenter = e.GetPosition(_imgZoom);
ptPinchCenter = _previousTransform.Transform(ptPinchCenter);
_scaleTransform.CenterX = ptPinchCenter.X;
_scaleTransform.CenterY = ptPinchCenter.Y;
_rotateTransform.CenterX = ptPinchCenter.X;
_rotateTransform.CenterY = ptPinchCenter.Y;
_ptPinchPositionStart = new Point(0,0);
}
}
void DragCompleted(object sender, DragCompletedGestureEventArgs e)
{
if (_isDragging)
{
TransferTransforms();
_isDragging = false;
}
}
void DragDelta(object sender, DragDeltaGestureEventArgs e)
{
if (_isDragging)
{
_translateTransform.X += e.HorizontalChange;
_translateTransform.Y += e.VerticalChange;
}
}
void DragStarted(object sender, DragStartedGestureEventArgs e)
{
_isDragging = e.OriginalSource == _imgZoom;
}
void TransferTransforms()
{
_previousTransform.Matrix = Multiply(_previousTransform.Matrix, _currentTransform.Value);
// Set current transforms to default values
_scaleTransform.ScaleX = _scaleTransform.ScaleY = 1;
_scaleTransform.CenterX = _scaleTransform.CenterY = 0;
_rotateTransform.Angle = 0;
_rotateTransform.CenterX = _rotateTransform.CenterY = 0;
_translateTransform.X = _translateTransform.Y = 0;
}
Matrix Multiply(Matrix a, Matrix b)
{
return new Matrix(a.M11 * b.M11 + a.M12 * b.M21,
a.M11 * b.M12 + a.M12 * b.M22,
a.M21 * b.M11 + a.M22 * b.M21,
a.M21 * b.M12 + a.M22 * b.M22,
a.OffsetX * b.M11 + a.OffsetY * b.M21 + b.OffsetX,
a.OffsetX * b.M12 + a.OffsetY * b.M22 + b.OffsetY);
}
}