Xamarin.Forms iOS Create animation using images - xamarin.forms

I work on Xamarin.Fomrs shared project. I want to display multiple images at same place with 100 ms interval. So that it will look like a GIF. In Android It is working. I created drawable file and in that I have put all the images with time interval. But in iOS, I am facing problem.
I found CAKeyFrameAnimation is used to implement this type of functionality. But I couldn't find how to implement it as I want.
I have implemented CAKeyFrameAnimation in ImageRenderer like this
class AnimatedImageRenderer : ImageRenderer
{
public AnimatedImageRenderer() { }
Animation objAnimation = new Animation();
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (Control != null)
{
try
{
CAKeyFrameAnimation anim = CAKeyFrameAnimation.FromKeyPath("contents");
anim.Duration = 1;
//anim.KeyTimes = new[] {
// NSNumber.FromDouble (0), // FIRST VALUE MUST BE 0
// NSNumber.FromDouble (0.1),
// NSNumber.FromDouble(0.2),
// NSNumber.FromDouble(0.3),
// NSNumber.FromDouble(0.5),
// NSNumber.FromDouble(0.6),
// NSNumber.FromDouble(0.8),
// NSNumber.FromDouble(1.0), // LAST VALUE MUST BE 1
// };
anim.Values = new NSObject[] {
FromObject(UIImage.FromFile("bomb1.png")),
FromObject(UIImage.FromFile("bomb2.png")),
FromObject(UIImage.FromFile("bomb3.png")),
FromObject(UIImage.FromFile("bomb4.png")),
FromObject(UIImage.FromFile("bomb5.png")),
FromObject(UIImage.FromFile("bomb6.png")),
FromObject(UIImage.FromFile("bomb7.png")),
};
//anim.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear);
anim.RepeatCount = 1;
anim.RemovedOnCompletion = false;
//anim.CalculationMode = CAAnimation.AnimationLinear;
//c.Init();
Control.Layer.AddAnimation(anim, "bomb");
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
// ModCommon.TraceLog("AnimatedImageRenderer tm_Tick" + ex.Message);
}
}
}
}
I don't know what extra property is missing. Please guide me.
Thank you :)

You should use CGImage instead of UIImage. Change your animation's value to:
anim.Values = new NSObject[] {
FromObject(UIImage.FromFile("bomb1.png").CGImage),
FromObject(UIImage.FromFile("bomb2.png").CGImage),
FromObject(UIImage.FromFile("bomb3.png").CGImage),
FromObject(UIImage.FromFile("bomb4.png").CGImage),
FromObject(UIImage.FromFile("bomb5.png").CGImage),
FromObject(UIImage.FromFile("bomb6.png").CGImage),
FromObject(UIImage.FromFile("bomb7.png").CGImage),
};

Related

HERE-SDK lite drag marker in MapView

