java - 在微调器中显示 TTS 可用语言
问题描述
我最近开始了 android 编程,我正在尝试查看设备上可以使用哪些文本到语音的语言并将它们显示在微调器中,但我遇到了一个非常奇怪的问题。
这是代码的相关部分:
package com.example.dshawn.ttsapp;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;
import java.util.*;
public class MainActivity extends AppCompatActivity implements
AdapterView.OnItemSelectedListener {
private TextToSpeech mTTS;
Locale[] locales = Locale.getAvailableLocales();
List<Locale> localeList = new ArrayList<Locale>();
List<String> country= new ArrayList<String>();
List<String> asdf= new ArrayList<String>();
int sum=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int i) {
if (i==TextToSpeech.SUCCESS){
for (Locale locale : locales) {
int res = mTTS.isLanguageAvailable(locale);
if (res == TextToSpeech.LANG_COUNTRY_AVAILABLE) {
sum++;
localeList.add(locale);
country.add(locale.getDisplayName());
}
}
asdf.add(Integer.toString(sum));
}
}
});
//Getting the instance of Spinner and applying OnItemSelectedListener on it
Spinner spin = (Spinner) findViewById(R.id.spinner);
spin.setOnItemSelectedListener(this);
//Creating the ArrayAdapter instance having the country list
ArrayAdapter<String> aa = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,country);
aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//Setting the ArrayAdapter data on the Spinner
spin.setAdapter(aa);
}
//Performing action onItemSelected and onNothing selected
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {
Toast.makeText(getApplicationContext(),country.get(position) , Toast.LENGTH_LONG).show();
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}
在这个 TTS 初始化之后,我尝试打印总和,它显示为 0。我尝试通过执行类似 String=country.get(1); 的操作来访问 localeList 和国家/地区中的元素。它会在编译器中给出一个错误,说我试图访问的索引不存在并且列表中有 0 个元素。所以在这一点上,设备上似乎可能没有可用的语言,但奇怪的是,当我通过 ArrayAdapter 将国家/地区 ArrayList 放入我的微调器下拉菜单时,我设备上的实际可用国家/地区确实显示在微调器中菜单,但它坏了,这是我的意思的 GIF:
微调器永远不会进入我的 onItemSelected 侦听器,并且单击后该项目不会显示在微调器中。我进入了设备的设置,显示的确实是该设备上 TTS 的可用语言环境。并且当我删除似乎从未访问过的代码的“if(res == TextToSpeech.LANG_COUNTRY_AVAILABLE)”部分时,微调器下拉菜单中将没有任何内容。因此,它显然以某种方式获取了可用的语言环境,但是当我尝试访问数组列表时,它表现得好像它是空的,但不知何故,它使用了那个“空”的数组列表并将正确的国家/地区放入微调框,但微调框可能被破坏了,因为ArrayList 坏了,
这里可能是什么问题?我已经尝试了我能想到的一切,我只知道问题在于 TTS 初始化部分。
基本上我无法访问在 TTS 的“onInit”方法中设置或添加的任何项目,这也会导致我的微调器损坏。
解决方案
我认为问题在于您在填充列表之前创建了适配器(使用国家/地区列表)(因为尚未初始化 TTS)。
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
private TextToSpeech mTTS;
Locale[] locales = Locale.getAvailableLocales();
List<Locale> localeList = new ArrayList<Locale>();
List<String> country = new ArrayList<String>();
// * - Move these two variables out here
ArrayAdapter<String> aa;
Spinner spin;
int sum = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i("XXX", "onCreate() was called");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int i) {
if (i == TextToSpeech.SUCCESS) {
// * - delay important tasks until TTS is initialized
startWhenTTSIsInitialized();
}
}
});
//Getting the instance of Spinner and applying OnItemSelectedListener on it
spin = (Spinner) findViewById(R.id.spinner);
}
private void startWhenTTSIsInitialized() {
Log.i("XXX", "startWhenTTSIsInitialized() was called");
for (Locale locale : locales) {
int res = mTTS.isLanguageAvailable(locale);
if (res == TextToSpeech.LANG_COUNTRY_AVAILABLE) {
sum++;
localeList.add(locale);
// * - 'country' is used to populate the adapter, so
// this line must come first
country.add(locale.getDisplayName());
}
}
//Creating the ArrayAdapter instance having the country list
// * - now it's safe to set the adapter because the country list has been populated
aa = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, country);
aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//Setting the ArrayAdapter data on the Spinner
spin.setAdapter(aa);
spin.setOnItemSelectedListener(this);
}
//Performing action onItemSelected and onNothing selected
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {
Log.i("XXX", "onItemSelected() was called");
Toast.makeText(getApplicationContext(), country.get(position), Toast.LENGTH_LONG).show();
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}