Is there any way I could change the Uris of the default tile images in the WMAppManifest.xml at runtime?
For example I would like to enable an option for users to select the tile image in the settings of my app. This is not the problem because I can then update the main tile with the new image if the app is pinned to the start, but if the app is not pinned and the user wants to pin the app another time then the default image will be used, and this is not the behavior I want, I want the tile to have the image the user selected in the settings. How to achieve this if possible?
I figured it out, I didn't know the ShellTile.ActiveTiles would always contain the default tile, whether the app is pinned or not, so I just updated this tile when the settings item changed:
private async void UpdateTile(bool isTransparent)
{
ShellTile defaultTile = ShellTile.ActiveTiles.FirstOrDefault();
if (defaultTile != null)
{
string tileFolder = isTransparent ? "Transparent" : "Normal";
defaultTile.Update(new FlipTileData()
{
SmallBackgroundImage = new Uri("appdata:/Assets/Tiles/" + tileFolder + "/Logo.scale-100.png"),
BackgroundImage = new Uri("appdata:/Assets/Tiles/" + tileFolder + "/Logo.scale-180.png"),
WideBackgroundImage = new Uri("appdata:/Assets/Tiles/" + tileFolder + "/WideLogo.scale-180.png")
});
}
}
Related
I am using Xamarin and C# but I suspect the problem is equally valid in a Java environment.
I have an ActionBar Activity that hosts three tabs each of which hosts a fragment. It uses a ViewPager to allow the user to swipe between the tabs.
The requirement is to programmatically screenshot each tab and then email these as attachments.
The problem is that whilst the ActionBar/ViewPager works well it also optimises the tabs - effectively it isn't creating a fragment's view until it is next in line to be shown. So, if you're on tab 0 - the first tab - then the fragment view for tab 2 is null. So it can't be screenshot.
To overcome this I have tried to set any tab/fragment that has a null view to be selected. This generates the view but because setting it to be selected does not actually render it on screen the view does not have a width or a height value so again it cannot be screenshot (this is the reason for the defensive check at the start of the code taking the screenshot).
So, I guess my question is how can I force the tab to be rendered on screen so that it is correctly filled out and can be screenshot?
My main code extracts are as follows:
private void EmailReport()
{
List <Bitmap> bitmaps = new List<Bitmap>();
List <string> summaryFiles = new List<string>();
// remember the tab we're on
var selectedTab = this.ActionBar.SelectedNavigationIndex;
// take the screenshots
for (int fragmentNumber = 0; fragmentNumber < projectFragmentPagerAdapter.Count; fragmentNumber++)
{
Android.Support.V4.App.Fragment fragment = projectFragmentPagerAdapter.GetItem(fragmentNumber);
if (fragment.View == null)
{
this.ActionBar.GetTabAt(fragmentNumber).Select();
fragment = projectFragmentPagerAdapter.GetItem(fragmentNumber);
}
bitmaps.Add(ScreenShot(fragment.View));
}
// set the active tab back
this.ActionBar.GetTabAt(selectedTab).Select();
//write the screenshots into file
int i = 0;
foreach(Bitmap bitmap in bitmaps)
{
if (bitmap != null)
summaryFiles.Add(BitmapToFile(bitmap, this.ActionBar.GetTabAt(i).Text));
i++;
}
// now send the file
EmailSupport.SendAttachments(this, summaryFiles);
}
private Bitmap ScreenShot(View fragmentRootView)
{
if (fragmentRootView == null || fragmentRootView.Width == 0 || fragmentRootView.Height == 0)
return null;
fragmentRootView.DrawingCacheEnabled = true;
//create a bitmap for the layout and then draw the view into it
Bitmap bitmap = Bitmap.CreateBitmap(fragmentRootView.Width, fragmentRootView.Height,Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(bitmap);
//Get the view's background
Drawable bgDrawable = fragmentRootView.Background;
if (bgDrawable!=null) // has background drawable, then draw it on the canvas
bgDrawable.Draw(canvas);
else // does not have background drawable, then draw white background on the canvas
canvas.DrawColor(Color.White);
// draw the view on the canvas
fragmentRootView.Draw(canvas);
fragmentRootView.DrawingCacheEnabled = false;
return bitmap;
}
Any help would be gratefully received.
The solution in the end was very simple. The ViewPager has a setting controlling the number of pages (fragments) that it will hold "activated". This defaults to 1. As I had 3 tabs this meant there was always one tab (fragment) out of reach.
So, whilst setting up the ViewPager do the following before the tabs are added:
reportViewPager.OffscreenPageLimit = pageCount - 1;
Or in Java
reportViewPager.setOffscreenPageLimit(pageCount - 1);
I hope this helps someone else avoid wasting hours.
My app has the option to create many secondary tiles. When user try to pin an existing tile, the app asks the user to go to the Start Screen to remove the tile first.
Is there a way programmatically to navigate to the WP Start Screen from my app?
UPDATE
I know user can just click the start button or back button. But I want to detect if that navigation is made to set certain flags. And it would be a little convenient for the user if the apps could help them to navigate automatically.
As you said "When user try to pin an existing tile" means you want to update the existing tile . Use the code for Updating the existing tile.
public static void UpdateAppTile(string navigationUri)
{
var tile = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains(navigationUri));
if (tile != null)
{
var tileData = new FlipTileData
{
SmallBackgroundImage = new Uri("/Assets/Tiles/small.png", UriKind.Relative),
BackgroundImage = new Uri("/Assets/Tiles/medium.png", UriKind.Relative),
WideBackgroundImage = new Uri("/Assets/Tiles/wide.png", UriKind.Relative),
// other properties
};
tile.Update(tileData);
}
}
And for deleting the tile
public static void DeleteAppTile(string navigationUri)
{
var tile = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains(navigationUri));
if (tile != null)
{
tileToFind.Delete();
}
}
From the UX point of view, you should already avoid such situations by disabling (or adding to the tile 'unpin from start' option) for the corresponding tile, if it's already pinned to start.
public static bool CheckIfTileExists(string tileUri)
{
ShellTile shellTile = ShellTile.ActiveTiles.FirstOrDefault(
tile => tile.NavigationUri.ToString().Contains(tileUri));
if (shellTile == null)
return false;
return true;
}
I am testing a basic secondary live tile(ShellTile) functionality with the code below. Creating the tile works fine but using the tile to navigate to the URI always works in debug mode but not when testing disconnected from the computer and I don't know why. I am testing with just 1 tile. Funny thing is, if I restart, secondary tile will work one more time after the restart. What am I missing?
1> This is the code behind that makes the secondary tile
string path = #"/Views/test.xaml?text=" + parameter.ToString();
StandardTileData tileData = new StandardTileData
{
Title = parameter.ToString(),
BackTitle = parameter.ToString(),
BackContent = parameter.ToString()
};
ShellTile.Create(new Uri(path, UriKind.Relative), tileData);
2.test.xaml code
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string text= "";
text= NavigationContext.QueryString["text"];
}
Thanks,
Jamie
When the Tile which NavigationUri is same with your parameter, the ShellTile.Create method will crash. You should check if the tile is exist first, like this:
ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains(parameter));
You can choose Contains or Equals by your content. and then:
if (TileToFind != null)
{
// Tile is existed, you can update it, but not add the same uri tile
}
else
{
// you can add new tile
}
I am developing an app for WP8.I want to know how to find out that my app is coming to foreground by clicking on the App-list or primary tile which user created.In a way I want to know how many users creates primary tile.
You can add a navigation parameter to your secondary tile like this :
string tileParameter = "Param=myParameter";
ShellTile tile = CheckIfTileExist(tileParameter);
if (tile == null)
{
StandardTileData secondaryTile = new StandardTileData
{
Title = tileParameter,
BackgroundImage = new Uri("Background-Secondary.png", UriKind.Relative),
Count = 2,
BackContent = "Secondary Tile Test"
};
ShellTile.Create(new Uri("/MainPage.xaml?" + tileParameter, UriKind.Relative), secondaryTile);
}
and then, in your MainPage's OnNavigatedTo event, you can get this parameter with something like this:
if (this.NavigationContext.QueryString.ContainsKey("Param"))
{
string param = this.NavigationContext.QueryString["Param"];//Get "Param" this query string.
//Do whatever you want with this parameter
}
Do you have a query string in your URI? If so you can check the NavigationContext.QueryString and see if the parameter used from your secondary tile is set or not.
I have added four images and by default i have background image. I used a button to change the background randomly. It is panorama page and i just want my app to save the last state(i.e to remember the last background image) and if my app is activated then the last image should be the default background image. Since i have already added some images to my app so i think this doesn't need Isolated Storage. What i need is if the current background image(imguri) is bg1.jpg, and if i exit the app and if i relaunch it then the default background image should be bg1.jpg. Need help!
private void BackgroundBrowser_Click(object sender, RoutedEventArgs e)
{
string imguri = "";
click_count = click_count % 5;
switch (click_count)
{
case 0: imguri = "Image/bg.jpg"; break;
case 1: imguri = "Image/bg1.jpg"; break;
case 2: imguri = "Image/bg3.jpg"; break;
case 3: imguri = "Image/bg2.jpg"; break;
case 4: imguri = ""; break;
}
click_count++;
var app = Application.Current as App;
app.appBmp = new BitmapImage(new Uri(imguri, UriKind.Relative));
ImageBrush imageBrush = new ImageBrush();
imageBrush.Stretch = Stretch.UniformToFill;
imageBrush.Opacity = 0.7;
imageBrush.ImageSource = app.appBmp;
this.LayoutRoot.Background = imageBrush;
app.appbrush = imageBrush;
app.backchanged = true;
}
You can use Application or User Settings. Go to project properties and click the Settings tab. Then create a setting name LastImagePath with String as a type:
Now just before this line:
var app = Application.Current as App;
Add this to save the path to the LastImagePath settings:
Properties.Settings.Default.LastImagePath = imguri;
Properties.Settings.Default.Save();
To load the last image, you can load up the setting wherever you want like this:
if (!(Properties.Settings.Default.LastImagePath == null))
imgpath = Properties.Settings.Default.LastImagePath;
you need save the last image name in a file when your application exit and read image name from the file and load it when your application start again. I think this is the simplest solution.
You can also use System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings in a similar manner to what DelegateX has shown. Mind that regardless of how do you 'save' your setting, it will be stored in the isolated storage space. It is just nicely wrapped and hidden as a Properties/ApplicationSettings/Session etc proeprties or class names, but in fact the data will land on ISO, and will evaporate when you uninstall the app from the device.
All items stored in the User/Application settings need to be serializable (there is a note at the bottom of the documentation here). Learn more about serialization here.