как синхронизировать 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 ответ:
ОК, как @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; } } }); }