问题
How can i show/Hide imageView in recyclerView as TTS(text to speech) plays for all the available list items, one by one!
Activity method -This method is called r with Loop(not working, no bugs but simply do not give my expected output
int position=0;
public void convertTextToSpeech() {
Multiples multiples1=items.get(position);
for (Multiples item : items) {
text = item.first + " " + item.getSecond() + " Za " + item.getResult() + ".";
tts.speak(text, TextToSpeech.QUEUE_ADD, null);
boolean speakingEnd = tts.isSpeaking();
if (speakingEnd) {
Toast.makeText(getApplicationContext(), "Speaking...."+position, Toast.LENGTH_SHORT).show();
multiples1.setImage_show(true);
mAdapter.notifyItemChanged(position);
} else {
Toast.makeText(getApplicationContext(), "Done...."+position, Toast.LENGTH_SHORT).show();
}
position++;
}
}
The complete code is below for more understanding,
First, i displayed all items in recyclerView. Afterward, I am calling the displayed item in a method having for loop to TTS play each rows(list item). The problem i am facing now is the imageView is not displaying as each recyclerView item are being read by TTS.
Expected output is whenever TTS plays for each row item textView, An imageView(#image1) should show simultaneously
UPDATED TRIED CODE
DisplayActivityResultAdapter.java
......
.......
int position = 0;
public void convertTextToSpeech() {
Multiples multiples1=items.get(position);
for (Multiples item : items) {
text = item.first + " " + item.getSecond() + " Za " + item.getResult() + ".";
tts.speak(text, TextToSpeech.QUEUE_ADD, null);
boolean speakingEnd = tts.isSpeaking();
// Toast.makeText(getApplicationContext(), "Speaking...."+position, Toast.LENGTH_SHORT).show();
// multiples1.setImage_show(true);
// mAdapter.notifyItemChanged(position);
// Log.i("values","------------------------------------------Row value-"+item.getFirst()+" X "+item.getSecond()+", Position="+position);
//------------------------
MyAdapter m= (MyAdapter) mAdapter;
m.updateItem(item,position);
position++;
}
}
}
MyAdapter.java
.....
.....
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
if (holder instanceof MyAdapter.MyViewHolder) {
final MyAdapter.MyViewHolder view = (MyAdapter.MyViewHolder) holder;
Multiples p = items.get(position);
view.name.setText(p.first + " X " + p.getSecond() + "= "+p.getResult());
if(position>0) {
if (p.image_show) {
view.image1.setVisibility(View.VISIBLE);
view.image.setVisibility(View.INVISIBLE);
} else {
view.image1.setVisibility(View.INVISIBLE);
view.image.setVisibility(View.VISIBLE);
}
}
}
}
public void updateItem(Multiples newItem, int pos) {
Log.i("values","-----In updateItem Log----Row value-"+newItem.getFirst()+" X "+newItem.getSecond()+", Position="+pos);
items.set(pos, newItem); //update passed value in your adapter's data structure
Log.e("msg","-----items.get(pos)------------->"+items.get(pos).getFirst()+" X " +items.get(pos).getSecond());
notifyItemChanged(pos,newItem);
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return items.size();
}
}
回答1:
You main fail is absence of listener for TTS. Without it you don't know when you should update your RecyclerView
.
Listener can looks like this:
class MyListener extends UtteranceProgressListener {
@Override
public void onStart(String utteranceId) {
int currentIndex = Integer.parseInt(utteranceId);
mMainAdapter.setCurrentPosition(currentIndex);
handler.post(new Runnable() {
@Override
public void run() {
mMainAdapter.notifyDataSetChanged();
}
});
}
@Override
public void onDone(String utteranceId) {
int currentIndex = Integer.parseInt(utteranceId);
mMainAdapter.setCurrentPosition(-1);
handler.post(new Runnable() {
@Override
public void run() {
mMainAdapter.notifyDataSetChanged();
}
});
if (currentIndex < data.size() - 1) {
playSound(currentIndex + 1);
}
}
@Override
public void onError(String utteranceId) {
}
}
I've created a test project to show how it can be implemented. Here you can see how it works. Here is my github repository.
回答2:
Put the below code snippet inside your Adapter
in OnBindViewHolder
text = item.first + " " + item.getSecond() + " Za " + item.getResult() + ".";
tts.speak(text, TextToSpeech.QUEUE_ADD, null);
boolean speakingEnd = tts.isSpeaking();
if(speakingEnd){
Toast.makeText(getApplicationContext(), "Speaking...."+position, Toast.LENGTH_SHORT).show();
multiples1.setImage_show(true);
mAdapter.notifyItemChanged(position);
} else {
Toast.makeText(getApplicationContext(), "Done...."+position, Toast.LENGTH_SHORT).show();
}
May this help Thanks.
回答3:
Please check this out. In your code, you are missed UtteranceProgressListener
.
You have to add UtteranceProgressListener
which will give you speech completion listener events. Also, you will need utteranceID which will be passed to tts.speak()
that helps you to identify the speech if you need it.
Take a variable as,
String utterId = "";
then in your TextToSpeech
onInit
before calling convertTextToSpeech
register this listener to your tts.
...
else{
tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {
}
@Override
public void onDone(String utteranceId) {
convertTextToSpeech(position);
}
@Override
public void onError(String utteranceId) {
}
});
convertTextToSpeech(0);
}
Initially, 0 is passed to convertTextToSpeech
as it is the first time call. Here I've made some changes to the convertTextToSpeech
. In this, I've removed the loop you were using earlier instead, it will be a recursive function.
public void convertTextToSpeech(int pos) {
if (pos >= items.size()) return;
position = pos;
final Multiples multiples = items.get(position);
text = multiples.first + " " + multiples.getSecond() + " Za " + multiples.getResult() + ".";
utterId = (new Random().nextInt() % 9999999) + ""; // "" is String force
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Bundle params = new Bundle();
params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utterId);
tts.speak(text, TextToSpeech.QUEUE_FLUSH, params, utterId);
} else {
HashMap<String, String> params = new HashMap<>();
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utterId);
tts.speak(text, TextToSpeech.QUEUE_FLUSH, params);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
MyAdapter m = (MyAdapter) mAdapter;
multiples.setImage_show(true);
m.updateItem(multiples, position);
position++;
}
});
}
As you can see the tts.speak()
is deprecated you should use the new one to avoid issues in the latest android os.
In your MyAdapter
, you have to set previous item image_show
to false.
public void updateItem(Multiples newItem, int pos) {
if (pos > 0) {
items.get(pos - 1).setImage_show(false);
}
Log.i("values", "-----In updateItem Log----Row value-" + newItem.getFirst() + " X " + newItem.getSecond() + ", Position=" + pos);
items.set(pos, newItem); //update passed value in your adapter's data structure
Log.e("msg", "-----items.get(pos)------------->" + items.get(pos).getFirst() + " X " + items.get(pos).getSecond());
notifyDataSetChanged();
}
Check the gif uploaded. Please keep us updated.
If you need any help you can ask. Thanks
来源:https://stackoverflow.com/questions/55516858/unable-to-show-imageview-in-recyclerview-synchronously-with-tts