如何同步Android tts与recyclerview平滑滚动

问题描述:

好吧,所以我有一个回收站视图,我添加了一堆文本,文本是在固定的高度和宽度的卡片,当我按下按钮时,文本被读出使用androids TTS引擎。如何同步Android tts与recyclerview平滑滚动

问题是如果文本超出视图中的空间我希望回收视图滚动到文本/回收站视图的开始位置,读出文本并滚动视图,同时保持或减慢与Android tts引擎,所以我已经在我的回收视图上设置了一个自定义的linearlayoutmanager,在here的帮助下,我可以根据浮点变量加快或减慢滚动速度,然后尝试通过几种方法完成此操作无果,我发现我需要使用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希望获得更好的结果,但没有任何更改可以帮助我吗?

+0

你是一个新的'UtteranceProgressListener'每次设定你的'speakWordsExclusive'方法,因此一个新的可运行。尝试子类化'UtteranceProgressListener'。同时删除将RecyclerView更新为单独的方法并对其进行同步。这应该有助于您进一步观察问题。 – brandall

+0

非常感谢我想出了一些东西,但是如果你不介意看一看@brandall,那么它就不能工作了 –

确定像@brandall说其设置一个UtteranceProgressListener一次,最好从onInit(int initStatus),所以我切换到这个模型,并让它工作,我的代码一般用于滚动视图,注意代码我会贴抛出onDone一个NPE在那里我设置背景色用的东西,鉴于它不是做确保你从UI线程更新视图

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

     } 
    }); 
}