如何使用recyclerview smoothscroll同步android tts

时间:2016-11-07 14:41:10

标签: android android-recyclerview text-to-speech smooth-scrolling

好的,所以我有一个回收站视图,我添加了一堆文本,文本在卡片中具有固定的高度和宽度,当我按下按钮时,使用机器人TTS引擎读出文本。

问题是如果文本超出了视图中的空间我希望回收器视图滚动到文本/回收器视图的开头,读出文本并滚动视图,同时保持向上或减慢速度android tts引擎,所以我在here的帮助下在我的Recycler视图上设置了一个自定义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);
        }
    }
} 

我在这里设置的位置变量显然不是位置但它是相同的并且打印输出反映了,如下所示

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 个答案:

答案 0 :(得分:0)

好像@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;
            }

        }
    });
}