C# 如何在Xamarin.Forms中为ToolbarItem创建自定义渲染器?

C# 如何在Xamarin.Forms中为ToolbarItem创建自定义渲染器?,c#,xamarin.forms,xamarin.android,speech-to-text,C#,Xamarin.forms,Xamarin.android,Speech To Text,我正在使用Xamarin.Forms应用程序。我正试图通过一个工具栏项单击向Xamarin.Forms添加语音到文本功能。当我单击工具上的按钮时,我希望内置电话语音服务打开并将我的语音转换为文本,并添加到页面的标签中 问题:触发特定于android的语音服务。我需要工具栏项的自定义渲染器。因此,我可以在该自定义渲染器的OnClick方法中将语音代码添加到文本中。但我似乎找不到工具栏项的渲染器类 下面是我当前尝试使用工具栏项渲染器的代码 VoiceToolbarItemRenderer.cs [a

我正在使用Xamarin.Forms应用程序。我正试图通过一个工具栏项单击向Xamarin.Forms添加语音到文本功能。当我单击工具上的按钮时,我希望内置电话语音服务打开并将我的语音转换为文本,并添加到页面的标签中

问题:触发特定于android的语音服务。我需要工具栏项的自定义渲染器。因此,我可以在该自定义渲染器的OnClick方法中将语音代码添加到文本中。但我似乎找不到工具栏项的渲染器类

下面是我当前尝试使用工具栏项渲染器的代码

VoiceToolbarItemRenderer.cs

[assembly: ExportRenderer(typeof(VoiceToolbarItem), typeof(VoiceToolbarItemRenderer))]

namespace Xamarin_App.Droid
{
    public class VoiceToolbarItemRenderer : PageRenderer, Android.Views.View.IOnClickListene
{

    private bool isRecording;
    private readonly int VOICE = 10;
    private MainActivity activity;

    private VoiceToolbarItem sharedToolbarItem;
    private Toolbar nativeButton;

    private SpeechRecognizer mSpeechRecognizer;
    private Intent mSpeechRecognizerIntent;


    public VoiceToolbarItemRenderer(Context context) : base(context)
    {
        isRecording = false;
    }

    protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
    {
        base.OnElementChanged(e);
        activity = this.Context as MainActivity;
        nativeButton = new global::Android.Widget.Toolbar(Context);

        if (e.OldElement == null)
        {
            // perform initial setup
            //SetNativeControl();
            nativeButton.Clickable = true;
            nativeButton.Focusable = true;

            nativeButton.SetOnClickListener(this);

        }

        if (e.OldElement != null)
        {
            activity.ActivityResult -= HandleActivityResult;
        }

        if (e.NewElement != null)
        {
            activity.ActivityResult += HandleActivityResult;
            sharedToolbarItem = e.NewElement.ToolbarItems as VoiceToolbarItem;
        }
    }

    public void OnClick(Android.Views.View view)
    {

        try
        {
            string rec = Android.Content.PM.PackageManager.FeatureMicrophone;
            if (rec != "android.hardware.microphone")
            {
                // no microphone, no recording. Disable the button and output an alert
                var alert = new AlertDialog.Builder(Context);
                alert.SetTitle("You don't seem to have a microphone to record with");
                alert.SetPositiveButton("OK", (sender, e) => {

                    return;
                });

                alert.Show();
            }
            else
            {

                // create the intent and start the activity

                var voiceIntent = new Intent(RecognizerIntent.ActionRecognizeSpeech);
                voiceIntent.PutExtra(RecognizerIntent.ExtraLanguageModel, RecognizerIntent.LanguageModelFreeForm);


               // if there is more then 1.5s of silence, consider the speech over
                voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputCompleteSilenceLengthMillis, 1500);
                voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputPossiblyCompleteSilenceLengthMillis, 1500);
                voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputMinimumLengthMillis, 15000);
                voiceIntent.PutExtra(RecognizerIntent.ExtraMaxResults, 1);

                // you can specify other languages recognised here, for example
                // voiceIntent.PutExtra(RecognizerIntent.ExtraLanguage, Java.Util.Locale.German);
                // if you wish it to recognise the default Locale language and German
                // if you do use another locale, regional dialects may not be recognised very well

