android - 如何修复“UnsupportedOperationException:AdapterView 不支持 addView(View, LayoutParams)”
问题描述
从纵向更改为横向时,我想保存实例。但是当我尝试恢复我的字母按钮背景的实例并启用时,它告诉我这个错误。当我注释掉这些代码时,程序运行良好。
这是字母类
public class Letter extends BaseAdapter {
private String[] letters;
private LayoutInflater letterInf;
public Letter(Context c){
letters = new String[26];
for(int a = 0; a < letters.length; a++){
letters[a] = ""+(char)(a+'A');
}
letterInf = LayoutInflater.from(c);
}
@Override
public int getCount() {
return letters.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Button btnLetter;
if(convertView == null){
btnLetter = (Button) letterInf.inflate(R.layout.letter, null, false);
}else{
btnLetter = (Button) convertView;
}
btnLetter.setText(letters[position]);
return btnLetter;
}
}
这就是我尝试恢复 onRestoreInstance (整个版本)
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
currPart = savedInstanceState.getInt("currPart");
numChars = savedInstanceState.getInt("numChars");
numCorr = savedInstanceState.getInt("numCorr");
int[] savedBodyPartVisibility = savedInstanceState.getIntArray("bodyPartVisibility");
for(int i = 0; i<savedBodyPartVisibility.length; i++){
bodyParts[i].setVisibility(savedBodyPartVisibility[i]);
}
//saved word
currWord = savedInstanceState.getString("currWord");
hint = savedInstanceState.getString("hint");
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){//get orientation
tvHint.setText("Hint:"+hint);// if landscape, show hint
//Toast.makeText(getBaseContext(), "This is landscape!", Toast.LENGTH_SHORT).show();
}
charViews = new TextView[currWord.length()];
wordLayout.removeAllViews();
for(int c = 0; c<currWord.length(); c++){
charViews[c] = new TextView(this);
charViews[c].setText(""+currWord.charAt(c));
charViews[c].setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
charViews[c].setGravity(Gravity.CENTER);
charViews[c].setTextColor(Color.WHITE);
charViews[c].setBackgroundResource(R.drawable.letter_bg);
wordLayout.addView(charViews[c]);
}
//saved charView
int[] savedCharViewColor = savedInstanceState.getIntArray("charViewColor");
for(int i = 0; i< savedCharViewColor.length; i++){
charViews[i].setTextColor(savedCharViewColor[i]);
}
//int numLetters = savedInstanceState.getInt("numLetters");
//letter enable//letter button background color
boolean[] savedLetterEnable = savedInstanceState.getBooleanArray("letterEnable");
int[] savedLettersColor = savedInstanceState.getIntArray("lettersColor");
for(int i = 0; i<savedLetterEnable.length; i++){
letters.getChildAt(i).setEnabled(savedLetterEnable[i]);
//letters.getChildAt(i).setBackgroundColor(savedLettersColor[i]);
}
}
解决方案
您无法以这种方式恢复它,因为视图在 RecyclerView/ListView 中被回收。这意味着只有其中一些被渲染,当你滚动它时,它会重用已经渲染的视图。
所以在大多数情况下,它不会有那么多子视图作为数据源中的项目。
正确的方法是在适配器内存储有关项目状态的信息。
我创建了一个简单的示例,让您了解它的外观。请注意,这setOnSelectedListener(new OnSelectedListener(){...}
是假代码,您应该编写正确的侦听器(onClick,或者如果您想使用 Checkboxes,则根据您的需要使用 onCheckedCHange 或其他任何东西)。
public class Letter extends BaseAdapter {
private String[] letters;
private LayoutInflater letterInf;
private Set<String> selectedLetters = new ArraySet();
public Letter(Context c){
letters = new String[26];
for(int a = 0; a < letters.length; a++){
letters[a] = ""+(char)(a+'A');
}
letterInf = LayoutInflater.from(c);
}
Set<String> getState() {
return selectedLetters;
}
void restoreState(Set<String> selectedLetters) {
this.selectedLetters = selectedLetters;
notifyDataSetInvalidated();
}
@Override
public int getCount() {
return letters.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Button btnLetter;
if(convertView == null){
btnLetter = (Button) letterInf.inflate(R.layout.letter, null, false);
}else{
btnLetter = (Button) convertView;
}
if(selectedLetters.contains(letters[position])) {
btnLetter.setSelected(true);
} else {
btnLetter.setSelected(false);
}
btnLetter.setOnSelectedListener(new OnSelectedListener() {
void onSelected(..., boolean isSelected) {
if(isSelected) {
selectedLetters.add(letters[position]);
} else {
selectedLetters.remove(letters[position]);
}
}
});
btnLetter.setText(letters[position]);
return btnLetter;
}
}
然后,每当您保存状态时,您都会从适配器中获取它getState
并将其放入 savedInstanceState 中。
每当您恢复状态时,您都会从 savedState 获取它并放入适配器restoreState
推荐阅读
- jmeter - 在 JMeter 的 HTTP 采样器中遍历每一行并访问每一列
- javascript - 将基于 ES6 钩子的应用程序转换为基于类的组件
- android - Volley NetworkResponse 中的重复数据
- jmeter - 如何在性能测试期间在 jmeter 中执行并发 10000K 线程?
- python - 如何在python循环中使用多处理快速生成解决方案?
- c++ - 使用双端队列滑动窗口(运行时错误)
- python - 蟒蛇新手。你如何 Print() 和缩进和空格而不给出错误?
- javascript - react hooks编辑表单没有选择要编辑的记录。currentId是正确的,但是选择的记录是未定义的
- r - 按组创建向量,r 中的行
- wpf - ReactiveUI ViewModelViewHost 非常慢,与 HandyControl 一起使用时