как синхронизировать android tts с recyclerview smoothscroll


Итак, у меня есть вид recycler, в который я добавляю кучу текста, Текст находится в карточках с фиксированной высотой и шириной, когда я нажимаю кнопку, текст считывается с помощью андроидов TTS engine.

Проблема в том, что если текст превышает пространство в представлении, я хочу, чтобы представление recycler прокручивалось до начала текста / представления recycler, считывало текст и прокручивало представление по ходу движения, сохраняя или замедляя его с помощью движка android tts, поэтому я установил пользовательский linearlayoutmanager на своем компьютере. переработчик вид с помощью здесь, что позволяет мне ускорить или замедлить прокрутку в зависимости от поплавка переменной, я тогда пытался сделать это несколькими способами, но безрезультатно и обнаружил, что мне нужно использовать UtteranceProgressListener поэтому я создал метод, который обновляет положение карты и попытался передать это UtteranceProgressListener такой

    public void speakWordsExclusive(String speech, final int position) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        myTTS.speak(speech, TextToSpeech.QUEUE_ADD, params, "");
    }
    else{
        myTTS.speak(speech, TextToSpeech.QUEUE_ADD, map);
    }
    myTTS.setOnUtteranceProgressListener(new UtteranceProgressListener() {
        @Override
        public void onStart(final String utteranceId) {
        }

        @Override
        public void onDone(final String utteranceId) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
       //position should print 1,2,3, etc but just gives me the last number
       System.out.println("position UtteranceProgress " + position );
       //the line below will smooth scroll the view to the end position with 
       //no care for which cards is being read
       SpeakGridDB.recyclerView.getLayoutManager()
      .smoothScrollToPosition(SpeakGridDB.recyclerView, null, position );
                }
            });
        }
        @Override
        public void onError(String utteranceId) {
        }
    });
}

Это не работает позиция всегда просто наибольшее число, так что если бы я ожидал 1,2,3,4 я бы на самом деле просто получить 4, как это,

11-07 14:23:09.121 28882-28882/ss.sealstudios.com.socialstories 
I/System.out: position UtteranceProgress 4 
11-07 14:23:09.741 28882-  
28882/ss.sealstudios.com.socialstories 
I/System.out: position UtteranceProgress 4 
11-07 14:23:10.353 28882-
28882/ss.sealstudios.com.socialstories 
I/System.out: position UtteranceProgress 4 
11-07 14:23:10.944 28882-  
28882/ss.sealstudios.com.socialstories 
I/System.out: position UtteranceProgress 4

Я даю UtteranceProgressListener позицию из метода ниже

    public void speakAndMoveExclusive() {
    final ArrayList<String> list = new ArrayList<>();
    list.clear();
    words = list.toString();
    SpeakGridDB.recyclerView.getLayoutManager().scrollToPosition(0);
    for (int i = 0; i < SpeakGridDB.cardMakerList.size(); i++) {
        list.add(SpeakGridDB.cardMakerList.get(i).getCardSpeech());
        words = list.toString();
    }
    System.out.println(words);
    if (words == null) {
        speakWords("");
    } else if (words.contains(", 's")) {
        formatString = words.replaceFirst(", 's", "'s");
    } else if (words.contains(", ing")) {
        formatString = words.replaceFirst(", ing", "ing");
    }else{
        formatString = words;
    }
    List<String> items = Arrays.asList(formatString.split("\s*,\s*"));
    if (items.contains("[]")){
        speakWords("");
    }
    else{
        for(int j = 0; j < items.size();j++){

            speakWordsExclusive(items.get(j), j);
            //the below line prints the position just fine
            System.out.println("position j " + j);
            params.putString
            (TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"UniqueID" + j);
            map.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"UniqueID" + 
            j);
        }
    }
} 

Переменная положения ive, установленная здесь, очевидно, не является позицией, но она идентична, и распечатка отражает это, как показано ниже

11-07 14:23:08.452 28882-28882/ss.sealstudios.com.socialstories 
I/System.out: position j 0
11-07 14:23:08.454 28882-28882/ss.sealstudios.com.socialstories 
I/System.out: position j 1
11-07 14:23:08.456 28882-28882/ss.sealstudios.com.socialstories  
I/System.out: position j 2
11-07 14:23:08.459 28882-28882/ss.sealstudios.com.socialstories 
I/System.out: position j 3

Если я просто даю это статическому int и даю это onUtteranceProgressListener, то я получаю немного лучший результат, но он все еще не синхронизирован друг с другом

Так что мне интересно, что происходит между ними я просмотрел документы и не могу найти в них никакого смысла я перевел свой звонок в onStart вместо onDone надеясь на лучший результат но ничего не меняется может ли кто-нибудь помочь мне с этим?

1 2

1 ответ:

ОК, как @brandall сказал, что лучше всего установить UtteranceProgressListener один раз и желательно из onInit (int initStatus) поэтому я переключился на эту модель и она работает, мой код обычно работает для прокрутки представления, обратите внимание, что код, который я вставлю, бросает NPE в onDone, где я устанавливаю цвет фона что-то делать с ним не в поле зрения убедитесь, что вы обновляете представление из потока пользовательского интерфейса

    public void onInit(int initStatus) {
    if (initStatus == TextToSpeech.SUCCESS) {
        myTTS.setLanguage(Locale.UK);
        //myExclusiveTTS.setLanguage(Locale.UK);
        myExclusiveTTS.setOnUtteranceProgressListener(new 
        UtteranceProgressListener() {
                @Override
                public void onDone(String utteranceId) {

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            SpeakGridDB.recyclerView.getLayoutManager()
                           .getChildAt(cardCountPosition)
                           .setBackgroundResource(R.drawable.border);
                            cardCountPosition ++;

                            if(cardCountPosition ==                 
                            SpeakGridDB.cardMakerList.size()){
                                cardCountPosition = 0;

                            }
                        }
                    });

                }

                @Override
                public void onError(String utteranceId) {
                }

                @Override
                public void onStart(String utteranceId) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                         moveView();
                         SpeakGridDB.recyclerView.getLayoutManager()
                        .getChildAt(cardCountPosition).setBackgroundResource
                        (R.drawable.selected_blue_border);
                        }
                    });
                }
            });

    } else if (initStatus == TextToSpeech.ERROR) {
        Toast.makeText(this, "Oops sorry! Text To Speech failed... 
        SimpleAAC cannot fix this", Toast.LENGTH_LONG).show();
    }
}

    public void moveView(){
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            if (cardCountPosition < SpeakGridDB.cardMakerList.size()){
           SpeakGridDB.recyclerView.getLayoutManager()
          .smoothScrollToPosition(SpeakGridDB.recyclerView, null,
           cardCountPosition + 1);
            }
            else{
               //this is never called
                cardCountPosition = 0;
            }

        }
    });
}