gpt4 book ai didi

xamarin.forms - Xamarin Forms 滑动按钮

转载 作者:行者123 更新时间:2023-12-03 23:22:38 30 4
gpt4 key购买 nike

我希望在我的应用程序中添加一个滑动功能,该功能与(旧的?)iPhone 上的解锁机制几乎相同(参见图片)。

enter image description here
enter image description here

我正在努力解决如何在跨平台解决方案上实现这一点。我的直接想法是使用 slider 和自定义渲染器,但不确定如果用户在完成幻灯片之前放开,如何创建捕捉开始的功能。如果有人可以协助该功能,或者他们对如何实现此功能有更好的建议,将不胜感激。

最佳答案

除非和直到 - 您确实需要为每个平台提供特别原生的外观;您几乎可以使用 PanGestureRecognizer 编写自己的自定义 slider 控件, 和 AbsoluteLayout ( 无需任何自定义渲染器 )。对于捕捉效果,您可以使用 Translation animationCubic easing影响。

例如,您可以定义一个控件如下;此示例控件扩展了 AbsoluteLayout同时允许您定义代表拇指和轨迹栏的自己的控件。它还创建了一个几乎不可见的最顶层来充当平移手势监听器。一旦手势完成,它会检查滑动是否完成(即轨迹栏的整个宽度) - 然后提升 SlideCompleted事件。

public class SlideToActView : AbsoluteLayout
{
public static readonly BindableProperty ThumbProperty =
BindableProperty.Create(
"Thumb", typeof(View), typeof(SlideToActView),
defaultValue: default(View), propertyChanged: OnThumbChanged);

public View Thumb
{
get { return (View)GetValue(ThumbProperty); }
set { SetValue(ThumbProperty, value); }
}

private static void OnThumbChanged(BindableObject bindable, object oldValue, object newValue)
{
((SlideToActView)bindable).OnThumbChangedImpl((View)oldValue, (View)newValue);
}

protected virtual void OnThumbChangedImpl(View oldValue, View newValue)
{
OnSizeChanged(this, EventArgs.Empty);
}

public static readonly BindableProperty TrackBarProperty =
BindableProperty.Create(
"TrackBar", typeof(View), typeof(SlideToActView),
defaultValue: default(View), propertyChanged: OnTrackBarChanged);

public View TrackBar
{
get { return (View)GetValue(TrackBarProperty); }
set { SetValue(TrackBarProperty, value); }
}

private static void OnTrackBarChanged(BindableObject bindable, object oldValue, object newValue)
{
((SlideToActView)bindable).OnTrackBarChangedImpl((View)oldValue, (View)newValue);
}

protected virtual void OnTrackBarChangedImpl(View oldValue, View newValue)
{
OnSizeChanged(this, EventArgs.Empty);
}

private PanGestureRecognizer _panGesture = new PanGestureRecognizer();
private View _gestureListener;
public SlideToActView()
{
_panGesture.PanUpdated += OnPanGestureUpdated;
SizeChanged += OnSizeChanged;

_gestureListener = new ContentView { BackgroundColor = Color.White, Opacity = 0.05 };
_gestureListener.GestureRecognizers.Add(_panGesture);
}

public event EventHandler SlideCompleted;

private const double _fadeEffect = 0.5;
private const uint _animLength = 50;
async void OnPanGestureUpdated(object sender, PanUpdatedEventArgs e)
{
if (Thumb == null | TrackBar == null)
return;

switch (e.StatusType)
{
case GestureStatus.Started:
await TrackBar.FadeTo(_fadeEffect, _animLength);
break;

case GestureStatus.Running:
// Translate and ensure we don't pan beyond the wrapped user interface element bounds.
var x = Math.Max(0, e.TotalX);
if (x > (Width - Thumb.Width))
x = (Width - Thumb.Width);

if (e.TotalX < Thumb.TranslationX)
return;
Thumb.TranslationX = x;
break;

case GestureStatus.Completed:
var posX = Thumb.TranslationX;

// Reset translation applied during the pan (snap effect)
await TrackBar.FadeTo(1, _animLength);
await Thumb.TranslateTo(0, 0, _animLength * 2, Easing.CubicIn);

if (posX >= (Width - Thumb.Width - 10/* keep some margin for error*/))
SlideCompleted?.Invoke(this, EventArgs.Empty);
break;
}
}

void OnSizeChanged(object sender, EventArgs e)
{
if (Width == 0 || Height == 0)
return;
if (Thumb == null || TrackBar == null)
return;


Children.Clear();

SetLayoutFlags(TrackBar, AbsoluteLayoutFlags.SizeProportional);
SetLayoutBounds(TrackBar, new Rectangle(0, 0, 1, 1));
Children.Add(TrackBar);

SetLayoutFlags(Thumb, AbsoluteLayoutFlags.None);
SetLayoutBounds(Thumb, new Rectangle(0, 0, this.Width/5, this.Height));
Children.Add(Thumb);

SetLayoutFlags(_gestureListener, AbsoluteLayoutFlags.SizeProportional);
SetLayoutBounds(_gestureListener, new Rectangle(0, 0, 1, 1));
Children.Add(_gestureListener);
}
}

示例用法:
<StackLayout Margin="40">
<local:SlideToActView HeightRequest="50" SlideCompleted="Handle_SlideCompleted">
<local:SlideToActView.Thumb>
<Frame CornerRadius="10" HasShadow="false" BackgroundColor="Silver" Padding="0">
<Image Source="icon.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="40" WidthRequest="40" />
</Frame>
</local:SlideToActView.Thumb>