I am just trying out the SDK Lite API and I am wondering how I can achieve to drag a MapMarker object from one place to another. I suggest, it works somehow with disabling the default onPan gesture, but actually the problem starts with picking an existing object.
Here is my code so far:
public void pickMarker(Point2D p) {
map.getGestures().disableDefaultAction(GestureType.PAN);
map.pickMapItems(p, 20f, pickMapItemsResult -> {
if (pickMapItemsResult != null) {
pickedMarker = pickMapItemsResult.getTopmostMarker();
} else {
map.getGestures().enableDefaultAction(GestureType.PAN);
}
});
}
public void dragMarker(Point2D p) {
if (pickedMarker != null) {
pickedMarker.setCoordinates(map.getCamera().viewToGeoCoordinates(p));
}
}
public boolean releaseMarker(Point2D p) {
map.getGestures().enableDefaultAction(GestureType.PAN);
if (pickedMarker != null) {
GeoCoordinates newCoordinates = map.getCamera().viewToGeoCoordinates(p);
pickedMarker.setCoordinates(newCoordinates);
pickedMarker = null;
return true;
}
return false;
}
while these functions are called on the three states of the onPanListener:
mapView.getGestures().setPanListener((gestureState, point2D, point2DUpdate, v) -> {
if (gestureState.equals(GestureState.BEGIN)) {
mapViewUIEngine.pickMarker(point2D);
}
if (gestureState.equals(GestureState.UPDATE)) {
mapViewUIEngine.dragMarker(point2DUpdate);
}
if (gestureState.equals(GestureState.END)) {
if (mapViewUIEngine.releaseMarker(point2DUpdate)) {
regionController.movePoint(0,
updateNewLocation(point2D, point2DUpdate);
}
}
});
From one of the developer in Github I now know, that the polygon is returned instead of the marker (which is lying on a polygon line, but how can I get the marker instead?
You can use map markers to precisely point to a location on the map.
The following method will add a custom map marker to the map:
MapImage mapImage = MapImageFactory.fromResource(context.getResources(), R.drawable.here_car);
MapMarker mapMarker = new MapMarker(geoCoordinates);
mapMarker.addImage(mapImage, new MapMarkerImageStyle());
mapView.getMapScene().addMapMarker(mapMarker);
For more details, please refer
https://developer.here.com/documentation/android-sdk/dev_guide/topics/map-items.html#add-map-markers

Sitecore: Show input option after using menu context item

I've added a menu context item to the TreelistEx. This menu item sends a messages that I later catch in a HandleMessage method.
In this method i create a new item ( template type and parent item are given in the source of the treelist field ).
All i need now is a way to ask the user for a name. But i haven't been able to find a simple way to do this.
class MyTreeListEx : TreelistEx, IMessageHandler
{
void IMessageHandler.HandleMessage(Message message)
{
if (message == null)
{ return; }
if (message["id"] == null)
{ return; }
if (!message["id"].Equals(ID))
{ return; }
switch (message.Name)
{
case "treelist:edit":
// call default treelist code
case "mytreelistex:add":
// my own code to create a new item
}
}
}
Does anyone have any suggestions on how to achieve this ?
Edit: added image & code + i'm using Sitecore 8 Update 1
I don't know which version of Sitecore you use but what you can try is SheerResponse.Input method.
You can use it like this:
using Sitecore.Configuration;
using Sitecore.Globalization;
using Sitecore.Shell.Applications.ContentEditor.FieldTypes;
using Sitecore.Web.UI.Sheer;
void IMessageHandler.HandleMessage(Message message)
{
...
case "mytreelistex:add":
Sitecore.Context.ClientPage.Start(this, "AddItem");
break;
}
protected static void AddItem(ClientPipelineArgs args)
{
if (args.IsPostBack)
{
if (!args.HasResult)
return;
string newItemName = args.Result;
// create new item here
// if you need refresh the page:
//SheerResponse.Eval("scForm.browser.getParentWindow(scForm.browser.getFrameElement(window).ownerDocument).location.reload(true)");
}
else
{
SheerResponse.Input("Enter the name of the new item:", "New Item Default Name", Settings.ItemNameValidation,
Translate.Text("'$Input' is not a valid name."), Settings.MaxItemNameLength);
args.WaitForPostBack();
}
}
This code will even validate your new item name for incorrect characters and length.

Adobe Flex: memory leak when pushView an popView

I am having problems of memory leaks with an app I had build in Adobe Flex, using Flex Builder. After using it for 30-40 minutes it starts to go slower and slower.
The app shows images as a catalog, but when I push and pop the views my memory rise considerably.
My thoughts are that if I set all my objects to null and dispose all the bitmapdata that I use I could free enough memory to keep using the app with no problems, but it seems like the problem is not there.
I have 3 views in my app menuView.mxml,categoriesView.mxml and productsView.mxml.
My App starts up in my pc (not in tablet) with TotalMemory: 47Mb and Private Memory : 88 MB
After pushing and poping the views for 5 times I get TotalMemory: 61Mb and Private Memory : 101 MB
Imagine if I do this several times. The app begins to go very slow in my Ipad or my Samsung Galaxy Tab.
Why is this happening? I have no idea how to solve this.
Please help! Thanks a lot!!
I put some code below.
When I am in menuView I use the following code to push the view from menuView to categoriesView
protected function button3_clickHandler(event:MouseEvent):void
{
if((FlexGlobals.topLevelApplication.getIdClienteServidorCompraActual( )!=null)&& (FlexGlobals.topLevelApplication.getIdClienteServidorCompraA ctual()>0))
{
navigator.pushView(categoriesView);
}
}
When I am in categoriesView I use the following code to push the view from categoriesView to productsView. In this view I have 3 buttons for each category.
protected function buttonC1_clickHandler(event:MouseEvent):void
{
//Categoria general con todos
var ab:ArrayCollection = getIdAmbienteServidor();
cleanMemory();
navigator.pushView(productsView, null);
}
private function cleanMemory():void
{
result.splice(0);
result = null;
System.gc();
}
When I am in productsView I use the following code to pop(I USE PUSH INSTEAD OF POP DUE TO DIFFERENT OPTIONS I HAVE) the view from productsView to categoriesView .
protected function button1_clickHandler(event:MouseEvent):void
{
cleanMemory();
navigator.pushView(menuView);
}
private function cleanMemory():void
{
if(image1 != null)
{
image1.source = "";
if(image1.bitmapData != null)
{
image1.bitmapData.dispose();
}
}
if(image2 != null)
{
image2.source = "";
if(image2.bitmapData != null)
{
image2.bitmapData.dispose();
}
}
if(result != null)
{
result.splice(0);
result = null;
}
if(result1 != null)
{
result1.splice(0);
result1 = null;
}
if(result2 != null)
{
result2.splice(0);
result2 = null;
}
dbConnection = null;
object1 = null;
object2 = null;
dataToSave = null;
cGreyImageSmallAsset = null;
cRedImageSmallAsset.bitmapData.dispose();
cRedImageSmallAsset = null;
cOrangeImageAsset.bitmapData.dispose();
cOrangeImageAsset = null;
cGreenImageAsset.bitmapData.dispose();
cGreenImageAsset = null;
cPinkImageAsset.bitmapData.dispose();
cPinkImageAsset = null;
cBlueImageAsset.bitmapData.dispose();
cBlueImageAsset = null;
cGreyImageAsset.bitmapData.dispose();
cGreyImageAsset = null;
cRedImageAsset.bitmapData.dispose();
cRedImageAsset = null;
cGreenImageSmall = null;
cOrangeImageSmall = null;
cPinkImageSmall = null;
cBlueImageSmall = null;
cGreyImageSmall = null;
cRedImageSmall= null;
cGreenImage = null;
cPinkImage = null;
cBlueImage= null;
cGreyImage = null;
cRedImage= null;
cOrangeImage= null;
System.gc();
}
I load the images with.
private function setImages():void
{
if(object1!=null)
{
panelLeft.visible = true;
buttonLeftMore.visible = true;
image1.source = "file://" + File.applicationStorageDirectory.nativePath + "/b"+object1.idArchivo+"_500.jpg";
setObject1MainTexts();
}
else
{
image1.source = "";
panelLeft.visible = false;
buttonLeftMore.visible = false;
}
if(object2!=null)
{
panelRight.visible = true;
buttonRightMore.visible = true;
image2.source = "file://" + File.applicationStorageDirectory.nativePath + "/b"+object2.idArchivo+"_500.jpg";
setObject2MainTexts();
}
else
{
image2.source = "";
panelRight.visible = false;
buttonRightMore.visible = false;
}
}
When I am in categoriesView i use the following code to pop(I USE PUSH INSTEAD OF POP DUE TO DIFFERENT OPTIONS I HAVE) the view from categoriesView to menuView.
protected function button1_clickHandler(event:MouseEvent):void
{
cleanMemory();
navigator.pushView(menuPrincipalBelda);
}
private function cleanMemory():void
{
result.splice(0);
result = null;
System.gc();
}
Thanks in advance!
I discover the problem: I was not removing the EventListener, now is working fine.
I leave you guys with some examples. If you do not remove them, then memory increases a lot! Be careful with this.
stage.addEventListener("keyUp", handleButtons, false, 1);
stage.removeEventListener("keyUp",handleButtons,false);
xeasy.addEventListener(ResultEvent.RESULT, AppWS_resultHandler);
xeasy.removeEventListener(ResultEvent.RESULT,AppWS_resultHandler, false);
Thanks to everybody!!
Remember that Flex Builder uses the Flash virtual machine and this frees the memory when considered necessary, even if you try to force him to clean the garbage collector will not do if you have free memory and does not consider it necessary.
Test the movie embedded in the images you need in the application, and not constantly loading. Since this may be letting some low-level relationship.
regards
When I worked with GC I found that it became of advantage to try several different ways! I used 3 in total over time, but just can only find one at the moment as this was the one noticeable better working in this App. so here it is and if needed I can send the other two as well must just look for them!
private var gcCount:int;
private function startGCCycle():void {
gcCount = 0;
addEventListener(Event.ENTER_FRAME, doGC);
}
private function doGC(evt:Event):void {
flash.system.System.gc();
if(++gcCount > 1) {
removeEventListener(Event.ENTER_FRAME, doGC);
setTimeout(lastGC, 40);
}
}
private function lastGC():void{
flash.system.System.gc();
}
]]>
I just was looking at something else which you should try as well it worked for me very well!
FlexGlobals.topLevelApplication.deleteReferenceOnParentDocument(this) I used these in a creationComplete in MXML where I had to open 45 Main Canvases one after another but each time with three PopUps = 180 which was easy to handle in the way I worked the GC in! regards aktell

