首页 > 解决方案 > 如何修复“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]);
    }


}

标签: android

解决方案


您无法以这种方式恢复它,因为视图在 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


推荐阅读