Creating File Reference For An XF Shared .FSProj File
November 30, 2018 3 Comments
(Part 4 of the Panzer General Portable Project)
As I talked about in the last post, I have about 700 images to be referenced from the Panzer General Portable game. When dealing with images in Xamarin Forms (XF), there are two choices: make the image an embedded resource in the shared project or create a stub in the shared project and have the image in both the iOS and Android project. Following Occam’s Razor, I opted for one file in the shared project.
Going back to the project, I opened the shared project and added the folder that contained all of the images. A demo project looks like this:
So far so good.
I then high-lighted all of the images (that took a bit) and right clicked –> Build Action –> EmbeddedResource
Visual Studio then tagged each of the files with a ResourceId of the file name:
So far, so bad. When I tried to reference these files in my code, the app could not find the images
So it turns out that when you are doing cross-platform development, Xamarin tries to reconcile any problems to the lowest level. In this case, Android has some very specific opinions about naming and the file names that I used did not match. iOS does not seem to have such limitations. The frustrating thing for me is that Visual Studio for Mac let me assign illegal values and did not issue any warnings so it took way too long of trial and error to figure this out. In my case, I used an underscore “_", which is an illegal character.
When I renamed a test image and followed the same steps, I got it working
So I then went back and changed the naming of the photo parsing script. But then I realized that highlighting all of the files in the solution explorer is a drag, so I wrote a new script that gave the correct file name and ResourceId for the fsproj file:
1 let createBlock (resource:string) (logicalName:string)= 2 ""\"><LogicalName>" + logicalName + "</LogicalName></EmbeddedResource>"
I then looped though all of the images files and created a text file
1 let getOutput path = 2 let resources = getResources path 3 let logicalNames = getLogicalNames path 4 resources 5 |> Array.zip logicalNames 6 |> Array.map(fun (r,ln) -> createBlock ln r) 7 |> Array.map(fun s -> " " + s)
the getLogicalNames function makes the ResourceId (Logical name in the .fsproj) acceptable to Android
1 let getLogicalNames path = 2 subDirectoryInfos path 3 |> Array.collect(fun sdi -> sdi.GetFiles()) 4 |> Array.map(fun f -> f.Name) 5 |> Array.map(fun n -> n.ToLowerInvariant()) 6 |> Array.map(fun n -> n.Replace(".jpeg",String.Empty)) 7 |> Array.map(fun n -> n.Replace("_",String.Empty))
I took the contents of that file, open the Panzer General project .fsproj file, pasted it in, and I got my images working
Gist is here
Pingback: F# Weekly #48, 2018 – F# Advent starts tomorrow! – Sergey Tihon's Blog
Pingback: F#周报2018年第48期 – 技术成就梦想
Pingback: F#周报2018年第48期 – 大白博客