xamarin.forms - Dynamically hiding Xamarin Forms ListView item and setting the height of invisible item to 0 not working on iOS
问题描述
In a Xamarin Forms ListView, a StackLayout is placed in a ViewCell. The following trigger is used to set the StackLayout's height and margin to 0 so that there is no gap in the ListView.
<StackLayout.Triggers>
<Trigger TargetType="StackLayout" Property="IsVisible" Value="False">
<Setter Property="HeightRequest" Value="0" />
<Setter Property="Margin" Value="0" />
</Trigger>
</StackLayout.Triggers>
The code works perfectly on Android. But there are still gaps on iOS.
Normally calling ViewCell.ForceUpdateSize on a tapping event can help resolve such an issue. But we need to do it grammatically. So I tried to create a CustomViewCell but it doesn't help.
public class CustomViewCell : ViewCell
{
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
var viewModel = (tecommobile.ViewModels.Input)BindingContext;
viewModel.PropertyChanged += (sender, e) =>
{
if (Device.RuntimePlatform == Device.iOS)
{
if (e.PropertyName == "IsVisible")
{
//ForceUpdateSize(); crashes, the possible cause could be the height of the StackLayout is already set to 0. The test shows that the tapped event doesn't fire if the height is 0.
}
}
};
}
}
Please advise a solution or any workaround. Thanks.
解决方案
我们应该使用TriggerAction来改变这个值,并告诉ViewCell更新它的大小。
public class ForceUpdateSizeTriggerAction : TriggerAction<VisualElement>
{
public double HeighRequest { set; get; } // you could set it as bindable property if you want to binding its value in runtime
public Thickness CustomMargin { set; get; }
public ForceUpdateSizeTriggerAction() : base()
{
}
protected override void Invoke(VisualElement sender)
{
var parent = sender.Parent;
while (parent != null && !(parent is ViewCell))
{
parent = parent.Parent;
}
if (parent is ViewCell cell)
{
Device.BeginInvokeOnMainThread(() =>
{
var view = sender as View;
view.HeightRequest = HeighRequest;
view.Margin = CustomMargin;
cell.ForceUpdateSize();
});
}
}
}
在xml中
<StackLayout.Style>
<Style TargetType="StackLayout">
<Setter Property="HeightRequest" Value="xxx"/> //default height
<Style.Triggers>
<DataTrigger TargetType="StackLayout" Binding="{Binding xxx}" Value="False"> /// xxx here is the property which binding to the IsVisible of stacklayout
<DataTrigger.EnterActions>
<local:ForceUpdateSizeTriggerAction HeighRequest="0.01" CustomMargin="0"/>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<local:ForceUpdateSizeTriggerAction HeighRequest="xxx" CustomMargin="xxx"/> // set the default value of height and margin here
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</StackLayout.Style>
并且不要忘记设置HasUnevenRows="True"
列表视图。
推荐阅读
- xcode - macOS Hardened Runtime 是 OS SDK 的一部分吗?
- javascript - 在 HTML 页面之间传输数据似乎不起作用?
- ios - iOS - 键盘显示时顶部单元格从屏幕上移开
- ruby-on-rails - 在 Rails 嵌套路线上需要帮助
- javascript - 如何使用 post 方法使用 Papaparse 下载 csv 文件?
- python - 不使用**计算指数的迭代函数
- sas - 为什么 proc sql sum 函数返回计数而不是总值?
- sapui5 - 表模型刷新后SAP UI5表的列排序丢失
- r - 如何在 r 中创建日期序列
- python - 如何将图像转换为二进制字符串?