I am working on iOS Tabs using custom TabbedRenderer, In renderer page I am resizing & setting icons. But for the first Tab icon not getting resized rest of all tabs setting icons fine.
public class CustomTabRenderer_iOS : TabbedRenderer
{
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
foreach (var item in TabBar.Items)
{
item.Image = GetTabIcon(item.Title);
}
}
private UIImage GetTabIcon(string title)
{
UITabBarItem item = null;
switch (title)
{
case "Dairy":
item = new UITabBarItem("Dairy", UIImage.FromFile("dairy"), 0);
break;
case "My kid":
item = new UITabBarItem("My kid",UIImage.FromFile("kid"),0);
break;
case "Events":
item = new UITabBarItem("Events", UIImage.FromFile("events"), 0);
break;
case "About":
item = new UITabBarItem("About", UIImage.FromFile("about"), 0);
break;
}
var img = (item != null) ? UIImage.FromImage(item.SelectedImage.CGImage, item.SelectedImage.CurrentScale, item.SelectedImage.Orientation) : new UIImage();
var imgR = ResizeImage(img, 20, 20);
return imgR;
}
public UIImage ResizeImage(UIImage sourceImage, float width, float height)
{
UIGraphics.BeginImageContext(new SizeF(width, height));
sourceImage.Draw(new RectangleF(0, 0, width, height));
var resultImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return resultImage;
}
}
Below is TabbedPage from PCL project
<Shared:MyTabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:edTheSIS"
x:Class="edTheSIS.ParentDashboard"
xmlns:Shared="clr-namespace:edTheSIS.Shared;assembly=edTheSIS">
<local:DairyTabPage Icon="dairy" HeightRequest="10" WidthRequest="10" ></local:DairyTabPage>
<local:MykidTab Icon="kid" ></local:MykidTab>
<local:Events Icon="events"></local:Events>
<local:About Icon="about"></local:About>
</Shared:MyTabbedPage>
See below screenshot
second screenshot below
According to the iOS Human Interface Guidelines, the images should be sizes as shown in the table underneath for a tab bar.
If you size the icons accordingly, they should always show right. There would be no reason to resize in code.
When you still want to use the code to resize an icon, update your ViewWillLayoutSubviews method like this, also setting the SelectedImage property:
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
foreach (var item in TabBar.Items)
{
item.Image = GetTabIcon(item.Title);
item.SelectedImage = GetTabIcon(item.Title);
}
}
The tab bar icon size on iOS can be set with the UITabBarItem.ImageInset in a custom TabbedRenderer
[assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedPageRenderer))]
namespace AppNameSpace.iOS.Renderers
{
class CustomTabbedPageRenderer : TabbedRenderer
{
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
if (Element is TabbedPage)
if (TabBar?.Items != null)
foreach (var item in TabBar.Items)
item.ImageInsets = new UIEdgeInsets(16, 16, 16, 16);
}
}
}
Related
I have made dependency services on both side and Interface in shared library on Xamarin platform
when i use it in xaml.cs hard coded it works but when i use it in ViewModel using messaging center to set count of notification in Toolbar of application it doesn't works
Does anyone have any kind of idea whats happening or should i do ?
this code works from Xaml.cs page
DependencyService.Get<IToolbarItemBadgeService>().SetBadge(this, ToolbarItems[0], "2", Color.Red, Color.White);
And Below Code doesn't works
From ViewModel
" MessagingCenter.Send(new MessagingCenterModel { }, "NotificationCount", NotificationListCount);
At Xaml.cs Page
MessagingCenter.Subscribe<MessagingCenterModel, string>(this, "NotificationCount", (sender, args) =>
{
DependencyService.Get<IToolbarItemBadgeService>().SetBadge(this, ToolbarItems[0], args, Color.Red, Color.White);
});
InterFaceCode
public interface IToolbarItemBadgeService
{
void SetBadge(Page page, ToolbarItem item, string value, Color backgroundColor, Color textColor);
}
Dependency service
public class ToolbarItemBadgeService : IToolbarItemBadgeService
{
public void SetBadge(Page page, ToolbarItem item, string value, Color backgroundColor, Color textColor)
{
Device.BeginInvokeOnMainThread(() =>
{
var toolbar = CrossCurrentActivity.Current.Activity.FindViewById(Resource.Id.toolbar) as Android.Support.V7.Widget.Toolbar;
if (toolbar != null)
{
if (!string.IsNullOrEmpty(value))
{
var idx = page.ToolbarItems.IndexOf(item);
if (toolbar.Menu.Size() > idx)
{
var menuItem = toolbar.Menu.GetItem(idx);
BadgeDrawable.SetBadgeText(CrossCurrentActivity.Current.Activity, menuItem, value, backgroundColor.ToAndroid(), textColor.ToAndroid());
}
}
}
});
}
}
BadgeDrawable Class
public class BadgeDrawable : Drawable
{
private const string BadgeValueOverflow = "*";
private Paint _badgeBackground;
private Paint _badgeText;
private Rect _textRect = new Rect();
private string _badgeValue = "";
private bool _shouldDraw = true;
Context _context;
public override int Opacity => (int)Format.Unknown;
public BadgeDrawable(Context context, Color backgroundColor, Color textColor)
{
_context = context;
float textSize = context.Resources.GetDimension(Resource.Dimension.textsize_badge_count);
_badgeBackground = new Paint();
_badgeBackground.Color = backgroundColor;
_badgeBackground.AntiAlias = true;
_badgeBackground.SetStyle(Paint.Style.Fill);
_badgeText = new Paint();
_badgeText.Color = textColor;
_badgeText.SetTypeface(Typeface.Default);
_badgeText.TextSize = textSize;
_badgeText.AntiAlias = true;
_badgeText.TextAlign = Paint.Align.Center;
}
public override void Draw(Canvas canvas)
{
if (!_shouldDraw)
{
return;
}
Rect bounds = Bounds;
float width = bounds.Right - bounds.Left;
float height = bounds.Bottom - bounds.Top;
float oneDp = 1 * _context.Resources.DisplayMetrics.Density;
// Position the badge in the top-right quadrant of the icon.
float radius = ((Java.Lang.Math.Max(width, height) / 2)) / 2;
float centerX = (width - radius - 1) + oneDp * 2;
float centerY = radius - 2 * oneDp;
canvas.DrawCircle(centerX, centerY, (int)(radius + oneDp * 5), _badgeBackground);
// Draw badge count message inside the circle.
_badgeText.GetTextBounds(_badgeValue, 0, _badgeValue.Length, _textRect);
float textHeight = _textRect.Bottom - _textRect.Top;
float textY = centerY + (textHeight / 2f);
canvas.DrawText(_badgeValue.Length > 2 ? BadgeValueOverflow : _badgeValue,
centerX, textY, _badgeText);
}
// Sets the text to display. Badge displays a '*' if more than 2 characters
private void SetBadgeText(string text)
{
_badgeValue = text;
// Only draw a badge if the value isn't a zero
_shouldDraw = !text.Equals("0");
InvalidateSelf();
}
public override void SetAlpha(int alpha)
{
// do nothing
}
public override void SetColorFilter(ColorFilter cf)
{
// do nothing
}
public static void SetBadgeCount(Context context, IMenuItem item, int count, Color backgroundColor, Color textColor)
{
SetBadgeText(context, item, $"{count}", backgroundColor, textColor);
}
public static void SetBadgeText(Context context, IMenuItem item, string text, Color backgroundColor, Color textColor)
{
if (item.Icon == null)
{
return;
}
BadgeDrawable badge = null;
Drawable icon = item.Icon;
if (item.Icon is LayerDrawable)
{
LayerDrawable lDrawable = item.Icon as LayerDrawable;
if (string.IsNullOrEmpty(text) || text == "0")
{
icon = lDrawable.GetDrawable(0);
lDrawable.Dispose();
}
else
{
for (var i = 0; i < lDrawable.NumberOfLayers; i++)
{
if (lDrawable.GetDrawable(i) is BadgeDrawable)
{
badge = lDrawable.GetDrawable(i) as BadgeDrawable;
break;
}
}
if (badge == null)
{
badge = new BadgeDrawable(context, backgroundColor, textColor);
icon = new LayerDrawable(new Drawable[] { item.Icon, badge });
}
}
}
else
{
badge = new BadgeDrawable(context, backgroundColor, textColor);
icon = new LayerDrawable(new Drawable[] { item.Icon, badge });
}
badge?.SetBadgeText(text);
item.SetIcon(icon);
icon.Dispose();
}
}
Firstly , make sure that we had Subscribe the message before we send it . Otherwise the codes in Subscribe will never been called .
In addition , the code in Dependency Service could only set the badge of ToolbarItem in the navigation bar (on tabbed bar it will never work).
If you want to set the badge of tabbed page icon , you could use the plugin Plugin.Badge .
I want to improve the size and background of my content page on ios,
var About = new ContentPage() { Title = "About" };
var layout = new StackLayout();
var line1 = new Label() { Text = viewModel.Member.Line1, FontSize = 16, HorizontalTextAlignment = TextAlignment.Center };
var MapTab = new ContentPage() {Title = "Map"};
Android:
The title of the content page appears very small on ios and not visible. I need help in trying to improve the looks and make it bigger.
You'll have to implement Custom Renderer for your TabbedPage. See this link:
Extending TabbedPage in Xamarin Forms.
It says, that:
To do these customizations we will use a custom renderer on each platform to render the TabbedPage.
I will duplicate the code snippets from the source as a example:
YourTabbedPage.xaml:
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomTabbedPage.MainPage"
xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.ToolbarPlacement="Bottom">
<TabbedPage.Children>
<ContentPage Title="Home" Icon="ic_home.png" BackgroundColor="White"/>
<ContentPage Title="Favorites" Icon="ic_favorite.png" BackgroundColor="White"/>
<ContentPage Title="App" Icon="app_logo_unselected.png" x:Name="home" BackgroundColor="White"/>
<ContentPage Title="Friends" Icon="ic_people.png" BackgroundColor="White"/>
<ContentPage Title="Settings" Icon="ic_settings.png" BackgroundColor="White"/>
</TabbedPage.Children>
</TabbedPage>
iOS Custom Renderer:
public class ExtendedTabbedPageRenderer : TabbedRenderer
{
public override void ViewWillAppear(bool animated)
{
if (TabBar?.Items == null)
return;
var tabs = Element as TabbedPage;
if (tabs != null)
{
for (int i = 0; i < TabBar.Items.Length; i++)
{
UpdateTabBarItem(TabBar.Items[i], tabs.Children[i].Icon);
}
}
base.ViewWillAppear(animated);
}
private void UpdateTabBarItem(UITabBarItem item, string icon)
{
if (item == null || icon == null)
return;
// Set the font for the title.
item.SetTitleTextAttributes(new UITextAttributes() { Font = UIFont.FromName("GillSans-UltraBold", 12), TextColor = Color.FromHex("#757575").ToUIColor() }, UIControlState.Normal);
item.SetTitleTextAttributes(new UITextAttributes() { Font = UIFont.FromName("GillSans-UltraBold", 12), TextColor = Color.FromHex("#3C9BDF").ToUIColor() }, UIControlState.Selected);
}
}
Android Custom Renderer:
public class ExtendedTabbedPageRenderer : TabbedPageRenderer
{
Xamarin.Forms.TabbedPage tabbedPage;
BottomNavigationView bottomNavigationView;
Android.Views.IMenuItem lastItemSelected;
int lastItemId=-1;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TabbedPage> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
tabbedPage = e.NewElement as ExtendedTabbedPage;
bottomNavigationView = (GetChildAt(0) as Android.Widget.RelativeLayout).GetChildAt(1) as BottomNavigationView;
bottomNavigationView.NavigationItemSelected += BottomNavigationView_NavigationItemSelected;
//Call to change the font
ChangeFont();
}
if (e.OldElement != null)
{
bottomNavigationView.NavigationItemSelected -= BottomNavigationView_NavigationItemSelected;
}
}
//Change Tab font
void ChangeFont()
{
var fontFace = Typeface.CreateFromAsset(Context.Assets, "gilsansultrabold.ttf");
var bottomNavMenuView = bottomNavigationView.GetChildAt(0) as BottomNavigationMenuView;
for (int i = 0; i < bottomNavMenuView.ChildCount; i++)
{
var item = bottomNavMenuView.GetChildAt(i) as BottomNavigationItemView;
var itemTitle = item.GetChildAt(1);
var smallTextView = ((TextView)((BaselineLayout)itemTitle).GetChildAt(0));
var largeTextView = ((TextView)((BaselineLayout)itemTitle).GetChildAt(1));
lastItemId = bottomNavMenuView.SelectedItemId;
smallTextView.SetTypeface(fontFace, TypefaceStyle.Bold);
largeTextView.SetTypeface(fontFace, TypefaceStyle.Bold);
//Set text color
var textColor = (item.Id == bottomNavMenuView.SelectedItemId) ? tabbedPage.On<Xamarin.Forms.PlatformConfiguration.Android>().GetBarSelectedItemColor().ToAndroid() : tabbedPage.On<Xamarin.Forms.PlatformConfiguration.Android>().GetBarItemColor().ToAndroid();
smallTextView.SetTextColor(textColor);
largeTextView.SetTextColor(textColor);
}
}
void BottomNavigationView_NavigationItemSelected(object sender, BottomNavigationView.NavigationItemSelectedEventArgs e)
{
var normalColor = tabbedPage.On<Xamarin.Forms.PlatformConfiguration.Android>().GetBarItemColor().ToAndroid();
var selectedColor = tabbedPage.On<Xamarin.Forms.PlatformConfiguration.Android>().GetBarSelectedItemColor().ToAndroid();
if(lastItemId!=-1)
{
SetTabItemTextColor(bottomNavMenuView.GetChildAt(lastItemId) as BottomNavigationItemView, normalColor);
}
SetTabItemTextColor(bottomNavMenuView.GetChildAt(e.Item.ItemId) as BottomNavigationItemView, selectedColor);
this.OnNavigationItemSelected(e.Item);
lastItemId = e.Item.ItemId;
}
void SetTabItemTextColor(BottomNavigationItemView bottomNavigationItemView, Android.Graphics.Color textColor)
{
var itemTitle = bottomNavigationItemView.GetChildAt(1);
var smallTextView = ((TextView)((BaselineLayout)itemTitle).GetChildAt(0));
var largeTextView = ((TextView)((BaselineLayout)itemTitle).GetChildAt(1));
smallTextView.SetTextColor(textColor);
largeTextView.SetTextColor(textColor);
}
}
I created a content class for the two pages I wanted to improve on, the map and the memberaboutpage and I instead of using the content page, I did this
var About = new MemberAboutPage { Title = "About" };
var layout = new StackLayout();
var MapTab = new MapPage() { Title = "Map" };
Then I added the pages to the pages I created and mirrored to the ios rendere page below, this page formats the tabs and makes them more nicer looking and alos prevents the overlapping on iPhone X. Happy Programming Mates
'[assembly: ExportRenderer(typeof(CardPage), typeof(MyiOSTabbedPage))]
[assembly: ExportRenderer(typeof(LoginPage), typeof(MyiOSTabbedPage))]
[assembly: ExportRenderer(typeof(MemberAboutPage), typeof(MyiOSTabbedPage))]
[assembly: ExportRenderer(typeof(MapPage), typeof(MyiOSTabbedPage))]
namespace CHA.iOS.Renderers
{
public class MyiOSTabbedPage : PageRenderer
{
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
nfloat tabSize = 44.0f;
UIInterfaceOrientation orientation = UIApplication.SharedApplication.StatusBarOrientation;
CGRect rect = this.View.Frame;
rect.Y = this.NavigationController != null ? tabSize : tabSize + 20;
this.View.Frame = rect;
if (TabBarController != null)
{
CGRect tabFrame = this.TabBarController.TabBar.Frame;
tabFrame.Height = tabSize;
tabFrame.Y = this.NavigationController != null ? 0 : 0;
this.TabBarController.TabBar.Frame = tabFrame;
this.TabBarController.TabBar.BarTintColor = UIColor.FromRGB(234,232,232);
var textAttr = new UITextAttributes
{
Font = UIFont.SystemFontOfSize(20)
};
var selectedAttr = new UITextAttributes
{
TextColor = UIColor.FromRGB(63,165,186),
Font=UIFont.BoldSystemFontOfSize(20)
};
foreach (var i in this.TabBarController.TabBar.Items)
{
i.SetTitleTextAttributes(textAttr, UIControlState.Normal);
i.SetTitleTextAttributes(selectedAttr, UIControlState.Selected);
}
}
}
}'
In my Xamarin forms application, I need to set a top padding for Entry control in iOS. I created renderers for Entry , but only I am able to set Left and Right padding. Please help me. Following is the my Entry Renderer
public class CustomRenderer: EntryRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged (e);
if (Control != null) {
Control.LeftView = new UIView (new CGRect (0, 0, 15, 0));
Control.LeftViewMode = UITextFieldViewMode.Always;
}
}
}
To accomplish this, we need to do two things:
Increase the height of the Entry in Xamarin.Forms
Create an iOS Custom Renderer to align the text to the bottom of the UITextField
Increase The Entry Height in Xamarin.Forms
In this example, I use a RelativeLayout to set the height of the Padded Entry to 50, Constraint.Constant(50).
using System;
using Xamarin.Forms;
namespace CustomEntrySample
{
public class EntryWithTopPadding : Entry
{
}
public class App : Application
{
public App()
{
var normalEntry = new Entry
{
Text = "This Entry Has Normal Padding",
BackgroundColor = Color.Lime
};
var paddedEntry = new EntryWithTopPadding
{
Text = "This Entry Has Extra Top Padding",
BackgroundColor = Color.Aqua
};
var mainLayout = new RelativeLayout();
mainLayout.Children.Add(
normalEntry,
Constraint.Constant(0),
Constraint.RelativeToParent(parent => parent.Y + 10),
Constraint.RelativeToParent(parent => parent.Width)
);
mainLayout.Children.Add(
paddedEntry,
Constraint.Constant(0),
Constraint.RelativeToView(normalEntry, (parent, view) => view.Y + view.Height + 10),
Constraint.RelativeToParent(parent => parent.Width),
Constraint.Constant(50)
);
MainPage = new NavigationPage(
new ContentPage
{
Title = "Title",
Content = mainLayout,
Padding = new Thickness(10, 0, 10, 0)
}
);
}
}
}
Create Custom Renderer to Align Text to the Bottom of UITextField
Set the VerticalAlignment property of the UITextField to UIControlContentVerticalAlignment.Bottom
using UIKit;
using CustomEntrySample;
using CustomEntrySample.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(EntryWithTopPadding), typeof(EntryWithTopPaddingCustomRenderer))]
namespace CustomEntrySample.iOS
{
public class EntryWithTopPaddingCustomRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if(Control == null)
return;
Control.VerticalAlignment = UIControlContentVerticalAlignment.Bottom;
}
}
}
Use this for setting padding to an entry cell:
Padding in IOS :
Control.LeftView = new UIView(new CGRect(0,15,0,0));
Control.LeftViewMode = UITextFieldViewMode.Always;
Control.RightView = new UIView(new CGRect(0,10, 0, 0));
Control.RightViewMode = UITextFieldViewMode.Always;
Padding in Android:
Control.SetPadding(0, 10, 0, 0);
Accordingly, you can set the value to make text start from specific position.
I want to take a snapshot of my UserControl, which has not been shown yet.
That's my code:
public Screenshot(MyViewModel viewModel)
{
if (viewModel == null)
return;
// Create a TabControl, where View is hosted in
var visualTab = new TabControl();
visualTab.Width = FrameworkAdjustments.VisualSize.Width;
visualTab.Height = FrameworkAdjustments.VisualSize.Height;
visualTab.TabStripPlacement = Dock.Left;
// Tabs should only be shown, if there are more than one 'SubView'
Visibility tabVisibility = Visibility.Collapsed;
if (viewModel.SubViews.Count > 1)
tabVisibility = Visibility.Visible;
foreach (var subView in viewModel.SubViews)
{
var tab = new TabItem();
tab.Header = subView.TranslatedId; // multilanguage header
tab.Visibility = tabVisibility;
if (subView.Id == viewModel.ActiveSubView.Id)
{
tab.IsSelected = true;
// Without the following line my UI works, but my TabControl is empty.
tab.Content = ViewManager.GetViewById(subView.Id);
// ViewManager.GetViewById(subView.Id); returns a UserControl
}
tab.Measure(FrameworkAdjustments.VisualSize);
tab.Arrange(new Rect(FrameworkAdjustments.VisualSize));
visualTab.Items.Add(tab);
}
_ContentCtrl = new ContentControl() { Width = FrameworkAdjustments.VisualSize.Width, Height = FrameworkAdjustments.VisualSize.Height };
_ContentCtrl.Content = visualTab;
_ContentCtrl.Measure(FrameworkAdjustments.VisualSize);
_ContentCtrl.Arrange(new Rect(FrameworkAdjustments.VisualSize));
RenderTargetBitmap bmp = new RenderTargetBitmap((int)FrameworkAdjustments.VisualSize.Width, (int)FrameworkAdjustments.VisualSize.Height, 96, 96, PixelFormats.Pbgra32);
bmp.Render(_ContentCtrl);
this.ItemBrush = new ImageBrush(bmp);
}
This code runs for each 'MyViewModel' when I start my App.
'MyViewModel' contains a List of 'SubViews' which are the content of the Tabs and they contain a 'FunctionKeyBar' which's buttons can be activated by using 'F1' to 'F12'. But after creating my screenshot I can't use the F1 to F12 anymore. Also there are other problems, like switch language.
Is there an other way to create a snapshot of a control which has not came into view?
Thanks for all replys.
Greetings Benny
Approach : Set Margin to negative to keep it hidden, Add the control to the Grid / any other container.
Follow these steps :
1) Create a Task to create and add your ContentControl to the Grid.
2) Call user-define CaptureScreen () function.
3) Visibility must not be Hidden/Collapsed. Margin can be negative to hide the control.
In this example, I have done this in a Button.Click.
async private void Button_Click(object sender, RoutedEventArgs e)
{
Task<ContentControl> t = AddContentControl();
ContentControl ctrl = await t;
RenderTargetBitmap bmp = CaptureScreen(ctrl, 5000, 5000);
Img.Source = bmp;
}
/* Add the ContentControl to the Grid, and keep it hidden using neg. Margin */
private Task<ContentControl> AddContentControl()
{
Task<ContentControl> task = Task.Factory.StartNew(() =>
{
ContentControl ctrl = null;
Dispatcher.Invoke(() =>
{
ctrl = new ContentControl() { Content = "Not shown", Width = 100, Height = 25, Margin = new Thickness(-8888, 53, 0, 0) };
Grd.Children.Add(ctrl);
});
return ctrl;
});
return task;
}
/* Important , wont work with Visibility.Collapse or Hidden */
private static RenderTargetBitmap CaptureScreen(Visual target, double dpiX, double dpiY)
{
if (target == null)
{
return null;
}
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
(int)(bounds.Height * dpiY / 96.0),
dpiX,
dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(target);
ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
}
rtb.Render(dv);
return rtb;
}
Now I found a solution, thanks to AnjumSKan.
I took his code and changed it a little bit. As I said, I need to create the snapshot on application startup or culture changed and I have more than one view. in my Function AddContentControl, I add the Content to my TabControl which has negative Margin. Add the end I call HiddenTab.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Render, new Action(CreateSnapshotOnRender));
('HiddenTab' is my TabControl which is not shown to user). This calls a function called CreateSnapshotOnRender, where I call AnjumSKhan's CaptureScreen-method from. After that I call again the function AddContentControl with my next content. This looks as following:
private void CreateScreenshotOnRender()
{
HiddenTab.Measure(ViewSize);
HiddenTab.Arrange(new Rect(ViewSize));
var snapshot = CaptureScreen(HiddenTab, dpiX, dpiY);
/* Do anything with snapshot */
_Index++; // counter to know thich view is next
CreateAllScreenshots();
}
Thanks again to AnjumSKan, because you lead me to this. Thats why I marked your Answer as the correct one.
I am following this MSDN article to create resolution dependent backgrounds in Windows Phone 8, but it's showing blank background always.
Any one has idea what's wrong with it? Anybody has any alternative solutions?
public enum Resolutions { WVGA, WXGA, HD720p, HD };
private static bool IsWvga
{
get
{
return App.Current.Host.Content.ScaleFactor == 100;
}
}
private static bool IsWxga
{
get
{
return App.Current.Host.Content.ScaleFactor == 160;
}
}
private static bool Is720p
{
get
{
return App.Current.Host.Content.ScaleFactor == 150;
}
}
private static bool IsHD
{
get
{
return App.Current.Host.Content.ScaleFactor == 150;
}
}
Add this to the top of your class and use these static variables to set resolution specific images. You said you want to set "resolution dependent backgrounds", from which I understand you want to set some image on the background? If you want the image to the background of the page then set ImageBrush of your LayoutRoot Grid to resolution specific images ( 480x800.jpg, 720x1280.jpg etc) like this
ImageBrush image = new ImageBrush();
if (IsWvga)
{
//set your bitmap
}
else if (IsWxga)
{
//set your bitmap
}
else if (Is720p)
{
//set your bitmap
}
else if(IsHD)
{
//set your bitmap
}
image.Stretch = Stretch.UniformToFill;
LayoutRoot.Background = image;
OR
if you want your screen UI elements to fit in the resolutions then set the height of your UI elements to auto in XAML, or set the resolution specific height of your UI elements on the OnNavigatedTo event of your page. This may be any random grid of your page which needs to fit in
if (IsWvga)
{
grid.Height = 500;
}
else if (IsWxga)
{
grid.Height = 600;
}
else if (Is720p)
{
grid.Height = 700;
}
else if (IsHD)
{
grid.Height = 800;
}
MSDN article has mistake in MultiResImageChooser class, MultiResImageChooser is written as MultiResImageChooserUri & relative URIs are missing leading slash. Correct class is given below.
public class MultiResImageChooser
{
public Uri BestResolutionImage
{
get
{
switch (ResolutionHelper.CurrentResolution)
{
case Resolutions.HD:
return new Uri("/Assets/MyImage.screen-720p.jpg", UriKind.Relative);
case Resolutions.WXGA:
return new Uri("/Assets/MyImage.screen-wxga.jpg", UriKind.Relative);
case Resolutions.WVGA:
return new Uri("/Assets/MyImage.screen-wvga.jpg", UriKind.Relative);
default:
throw new InvalidOperationException("Unknown resolution type");
}
}
}
}