                voiceIntent.PutExtra(RecognizerIntent.ExtraLanguage, Java.Util.Locale.Default);
                activity.StartActivityForResult(voiceIntent, VOICE);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    private void HandleActivityResult(object sender, ActivityResultEventArgs e)
    {
        if (e.RequestCode == VOICE)
        {
            if (e.ResultCode == Result.Ok)
            {
                var matches = e.Data.GetStringArrayListExtra(RecognizerIntent.ExtraResults);
                if (matches.Count != 0)
                {
                    string textInput = matches[0];

                    // limit the output to 500 characters
                    if (textInput.Length > 500)
                        textInput = textInput.Substring(0, 500);
                    sharedToolbarItem.OnTextChanged?.Invoke(textInput);
                    //textBox.Text = textInput;
                }
                else
                    sharedToolbarItem.OnTextChanged?.Invoke("No speech was recognised");
            }
        }

    }

}
[程序集:ExportRenderer(typeof(VoiceToolbarItem)、typeof(VoiceToolbarItemRenderer))]
命名空间Xamarin_App.Droid
{
公共类VoiceToolbarItemRenderer:PageRenderer,Android.Views.View.IOnClickListene
{
私人档案记录;
专用只读int语音=10;
私人活动;
私有VoiceToolbarItem共享ToolBarItem;
专用工具栏nativeButton;
私人语音识别器;
私人意图mSpeechRecognizerIntent;
公共VoiceToolbarItemRenderer(上下文):基本(上下文)
{
isRecording=false;
}
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
activity=this.Context作为MainActivity;
nativeButton=新的全局::Android.Widget.Toolbar(上下文);
if(e.OldElement==null)
{
//执行初始设置
//SetNativeControl();
nativeButton.Clickable=true;
nativeButton.Focusable=true;
nativeButton.SetOnClickListener(此);
}
if(e.OldElement!=null)
{
activity.ActivityResult-=手动过滤活性Result;
}
if(例如NewElement!=null)
{
activity.ActivityResult+=手动过滤活性Result;
sharedToolbarItem=e.NewElement.ToolbarItems作为VoiceToolbarItem;
}
}
public void OnClick(Android.Views.View)
{
尝试
{
string rec=Android.Content.PM.PackageManager.feature麦克风;
if(rec!=“安卓.硬件.麦克风”)
{
//没有麦克风,没有录音。禁用按钮并输出警报
var alert=new AlertDialog.Builder(上下文);
SetTitle(“你似乎没有麦克风来录音”);
alert.SetPositiveButton(“确定”,(发送方,e)=>{
返回;
});
alert.Show();
}
其他的
{
//创建意图并开始活动
var voiceIntent=新意图(RecognizerIntent.ActionRecognizeSpeech);
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguageModel,RecognizerIntent.LanguageModelFreeForm);
如果还有1.5秒的沉默,请考虑演讲。
voiceIntent.PutExtra(识别器Intent.ExtraspeechInputCompleteSilenceLength,1500);
voiceIntent.PutExtra(识别器Intent.ExtraspeechInputPossiblyCompleteSilenceLength,1500);
voiceIntent.PutExtra(识别器Intent.ExtraSpeechInputMinimumLengthMillis,15000);
voiceIntent.PutExtra(RecognizerIntent.ExtraMaxResults,1);
//例如,您可以在此处指定可识别的其他语言
//PutExtra(RecognizerIntent.ExtraLanguage,Java.Util.Locale.German);
//如果您希望它识别默认的语言环境语言和德语
//如果你使用另一个地区,地区方言可能不会被很好地识别
PutExtra(RecognizerIntent.ExtraLanguage,Java.Util.Locale.Default);
activity.StartActivityForResult(语音意图、语音);
}
}
捕获(例外情况除外)
{
控制台写入线(例如消息);
}
}
私有void HandleActivityResult(对象发送方,ActivityResultEventArgs e)
{
如果(例如,请求代码==语音)
{
if(e.ResultCode==Result.Ok)
{
var matches=e.Data.GetStringArrayListExtra(RecognizerIntent.ExtraResults);
如果(matches.Count!=0)
{
字符串textInput=匹配[0];
//将输出限制为500个字符
如果(textInput.Length>500)
textInput=textInput.Substring(0500);
sharedToolbarItem.OnTextChanged?.Invoke(textInput);
//Text=textInput;
}
其他的
sharedToolbarItem.OnTextChanged?.Invoke(“未识别语音”);
}
}
}
}
}


如果有人想制作toolbarItem的自定义呈现程序或任何其他建议,请告诉我。

我想您指的是导航栏(或获取页面标题的栏,对吗?)

如果是这种情况,那么您有两个选择:

  • 等待Xamarin的下一个版本。他们正在开发的表单能够向工具栏添加内容。(例如,您可以拥有自己的后退按钮)

  • 您可以制作自己的工具栏,只需确保不在NavigationPage上显示导航栏,并制作自己的工具栏(例如,水平堆叠布局(或flexlayout)),在其中放置标题和所需按钮,并具有背景色


  • 我尝试过为工具栏定制渲染器,但这似乎不是一件容易的工作。

    您可以按照下面的步骤来实现徽章图标