Silverlight DataGrid scrollbar synchronization

I have 2 Silverlight DataGrids one on top of another. I want to synchronize their horizontal scrollbars.
I have tried to put them both in separate scrollviewers and set the horizontal offset of source scrollviewer to horizontal offset of target scrollviewer but that does not work, the below DataGrid scrollviewer disappers.I think that might be because these Datagrid are inside a StackPanel?
I also tried to put these 2 grids in a third grid and apply scrollviewer on that but that does not work either
Does anyone have an idea how to go about this?
Thanks a lot in advance
I did this in SL4, have no idea if it works in SL3, sorry. The docs state that the API is there but I have not tried it.
The trick is to use automation peers. Get the scroll pattern automation peers for both grids. When scrolling happens on one grid, scroll the other one through the automation peer.
To make this more concrete, assuming we have 2 grids, named _dgGrowth and _dgTotals:
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
public partial class MyPageWithGrids : Page {
...
private ScrollBar _sbGrowth, _sbTotals;
private AutomationPeer _peerGrowth, _peerTotals;
private bool _ignoreScrollEvents;
private void OnPageLoaded(object sender, RoutedEventArgs e) {
_sbGrowth = GetHorizontalScrollBar(_dgGrowth);
if (_sbGrowth != null) {
_sbGrowth.Scroll += OnScrollGrowthGrid;
}
_sbTotals = GetHorizontalScrollBar(_dgTotals);
if (_sbTotals != null) {
_sbTotals.Scroll += OnScrollTotalsGrid;
}
_peerGrowth = FrameworkElementAutomationPeer.CreatePeerForElement(_dgGrowth);
_peerTotals = FrameworkElementAutomationPeer.CreatePeerForElement(_dgTotals);
}
private ScrollBar GetHorizontalScrollBar(DataGrid parentGrid) {
return parentGrid.Descendents().OfType<ScrollBar>().FirstOrDefault(sb => sb.Name == "HorizontalScrollbar");
}
private void OnScrollTotalsGrid(object sender, ScrollEventArgs e) {
if (! _ignoreScrollEvents) {
SyncHorizontalScroll(_peerTotals, _peerGrowth);
}
}
private void OnScrollGrowthGrid(object sender, ScrollEventArgs e) {
if (! _ignoreScrollEvents) {
SyncHorizontalScroll(_peerGrowth, _peerTotals);
}
}
private void SyncHorizontalScroll(AutomationPeer source, AutomationPeer copy) {
IScrollProvider sourceProvider = null;
if (source != null) {
sourceProvider = (IScrollProvider) source.GetPattern(PatternInterface.Scroll);
}
IScrollProvider copyProvider = null;
if (copy != null) {
copyProvider = (IScrollProvider) copy.GetPattern(PatternInterface.Scroll);
}
if (sourceProvider != null && copyProvider != null) {
_ignoreScrollEvents = true;
// scroll copy at horizontal position of source, and keep vertical position
copyProvider.SetScrollPercent(sourceProvider.HorizontalScrollPercent, copyProvider.VerticalScrollPercent);
_ignoreScrollEvents = false;
}
}
}
What is not shown is setting up the Loaded event to OnPageLoaded and the Descendants() method found in this question.

