Как исправить «UnsupportedOperationException: addView(View, LayoutParams) не поддерживается в AdapterView»

Я хочу сохранить экземпляр при переходе с книжной на альбомную. Но когда я пытаюсь восстановить экземпляр фона моей кнопки письма и включить, он сообщает мне об этой ошибке. Программа пошла хорошо, когда я прокомментировал эти коды.

это буквенный класс

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]);
    }


}

Пожалуйста, опубликуйте весь метод onRestoreInstanceState

Kruti Parekh 18.02.2019 06:03
1
1
47
1

Ответы 1

Вы не можете восстановить его таким образом, потому что представления перерабатываются в RecyclerView/ListView. Это означает, что отрисовываются только некоторые из них, и при прокрутке повторно используются уже отрендеренные представления.

Таким образом, в большинстве случаев у него не будет столько дочерних представлений, сколько элементов в источнике данных.

Правильный подход — хранить информацию о состоянии элементов внутри адаптера.

Я создал простой пример, чтобы дать вам представление о том, как это может выглядеть. Обратите внимание, что setOnSelectedListener(new OnSelectedListener(){...} — это поддельный код, и вы должны написать правильный слушатель (onClick или, если вы хотите использовать флажки, тогда 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 и помещаете в saveInstanceState.

Всякий раз, когда вы восстанавливаете состояние, вы получаете его из сохраненного состояния и вставляете адаптер restoreState

Вы имеете в виду, что мне нужно написать setOnClickListener моего btnLetter? Но что означает boolean isSelected в предложенном вами коде? что я должен написать в onClick()? Спасибо.

Selina 18.02.2019 23:14

Я изменил класс Letter `//new add btnLetter.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { selectedLetters.add(letters[position]); } }); если (selectedLetters.contains (буквы [позиция])) { btnLetter.setEnabled (true); }else{ btnLetter.setEnabled(false); } // новое добавление `, но сначала оно активировало все мои кнопки

Selina 19.02.2019 00:27

selectedLetters пуст до того, как вы что-нибудь нажмете?

RadekJ 19.02.2019 07:03

Другие вопросы по теме