我正在使用FAB
为android
和iOS
平台创建自定义Xamarin.Forms
按钮。
一切正常,但现在我希望能够以某种方式从scrolled
按钮的最近父级接收FAB
事件,因此我将能够隐藏{{1 }}按钮在用户滚动时,然后在滚动2秒后再次显示?。
父级可以是普通的FAB
项目,也可以是ScrollView
。
是否可以通过每个平台使用相同的自定义渲染器来实现?还是完全可以实现?
这是我到目前为止所做的:
ListView
类:
FabButton
public partial class FabButton : Button
{
public static BindableProperty ButtonColorProperty = BindableProperty.Create(nameof(ButtonColor), typeof(Color), typeof(FabButton), Color.Accent);
public Color ButtonColor
{
get => (Color)GetValue(ButtonColorProperty);
set => SetValue(ButtonColorProperty, value);
}
public FabButton()
{
InitializeComponent();
}
}
自定义渲染器:
iOS
public class FabButtonRenderer:ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if(e.NewElement == null)
return;
if (Element.WidthRequest <= 0)
Element.WidthRequest = 60;
if (Element.HeightRequest <= 0)
Element.HeightRequest = 60;
if (Element.Margin == new Thickness(0, 0, 0, 0))
Element.Margin = new Thickness(0, 0, 20, 20);
Element.CornerRadius = (int) Element.WidthRequest / 2;
Element.BorderWidth = 0;
Element.Text = null;
Control.BackgroundColor = ((FabButton) Element).ButtonColor.ToUIColor();
}
public override void Draw(CGRect rect)
{
base.Draw(rect);
Layer.ShadowRadius = 0.2f;
Layer.ShadowColor = UIColor.Black.CGColor;
Layer.ShadowOffset = new CGSize(1, 1);
Layer.ShadowOpacity = 0.80f;
Layer.ShadowPath = UIBezierPath.FromOval(Layer.Bounds).CGPath;
Layer.MasksToBounds = false;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == nameof(FabButton.ButtonColor))
Control.BackgroundColor = ((FabButton) Element).ButtonColor.ToUIColor();
}
}
自定义渲染器:
android
答案 0 :(得分:1)
我认为Scrollview的“ Scrolled”事件可以为您提供帮助,您将获得X和Y轴值,基于此,您必须在滚动时隐藏fab按钮。 并在2秒钟后使用“ Device.StartTimer”。
答案 1 :(得分:1)
很遗憾,没有built-in
的方法。
由于我的原因,Floating Action Button
可能会受到ScrollView
控件滚动或列表视图控件的影响
我想到的唯一方法是明确指定ScrollView
控件Floating Action Button
的连接位置,因为这将是在将Floating Action Button
连接到列表视图ScrollView
时,实现起来很麻烦,并且由于最好使用MVVM
模式,因此我找到了一种更简单的方法。
首先,我声明了一个接口IFloatingActionButtonHost
:
public interface IFloatingActionButtonHost
{
bool ShouldBeHiddenWhenScrolling { get; }
event Action LinkedScrollViewScrolled;
}
然后,我在BindableProperty
控件内声明了FabButton
,如下所示:
public static BindableProperty ButtonHostProperty = BindableProperty.Create(nameof(ButtonHost), typeof(IFloatingActionButtonHost), typeof(FabButton));
public IFloatingActionButtonHost ButtonHost
{
get => (IFloatingActionButtonHost)GetValue(ButtonHostProperty);
set => SetValue(ButtonHostProperty, value);
}
例如,在Renderer
渲染器上的iOS
中,我检查了此属性是否不为null,以及是否应隐藏Floating Action Button
当目标ScrollView
滚动或不滚动然后在界面中订阅该事件时。
var fabButton = (FabButton)Element;
if (fabButton.ButtonHost != null && fabButton.ButtonHost.ShouldBeHiddenWhenScrolling)
{
fabButton.ButtonHost.LinkedScrollViewScrolled += OnLinkedScrollView_Scrolled;
}
然后我在渲染器中处理了事件:
private void OnLinkedScrollView_Scrolled()
{
Element.IsVisible = false;
Device.StartTimer(TimeSpan.FromSeconds(3), () =>
{
if(Element != null){
Element.IsVisible = true;
}
return false;
});
}
OnElementPropertyChanged
实现也应更改。
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == nameof(FabButton.ButtonColor))
Control.BackgroundColor = ((FabButton) Element).ButtonColor.ToUIColor();
else if(e.PropertyName == nameof(FabButton.ButtonHost)){
var fabButton = (FabButton)Element;
if (fabButton.ButtonHost != null && fabButton.ButtonHost.ShouldBeHiddenWhenScrolling)
{
fabButton.ButtonHost.LinkedScrollViewScrolled += OnLinkedScrollView_Scrolled;
}
}
}
在每个页面code-behind
上,我使页面继承自该接口,然后将页面实例传递给目标ViewModel
。
P.S。。对于ListView
,我不得不编写一个自定义渲染器以暴露Scrolled
事件。抱歉,我找不到更好的方法。
这是我尝试解决的问题,如果您有更好的解决方案,请为此问题写另一个答案,我会将其标记为最佳答案。