UIImagePickerController Crashing Monotouch

I am trying to write an application, but it is constantly crashing when using the uiimagepickercontroller. I thought that it might be because I was not disposing of the picker after each use, but it will often freeze up on first run as well. Usually I'll take a picture and it just freezes, never asking to "use" the picture.
Do you have any suggestions? Here is my code. Has anyone gotten this to work?
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
myPicker = new UIImagePickerController();
myPicker.Delegate = new myPickerDelegate(this);
myAlbumButton.Clicked += delegate {
if(UIImagePickerController.IsSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary)){
myPicker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary;
myPicker.AllowsEditing = true;
this.PresentModalViewController (myPicker, true);
}else{
Console.WriteLine("cannot get album");
}
};
myCameraButton.Clicked += delegate {
if(UIImagePickerController.IsSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){
myPicker.SourceType = UIImagePickerControllerSourceType.Camera;
//myPicker.AllowsEditing = true;
this.PresentModalViewController (myPicker, true);
}else{
Console.WriteLine("cannot get camera");
}
};
}
private class myPickerDelegate : UIImagePickerControllerDelegate
{
private TestView _vc;
public myPickerDelegate ( TestView controller):base()
{
_vc = controller;
}
public override void FinishedPickingImage (UIImagePickerController myPicker, UIImage image, NSDictionary editingInfo)
{
// TODO: Implement - see: http://go-mono.com/docs/index.aspx?link=T%3aMonoTouch.Foundation.ModelAttribute
_vc.myImageView.Image = image;
myPicker.DismissModalViewControllerAnimated(true);
}
}
Try to call your event handlers code from the main thread by using BeginInvokeOnMainThread().
So my issue was very similar.
Instead of having a delegate class, I had the delegates inline for the picker.
For some reason the app froze every time after talking the image, not stopping in any breakpoint after that.
The solution that worked for me was to use this book:
http://www.scribd.com/doc/33770921/Professional-iPhone-Programming-with-MonoTouch-and-NET-C

Resources