- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
@ 。
简单来说就是拖拽物(pan)体到坑(pit)中,手势容器控件PanContainer描述了pan运动和pit位置的关系,并在手势运动中产生一系列消息事件.
今天使用这个控件,做一个模仿微信“按住-说话”的小功能,最终效果如下:
使用 .NET MAU 实现跨平台支持,本项目可运行于Android、iOS平台.
新建.NET MAUI项目,命名 HoldAndSpeak MainPage.xaml中创建一个 PitContentLayout Grid容器,并对Grid容器进行如下布局:
在手机屏幕的底部设置两行两列的布局:
第一行第一列,对应取消发送手势区域, 第一行第二列,对应语音转文字手势区域, 第二行独占两列,对应发送手势区域.
布局如下图所示 。
<Grid x:Name="PitContentLayout"
Opacity="1">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
</Grid>
创建三个PitGrid控件,并对这三个功能区域的PitGrid控件命名, CancelPit 、 TransliterationPit ,分别对应了取消发送、语音转文字、发送.
为每个PitGrid控件添加内容:
发送区域是一个底部弧形区域,我们用一个巨大的圆形+Y轴方向的偏移,通过只保留屏幕底部往上的一部分圆形区域来实现底部弧形区域的效果,代码如下:
<BoxView TranslationY="450"
x:Name="SendBox"
HeightRequest="1000"
WidthRequest="1000"
CornerRadius="500">
</BoxView>
取消发送和语音转文字区域是一个圆形区域,我们用一个正常大小的圆形来实现.
PitContentLayout区域整体代码如下 。
<Grid x:Name="PitContentLayout"
Opacity="1">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<controls1:PitGrid x:Name="CancelPit"
TranslationX="-40"
PitName="CancelPit">
<BoxView x:Name="CancelBox"
HeightRequest="80"
WidthRequest="80"
CornerRadius="50"
Margin="7.5"
Color="{StaticResource PhoneContrastBackgroundBrush}"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"></BoxView>
<Label x:Name="CancelLabel"
TextColor="{StaticResource PhoneContrastForegroundBrush}"
FontFamily="FontAwesome"
FontSize="28"
Rotation="-10"
HorizontalOptions="CenterAndExpand"
Margin="0"></Label>
</controls1:PitGrid>
<controls1:PitGrid x:Name="TransliterationPit"
PitName="TransliterationPit"
TranslationX="40"
Grid.Column="1">
<BoxView x:Name="TransliterationBox"
HeightRequest="80"
WidthRequest="80"
CornerRadius="50"
Margin="7.5"
Color="{StaticResource PhoneContrastBackgroundBrush}"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"></BoxView>
<Label x:Name="TransliterationLabel"
TextColor="{StaticResource PhoneContrastForegroundBrush}"
FontSize="28"
Text="文"
Rotation="10"
HorizontalOptions="CenterAndExpand"
Margin="0"></Label>
</controls1:PitGrid>
<controls1:PitGrid x:Name="SendPit"
PitName="SendPit"
Grid.ColumnSpan="2"
Grid.Row="1">
<BoxView TranslationY="450"
x:Name="SendBox"
HeightRequest="1000"
WidthRequest="1000"
CornerRadius="500"
Margin="7.5"
Color="{StaticResource PhoneContrastBackgroundBrush}"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"></BoxView>
<Label x:Name="SendLabel"
TranslationY="30"
FontSize="28"
Rotation="45"
TextColor="{StaticResource PhoneContrastForegroundBrush}"
FontFamily="FontAwesome"
HorizontalOptions="CenterAndExpand"
Margin="0"></Label>
</controls1:PitGrid>
</Grid>
效果如下 。
创建一个手势控件。他包裹的内容。是一个带有按住说话的按钮.
<controls1:PanContainer BackgroundColor="Transparent"
x:Name="DefaultPanContainer"
OnTapped="DefaultPanContainer_OnOnTapped"
AutoAdsorption="False"
OnfinishedChoise="DefaultPanContainer_OnOnfinishedChoise">
<Grid PropertyChanged="BindableObject_OnPropertyChanged"
VerticalOptions="Start"
HorizontalOptions="Start">
<BoxView HeightRequest="80"
WidthRequest="250"
Margin="7.5"
Color="{StaticResource PhoneContrastBackgroundBrush}"></BoxView>
<Label x:Name="PauseLabel"
HorizontalOptions="CenterAndExpand"
FontSize="28"
TextColor="{StaticResource PhoneForegroundBrush}"
Text="按住 说话"
Margin="0"></Label>
</Grid>
</controls1:PanContainer>
此时应该是可以拖动,并且在拖拽开始,进入pit,离开pit,释放时,分别触发Start,In,Out,Over四个状态.
但我们希望在拖拽时隐藏这个按钮,这将在创建动画章节将介绍.
创建一个圆角矩形,用来显示正在说话的动画.
<Grid Grid.Row="1"
Opacity="1"
x:Name="TalkBoxLayout">
<BoxView x:Name="TalkBox"
HeightRequest="80"
WidthRequest="200"
CornerRadius="20"
Margin="7.5"
Color="{StaticResource PhoneAccentBrush}"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"></BoxView>
<controls:PlayingMotionView HorizontalOptions="CenterAndExpand"
x:Name="MotionView"
Margin="0"></controls:PlayingMotionView>
</Grid>
</Grid>
效果如下 。
在拖拽时我们希望可以隐藏拖拽物,设置 PanScale 和 PanScaleAnimationLength 属性为0,代码如下:
<controls1:PanContainer BackgroundColor="Transparent"
x:Name="DefaultPanContainer"
OnTapped="DefaultPanContainer_OnOnTapped"
AutoAdsorption="False"
PanScale="0.0"
PanScaleAnimationLength="0">
Codebeind代码中,配置Active和DeActive方法,用于激活和取消激活功能区域按钮的样式.
激活时,对应功能区域按钮背景颜色变为白色,字体颜色变为黑色,并且放大到1.2倍。 取消激活时,恢复到原来的样式.
代码如下 。
private void Active(BoxView currentContent, Label text, Color toColor, Color txtToColor, double scaleTo = 1.2)
{
currentContent.AbortAnimation("ActivateFunctionAnimations");
var parentAnimation = new Animation();
var txtFromColor = text.TextColor;
var animation2 = new Animation(t => text.TextColor = GetColor(t, txtFromColor, txtToColor), 0, 1, Easing.SpringOut);
var fromColor = currentContent.Color;
var animation4 = new Animation(t => currentContent.Color = GetColor(t, fromColor, toColor), 0, 1, Easing.SpringOut);
var animation5 = new Animation(v => currentContent.Scale = v, currentContent.Scale, scaleTo);
parentAnimation.Add(0, 1, animation2);
parentAnimation.Add(0, 1, animation4);
parentAnimation.Add(0, 1, animation5);
parentAnimation.Commit(this, "ActivateFunctionAnimations", 16, 300);
}
private void DeActive(BoxView currentContent, Label text)
{
currentContent.AbortAnimation("DeactivateFunctionAnimations");
var parentAnimation = new Animation();
var txtFromColor = text.TextColor;
var txtToColor = (Color)Application.Current.Resources["PhoneContrastForegroundBrush"];
var animation2 = new Animation(t => text.TextColor = GetColor(t, txtFromColor, txtToColor), 0, 1, Easing.SpringOut);
var fromColor = currentContent.Color;
var toColor = (Color)Application.Current.Resources["PhoneContrastBackgroundBrush"];
var animation4 = new Animation(t => currentContent.Color = GetColor(t, fromColor, toColor), 0, 1, Easing.SpringOut);
var animation5 = new Animation(v => currentContent.Scale = v, currentContent.Scale, 1.0);
parentAnimation.Add(0, 1, animation2);
parentAnimation.Add(0, 1, animation4);
parentAnimation.Add(0, 1, animation5);
parentAnimation.Commit(this, "DeactivateFunctionAnimations", 16, 300);
}
在拖拽进入pit的事件中设置激活状态,在拖拽离开pit的事件中设置取消激活状态.
case PanType.Out:
switch (args.CurrentPit?.PitName)
{
case "CancelPit":
DeActive(this.CancelBox, this.CancelLabel);
break;
case "SendPit":
DeActive(this.SendBox, this.SendLabel);
break;
case "TransliterationPit":
DeActive(this.TransliterationBox, this.TransliterationLabel);
break;
default:
break;
}
break;
case PanType.In:
var parentAnimation = new Animation();
Color toColor = default;
double translationX = default;
double width = default;
switch (args.CurrentPit?.PitName)
{
case "CancelPit":
Active(this.CancelBox, this.CancelLabel, Colors.White, Colors.Black);
this.TalkBox.AbortAnimation("TalkBoxAnimations");
break;
case "SendPit":
Active(this.SendBox, this.SendLabel, Colors.Gray, Colors.Black, 1.0);
break;
case "TransliterationPit":
Active(this.TransliterationBox, this.TransliterationLabel, Colors.White, Colors.Black);
break;
default:
break;
}
创建GetColor方法,使用插值法用于获取渐变过程中获取当前进度的颜色 。
private Color GetColor(double t, Color fromColor, Color toColor)
{
return Color.FromRgba(fromColor.Red + t * (toColor.Red - fromColor.Red),
fromColor.Green + t * (toColor.Green - fromColor.Green),
fromColor.Blue + t * (toColor.Blue - fromColor.Blue),
fromColor.Alpha + t * (toColor.Alpha - fromColor.Alpha));
}
在进入功能区域时,TalkBox的颜色,偏移量和宽度都会发生变化,创建一个复合动画TalkBoxAnimations,用于触发TalkBox的动画效果.
this.TalkBox.AbortAnimation("TalkBoxAnimations");
var fromColor = this.TalkBox.Color;
var animation2 = new Animation(t => this.TalkBox.Color = GetColor(t, fromColor, toColor), 0, 1, Easing.SpringOut);
var animation4 = new Animation(v => this.TalkBoxLayout.TranslationX = v, this.TalkBoxLayout.TranslationX, translationX);
var animation5 = new Animation(v => this.TalkBox.WidthRequest = v, this.TalkBox.Width, width);
parentAnimation.Add(0, 1, animation2);
parentAnimation.Add(0, 1, animation4);
parentAnimation.Add(0, 1, animation5);
parentAnimation.Commit(this, "TalkBoxAnimations", 16, 300);
最终效果如下:
创建一个用于显示功能区域和TalkBox的渐变动画,用于在拖拽开始和结束时,显示和隐藏这两个控件.
private void ShowLayout(double opacity = 1)
{
this.PitContentLayout.FadeTo(opacity);
this.TalkBoxLayout.FadeTo(opacity);
}
case PanType.Over:
ShowLayout(0);
break;
case PanType.Start:
ShowLayout();
break;
Github:maui-samples 。
最后此篇关于[MAUI]模仿微信“按住-说话”的交互实现的文章就讲到这里了,如果你想了解更多关于[MAUI]模仿微信“按住-说话”的交互实现的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我在 uipickerview 中有一个 uitextfield,我试图禁用任何类型的格式,我使用 UIResponderStandardEditActions 来禁用随之而来的所有操作,但我不知道如
如何让 Python 说出一些文字? 我可以将 Festival 与子进程一起使用,但我无法控制它(或者可能在交互模式下,但它不会是干净的)。 是否有 Python TTS 库?像 Festival、
在我的应用程序中,我想知道是否有任何可以阅读印地文文本的 tts 引擎。我的代码 tts.setLanguage(Locale.US); 很遗憾,Android 不支持印地语。请参阅下面支持的语言环境
@ 目录 创建页面布局 创建手势控件 创建TalkBox 创建动画 拖拽物动画
我有一个简单的 Angular 模态,是用 Angular ui.bootstrap 引发的。它打开得很好,传递值等,但不会关闭或取消。我认为这是 $scopes 的讨论问题。我知道每个模式都有自己的
scss基本上是sass功能的改进实现。我的工作区使用.scss文件。什么是正确的或通用的方式来指代scss时说?我们刚刚把这些文件称为“sass”文件。在只使用scss而不使用sass文件的环境中,
有谁知道我在哪里可以找到一个好的起点来编写一个函数,该函数接受一个字符串并将其转换为 leet speak? function stringToLeetSpeak($string) { // Lo
我目前正在实现视频通话应用程序,例如使用 Twilio Video 的 Google Hangout。我想在后台显示当时正在讲话的人的视频。 是否可以检测谁在使用 Twilio Video JS SD
所以我找到了这段代码: #!/usr/bin/python import sys #for cmd line argv import time #for delay import p
我想让我的机器人能够制作一个 webhook,由命令触发,然后 webhook 可以在一定间隔内说出消息。我想获取已创建的 webhook 的 token 和 id,然后将其放在一个持续不断的 set
我想让 Alexa 说出对意图的响应,但是通过手动调用包含 Alexa 技能代码的 Lambda 函数,而不是直接对 Echo 说出意图。 例如,您能否以某种方式(通过 AWS-SDK 或通过物联网“
我编写 Python 有一段时间了,但 DJango 和一般的 Web 编程对我来说是新的。 我在 Python View 中执行了一个很长的操作。由于我认为 local() 函数需要很长时间才能返回
我是一名优秀的程序员,十分优秀!