Я хочу сохранить экземпляр при переходе с книжной на альбомную. Но когда я пытаюсь восстановить экземпляр фона моей кнопки письма и включить, он сообщает мне об этой ошибке. Программа пошла хорошо, когда я прокомментировал эти коды.
это буквенный класс
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 или, если вы хотите использовать флажки, тогда 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()? Спасибо.
Я изменил класс 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); } // новое добавление `, но сначала оно активировало все мои кнопки
selectedLetters пуст до того, как вы что-нибудь нажмете?
Пожалуйста, опубликуйте весь метод onRestoreInstanceState