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

时间:2018-06-26 18:54:54

标签: c# xamarin.forms xamarin.android speech-to-text

我正在使用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");
            }
        }

    }

}

}

如果有人对制作toolbarItem的自定义渲染器有任何想法,请告诉我。

1 个答案:

答案 0 :(得分:2)

通过工具栏,我想您是指导航栏(或您获得“页面标题”的栏,对吧?)

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

  1. 等待Xamarin的下一个发行版。他们正在努力将表格添加到工具栏。 (例如,您可以拥有自己的后退按钮)

  2. 您可以制作自己的工具栏,只需确保在NavigationPage上不显示导航栏,然后制作自己的工具栏(例如,水平堆栈布局(或flexlayout),用于放置标题和所需的按钮) ,并且具有背景色。

我尝试为工具栏做自定义渲染器,看来这不是一件容易的事。