OnTouchEvent 从未在 Xamarin Android 自定义渲染器中调用
OnTouchEvent never called in Xamarin Android Custom Renderer
我已经为 Android 创建了一个自定义渲染器,并为自定义 Slider 控件实现了它。我有 2 个解决方案。在这两种解决方案中,Android 应用程序都是在 Android Phone 上构建和启动的。测试程序显示滑块正常,我可以毫无问题地上下拖动拇指。第二种解决方案是更大的解决方案,其中应实施滑块。如果我 运行 该解决方案会显示滑块,但我无法上下移动拇指。永远不会触发 OnTouchEvent。以下是 Slider 所需的所有代码。我知道很多,但我希望有人看到我的问题。
我的猜测是命名空间上的 ExportRenderer 属性以某种方式找不到或未被触发。 'OnElementChanged' 重写被调用但没有进一步调用。
这是 Android 项目中 DraggableView(滑块的拇指)的自定义渲染器
using Android.Content;
using Android.Views;
using TGB.Xamarin.Forms.TestApp.Droid.Renderers.Views;
using TGB.Xamarin.Forms.Views;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using static TGB.Xamarin.Forms.Views.DraggableView;
using xam = global::Xamarin.Forms;
[assembly: ExportRenderer(typeof(DraggableView), typeof(DraggableViewRenderer))]
namespace TGB.Xamarin.Forms.TestApp.Droid.Renderers.Views
{
public class DraggableViewRenderer : VisualElementRenderer<xam.View>
{
float originalX;
float originalY;
float dX;
float dY;
bool firstTime = true;
bool touchedDown = false;
public DraggableViewRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<xam.View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
LongClick -= HandleLongClick;
}
if (e.NewElement != null)
{
LongClick += HandleLongClick;
var dragView = Element as DraggableView;
dragView.RestorePositionCommand = new Command(() =>
{
if (!firstTime)
{
SetX(originalX);
SetY(originalY);
}
});
}
}
private void HandleLongClick(object sender, LongClickEventArgs e)
{
var dragView = Element as DraggableView;
if (firstTime)
{
originalX = GetX();
originalY = GetY();
firstTime = false;
}
dragView.DragStarted();
touchedDown = true;
}
public override bool OnTouchEvent(MotionEvent e)
{
float x = e.RawX;
float y = e.RawY;
var dragView = Element as DraggableView;
var parent = dragView.Parent as xam.View;
switch (e.Action)
{
case MotionEventActions.Down:
if (dragView.DragMode == DragModes.Touch)
{
if (!touchedDown)
{
if (firstTime)
{
originalX = GetX();
originalY = GetY();
firstTime = false;
}
dragView.DragStarted();
}
touchedDown = true;
}
dX = x - this.GetX();
dY = y - this.GetY();
break;
case MotionEventActions.Move:
if (touchedDown)
{
var density = global::Xamarin.Essentials.DeviceDisplay.MainDisplayInfo.Density;
if (dragView.DragDirection == DragDirectionTypes.All || dragView.DragDirection == DragDirectionTypes.Horizontal)
{
var newX = x - dX;
if (parent != null)
{
if (newX + Width > parent.Width * density) newX = (float)(parent.Width * density - Width);
if (newX < 0) newX = 0;
}
SetX(newX);
}
if (dragView.DragDirection == DragDirectionTypes.All || dragView.DragDirection == DragDirectionTypes.Vertical)
{
var newY = y - dY;
if (parent != null)
{
if (newY + Height > parent.Height * density) newY = (float)(parent.Height * density - Height);
if (newY < 0) newY = 0;
}
SetY(newY);
}
}
break;
case MotionEventActions.Up:
touchedDown = false;
DraggableViewDragEndedEventArgs args = new DraggableViewDragEndedEventArgs
{
X = GetX(),
Y = GetY()
};
dragView.DragEnded(args);
break;
case MotionEventActions.Cancel:
touchedDown = false;
break;
}
return base.OnTouchEvent(e);
}
public override bool OnInterceptTouchEvent(MotionEvent e)
{
BringToFront();
return true;
}
}
}
这是.Net标准2.0项目中的DraggableView。
using System;
using System.Windows.Input;
using Xamarin.Forms;
namespace TGB.Xamarin.Forms.Views
{
public partial class DraggableView : ContentView
{
public event EventHandler DragStart = delegate { };
public delegate void DragEndEventHandler(object sender, DraggableViewDragEndedEventArgs args);
public event DragEndEventHandler DragEnd;
public enum DragDirectionTypes
{
All,
Vertical,
Horizontal
}
public enum DragModes
{
Touch,
LongPress
}
public static readonly BindableProperty DragDirectionProperty = BindableProperty.Create(
propertyName: "DragDirection",
returnType: typeof(DragDirectionTypes),
declaringType: typeof(DraggableView),
defaultValue: DragDirectionTypes.All,
defaultBindingMode: BindingMode.TwoWay);
public DragDirectionTypes DragDirection
{
get { return (DragDirectionTypes)GetValue(DragDirectionProperty); }
set { SetValue(DragDirectionProperty, value); }
}
public static readonly BindableProperty DragModeProperty = BindableProperty.Create(
propertyName: "DragMode",
returnType: typeof(DragModes),
declaringType: typeof(DraggableView),
defaultValue: DragModes.Touch,
defaultBindingMode: BindingMode.TwoWay);
public DragModes DragMode
{
get { return (DragModes)GetValue(DragModeProperty); }
set { SetValue(DragModeProperty, value); }
}
public static readonly BindableProperty IsDraggingProperty = BindableProperty.Create(
propertyName: "IsDragging",
returnType: typeof(bool),
declaringType: typeof(DraggableView),
defaultValue: false,
defaultBindingMode: BindingMode.TwoWay);
public bool IsDragging
{
get { return (bool)GetValue(IsDraggingProperty); }
set { SetValue(IsDraggingProperty, value); }
}
public static readonly BindableProperty RestorePositionCommandProperty = BindableProperty.Create(nameof(RestorePositionCommand), typeof(ICommand), typeof(DraggableView), default(ICommand), BindingMode.TwoWay, null, OnRestorePositionCommandPropertyChanged);
static void OnRestorePositionCommandPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var source = bindable as DraggableView;
if (source == null)
{
return;
}
source.OnRestorePositionCommandChanged();
}
private void OnRestorePositionCommandChanged()
{
OnPropertyChanged("RestorePositionCommand");
}
public ICommand RestorePositionCommand
{
get
{
return (ICommand)GetValue(RestorePositionCommandProperty);
}
set
{
SetValue(RestorePositionCommandProperty, value);
}
}
public void DragStarted()
{
DragStart(this, default);
IsDragging = true;
}
public void DragEnded(DraggableViewDragEndedEventArgs args)
{
IsDragging = false;
DragEnd(this, args);
}
}
}
在 EndDrag
处使用的 EventArgs class
using System;
using System.Collections.Generic;
using System.Text;
namespace TGB.Xamarin.Forms.Views
{
public class DraggableViewDragEndedEventArgs : EventArgs
{
public double X;
public double Y;
}
}
这是滑块 class:
using System;
using TGB.Xamarin.Forms.Views;
using Xamarin.Forms;
namespace TGB.Xamarin.Forms.Controls
{
public class Slider : AbsoluteLayout
{
private DraggableView m_Thumb;
public static readonly BindableProperty MinProperty = BindableProperty.Create(
"Min", typeof(int), typeof(Slider), 0, propertyChanged: (bindable, oldvalue, newvalue) => { ((Slider)bindable).InvalidateLayout(); });
/// <summary>
/// The minimum for the slider
/// </summary>
public int Min
{
set { SetValue(MinProperty, value); }
get { return (int)GetValue(MinProperty); }
}
public static readonly BindableProperty MaxProperty = BindableProperty.Create(
"Max", typeof(int), typeof(Slider), 100, propertyChanged: (bindable, oldvalue, newvalue) => { ((Slider)bindable).InvalidateLayout(); });
/// <summary>
/// The maximum for the slider
/// </summary>
public int Max
{
set { SetValue(MaxProperty, value); }
get { return (int)GetValue(MaxProperty); }
}
public static readonly BindableProperty ValueProperty = BindableProperty.Create(
"Value", typeof(int), typeof(Slider), 100, propertyChanged: (bindable, oldvalue, newvalue) => { ((Slider)bindable).InvalidateLayout(); });
/// <summary>
/// The value for the slider
/// </summary>
public int Value
{
set { SetValue(ValueProperty, value); }
get { return (int)GetValue(ValueProperty); }
}
public Slider()
{
BackgroundColor = System.Drawing.Color.Green;
Init();
}
private void Init()
{
m_Thumb = new DraggableView();
m_Thumb.DragEnd += Draggable_DragEnd;
m_Thumb.HorizontalOptions = new LayoutOptions { Alignment = LayoutAlignment.Fill, Expands = true };
AbsoluteLayout.SetLayoutBounds(m_Thumb, new Rectangle(0, 0, 1, 0.2));
AbsoluteLayout.SetLayoutFlags(m_Thumb, AbsoluteLayoutFlags.All);
m_Thumb.BackgroundColor = System.Drawing.Color.Orange;
this.Children.Add(m_Thumb);
}
private void Draggable_DragEnd(object sender, DraggableViewDragEndedEventArgs e)
{
var scope = Max - Min;
var regionSize = this.Height - m_Thumb.Height;
var perPixel = scope / regionSize;
Value = Min + Convert.ToInt32(e.Y * perPixel);
}
}
}
这是 MainPage.xaml 中的实现:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tgbc="clr-namespace:TGB.Xamarin.Forms.Controls;assembly=TGB.Xamarin.Forms"
mc:Ignorable="d"
x:Name="Page"
x:Class="ElectroSpit.MainPage">
<ContentPage.Resources>
<StyleSheet Source="Styles\Styles.css" />
</ContentPage.Resources>
<StackLayout x:Name="Main"
Orientation="Vertical"
BackgroundColor="Transparent"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<ContentView x:Name="Sidebar"
VerticalOptions="Start"
HorizontalOptions="Start"
StyleClass="Sidebar">
<ContentView.Content>
<Grid VerticalOptions="FillAndExpand" StyleClass="SidebarSlider">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0"
Grid.Column="0"
Orientation="Vertical"
VerticalOptions="FillAndExpand"
StyleClass="SidebarSlider" >
<!-- HERE ARE THE SLIDERS -->
<tgbc:Slider x:Name="Pitch" VerticalOptions="FillAndExpand" StyleClass="SidebarSlider" />
<tgbc:Slider x:Name="Tremolo" VerticalOptions="FillAndExpand" StyleClass="SidebarSlider" />
</StackLayout>
<StackLayout Grid.Row="0"
Grid.Column="1"
Orientation="Vertical">
<Label Text="Trans" StyleClass="SidebarLabel"/>
<StackLayout Orientation="Horizontal">
<Button x:Name="TransposeUp" Text="+" StyleClass="SidebarButton"/>
<Button x:Name="TransposeDown" Text="{Binding Transposition}" StyleClass="SidebarButton" />
</StackLayout>
<Label Text="Brightness" StyleClass="SidebarLabel"/>
<Stepper x:Name="Brichtness" Minimum="0" Maximum="100" StyleClass="SidebarStepper"/>
<Button x:Name="Settings" Text="Opt" StyleClass="SidebarButton"/>
<Label Text="Glide" StyleClass="SidebarLabel"/>
<Stepper x:Name="Glide" Minimum="0" Maximum="100" StyleClass="SidebarStepper"/>
<Label Text="Octave" StyleClass="SidebarLabel"/>
<StackLayout Orientation="Horizontal">
<Button x:Name="OctaveUp" Text="+" StyleClass="SidebarButton"/>
<Button x:Name="OctaveDown" Text="{Binding Octave}" StyleClass="SidebarButton"/>
</StackLayout>
</StackLayout>
<StackLayout>
<ContentView x:Name="Schema"
BackgroundColor="Transparent"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
</ContentView>
</StackLayout>
</Grid>
</ContentView.Content>
</ContentView>
<ContentView x:Name="Notes"
BackgroundColor="Transparent"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
</ContentView>
</StackLayout>
</ContentPage>
== 编辑 ==
工作应用程序和非工作应用程序的消息有所不同。这是我在工作应用程序上得到的:
05-22 10:29:42.178 D/Mono ( 6676): DllImport searching in: '__Internal' ('(null)').
05-22 10:29:42.178 D/Mono ( 6676): Searching for 'java_interop_jnienv_call_float_method_a'.
05-22 10:29:42.178 D/Mono ( 6676): Probing 'java_interop_jnienv_call_float_method_a'.
05-22 10:29:42.178 D/Mono ( 6676): Found as 'java_interop_jnienv_call_float_method_a'.
05-22 10:29:42.201 D/Mono ( 6676): DllImport searching in: '__Internal' ('(null)').
05-22 10:29:42.201 D/Mono ( 6676): Searching for 'java_interop_jnienv_call_long_method_a'.
05-22 10:29:42.201 D/Mono ( 6676): Probing 'java_interop_jnienv_call_long_method_a'.
05-22 10:29:42.201 D/Mono ( 6676): Found as 'java_interop_jnienv_call_long_method_a'.
05-22 10:29:42.260 D/Mono ( 6676): Requesting loading reference 6 (of 7) of TGB.Xamarin.Forms.Android.dll
05-22 10:29:42.260 D/Mono ( 6676): Loading reference 6 of TGB.Xamarin.Forms.Android.dll asmctx DEFAULT, looking for Xamarin.Essentials, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
05-22 10:29:42.260 D/Mono ( 6676): Assembly Ref addref TGB.Xamarin.Forms.Android[0xd57b8680] -> Xamarin.Essentials[0xebf7fd00]: 3
在非工作应用程序上:
05-22 09:46:52.254 D/Mono (14307): DllImport searching in: '__Internal' ('(null)').
05-22 09:46:52.254 D/Mono (14307): Searching for 'java_interop_jnienv_call_float_method_a'.
05-22 09:46:52.254 D/Mono (14307): Probing 'java_interop_jnienv_call_float_method_a'.
05-22 09:46:52.254 D/Mono (14307): Found as 'java_interop_jnienv_call_float_method_a'.
好的,找到了。控件已经在工作,我的错误在别处。如果您仔细观察 XAML,您会发现最后一个 StackLayout 没有 Grid.Row 和 Grid.Column 属性,导致它位于两个滑块的顶部。所以触摸不会到达滑块,而是到达 StackLayout 内的 ContentView,给我的印象是它不起作用。
我已经为 Android 创建了一个自定义渲染器,并为自定义 Slider 控件实现了它。我有 2 个解决方案。在这两种解决方案中,Android 应用程序都是在 Android Phone 上构建和启动的。测试程序显示滑块正常,我可以毫无问题地上下拖动拇指。第二种解决方案是更大的解决方案,其中应实施滑块。如果我 运行 该解决方案会显示滑块,但我无法上下移动拇指。永远不会触发 OnTouchEvent。以下是 Slider 所需的所有代码。我知道很多,但我希望有人看到我的问题。
我的猜测是命名空间上的 ExportRenderer 属性以某种方式找不到或未被触发。 'OnElementChanged' 重写被调用但没有进一步调用。
这是 Android 项目中 DraggableView(滑块的拇指)的自定义渲染器
using Android.Content;
using Android.Views;
using TGB.Xamarin.Forms.TestApp.Droid.Renderers.Views;
using TGB.Xamarin.Forms.Views;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using static TGB.Xamarin.Forms.Views.DraggableView;
using xam = global::Xamarin.Forms;
[assembly: ExportRenderer(typeof(DraggableView), typeof(DraggableViewRenderer))]
namespace TGB.Xamarin.Forms.TestApp.Droid.Renderers.Views
{
public class DraggableViewRenderer : VisualElementRenderer<xam.View>
{
float originalX;
float originalY;
float dX;
float dY;
bool firstTime = true;
bool touchedDown = false;
public DraggableViewRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<xam.View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
LongClick -= HandleLongClick;
}
if (e.NewElement != null)
{
LongClick += HandleLongClick;
var dragView = Element as DraggableView;
dragView.RestorePositionCommand = new Command(() =>
{
if (!firstTime)
{
SetX(originalX);
SetY(originalY);
}
});
}
}
private void HandleLongClick(object sender, LongClickEventArgs e)
{
var dragView = Element as DraggableView;
if (firstTime)
{
originalX = GetX();
originalY = GetY();
firstTime = false;
}
dragView.DragStarted();
touchedDown = true;
}
public override bool OnTouchEvent(MotionEvent e)
{
float x = e.RawX;
float y = e.RawY;
var dragView = Element as DraggableView;
var parent = dragView.Parent as xam.View;
switch (e.Action)
{
case MotionEventActions.Down:
if (dragView.DragMode == DragModes.Touch)
{
if (!touchedDown)
{
if (firstTime)
{
originalX = GetX();
originalY = GetY();
firstTime = false;
}
dragView.DragStarted();
}
touchedDown = true;
}
dX = x - this.GetX();
dY = y - this.GetY();
break;
case MotionEventActions.Move:
if (touchedDown)
{
var density = global::Xamarin.Essentials.DeviceDisplay.MainDisplayInfo.Density;
if (dragView.DragDirection == DragDirectionTypes.All || dragView.DragDirection == DragDirectionTypes.Horizontal)
{
var newX = x - dX;
if (parent != null)
{
if (newX + Width > parent.Width * density) newX = (float)(parent.Width * density - Width);
if (newX < 0) newX = 0;
}
SetX(newX);
}
if (dragView.DragDirection == DragDirectionTypes.All || dragView.DragDirection == DragDirectionTypes.Vertical)
{
var newY = y - dY;
if (parent != null)
{
if (newY + Height > parent.Height * density) newY = (float)(parent.Height * density - Height);
if (newY < 0) newY = 0;
}
SetY(newY);
}
}
break;
case MotionEventActions.Up:
touchedDown = false;
DraggableViewDragEndedEventArgs args = new DraggableViewDragEndedEventArgs
{
X = GetX(),
Y = GetY()
};
dragView.DragEnded(args);
break;
case MotionEventActions.Cancel:
touchedDown = false;
break;
}
return base.OnTouchEvent(e);
}
public override bool OnInterceptTouchEvent(MotionEvent e)
{
BringToFront();
return true;
}
}
}
这是.Net标准2.0项目中的DraggableView。
using System;
using System.Windows.Input;
using Xamarin.Forms;
namespace TGB.Xamarin.Forms.Views
{
public partial class DraggableView : ContentView
{
public event EventHandler DragStart = delegate { };
public delegate void DragEndEventHandler(object sender, DraggableViewDragEndedEventArgs args);
public event DragEndEventHandler DragEnd;
public enum DragDirectionTypes
{
All,
Vertical,
Horizontal
}
public enum DragModes
{
Touch,
LongPress
}
public static readonly BindableProperty DragDirectionProperty = BindableProperty.Create(
propertyName: "DragDirection",
returnType: typeof(DragDirectionTypes),
declaringType: typeof(DraggableView),
defaultValue: DragDirectionTypes.All,
defaultBindingMode: BindingMode.TwoWay);
public DragDirectionTypes DragDirection
{
get { return (DragDirectionTypes)GetValue(DragDirectionProperty); }
set { SetValue(DragDirectionProperty, value); }
}
public static readonly BindableProperty DragModeProperty = BindableProperty.Create(
propertyName: "DragMode",
returnType: typeof(DragModes),
declaringType: typeof(DraggableView),
defaultValue: DragModes.Touch,
defaultBindingMode: BindingMode.TwoWay);
public DragModes DragMode
{
get { return (DragModes)GetValue(DragModeProperty); }
set { SetValue(DragModeProperty, value); }
}
public static readonly BindableProperty IsDraggingProperty = BindableProperty.Create(
propertyName: "IsDragging",
returnType: typeof(bool),
declaringType: typeof(DraggableView),
defaultValue: false,
defaultBindingMode: BindingMode.TwoWay);
public bool IsDragging
{
get { return (bool)GetValue(IsDraggingProperty); }
set { SetValue(IsDraggingProperty, value); }
}
public static readonly BindableProperty RestorePositionCommandProperty = BindableProperty.Create(nameof(RestorePositionCommand), typeof(ICommand), typeof(DraggableView), default(ICommand), BindingMode.TwoWay, null, OnRestorePositionCommandPropertyChanged);
static void OnRestorePositionCommandPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var source = bindable as DraggableView;
if (source == null)
{
return;
}
source.OnRestorePositionCommandChanged();
}
private void OnRestorePositionCommandChanged()
{
OnPropertyChanged("RestorePositionCommand");
}
public ICommand RestorePositionCommand
{
get
{
return (ICommand)GetValue(RestorePositionCommandProperty);
}
set
{
SetValue(RestorePositionCommandProperty, value);
}
}
public void DragStarted()
{
DragStart(this, default);
IsDragging = true;
}
public void DragEnded(DraggableViewDragEndedEventArgs args)
{
IsDragging = false;
DragEnd(this, args);
}
}
}
在 EndDrag
处使用的 EventArgs classusing System;
using System.Collections.Generic;
using System.Text;
namespace TGB.Xamarin.Forms.Views
{
public class DraggableViewDragEndedEventArgs : EventArgs
{
public double X;
public double Y;
}
}
这是滑块 class:
using System;
using TGB.Xamarin.Forms.Views;
using Xamarin.Forms;
namespace TGB.Xamarin.Forms.Controls
{
public class Slider : AbsoluteLayout
{
private DraggableView m_Thumb;
public static readonly BindableProperty MinProperty = BindableProperty.Create(
"Min", typeof(int), typeof(Slider), 0, propertyChanged: (bindable, oldvalue, newvalue) => { ((Slider)bindable).InvalidateLayout(); });
/// <summary>
/// The minimum for the slider
/// </summary>
public int Min
{
set { SetValue(MinProperty, value); }
get { return (int)GetValue(MinProperty); }
}
public static readonly BindableProperty MaxProperty = BindableProperty.Create(
"Max", typeof(int), typeof(Slider), 100, propertyChanged: (bindable, oldvalue, newvalue) => { ((Slider)bindable).InvalidateLayout(); });
/// <summary>
/// The maximum for the slider
/// </summary>
public int Max
{
set { SetValue(MaxProperty, value); }
get { return (int)GetValue(MaxProperty); }
}
public static readonly BindableProperty ValueProperty = BindableProperty.Create(
"Value", typeof(int), typeof(Slider), 100, propertyChanged: (bindable, oldvalue, newvalue) => { ((Slider)bindable).InvalidateLayout(); });
/// <summary>
/// The value for the slider
/// </summary>
public int Value
{
set { SetValue(ValueProperty, value); }
get { return (int)GetValue(ValueProperty); }
}
public Slider()
{
BackgroundColor = System.Drawing.Color.Green;
Init();
}
private void Init()
{
m_Thumb = new DraggableView();
m_Thumb.DragEnd += Draggable_DragEnd;
m_Thumb.HorizontalOptions = new LayoutOptions { Alignment = LayoutAlignment.Fill, Expands = true };
AbsoluteLayout.SetLayoutBounds(m_Thumb, new Rectangle(0, 0, 1, 0.2));
AbsoluteLayout.SetLayoutFlags(m_Thumb, AbsoluteLayoutFlags.All);
m_Thumb.BackgroundColor = System.Drawing.Color.Orange;
this.Children.Add(m_Thumb);
}
private void Draggable_DragEnd(object sender, DraggableViewDragEndedEventArgs e)
{
var scope = Max - Min;
var regionSize = this.Height - m_Thumb.Height;
var perPixel = scope / regionSize;
Value = Min + Convert.ToInt32(e.Y * perPixel);
}
}
}
这是 MainPage.xaml 中的实现:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tgbc="clr-namespace:TGB.Xamarin.Forms.Controls;assembly=TGB.Xamarin.Forms"
mc:Ignorable="d"
x:Name="Page"
x:Class="ElectroSpit.MainPage">
<ContentPage.Resources>
<StyleSheet Source="Styles\Styles.css" />
</ContentPage.Resources>
<StackLayout x:Name="Main"
Orientation="Vertical"
BackgroundColor="Transparent"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<ContentView x:Name="Sidebar"
VerticalOptions="Start"
HorizontalOptions="Start"
StyleClass="Sidebar">
<ContentView.Content>
<Grid VerticalOptions="FillAndExpand" StyleClass="SidebarSlider">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0"
Grid.Column="0"
Orientation="Vertical"
VerticalOptions="FillAndExpand"
StyleClass="SidebarSlider" >
<!-- HERE ARE THE SLIDERS -->
<tgbc:Slider x:Name="Pitch" VerticalOptions="FillAndExpand" StyleClass="SidebarSlider" />
<tgbc:Slider x:Name="Tremolo" VerticalOptions="FillAndExpand" StyleClass="SidebarSlider" />
</StackLayout>
<StackLayout Grid.Row="0"
Grid.Column="1"
Orientation="Vertical">
<Label Text="Trans" StyleClass="SidebarLabel"/>
<StackLayout Orientation="Horizontal">
<Button x:Name="TransposeUp" Text="+" StyleClass="SidebarButton"/>
<Button x:Name="TransposeDown" Text="{Binding Transposition}" StyleClass="SidebarButton" />
</StackLayout>
<Label Text="Brightness" StyleClass="SidebarLabel"/>
<Stepper x:Name="Brichtness" Minimum="0" Maximum="100" StyleClass="SidebarStepper"/>
<Button x:Name="Settings" Text="Opt" StyleClass="SidebarButton"/>
<Label Text="Glide" StyleClass="SidebarLabel"/>
<Stepper x:Name="Glide" Minimum="0" Maximum="100" StyleClass="SidebarStepper"/>
<Label Text="Octave" StyleClass="SidebarLabel"/>
<StackLayout Orientation="Horizontal">
<Button x:Name="OctaveUp" Text="+" StyleClass="SidebarButton"/>
<Button x:Name="OctaveDown" Text="{Binding Octave}" StyleClass="SidebarButton"/>
</StackLayout>
</StackLayout>
<StackLayout>
<ContentView x:Name="Schema"
BackgroundColor="Transparent"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
</ContentView>
</StackLayout>
</Grid>
</ContentView.Content>
</ContentView>
<ContentView x:Name="Notes"
BackgroundColor="Transparent"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
</ContentView>
</StackLayout>
</ContentPage>
== 编辑 ==
工作应用程序和非工作应用程序的消息有所不同。这是我在工作应用程序上得到的:
05-22 10:29:42.178 D/Mono ( 6676): DllImport searching in: '__Internal' ('(null)').
05-22 10:29:42.178 D/Mono ( 6676): Searching for 'java_interop_jnienv_call_float_method_a'.
05-22 10:29:42.178 D/Mono ( 6676): Probing 'java_interop_jnienv_call_float_method_a'.
05-22 10:29:42.178 D/Mono ( 6676): Found as 'java_interop_jnienv_call_float_method_a'.
05-22 10:29:42.201 D/Mono ( 6676): DllImport searching in: '__Internal' ('(null)').
05-22 10:29:42.201 D/Mono ( 6676): Searching for 'java_interop_jnienv_call_long_method_a'.
05-22 10:29:42.201 D/Mono ( 6676): Probing 'java_interop_jnienv_call_long_method_a'.
05-22 10:29:42.201 D/Mono ( 6676): Found as 'java_interop_jnienv_call_long_method_a'.
05-22 10:29:42.260 D/Mono ( 6676): Requesting loading reference 6 (of 7) of TGB.Xamarin.Forms.Android.dll
05-22 10:29:42.260 D/Mono ( 6676): Loading reference 6 of TGB.Xamarin.Forms.Android.dll asmctx DEFAULT, looking for Xamarin.Essentials, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
05-22 10:29:42.260 D/Mono ( 6676): Assembly Ref addref TGB.Xamarin.Forms.Android[0xd57b8680] -> Xamarin.Essentials[0xebf7fd00]: 3
在非工作应用程序上:
05-22 09:46:52.254 D/Mono (14307): DllImport searching in: '__Internal' ('(null)').
05-22 09:46:52.254 D/Mono (14307): Searching for 'java_interop_jnienv_call_float_method_a'.
05-22 09:46:52.254 D/Mono (14307): Probing 'java_interop_jnienv_call_float_method_a'.
05-22 09:46:52.254 D/Mono (14307): Found as 'java_interop_jnienv_call_float_method_a'.
好的,找到了。控件已经在工作,我的错误在别处。如果您仔细观察 XAML,您会发现最后一个 StackLayout 没有 Grid.Row 和 Grid.Column 属性,导致它位于两个滑块的顶部。所以触摸不会到达滑块,而是到达 StackLayout 内的 ContentView,给我的印象是它不起作用。