xamarin 相关问题

Xamarin是一个由Xamarin.iOS,Xamarin.Android,Xamarin.Mac和Xamarin Test Cloud组成的平台。它允许您编写适用于iOS,Android和Mac的跨平台本机应用程序,并在整个生命周期内关注您的应用程序。 Xamarin.Forms的引入支持iOS,Android和Windows的Native UI开发

如何检测webview滚动到底部?

我想知道用户何时结束在显示条款和条件的 Web 视图上的滚动,以便仅当用户阅读此内容时才显示“接受”按钮。 我想知道用户何时结束在显示条款和条件的 Web 视图上的滚动,以便仅当用户阅读此内容时才显示“接受”按钮。 <StackLayout Spacing="0" BackgroundColor="{StaticResource WhiteColor}"> <CustomView:HeaderView VerticalOptions="Start" LeftImageSource="{Binding LeftImage}" RightImageSource="{Binding RightImage}" LeftCommand="{Binding LeftClickCommand}" RightCommand="{Binding RightClickCommand}" HeaderText="{Binding ScreenTitle}" PrevText="{Localize:ETranslate PrevText}" /> <WebView Source="{Binding Html, Converter={StaticResource HtmlSourceConverter}}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" /> </StackLayout> public class HtmlSourceConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var html = new HtmlWebViewSource(); if (value != null) { html.Html = value.ToString(); } return html; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 我尝试使用 Renderer 来实现此目的,但在 iOS WkWebViewRenderer 中没有 WebViewRenderer 中可用的 Scrolled() 方法。 有什么方法可以在 Xamarin.Forms 中实现这一点吗? WKWebView 内部有一个属性 ScrollView,所以我们可以用它覆盖 Delegate。 WKWebViewRenderer 中的代码 [assembly: ExportRenderer(typeof(WebView), typeof(MyRenderer))] namespace FormsA.iOS { public class MyDelegate : UIScrollViewDelegate { public override void Scrolled(UIScrollView scrollView) { if(scrollView.ContentOffset.Y >= scrollView.ContentSize.Height - scrollView.Frame.Size.Height) { //here rearch bottom } else if(scrollView.ContentOffset.Y < scrollView.ContentSize.Height) { } } } public class MyRenderer: WkWebViewRenderer { protected override void OnElementChanged(VisualElementChangedEventArgs e) { base.OnElementChanged(e); this.ScrollView.Delegate = new MyDelegate(); } } } 它在我这边工作得很好,请参阅https://stackoverflow.com/a/52872317/8187800. 我也有 Android 的解决方案。这是完整的解决方案,希望这对寻找相同解决方案的人有帮助! MyPage.xaml <webview:ScrollWebView x:Name="webView" Source="{Binding Html, Converter={StaticResource HtmlSourceConverter}}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" IsBottomReached="{Binding IsShowAgreeButton}"/> ScrollWebView 控件 public class ScrollWebView : WebView { public static BindableProperty IsBottomReachedProperty = BindableProperty.Create(nameof(IsBottomReached), typeof(bool), typeof(ScrollWebView), default(bool), BindingMode.TwoWay, propertyChanged: null); public bool IsBottomReached { get { return (bool)GetValue(IsBottomReachedProperty); } set { SetValue(IsBottomReachedProperty, value); } } } Android:ScrollWebViewRenderer [assembly: Xamarin.Forms.ExportRenderer(typeof(ScrollWebView), typeof(ScrollWebViewRenderer))] namespace MyApp.Droid { public class ScrollWebViewRenderer : WebViewRenderer { public static ScrollWebView view = null; public ScrollWebViewRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) { base.OnElementChanged(e); view = (ScrollWebView)Element; if (Control != null) { Control.ScrollChange += Control_ScrollChange; } } private void Control_ScrollChange(object sender, ScrollChangeEventArgs e) { var nativeWebView = e.V as global::Android.Webkit.WebView; int height = (int)Math.Floor(nativeWebView.ContentHeight * nativeWebView.Scale); int webViewheight = nativeWebView.Height; int cutOff = height - webViewheight; if (e.ScrollY >= cutOff) { view.IsBottomReached = true; System.Diagnostics.Debug.WriteLine("Bottom Reached"); } else { view.IsBottomReached = false; } } } } iOS:ScrollWebViewRenderer [assembly: ExportRenderer(typeof(ScrollWebView), typeof(ScrollWebViewRenderer))] namespace MyApp.iOS.RendererClasses { public class ScrollWebViewRenderer : WkWebViewRenderer { public static ScrollWebView view = null; public ScrollWebViewRenderer() { } protected override void OnElementChanged(VisualElementChangedEventArgs e) { base.OnElementChanged(e); view = (ScrollWebView)Element; MyDelegate myDel = new MyDelegate(); myDel.ProcessCompleted += MyDel_ProcessCompleted; this.ScrollView.Delegate = myDel; } private void MyDel_ProcessCompleted(object sender, bool isScrolledToBottom) { view.IsBottomReached = isScrolledToBottom; } } public class MyDelegate : UIScrollViewDelegate { public event EventHandler<bool> ProcessCompleted; public override void Scrolled(UIScrollView scrollView) { if (scrollView.ContentOffset.Y >= scrollView.ContentSize.Height - scrollView.Frame.Size.Height) { System.Diagnostics.Debug.WriteLine("Bottom Reached"); ProcessCompleted?.Invoke(this, true); } else { ProcessCompleted?.Invoke(this, false); } } } } 实现这个答案后,https://stackoverflow.com/a/66931493/15125666我仍然遇到Android渲染器的问题,因为它没有检测到用户何时到达WebView的底部。 为了解决这个问题,您需要在计算中添加一个缓冲区,这将在将内容高度乘以比例时考虑任何潜在的浮点错误。 这里是 Android 的更新代码:ScrollWebViewRenderer private void Control_ScrollChange(object sender, ScrollChangeEventArgs e) { var nativeWebView = e.V as global::Android.Webkit.WebView; int height = (int)(nativeWebView.ContentHeight * nativeWebView.Scale); int webViewheight = nativeWebView.Height; int bottomThreshold = (int)Math.Floor(0.004 * webViewheight); // the number that I used 0.004 was what worked for me. you might need to adjust it for your use case. int cutOff = height - webViewheight - bottomThreshold; if (e.ScrollY >= cutOff) { view.IsBottomReached = true; System.Diagnostics.Debug.WriteLine("Bottom Reached"); } else { view.IsBottomReached = false; } } 这里我添加了一个动态 bottomThreshold 缓冲区,并将其用于 cutOff 计算。它在计算中添加了一个小缓冲区,以确保即使很小的差异也不会妨碍到达底部的检测。

回答 3 投票 0

如何修复错误 XAGJS7028:无法在 .NET MAUI 中加载程序集“Xamarin.AndroidX.AppCompat.Resources”?

我正在将 Xamarin 表单代码迁移到 .NET MAUI。迁移后,当我构建 Android 项目时,出现以下错误: 错误 XAGJS7028 System.IO.FileNotFoundException:无法加载程序集 '

回答 1 投票 0

在 Android 14、xamarin 上请求 USB 权限失败

我尝试在Android 14和Xamarin项目上获得USB设备的许可。我使用USBSerialForAndroid(https://github.com/anotherlab/UsbSerialForAndroid/) 以下几行是我所做的工作。 ...

回答 1 投票 0

为什么PackageInfo总是为空?

我正在使用 Xamarin 开发一个具有通用主干和两个适用于 android 和 UWP 的侧分支的项目。 该项目是一个用 C# 构建的应用程序。 由于某种原因,PackageInfo 总是返回空...

回答 1 投票 0

Xamarin.Google.UserMessagingPlatform 指南?

我正处于使用 Xamarin / C# 设置 Android 应用程序的最后阶段。我已经实施了 Google Admob,但 GDPR 规则规定我必须有隐私声明才能展示广告。谷歌的文档...

回答 2 投票 0

Xamarin:默认显示警报背景颜色并不总是遵循应用程序主题

我有一个 Xamarin 应用程序,我在其中使用 DisplayAlert(),并且我注意到它通常会在浅色模式下显示警报,即使我处于深色模式下也是如此。在调试时,我检查了该值...

回答 1 投票 0

如何在 Xamarin Forms 中设置标签的名称

我正在尝试向标签添加名称,以便我可以使用 Content.FindByName<>() 方法找到它 据我所知 Xamarin.Forms.Label() 类没有 Name 属性 这是我的页面...

回答 6 投票 0

HttpClient.GetAsync 在 Xamarin.Android 上永远不会返回

我正在开发一个 Android 应用程序,由 Azure 上托管的 ASP.NET Core 应用程序支持。我正在使用共享库项目来测试控制台应用程序项目上的基本内容,然后再进行...

回答 3 投票 0

Android Xamarin c# 替换 Fragment 后无法更新视图

我有一个正在处理物品“制作”的片段,它显示一个“制作台”、物品成本清单和库存。 在片段的第一次初始化时,

回答 1 投票 0

Xamarin IOS 应用程序应用程序发布构建失败 [错误 MT1006:AMDeviceSecureInstallApplicationBundle 返回:0xe8008015。]

我正在尝试在 iphone Xs Max 中发布我的 IOS 应用程序,但失败并显示上述错误。在 Dubug 模式下它可以工作。 我已经尝试多次通过创建证书和配置文件...

回答 1 投票 0

.NET Maui 在 Mac 上使用 Jetbrains Rider 错误

这是 .net MAUI 的模板项目。选择新的解决方案后,我使用 Jetbrains IDE 界面创建一个新的 .net MAUI 项目。默认版本是 Pixel 5,这曾经用于工作...

回答 1 投票 0

Azure DevOps Android 发布到 Google Play 商店失败

我是 CI/CD 新手。我不明白我做错了什么。 我在 Azure Devops 中设置了一个管道,用于签署 aab 文件并将其放入 Artifacts 中。到目前为止,一切都很好。 然后我创建了一个版本

回答 1 投票 0

Xamarin.Android 应用程序中的深度链接不起作用

在我们的应用程序中,我们使用深层链接。它们在应用程序打开或在后台运行时工作,但在应用程序完全关闭时不起作用。 应用程序打开,但 OnNewIntent 和

回答 1 投票 0

Xamarin 表单数据绑定问题,视图未更新

我没有对整个页面使用绑定上下文页面或 x:DataType。我对每个组件使用单独的 x:DataType。如下所示: 主要问题是第一个组件的行为为 exp...

回答 1 投票 0

Xamarin iOS 图标设置

“我正在尝试在 Windows 设备上为我使用 Xamarin Forms 开发的 iOS 应用程序设置图标,但我似乎无法做到这一点。我已尝试了所有建议的方法,但它不起作用。我可以吗? ...

回答 1 投票 0

如何在wpf中的xamarin表单中隐藏标题栏

我想使用新的 MVVM 在 WPF 中的 Xamarin 表单中隐藏标题栏。我想在全屏模式下显示我的播放器页面,没有任何边框,并隐藏最小化、最大化和关闭按钮 我用过

回答 1 投票 0

为什么我的工具栏没有显示溢出图标?

我的主要活动使用无操作栏主题。我改用工具栏。现在我设计了一个菜单文件,用于填充工具栏右侧的图标。菜单文件的标记如下所示 <

回答 1 投票 0

如何将 Xamarin ImageSource 转换为像素操作格式(例如 SkiaSharp 或 GDI)?

我正在开发一个 Xamarin.Forms 项目,我需要对通过 Xamarin 的 ImageSource 加载的图像执行像素级操作。我正在寻找一种将 ImageSource 转换为格式的方法...

回答 1 投票 0

.NET MAUI 更改默认后退按钮行为

在我正在使用 MVVM 模式开发的 .NET MAUI 移动应用程序(目标设备:Android)中,当执行从主页到子页面的一些导航以便从某个特定位置返回时...

回答 1 投票 0

Xamarin iOS Firebase 分析

我不明白如何使用参数中的数组项来记录事件。 例如,如果我需要记录类似 EventNamesConstants.Login 的内容,我可以这样做 var 参数 = 新字典 我不明白如何使用参数中的数组项来记录事件。 例如,如果我需要记录类似 EventNamesConstants.Login 的内容,我可以这样做 var parameters = new Dictionary<object, object> { ParameterNamesConstants.Method, "Google" } }; Analytics.LogEvent(EventNamesConstants.Login, parameters); 但现在我需要登录EventNamesConstants.ViewItem 参数之一是项目数组,其中项目有名称。 当我尝试做类似的事情时 var items = new[]{ new Dictionary<object, object> { ParameterNamesConstants.ItemName, title } } }; var parameters = new Dictionary<object, object> { ParameterNamesConstants.Currency, currencyCode }, ParameterNamesConstants.Value, value }, ParameterNamesConstants.Items, items } }; 我收到一个错误。 我试图找到示例,但他们没有数组。 非常抱歉。 错误是: 不知道如何封送类型的对象 'System.Collections.Generic.Dictionary`2[System.Object,System.Object][]' to an NSObject Firebase 的 func Analytics.LogEvent 是: public static void LogEvent (string name, Dictionary<object, object>? parameters) { LogEvent (name, (parameters == null) ? null : ((parameters!.Keys.Count == 0) ? new NSDictionary<NSString, NSObject> () : NSDictionary<NSString, NSObject>.FromObjectsAndKeys (parameters!.Values.ToArray (), parameters!.Keys.ToArray (), nint.op_Implicit (parameters!.Keys.Count)))); } 请帮助我。 作为解决方法,您可以尝试以下方法来创建参数, var keys = new[] { new NSString("key1"), new NSString("key2"), }; var objects = new NSObject[] { new NSString("object1"), new NSString("object1"), }; NSDictionary dicionary = new NSDictionary<NSString, NSObject>(keys, objects); NSArray items = NSArray.FromNSObjects(dicionary); var parameters = new Dictionary<object, object> { { ParameterNamesConstants.Currency, currencyCode }, { ParameterNamesConstants.Value, value }, { ParameterNamesConstants.Items, items } }; 我还在我的应用中使用 Firebase Analytics。 这是 IDictionary<string, string> 上合适的扩展方法,任何人都可以使用它轻松地将 C# IDictionary 转换为 iOS NSDictionary /// <summary> /// Converts an <see cref="IDictionary{TKey, TValue}"/> of string key-value pairs to an <see cref="NSDictionary"/> of <see cref="NSString"/> keys and <see cref="NSObject"/> values. /// </summary> /// <param name="dictionary">The dictionary to convert. Cannot be null.</param> /// <returns>An <see cref="NSDictionary"/> with <see cref="NSString"/> keys and <see cref="NSObject"/> values corresponding to the entries in the input dictionary.</returns> /// <exception cref="ArgumentNullException">Thrown if the input dictionary is null.</exception> /// <remarks> /// This method iterates over the input dictionary to create a pair of arrays for keys and values, which are then used to construct the NSDictionary. /// It's designed to be used as an extension method for any IDictionary&lt;string, string&gt; instance. /// Note: Null keys or values in the input dictionary will result in exceptions, as <see cref="NSString"/> cannot be instantiated with a null reference. /// </remarks> /// <example> /// <code> /// var myDict = new Dictionary&lt;string, string&gt; { { "key1", "value1" }, { "key2", "value2" } }; /// var nsDict = myDict.ToNSDictionary(); /// </code> /// </example> public static NSDictionary<NSString, NSObject> ToNSDictionary(this IDictionary<string, string> dictionary) { ArgumentNullException.ThrowIfNull(dictionary); var keysAndValues = dictionary .Select(kv => (Key: new NSString(kv.Key), Value: new NSString(kv.Value))) .ToArray(); var keys = keysAndValues .Select(kv => kv.Key) .ToArray(); var values = keysAndValues .Select(kv => kv.Value) .ToArray(); return new NSDictionary<NSString, NSObject>(keys, values); } 如果您需要,这里还有一份 IDictionary<string, object> /// <summary> /// Converts an <see cref="IDictionary{TKey, TValue}"/> of string key-value pairs to an <see cref="NSDictionary"/> of <see cref="NSString"/> keys and <see cref="NSObject"/> values. /// </summary> /// <param name="dictionary">The dictionary to convert. Cannot be null.</param> /// <returns>An <see cref="NSDictionary"/> with <see cref="NSString"/> keys and <see cref="NSObject"/> values corresponding to the entries in the input dictionary.</returns> /// <exception cref="ArgumentNullException">Thrown if the input dictionary is null.</exception> /// <remarks> /// This method iterates over the input dictionary to create a pair of arrays for keys and values, which are then used to construct the NSDictionary. /// It's designed to be used as an extension method for any IDictionary&lt;string, object&gt; instance. /// Note: Null keys or values in the input dictionary will result in exceptions, as <see cref="NSString"/> cannot be instantiated with a null reference. /// </remarks> /// <example> /// <code> /// var myDict = new Dictionary&lt;string, object&gt; { { "key1", object1 }, { "key2", object2 } }; /// var nsDict = myDict.ToNSDictionary(); /// </code> /// </example> public static NSDictionary<NSString, NSObject> ToNSDictionary(this IDictionary<string, object> dictionary) { ArgumentNullException.ThrowIfNull(dictionary); var keys = dictionary.Keys .Select(arg => new NSString(arg)) .ToArray(); var objects = dictionary.Values .Select(NSObject.FromObject) .ToArray(); return new NSDictionary<NSString, NSObject>(keys, objects); } 仅供参考:我使用 ArgumentNullException.ThrowIfNull => 仅自 C#10 起可用,如果您在 C#10 下,请使用经典方法。

回答 2 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.