Xaml 如何在Xamarin表单中显示工具栏项图标的徽章计数
它不是关于如何显示通知徽章,也不是关于如何显示工具栏项目图标。很明显,如何在工具栏项目图标上显示徽章是个问题 我正在共享在XF内容页中创建带有图标的工具栏项目的代码: 在cs文件中:Xaml 如何在Xamarin表单中显示工具栏项图标的徽章计数,xaml,xamarin,xamarin.android,xamarin.forms,xamarin-studio,Xaml,Xamarin,Xamarin.android,Xamarin.forms,Xamarin Studio,它不是关于如何显示通知徽章,也不是关于如何显示工具栏项目图标。很明显,如何在工具栏项目图标上显示徽章是个问题 我正在共享在XF内容页中创建带有图标的工具栏项目的代码: 在cs文件中: ToolbarItem cartItem = new ToolbarItem(); scanItem.Text = "My Cart"; scanItem.Order = ToolbarItemOrder.Primary; scanItem.Icon = "carticon.png"
ToolbarItem cartItem = new ToolbarItem();
scanItem.Text = "My Cart";
scanItem.Order = ToolbarItemOrder.Primary;
scanItem.Icon = "carticon.png";
ToolbarItems.Add(cartItem );
在Xaml文件中:
<ContentPage.ToolbarItems>
<ToolbarItem Text="Cart" Priority="0" x:Name="menu1">
</ToolbarItem>
</ContentPage.ToolbarItems>
现在我想在上面添加的工具栏项目图标上放置一个徽章计数。如何实现这一目标 在本机工具栏中放置徽章图标实际上比它的价值更大。如果我需要徽章图标,我会删除导航页面
NavigationPage.SetHasNavigationBar(myPageInstance, false);
然后我从头开始创建自己的工具栏。在这个工具栏中,我可以在其中覆盖一个图像,你也可以根据需要在其中放置一个数字。比如说
<Grid>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding IconCommand}" />
</Grid.GestureRecognizers>
<iconize:IconImage
Icon="fa-drawer"
IconColor="white"
IconSize="20" />
<Grid Margin="15,-15,0,0">
<iconize:IconImage Grid.Row="0"
HeightRequest="40"
WidthRequest="40"
Icon="fa-circle"
IconColor="red"
IsVisible="{Binding IsCircleVisible}"
IconSize="10" />
</Grid>
</Grid>
我使用wtih FontAwesome作为图标在的帮助下,我实现了它。在实施之前,阅读并理解完整的讨论。感谢“斯拉瓦·切尼科夫”、“伊曼纽尔·萨贝塔”、“米尔扎·西坎德”、“萨蒂什”与您讨论并分享您的代码
SETP1:在PCL中创建一个助手类,并从nugget安装NGraphics包
public class CartIconHelper
{
private static Graphic _svgGraphic = null;
public const string ResourcePath = "ToolBarAndroidBadge.Resources.cartIcon.svg";
private static PathOp[] RoundRect(NGraphics.Rect rect, double radius)
{
return new PathOp[]
{
new NGraphics.MoveTo(rect.X + radius, rect.Y),
new NGraphics.LineTo(rect.X + rect.Width - radius, rect.Y),
new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X + rect.Width, rect.Y + radius)),
new NGraphics.LineTo(rect.X + rect.Width, rect.Y + rect.Height - radius),
new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X + rect.Width - radius, rect.Y + rect.Height)),
new NGraphics.LineTo(rect.X + radius, rect.Y + rect.Height),
new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X, rect.Y + rect.Height - radius)),
new NGraphics.LineTo(rect.X, rect.Y + radius), new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X + radius, rect.Y)),
new NGraphics.ClosePath()
};
}
public static string DrawCartIcon(int count, string path, double iconSize = 30, double scale = 2, string fontName = "Arial", double fontSize = 12, double textSpacing = 4)
{
var service = DependencyService.Get<IService>();
var canvas = service.GetCanvas();
if (_svgGraphic == null) using (var stream = typeof(CartIconHelper).GetTypeInfo().Assembly.GetManifestResourceStream(path))
_svgGraphic = new SvgReader(new StreamReader(stream)).Graphic;
//st = ReadFully(stream);
var minSvgScale = Math.Min(canvas.Size.Width / _svgGraphic.Size.Width, canvas.Size.Height / _svgGraphic.Size.Height) / 1.15;
var w = _svgGraphic.Size.Width / minSvgScale;
var h = _svgGraphic.Size.Height / minSvgScale;
_svgGraphic.ViewBox = new NGraphics.Rect(0, -14, w, h);
_svgGraphic.Draw(canvas);
if (count > 0)
{
var text = count > 99 ? "99+" : count.ToString();
var font = new NGraphics.Font(fontName, fontSize);
var textSize = canvas.MeasureText(text, font);
var textRect = new NGraphics.Rect(canvas.Size.Width - textSize.Width - textSpacing, textSpacing, textSize.Width, textSize.Height);
if (count < 10)
{
var side = Math.Max(textSize.Width, textSize.Height);
var elipseRect = new NGraphics.Rect(canvas.Size.Width - side - 2 * textSpacing, 0, side + 2 * textSpacing, side + 2 * textSpacing);
canvas.FillEllipse(elipseRect, NGraphics.Colors.Red);
textRect -= new NGraphics.Point(side - textSize.Width, side - textSize.Height) / 2.0;
}
else
{
var elipseRect = new NGraphics.Rect(textRect.Left - textSpacing, textRect.Top - textSpacing, textRect.Width + 2 * textSpacing, textSize.Height + 2 * textSpacing);
canvas.FillPath(RoundRect(elipseRect, 6), NGraphics.Colors.Red);
}
var testReact1= new NGraphics.Rect(20,12,0,0);
// canvas.DrawText(text, textRect + new NGraphics.Point(0, textSize.Height), font, NGraphics.TextAlignment.Center, NGraphics.Colors.Black);
canvas.DrawText("5", testReact1, font, NGraphics.TextAlignment.Left, NGraphics.Colors.White);
}
service.SaveImage(canvas.GetImage());
string imagePath = service.GetImage();
return imagePath;
// return st;
}
}
步骤3:在Android项目中实现此接口
class CanvasServices:IService
{
private readonly AndroidPlatform _platform;
public CanvasServices()
{
_platform = new AndroidPlatform();
}
public void SaveImage(IImage image)
{
var dir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var filePath = System.IO.Path.Combine(dir, "cart.png");
var stream = new FileStream(filePath, FileMode.Create);
image.SaveAsPng(stream);
//bitmap.Compress(image., 100, stream);
stream.Close();
}
public string GetImage()
{
var dir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var filePath = System.IO.Path.Combine(dir, "cart.png");
using (var streamReader = new StreamReader(filePath))
{
string content = streamReader.ReadToEnd();
System.Diagnostics.Debug.WriteLine(content);
}
return filePath;
}
public IImageCanvas GetCanvas()
{
NGraphics.Size size = new NGraphics.Size(30);
return _platform.CreateImageCanvas(size);
}
public NGraphics.AndroidPlatform GetPlatform()
{
return _platform;
}
}
SETP4:现在,在PCL项目中使用CartIcon助手在TabBarItem中显示徽章
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
var imagePath = CartIconHelper.DrawCartIcon(2, "ToolBarAndroidBadge.Resources.cartIcon.svg");
string deviceSepecificFolderPath = Device.OnPlatform(null, imagePath, null);
object convertedObject = new FileImageSourceConverter().ConvertFromInvariantString(deviceSepecificFolderPath);
FileImageSource fileImageSource = (FileImageSource)convertedObject;
ToolbarItem cartItem = new ToolbarItem();
cartItem.Text = "My Cart";
cartItem.Order = ToolbarItemOrder.Primary;
cartItem.Icon = fileImageSource;
ToolbarItems.Add(cartItem);
}
}
实现下面的代码,在工具栏图标上用文本绘制一个地圆
使用CoreAnimation;
使用核心图形;
使用基础;
使用ObjectRuntime;
使用制度;
使用System.Linq;
使用System.Runtime.InteropServices;
使用UIKit;
命名空间TeamCollaXform.Views.Services
{
公共静态类BarButtonItemExtensions
{
枚举关联策略
{
赋值=0,
保留_非原子=1,
复制_非原子=3,
RETAIN=01401,
副本=01403,
}
静态NSString BadgeKey=新NSString(@“BadgeKey”);
[DllImport(Constants.ObjectiveLibrary)]
静态外部无效对象jc_setAssociatedObject(IntPtr对象、IntPtr键、IntPtr值、AssociationPolicy策略);
[DllImport(Constants.ObjectiveLibrary)]
静态外部IntPtr objc_getAssociatedObject(IntPtr obj,IntPtr key);
静态CAShapeLayer GetBadgeLayer(UIBarButtonItem barButtonItem)
{
var handle=objc_getAssociatedObject(barButtonItem.handle,BadgeKey.handle);
if(handle!=IntPtr.Zero)
{
var value=ObjCRuntime.Runtime.GetNSObject(句柄);
if(值!=null)
返回值为CAShapeLayer;
其他的
返回null;
}
返回null;
}
静态空白DrawRoundedRect(CAShapeLayer层、CGRect rect、浮动半径、UIColor颜色、bool填充)
{
layer.FillColor=filled?color.CGColor:UIColor.White.CGColor;
layer.StrokeColor=color.CGColor;
layer.Path=UIBezierPath.FromRoundedRect(rect,radius).CGPath;
}
public static void AddBadge(此UIBarButtonItem barButtonItem,字符串文本,UIColor backgroundColor,UIColor textColor,bool filled=true,float fontSize=11.0f)
{
if(string.IsNullOrEmpty(text))
{
返回;
}
CGPoint offset=CGPoint.Empty;
if(backgroundColor==null)
backgroundColor=UIColor.Red;
var font=UIFont.SystemFontOfSize(fontSize);
if(UIDevice.CurrentDevice.CheckSystemVersion(9,0))
{
font=UIFont.monospacedGitSystemFontOfsize(fontSize,UIFontWeight.Regular);
}
var view=barButtonItem.ValueForKey(新的NSString(@“视图”))作为UIView;
var bLayer=GetBadgeLayer(巴布通体);
bLayer?.RemoveFromSuperLayer();
var badgeSize=text.StringSize(字体);
var高度=徽章大小。高度;
var width=badgeSize.width+5;/*填充*/
//确保我们至少有一个圆圈
if(宽度<高度)
{
宽度=高度;
}
//x位置从右侧偏移
var x=view.Frame.Width-宽度+偏移量.x;
var badgeFrame=新的CGRect(新的CGPoint(x:x-4,y:offset.y+5),大小:新的CGSize(宽度:宽度,高度:高度));
bLayer=新的CAShapeLayer();
DrawRoundedRect(bLayer,徽章框架,7.0f,背景色,填充);
view.Layer.AddSublayer(bLayer);
//初始化徽章标签
var label=new CATextLayer();
label.String=文本;
label.TextAlignmentMode=CATextLayerAlignmentMode.Center;
label.SetFont(CGFont.CreateWithFontName(font.Name));
label.FontSize=font.PointSize;
label.Frame=badgeFrame;
label.ForegroundColor=filled?textColor.CGColor:UIColor.White.CGColor;
label.BackgroundColor=UIColor.Clear.CGColor;
label.ContentsScale=UIScreen.MainScreen.Scale;
bLayer.AddSublayer(标签);
//将徽章另存为UIBarButtonItem属性
objc_setAssociatedObject(barButtonItem.Handle、BadgeKey.Handle、bLayer.Handle、AssociationPolicy.RETAIN_非原子);
}
公共静态void updateEdge(此UIBarButtonim BarButtonim、字符串文本、UIColor backgroundColor、UIColor textColor)
{
var bLayer=GetBadgeLayer(巴布通体);
if(string.IsNullOrEmpty(text)| | text==“0”)
{
bLayer?.RemoveFromSuperLayer();
objc_setAssociatedObject(barButtonItem.Handle、BadgeKey.Handle、new CAShapeLayer().Handle、AssociationPolicy.ASSIGN);
返回;
}
变量文本
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
var imagePath = CartIconHelper.DrawCartIcon(2, "ToolBarAndroidBadge.Resources.cartIcon.svg");
string deviceSepecificFolderPath = Device.OnPlatform(null, imagePath, null);
object convertedObject = new FileImageSourceConverter().ConvertFromInvariantString(deviceSepecificFolderPath);
FileImageSource fileImageSource = (FileImageSource)convertedObject;
ToolbarItem cartItem = new ToolbarItem();
cartItem.Text = "My Cart";
cartItem.Order = ToolbarItemOrder.Primary;
cartItem.Icon = fileImageSource;
ToolbarItems.Add(cartItem);
}
}
using CoreAnimation;
using CoreGraphics;
using Foundation;
using ObjCRuntime;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using UIKit;
namespace TeamCollaXform.Views.Services
{
public static class BarButtonItemExtensions
{
enum AssociationPolicy
{
ASSIGN = 0,
RETAIN_NONATOMIC = 1,
COPY_NONATOMIC = 3,
RETAIN = 01401,
COPY = 01403,
}
static NSString BadgeKey = new NSString(@"BadgeKey");
[DllImport(Constants.ObjectiveCLibrary)]
static extern void objc_setAssociatedObject(IntPtr obj, IntPtr key, IntPtr value, AssociationPolicy policy);
[DllImport(Constants.ObjectiveCLibrary)]
static extern IntPtr objc_getAssociatedObject(IntPtr obj, IntPtr key);
static CAShapeLayer GetBadgeLayer(UIBarButtonItem barButtonItem)
{
var handle = objc_getAssociatedObject(barButtonItem.Handle, BadgeKey.Handle);
if (handle != IntPtr.Zero)
{
var value = ObjCRuntime.Runtime.GetNSObject(handle);
if (value != null)
return value as CAShapeLayer;
else
return null;
}
return null;
}
static void DrawRoundedRect(CAShapeLayer layer, CGRect rect, float radius, UIColor color, bool filled)
{
layer.FillColor = filled ? color.CGColor : UIColor.White.CGColor;
layer.StrokeColor = color.CGColor;
layer.Path = UIBezierPath.FromRoundedRect(rect, radius).CGPath;
}
public static void AddBadge(this UIBarButtonItem barButtonItem, string text, UIColor backgroundColor, UIColor textColor, bool filled = true, float fontSize = 11.0f)
{
if (string.IsNullOrEmpty(text))
{
return;
}
CGPoint offset = CGPoint.Empty;
if (backgroundColor == null)
backgroundColor = UIColor.Red;
var font = UIFont.SystemFontOfSize(fontSize);
if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
{
font = UIFont.MonospacedDigitSystemFontOfSize(fontSize, UIFontWeight.Regular);
}
var view = barButtonItem.ValueForKey(new NSString(@"view")) as UIView;
var bLayer = GetBadgeLayer(barButtonItem);
bLayer?.RemoveFromSuperLayer();
var badgeSize = text.StringSize(font);
var height = badgeSize.Height;
var width = badgeSize.Width + 5; /* padding */
//make sure we have at least a circle
if (width < height)
{
width = height;
}
//x position is offset from right-hand side
var x = view.Frame.Width - width + offset.X;
var badgeFrame = new CGRect(new CGPoint(x: x - 4, y: offset.Y + 5), size: new CGSize(width: width, height: height));
bLayer = new CAShapeLayer();
DrawRoundedRect(bLayer, badgeFrame, 7.0f, backgroundColor, filled);
view.Layer.AddSublayer(bLayer);
// Initialiaze Badge's label
var label = new CATextLayer();
label.String = text;
label.TextAlignmentMode = CATextLayerAlignmentMode.Center;
label.SetFont(CGFont.CreateWithFontName(font.Name));
label.FontSize = font.PointSize;
label.Frame = badgeFrame;
label.ForegroundColor = filled ? textColor.CGColor : UIColor.White.CGColor;
label.BackgroundColor = UIColor.Clear.CGColor;
label.ContentsScale = UIScreen.MainScreen.Scale;
bLayer.AddSublayer(label);
// Save Badge as UIBarButtonItem property
objc_setAssociatedObject(barButtonItem.Handle, BadgeKey.Handle, bLayer.Handle, AssociationPolicy.RETAIN_NONATOMIC);
}
public static void UpdateBadge(this UIBarButtonItem barButtonItem, string text, UIColor backgroundColor, UIColor textColor)
{
var bLayer = GetBadgeLayer(barButtonItem);
if (string.IsNullOrEmpty(text) || text == "0")
{
bLayer?.RemoveFromSuperLayer();
objc_setAssociatedObject(barButtonItem.Handle, BadgeKey.Handle, new CAShapeLayer().Handle, AssociationPolicy.ASSIGN);
return;
}
var textLayer = bLayer?.Sublayers?.First(p => p is CATextLayer) as CATextLayer;
if (textLayer != null)
{
textLayer.String = text;
}
else
{
barButtonItem.AddBadge(text, backgroundColor, textColor);
}
}
}
}
using TeamCollaXform.Views.Services;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: Dependency(typeof(ToolbarItemBadgeService))]
namespace TeamCollaXform.Views.Services
{
/// <summary>
///
/// </summary>
public interface IToolbarItemBadgeService
{
void SetBadge(Page page, ToolbarItem item, string value, Color backgroundColor, Color textColor);
}
/// <summary>
///
/// </summary>
public class ToolbarItemBadgeService : IToolbarItemBadgeService
{
public void SetBadge(Page page, ToolbarItem item, string value, Color backgroundColor, Color textColor)
{
Device.BeginInvokeOnMainThread(() =>
{
var renderer = Platform.GetRenderer(page);
if (renderer == null)
{
renderer = Platform.CreateRenderer(page);
Platform.SetRenderer(page, renderer);
}
var vc = renderer.ViewController;
var rightButtomItems = vc?.ParentViewController?.NavigationItem?.RightBarButtonItems;
var idx = rightButtomItems.Length - page.ToolbarItems.IndexOf(item) - 1; //Revert
if (rightButtomItems != null && rightButtomItems.Length > idx)
{
var barItem = rightButtomItems[idx];
if (barItem != null)
{
barItem.UpdateBadge(value, backgroundColor.ToUIColor(), textColor.ToUIColor());
}
}
});
}
}
}
void OnAttachClicked(object sender, EventArgs e)
{
//var answer = await DisplayAlert("Question?", "Would you like to play a game", "Yes", "No");
//Debug.WriteLine("Answer: " + answer);
ToolbarItem cmdItem = sender as ToolbarItem;
DependencyService.Get<IToolbarItemBadgeService>().SetBadge(this, cmdItem, $"2", Color.DarkOrange, Color.White);
}
private void Button_Clicked(object sender, System.EventArgs e)
{
MessagingCenter.Send(this, "presnt");
}
MessagingCenter.Subscribe<YourPage>(this, "presnt", (sender) =>
{
IsPresented = true;
});