Spacing between icon and label in tabbedpage bar - xamarin.forms

I have a tabbedPage where I'm assigning text and icons for each tab as follows:
this.Children.Add(new SignaturesTab() { Title = "Signature" , Icon
= "sign_new#2x.png" });
this.Children.Add(new PhotosTab() { Title = "Photos", Icon =
"image_new#2x.png" });
On my iPhone, icon appears top of the label in the bar for each tab.
Code in Tab Renderer:
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
TabBar.TintColor = new UIColor(red: 0.23f, green: 0.56f, blue: 0.20f, alpha: 1.0f);
TabBar.UnselectedItemTintColor = new UIColor(red: 0.34f, green: 0.34f, blue: 0.34f, alpha: 1.0f);
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
if (TabBar.Items == null) return;
TabBar.SelectedImageTintColor = new UIColor(red: 0.23f, green: 0.56f, blue: 0.20f, alpha: 1.0f);
foreach (var uiTabBarItem in TabBar.Items)
{
var fontSize = new UITextAttributes(){ Font = UIFont.SystemFontOfSize(13)};
uiTabBarItem.SetTitleTextAttributes(fontSize, UIControlState.Normal);
}
}
Is there a way to provide spacing/margin between icon and label and to the borders.
Thanks

Using UIOffset and UIEdgeInsets can modify posittion of Title and Image in TabBarItem .
TabBarItem.TitlePositionAdjustment = new UIOffset(0, 1);
//UIOffset:Represents a position offset. UIOffset(nfloat horizontal, nfloat vertical);
TabBarItem.ImageInsets = new UIEdgeInsets(0, 0, 5, 0);
//Mean: UIEdgeInsets(nfloat top, nfloat left, nfloat bottom, nfloat right);
Modifying paramaters inside UIOffset and UIEdgeInsets to fit your want.
=============================Update==============================
Changing tab bar item icon color :
UITabBar.Appearance.SelectedImageTintColor = UIColor.Yellow;
//selected color ,this will change the whole tabbar item
Just four items be modified :
for (int i = 0; i < 4; i++)
{
var fontSize = new UITextAttributes(){ Font = UIFont.SystemFontOfSize(13)};
uiTabBarItem.SetTitleTextAttributes(fontSize, UIControlState.Normal);
uiTabBarItem.TitlePositionAdjustment = new UIOffset(0, 1);
uiTabBarItem.ImageInsets = new UIEdgeInsets(0, 0, 5, 0);
}

I make a trick with IBDesignable for doing that.
may it useful for you
import UIKit
#IBDesignable
class CustomTabBarItem: UITabBarItem {
#IBInspectable var titlePosition: CGSize = CGSize(width: 0, height: 0) {
didSet {
titlePositionAdjustment = UIOffset(horizontal: titlePosition.width, vertical: titlePosition.height)
}
}
#IBInspectable var imageInset: CGRect = CGRect(x: 0, y: 0, width: 0, height: 0) {
didSet {
imageInsets = UIEdgeInsets(top: imageInset.origin.x, left: imageInset.origin.y, bottom: imageInset.size.width, right: imageInset.size.height)
}
}
}

Related

Why rectangle's radius gets ignored in this situation?

