[MAUI]模仿微信“按住-说话”的交互实现

android长按动画效果,android 实现按住说话功能 今天工作上需要做一个仿微信语音聊天中的按住说话的功能。其实很简单,主要就是利用MediaRecorder实现录音,用MediaPlayer实现播放功能。下面我就具体说一下是怎么实现的。1,首先对按钮的onTouch事件进行监听。mBtnVoice.setText("按住说话");mBtnVoice.setOnTouchListener(new OnTouchListener() {@Overrid... 阅读详情


.NET MAUI 跨平台框架包含了识别平移手势的功能,在之前的博文 [MAUI 项目实战] 手势控制音乐播放器(二): 手势交互中利用此功能实现了pan-pit拖拽系统。

简单来说就是拖拽物(pan)体到坑(pit)中,手势容器控件PanContainer描述了pan运动和pit位置的关系,并在手势运动中产生一系列消息事件。

今天使用这个控件,做一个模仿微信“按住-说话”的小功能,最终效果如下:

在这里插入图片描述

使用.NET MAU实现跨平台支持,本项目可运行于Android、iOS平台。

创建页面布局

新建.NET MAUI项目,命名HoldAndSpeak
MainPage.xaml中创建一个PitContentLayoutGrid容器,并对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四个状态。

在这里插入图片描述

但我们希望在拖拽时隐藏这个按钮,这将在创建动画章节将介绍。

创建TalkBox

创建一个圆角矩形,用来显示正在说话的动画。

<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;
    }

在这里插入图片描述

TalkBox动画

创建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);

最终效果如下:

在这里插入图片描述

Layout动画

创建一个用于显示功能区域和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

android仿微信消息长按根据触摸位置弹出对话框 阅读详情

相关推荐

Android仿微信语音聊天功能

本文是仿照张鸿洋在慕课网的教学视频《Android-仿微信语音聊天》而作,从某种意义上来说并不能算作纯粹的原创,在此首先向这位大神致敬~ 文中详细介绍了该功能核心模块的具体实现

liusiqian的博客 1万+

android 实现按住说话功能