<local:SlideToActView.TrackBar>
<Frame CornerRadius="10" HasShadow="false" BackgroundColor="Gray" Padding="0">
<Label Text="Slide 'x' to cancel" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" />
</Frame>
</local:SlideToActView.TrackBar>
</local:SlideToActView>
<Label x:Name="MessageLbl" FontAttributes="Bold" TextColor="Green" />
</StackLayout>

代码隐藏
void Handle_SlideCompleted(object sender, System.EventArgs e)
{
MessageLbl.Text = "Success!!";
}

ios simulator
android emulator

更新:08/30

正如@morten-j-petersen 想要支持类似填充条的实现;增加了对此的支持。

更新控制代码
public class SlideToActView : AbsoluteLayout
{
public static readonly BindableProperty ThumbProperty =
BindableProperty.Create(
"Thumb", typeof(View), typeof(SlideToActView),
defaultValue: default(View));

public View Thumb
{
get { return (View)GetValue(ThumbProperty); }
set { SetValue(ThumbProperty, value); }
}

public static readonly BindableProperty TrackBarProperty =
BindableProperty.Create(
"TrackBar", typeof(View), typeof(SlideToActView),
defaultValue: default(View));

public View TrackBar
{
get { return (View)GetValue(TrackBarProperty); }
set { SetValue(TrackBarProperty, value); }
}

public static readonly BindableProperty FillBarProperty =
BindableProperty.Create(
"FillBar", typeof(View), typeof(SlideToActView),
defaultValue: default(View));

public View FillBar
{
get { return (View)GetValue(FillBarProperty); }
set { SetValue(FillBarProperty, value); }
}

private PanGestureRecognizer _panGesture = new PanGestureRecognizer();
private View _gestureListener;
public SlideToActView()
{
_panGesture.PanUpdated += OnPanGestureUpdated;
SizeChanged += OnSizeChanged;

_gestureListener = new ContentView { BackgroundColor = Color.White, Opacity = 0.05 };
_gestureListener.GestureRecognizers.Add(_panGesture);
}

public event EventHandler SlideCompleted;

private const double _fadeEffect = 0.5;
private const uint _animLength = 50;
async void OnPanGestureUpdated(object sender, PanUpdatedEventArgs e)
{
if (Thumb == null || TrackBar == null || FillBar == null)
return;

switch (e.StatusType)
{
case GestureStatus.Started:
await TrackBar.FadeTo(_fadeEffect, _animLength);
break;

case GestureStatus.Running:
// Translate and ensure we don't pan beyond the wrapped user interface element bounds.
var x = Math.Max(0, e.TotalX);
if (x > (Width - Thumb.Width))
x = (Width - Thumb.Width);

//Uncomment this if you want only forward dragging.
//if (e.TotalX < Thumb.TranslationX)
// return;
Thumb.TranslationX = x;
SetLayoutBounds(FillBar, new Rectangle(0, 0, x + Thumb.Width / 2, this.Height));
break;

case GestureStatus.Completed:
var posX = Thumb.TranslationX;
SetLayoutBounds(FillBar, new Rectangle(0, 0, 0, this.Height));

// Reset translation applied during the pan
await Task.WhenAll(new Task[]{
TrackBar.FadeTo(1, _animLength),
Thumb.TranslateTo(0, 0, _animLength * 2, Easing.CubicIn),
});

if (posX >= (Width - Thumb.Width - 10/* keep some margin for error*/))
SlideCompleted?.Invoke(this, EventArgs.Empty);
break;
}
}

void OnSizeChanged(object sender, EventArgs e)
{
if (Width == 0 || Height == 0)
return;
if (Thumb == null || TrackBar == null || FillBar == null)
return;


Children.Clear();

SetLayoutFlags(TrackBar, AbsoluteLayoutFlags.SizeProportional);
SetLayoutBounds(TrackBar, new Rectangle(0, 0, 1, 1));
Children.Add(TrackBar);

SetLayoutFlags(FillBar, AbsoluteLayoutFlags.None);
SetLayoutBounds(FillBar, new Rectangle(0, 0, 0, this.Height));
Children.Add(FillBar);

SetLayoutFlags(Thumb, AbsoluteLayoutFlags.None);
SetLayoutBounds(Thumb, new Rectangle(0, 0, this.Width/5, this.Height));
Children.Add(Thumb);

SetLayoutFlags(_gestureListener, AbsoluteLayoutFlags.SizeProportional);
SetLayoutBounds(_gestureListener, new Rectangle(0, 0, 1, 1));
Children.Add(_gestureListener);


}
}

XAML 用法
<StackLayout Margin="40">
<local:SlideToActView HeightRequest="50" SlideCompleted="Handle_SlideCompleted">
<local:SlideToActView.Thumb>
<Frame CornerRadius="10" HasShadow="false" BackgroundColor="Silver" Padding="0">
<Image Source="icon.png" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="40" WidthRequest="40" />
</Frame>
</local:SlideToActView.Thumb>

<local:SlideToActView.TrackBar>
<Frame CornerRadius="10" HasShadow="false" BackgroundColor="Gray" Padding="0">
<Label Text="Slide 'x' to cancel" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" />
</Frame>
</local:SlideToActView.TrackBar>

<local:SlideToActView.FillBar>
<Frame CornerRadius="10" HasShadow="false" BackgroundColor="Red" Padding="0" />
</local:SlideToActView.FillBar>
</local:SlideToActView>
<Label x:Name="MessageLbl" FontAttributes="Bold" TextColor="Green" />
</StackLayout>

enter image description here

关于xamarin.forms - Xamarin Forms 滑动按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45936224/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com