I have a Xamarin.Forms (v5.0.0.2515) project.
I have encountered this strange behavior using this scenario:
I have a view with 5 rectangles. RadiusX/RadiusY for each rectangle is 20.
I assign this view to a ContentView and everything looks normal (Fig. 1)
I assign another view to the ContentView
I assign back the view to the ContentView and rounded borders are gone (Fig. 2)
What can cause this issue?
This is a sample code to reproduce the issue.
using Xamarin.Forms;
namespace App
{
public class SamplePage : ContentPage
{
public SamplePage()
{
var grid = new Grid
{
RowDefinitions = new RowDefinitionCollection
{
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = GridLength.Star }
}
};
var btn = new Button { Text = "Replace the view!" };
Grid.SetRow(btn, 0);
grid.Children.Add(btn);
var rect = new Xamarin.Forms.Shapes.Rectangle
{
RadiusX = 20,
RadiusY = 20,
Fill = Brush.Azure,
StrokeThickness = 3,
Stroke = Brush.Black
};
var cv = new ContentView { Content = rect };
Grid.SetRow(cv, 1);
grid.Children.Add(cv);
btn.Clicked += (_, __) =>
{
cv.Content = new Label();
cv.Content = rect;
};
Content = grid;
}
}
}
Thanks.
Fig. 1
Fig. 2
According to your demo you provided, I found that the code cv.Content = new Label(); caused the problem. I changed the demo and you can check.
public partial class MainPage : ContentPage
{
public MainPage()
{
var grid = new Grid
{
RowDefinitions = new RowDefinitionCollection
{
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = GridLength.Star }
}
};
var btn = new Button { Text = "Replace the view!" };
Grid.SetRow(btn, 0);
grid.Children.Add(btn);
var rect = new Xamarin.Forms.Shapes.Rectangle
{
RadiusX = 50,
RadiusY = 10,
Fill = Brush.Azure,
StrokeThickness = 10,
Stroke = Brush.Black
};
var rect2 = new Xamarin.Forms.Shapes.Rectangle
{
RadiusX = 20,
RadiusY = 20,
Fill = Brush.Azure,
StrokeThickness = 3,
Stroke = Brush.Black
};
var cv = new ContentView {Content = rect2};
Grid.SetRow(cv, 1);
grid.Children.Add(cv);
btn.Clicked += (_,__) =>
{
cv.Content = rect;
};
Content = grid;
}
}
}

How to make the scroll bar visible always in xamarin forms in ios device and shift the scroll bar to left side of the screen?

How to make the scroll bar always visible in Xamarin forms in IOS device and shift the scroll bar to left side of the screen?
I tried this link:
Xamarin Forms ListView for iOS: Always Show ScrollBar
but getting exception that
Event registration is overwriting existing delegate. Either just use
events or your own delegate: hupp.iOS.Models.CustomScrollDelegate
UIKit.UIScrollView+_UIScrollViewDelegate
public class CustomScrollViewRenderer : ScrollViewRenderer
{
public UIView bar;
protected override async void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
// UIScrollView iosScrollView = (UIScrollView)NativeView;
this.ShowsVerticalScrollIndicator = ((CustomScrollViewLesson)e.NewElement).IsVerticalScrollbarEnabled;
this.ShowsHorizontalScrollIndicator = ((CustomScrollViewLesson)e.NewElement).IsHorizontalScrollbarEnabled;
this.IndicatorStyle = UIScrollViewIndicatorStyle.White;
this.ScrollIndicatorInsets = new UIEdgeInsets(0, 30, 0, 30);
this.FlashScrollIndicators();
//Hide the default Scroll Indicator.
this.ShowsVerticalScrollIndicator = false;
//Set Delegate
CustomScrollDelegate customScrollDelegate = new CustomScrollDelegate();
this.Delegate = customScrollDelegate;
//Create the background view of custom indicator.
double frameHeight = this.Frame.Size.Height;
double frameWidth = this.Frame.Size.Width;
double barBackgroundWidth = 6;
double statusBarHeight = 20; //this.ScrollIndicatorInsets = new UIEdgeInsets(0, 0, 0, this.Bounds.Size.Width - 10);
UIView barBackgroundView = new UIView();
CGRect barBVRect = new CGRect(frameWidth - barBackgroundWidth, statusBarHeight, barBackgroundWidth, frameHeight);
barBackgroundView.Frame = barBVRect;
barBackgroundView.BackgroundColor = UIColor.Gray;
barBackgroundView.Layer.CornerRadius = 2;
barBackgroundView.Layer.MasksToBounds = true;
//Create the bar of the custom indicator.
bar = new UIScrollView();
CGRect barRect = new CGRect(1, 0, 4, 0);
bar.Frame = barRect;
bar.BackgroundColor = UIColor.White;
bar.Layer.CornerRadius = 2;
bar.Layer.MasksToBounds = true;
//Add the views to the superview of the tableview.
barBackgroundView.AddSubview(bar);
this.Superview.AddSubview(barBackgroundView);//here also getting exception null value in superview.so i commented while debug
customScrollDelegate.bar = bar;
//Transfer the bar view to delegate.
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
Console.WriteLine("End of loading!!!");
double contentHeight = this.ContentSize.Height;
double frameHeight = this.Frame.Size.Height;
double barHeight = frameHeight * frameHeight / contentHeight;
//Reset the bar height when the table view finishes loading.
CGRect barRect = new CGRect(bar.Frame.X, bar.Frame.Y, bar.Frame.Width, barHeight);
bar.Frame = barRect;
}
}
public class CustomScrollDelegate : UIKit.UIScrollViewDelegate
{
public UIView bar;
double barY;
public override void Scrolled(UIScrollView scrollView)
{
double y = scrollView.ContentOffset.Y;
double contentHeight = scrollView.ContentSize.Height;
double frameHeight = scrollView.Frame.Size.Height;
double barHeight = frameHeight * frameHeight / contentHeight;
barY = y / (contentHeight - frameHeight) * (frameHeight - barHeight);
//Cut the bar Height when it over the top.
if (barY < 0)
{
barHeight = barHeight + barY;
barY = 0;
}
//Cut the bar height when it over the bottom.
if (barY > (frameHeight - barHeight))
{
barHeight = barHeight - (barY - (frameHeight - barHeight));
}
//Reset the barView rect. Let's move!!!
CGRect barRect = new CGRect(bar.Frame.X, barY, bar.Frame.Width, barHeight);
bar.Frame = barRect;
}
}
Please give a solution and thanks in advance