今天工作上需要做一个仿微信语音聊天中的按住说话的功能。其实很简单,主要就是利用MediaRecorder实现录音,用MediaPlayer实现播放功能。下面我就具体说一下是怎么实现的。 1,首先对按钮的onTouch事件进行监听。 mBtnVoice.setText("按住说话"); mBtnVoice.setOnTouchListener(new OnTouchListene

qq_28533013的博客 1万+

Android 仿微信语音聊天(2)

if (dialog!textHint.setText(“手指上滑,取消发送”);if (dialog!textHint.setText(“松开手指,取消发送”);if (dialog!textHint.setText(“录音时间过短”);if (dialog!/**更新音量*/if (dialog!

2401_84121798的博客 957

android 辅助功能 长按发语音,简单模拟微信长按语音发送效果

在此不多说,直接上代码吧:简单的布局文件android:id="@+id/rl"android:layout_width="fill_parent"android:layout_height="fill_parent"android:background="#ffffff">android:id="@+id/tv"android:layout_width="fill_parent"andro...

weixin_28896255的博客 929

微信小程序 - 超详细 “长按说话“ 实时语音录制与播放功能,仿微信发语音 “按住说话,松开取消“ 录音功能效果(详细示例源码,一键复制开箱即用!)

微信小程序长按录制声音,微信小程序仿微信长按说话,微信小程序怎么实现长按录音,微信小程序如何实现长按录音,上划取消发送功能,微信小程序如何实现录音功能,微信小程序长按录音右滑取消详细完整源码示例,微信小程序类似微信发语音功能如何实现,小程序实现按下录音松开发送语音,小程序模仿微信长按按钮录音,微信小程序说话录音功能,微信小程序按住录音松手取消结束,微信小程序原生仿微信长按发语音,微信小程序开发中长按说话并发送功能,微信小程序实现按住说话功能,微信小程序怎么做类似微信按住录音功能,小程序实现按下录音松开识别语

✅ 精选推荐文章 1万+

Android聊天按住说话功能

Android聊天按住说话功能,语音录入,语音播放。MediaPlayer、MediaRecorder的使用......

Android 实现录音和监听声音大小实现话筒动画效果

【代码】Android 实现录音和监听声音大小实现话筒动画效果。

chengzhenjia的博客 1571

Android 仿微信按住按钮语音发送实现聊天对话.rar

Android仿微信语音对话聊天的实现,按住 按钮后可录音并发放语音,可播放动画、播放音频,仿微信那样如果前一下正在播放,当点另一个,会先把前一个正在播放的停掉,录音完成后的回调,获取音量大小的Runnable,判断手指的横坐标是否超出按钮的范围,改变文本内容及button的背景色。一些技巧值得学习:   设置MediaRecorder的音频源为麦克风,设置音频的格式,设置音频的编码为amr,随机生成文件的名,mMediaRecorder.getMaxAmplitude()的取值范围:1-32767。只有准备完毕了,AudioRecorderButton才会计时并显示dialog。   手指上滑,取消发送,松开手指,取消发送,通过level去更新voice上的图片   技巧,避免使用switch的冗余代码。

(五)Android仿微信—仿微信聊天界面,以及语音录制功能

本例为模仿微信聊天界面UI设计,文字发送以及语言录制UI。 1先看效果图:       第一:chat.xml设计   Xml代码   xml version="1.0" encoding="utf-8"?>   RelativeLayout xmlns:android="http://schemas.andro

雷子的窝 2651

仿微信录音效果,按住说话松开取消

仿微信录音录音效果,按住说话松开取消效果,按住说话松开取消

Android开发--仿微信语音对讲录音,按住讲话进行录音,向上滑动可以进行取消录音.zip

Android开发--仿微信语音对讲录音,按住讲话进行录音,向上滑动可以进行取消录音.zip

实战经验:打造仿微信聊天键盘,解决常见问题

仿照微信聊天键盘的方法,实现了一个包含表情等功能的键盘区域,并解决了一些常见的问题。通过实践和调查,解决了切换键盘的问题,并实现了Emoji的Unicode显示和自定义删除时向前探索字符边界完成表情删除等操作。在过程中,以为很简单的一个东西花了大量的时间调查原因,发现键盘这一块水很深,当我看到ResultReceiver时,看到了AIDL通信,所以再Android这个体系中,Binder的机制需要了然于胸的,刚好我最近在学习Binder得各种知识,不久后会发布对应的博客,关注我,哈哈。此系列属于我的一个。

chuyouyinghe的专栏 1628

第一篇:常见CAN错误帧及其排查方向

在本文中主要阐述各类错误帧的形成原因以及在使用同星硬件设备出现错误帧时,应当 如何进行排查并消除错误帧。在 CAN 总线通信中,通常遇见的错误帧主要为以下五种,其 分别是:bit error、ACK error、stuff error、CRC error 以及 form error。

u013089100的博客 1745

android仿微信UI长按控件录音,转化为MP3,支持上传,播放等功能

主要实现功能点: 1.实现了长按录音及播放音频功能,并把录音资源格式转化为mp3(基于开源库LAME) 2.实现了把mp3文件上传到服务器(基于Retrofit2),支持再次下载播放,缓存功能 3.对于权限的管理,本Demo用的第三方库:https://github.com/yanzhenjie/AndPermission 4.本Demo内部封装了长按录音控件,解决了与列表滚动View的冲突 用...

qq_20089667的博客 3886

西门子触摸屏教程wincc flexible2008 sp5 Smart V3 V4中文版软件

西门子触摸屏教程wincc flexible2008 sp5 Smart V3 V4中文版软件

liang007dudu的博客 1万+

生物信息学新手必看:MAFFT多序列比对从安装到实战(附参数优化技巧)

本文为生物信息学新手提供了MAFFT多序列比对工具的完整指南。从Linux环境下的安装部署,到核心算法策略(如FFT-NS-i、L-INS-i)的选择逻辑,再到空位罚分等关键参数的深度解析与优化技巧,手把手教你完成从原始序列到高质量比对结果的实战流程,为后续进化树构建等分析奠定坚实基础。

weixin_29230773的博客 485

Android 模仿QQ,微信聊天界面长按提示框

效果图,有点糙 最近要在项目中实现一个长按提示 “复制” 的功能,本来想偷懒在网上找个开源的项目用,但是看了好几个都不是很满意,所以就打算按照自己的思路来实现一个。 如何使用 翠花,上代码 PromptViewHelper pvHelper = new PromptViewHelper(mActivity); pvHelper....

贵公子丶笔记 1974

硅纪元应用测评 | AI搜索引擎大比拼:360AI搜索、秘塔搜索、GenSpark AI和天工AI对比评测

搜索引擎输出的每个段落都有对应的出处,如果有错误,也是信息源的问题,从普通用户的角度来看,这与AI搜索的产品关系不大,能让用户对AI搜索的服务和得到的信息有一个隔离。同时,提供更多的定制选项,允许用户根据自己的偏好调整搜索结果的权重和排序,将使得搜索体验更加个性化和满足用户的具体需求。此外,大部分搜索工具还提供了一个无广告的搜索环境(360AI搜索部分内容会有广告),极大地提升了用户的搜索体验。AI搜索的本质依然是搜索,但它通过AI的逻辑分析和语言重新组织,使用户能够快速得到想要的信息。

guijiyuantech的博客 2013

Android 仿微信语音录音小控件

Android 仿微信语音录音小控件前段时间一直在做IM聊天这方面的撸码工作,涉及到了很多小控件,有时间我会慢慢给大家分享一下我的小成果,希望大家一起学习,一起进步,今天来和大家来说一下Android 仿微信语音录音小控件。

madreain的博客 1656

基于Freertos与lwip移植FreeModbusTcp协议

基于FreeRTOS的N32G457VEL7之LWIP网络协议栈移植-优快云博客。

Dd_456456的博客 3239

【一文读懂】卫星轨道的轨道参数(六根数)和位置速度矢量转换及其在终端距离、相对速度和多普勒频移计算中的应用

本文首先介绍了卫星轨道的六根数参数:半长轴 a、偏心率 e、轨道倾角 i、升交点赤经 Ω、近地点幅角 ω 以及真近点角 ν,并探讨了如何利用这些参数计算卫星与地面终端之间的距离、相对速度及由此产生的多普勒频移。利用开普勒运动公式计算当前瞬间的轨道半径;根据真近点角 ν 在围心坐标系中计算位置矢量和速度矢量;利用旋转矩阵(依次旋转 ω、i、Ω)将围心坐标系的状态矢量转换到地心惯性坐标系;最终结合地面终端信息,计算卫星与终端的欧氏距离、沿视线的相对速度及多普勒频移。

u011376987的博客 9497

Xamarin.Android和Xamarin.iOS在Visual Studio环境变动后同时报错不能编译的解决

Notes.iOS -> Notes -> Xamarin.Forms (>= 5.0.0.2515) Notes.iOS -> Xamarin.Forms (>= 5.0.0.2012)请将在 global.json 中指定的 .NET SDK 更改为需要当前可用的 MSBuild 版本的旧版本。

durian_cao的专栏 231

Qualcomm AI Engine Direct SDK(QNN)的使用介绍

Qualcomm AI Engine Direct SDK,高通新的AI模型推理框架,又名QNN,为AI开发提供统一API的底层框架。通过这个SDK,可以在高通的 CPU/GPU和HTP上对AI模型进行性能加速。2.Qualcomm AI Engine Direct SDK的公开英文文档。1.Qualcomm AI Engine Direct SDK的下载和安装。

u013250861的博客 6974
上一篇: [Asp.Net Core] 网站中的XSS跨站脚本攻击和防范
下一篇: Abp框架Web站点的安全性提升
林晓lx
林晓lx 2017年优快云移动跨平台大赛优秀奖获得者 2017年优快云移动跨平台大赛优秀奖获得者
博客等级 码龄15年 3761粉丝 123原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林晓lx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值