How to create scrollview with fading edges in Xamarin forms? (Xamarin.ios)

I already have a custom renderer for scrollview that will create fading edges on Xamarin.android. So my problem now is that my renderer on iOS is not working.
Here is what I have:
using System;
using CoreAnimation;
using CoreGraphics;
using Foundation;
using Omregistrering.CustomControls;
using Omregistrering.iOS.Renderers;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(FadeScrollView), typeof(FadeScrollViewRenderer))]
namespace Omregistrering.iOS.Renderers
{
public class FadeScrollViewRenderer : ScrollViewRenderer
{
private CAGradientLayer gradientLayer;
private Double FadePercentage = 0.2;
private CGColor OpaqueColor = UIColor.Black.CGColor;
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
//UpdateScrollView();
}
public override void ScrollRectToVisible(CGRect rect, bool animated)
{
base.ScrollRectToVisible(rect, animated);
}
private void UpdateScrollView()
{
// test with Bounces
ContentInset = new UIKit.UIEdgeInsets(0, 0, 0, 0);
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
ContentInsetAdjustmentBehavior = UIKit.UIScrollViewContentInsetAdjustmentBehavior.Never;
Bounces = false;
ScrollIndicatorInsets = new UIKit.UIEdgeInsets(0, 0, 0, 0);
}
private CGColor topOpacity()
{
var scrollViewHeight = Frame.Size.Height;
var scrollContentSizeHeight = ContentSize.Height;
var scrollOffset = ContentOffset.Y;
nfloat alpha = (scrollViewHeight >= scrollContentSizeHeight || scrollOffset <= 0) ? 1 : 0;
var color = new UIColor(white: 0, alpha: alpha);
return color.CGColor;
}
private CGColor bottomOpacity()
{
var scrollViewHeight = Frame.Size.Height;
var scrollContentSizeHeight = ContentSize.Height;
var scrollOffset = ContentOffset.Y;
nfloat alpha = (scrollViewHeight >= scrollContentSizeHeight || scrollOffset + scrollViewHeight >= scrollContentSizeHeight) ? 1 : 0;
var color = new UIColor(white: 0, alpha: alpha);
return color.CGColor;
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
gradientLayer = new CAGradientLayer();
gradientLayer.Frame = rect;
var maskLayer = new CALayer();
gradientLayer.Colors = new CGColor[] { topOpacity(), OpaqueColor, OpaqueColor, bottomOpacity() };
gradientLayer.Locations = new NSNumber[] { 0, (NSNumber)FadePercentage, (NSNumber)(1 - FadePercentage), 1 };
maskLayer.AddSublayer(gradientLayer);
this.Layer.Mask = maskLayer;
}
}
}
And the result is this:
The renderer is fading at the bottom edge but is not updated in any way.The ideer is of course to have fading edges also when scrolling up and down.
Here a screenshot from android were we are in the middle of a scroll and both edges are fading, giving the illusion of more content.
Anyone who have a solution or has done this on Xamarin.ios
Thanks
I don't think you need renderers here.
You could use two png with gradient toward transparent, for each edge.
Then with ScrollView.Scrolled event, you can know if you reached the top or the bottom of the scroll view.
Doing so, you can set the opacity of the 2 images according to the distance from the edge.
In the following example, we'll consider only bottom:
private void OnScrolled(object sender, ScrolledEventArgs e)
{
MyScrollView scrollView = sender as MyScrollView;
double scrollingSpace = scrollView.ContentSize.Height - scrollView.Height;
MyBottomImage.Opacity = 1 - e.ScrollY/scrollingSpace;
}
I hope you get the idea :)

IOS toolbar Icons color is changing when Gradient toolbar applied

I'm developing an IOS Application using Xamarin.Forms and in that I've customized the toolbar color to Gradient color using custom renderers.But,After this the Icons
color is changed as per the toolbar color and how to set the title text to white colour.Here is the renderer I'm using for toolbar customization
public class NavigationPageGradientHeaderRenderer:NavigationRenderer
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var control = (NavigationPageGradientHeader)this.Element;
var gradientLayer = new CAGradientLayer();
gradientLayer.Bounds = NavigationBar.Bounds;
gradientLayer.Colors = new CGColor[] { control.RightColor.ToCGColor(), control.LeftColor.ToCGColor() };
gradientLayer.StartPoint = new CGPoint(0.0, 0.5);
gradientLayer.EndPoint = new CGPoint(1.0, 0.5);
UIGraphics.BeginImageContext(gradientLayer.Bounds.Size);
gradientLayer.RenderInContext(UIGraphics.GetCurrentContext());
UIImage image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
NavigationBar.SetBackgroundImage(image, UIBarMetrics.Default);
}
}
After applying this the Icons look like this:
enter image description here
But I want the images background to be transparent like this:
enter image description here
and the title textcolor should be white.
How can I achieve this.Can anyone please help me with this.
Thank you
You can set the property in CustomRenderer
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var control = (MyNativePage)Element;
var gradientLayer = new CAGradientLayer();
gradientLayer.Bounds = NavigationBar.Bounds;
gradientLayer.Colors = new CGColor[] { UIColor.Red.CGColor,UIColor.White.CGColor };
gradientLayer.StartPoint = new CGPoint(0.0, 0.5);
gradientLayer.EndPoint = new CGPoint(1.0, 0.5);
UIGraphics.BeginImageContext(gradientLayer.Bounds.Size);
gradientLayer.RenderInContext(UIGraphics.GetCurrentContext());
UIImage image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
NavigationBar.SetBackgroundImage(image, UIBarMetrics.Default);
NavigationBar.TintColor = UIColor.White;
NavigationBar.TitleTextAttributes = new UIStringAttributes() { ForegroundColor =UIColor.White};
}
If you create an NavigationPage, then you can use like this
var myHomePage = new NavigationPage(dashboardPage){
Tint = Color.Red // put your color here };
You can set common color from App.xaml.cs;
public App()
{
InitializeComponent();
// MainPage = new MainPage();
MainPage = new RESTAPICallApp.Controllers.HomePage();
NavigationPage navigationRootPage = new NavigationPage(new RESTAPICallApp.Controllers.HomePage());
navigationRootPage.BarBackgroundColor = Color.LightSeaGreen;
navigationRootPage.BarTextColor = Color.Wheat;
MainPage = navigationRootPage;
}
For native Xamarin.iOS add this code in 'didFinishLaunchingWithOptions' method on AppDelegate.cs;
UINavigationBar.Appearance.Translucent = false;
UINavigationBar.appearance().barTintColor = UIColor.White
UINavigationBar.Appearance.SetTitleTextAttributes(new UITextAttributes() {
TextColor = UIColor.White,
TextShadowColor = UIColor.Clear
});

DataMatrix Barcode Format Blurred in ZXingBarcodeImageView Xamarin Forms Zxing 2.3.2

I'm trying to display DataMatrix barcode inside ZXingBarcodeImageView, the problem is whatever width and height I use the barcode is blurry with low resolution.
Screenshot
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<forms1:ZXingBarcodeImageView BarcodeFormat="DATA_MATRIX" BarcodeOptions="{datamatrix:DatamatrixEncodingOptions, Height=100, Width=100}" WidthRequest="100" HeightRequest="100" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BarcodeValue="123456" ></forms1:ZXingBarcodeImageView>
I tried to set different Height and Width in EncodingOptions and on the ZXingBarcodeImageView itself.
Any recommendation?
I had a similar issue.
Turns out you can set the EncodingOptions like this for example:
barcodeImageView.BarcodeOptions = new ZXing.Common.EncodingOptions() { Height = 300, Width = 300, PureBarcode = true };
Because generation happens at a lower level and it gets scaled up.
This answer helped me:
how to fix an unclear qr code image generated using zxing 2.1?
This bug is in ZXing portable only for DataMatrix so
I ended up by creating custom renderers for Android and iOS only(Windows works fine).
Android Code:
public class SDataMatrixRenderer : ImageRenderer
{
public SDataMatrixRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (Element == null)
{
return;
}
Control.SetImageBitmap(GetBitmap(((SDataMatrix)Element).BitMatrix));
}
private Bitmap GetBitmap(BitMatrix bitMatrix)
{
int BLACK = Color.Black;
int WHITE = Color.White;
// change the values to your needs
int requestedWidth = 200;
int requestedHeight = 200;
int width = bitMatrix.Width;
int height = bitMatrix.Height;
// calculating the scaling factor
int pixelsize = requestedWidth / width;
if (pixelsize > requestedHeight / height)
{
pixelsize = requestedHeight / height;
}
int[] pixels = new int[requestedWidth * requestedHeight];
// All are 0, or black, by default
for (int y = 0; y < height; y++)
{
int offset = y * requestedWidth * pixelsize;
// scaling pixel height
for (int pixelsizeHeight = 0; pixelsizeHeight < pixelsize; pixelsizeHeight++, offset += requestedWidth)
{
for (int x = 0; x < width; x++)
{
int color = bitMatrix[x, y] ? BLACK : WHITE;
// scaling pixel width
for (int pixelsizeWidth = 0; pixelsizeWidth < pixelsize; pixelsizeWidth++)
{
pixels[offset + x * pixelsize + pixelsizeWidth] = color;
}
}
}
}
Bitmap bitmap = Bitmap.CreateBitmap(requestedWidth, requestedHeight, Bitmap.Config.Argb8888);
bitmap.SetPixels(pixels, 0, requestedWidth, 0, 0, requestedWidth, requestedHeight);
return bitmap;
}
}
On iOS:
public class SDataMatrixRenderer : ImageRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (Element == null)
{
return;
}
Control.Image = GetImage(((SDataMatrix)Element).BitMatrix);
}
public UIImage GetImage(BitMatrix matrix)
{
UIGraphics.BeginImageContext(new CGSize(matrix.Width * 10, matrix.Height * 10));
CGContext context = UIGraphics.GetCurrentContext();
CGColor black = new CGColor(0f, 0f, 0f);
CGColor white = new CGColor(1.0f, 1.0f, 1.0f);
for (int x = 0; x < matrix.Width; x++)
{
for (int y = 0; y < matrix.Height; y++)
{
context.SetFillColor(matrix[x, y] ? black : white);
context.FillRect(new CGRect(x*10, y*10, 10, 10));
}
}
UIImage img = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return img;
}
}

Resources