Почему setText () не работает при восстановлении состояния фрагмента - PullRequest
0 голосов
/ 10 марта 2020

Я пытаюсь завершить sh кодирование приложения ti c ta c toe, которое использует два экземпляра одного и того же фрагмента, взаимодействующих вместе, чтобы каждый игрок мог играть на своей собственной сетке , как показано здесь (каждая сетка помещается в файл xml, который заменяет структуру кадра в главном xml). Приложение работает правильно, но я не могу восстановить состояние приложения после ротации. Для этого я использую данные c ArrayList, расположенные в другом классе с именем ArrayPersistence:

private static ArrayList<String> stringArrayList;

public ArrayPersistence(){}

public static void setStringArrayList(String[][] buttons)
{
    stringArrayList = new ArrayList<>(9);
    for(int i = 0; i < 3; i++)
        for(int y = 0; y < 3; y++)
        {
            stringArrayList.add(buttons[i][y]);
        }
    //System.out.println(stringArrayList);
}

public static ArrayList<String> getStringArrayList()
{
    //System.out.println(stringArrayList);
    return stringArrayList;
}

С помощью метода onSaveInstanceState я сохраняю текст, отображаемый на кнопках:

@Override
public void onSaveInstanceState(Bundle b)
{
    String[][] string = new String[3][3];
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            string[i][j] = buttons[i][j].getText().toString();
        }
    }
    ArrayPersistence.setStringArrayList(string);

    int y = 1;
    b.putInt("rebooted", y);
    super.onSaveInstanceState(b);
}

С помощью onActivityCreated я пытаюсь восстановить текст

@Override
public void onActivityCreated(Bundle b)
{
    super.onActivityCreated(b);
    if(b != null)
    {
        if (b.getInt("rebooted") == 1)
        {
            ArrayList<String> string = ArrayPersistence.getStringArrayList();
            System.out.println("Arraylist printed by onActivityCreated: "+string);
            int i = 0;

            for (int x = 0; x < 3; x++)
                for (int y = 0; y < 3; y++)
                {
                    i++
                    String s = string.get(i);
                    buttons[x][y].setText(s);//<--- Problem here
                }
        }
    }
}

Двумерный массив используется для хранения идентификаторов девяти кнопок. Приложение не показывает ошибок при компиляции или запуске, я просто не могу установить на кнопках сохраненный текст. Я добавил system.out для печати всего ArrayList, чтобы убедиться, что все сохранено и получено правильно, но не могу понять, почему setText() не может установить сохраненный текст


РЕДАКТИРОВАТЬ # 1

По запросу это код, используемый для получения идентификатора кнопок

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                         @Nullable Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.layout_tris, container, false);

    this.ID = getArguments().getInt("id");

    buttons[0][0] = v.findViewById(R.id.b1_1);
    buttons[0][0].setOnClickListener(this);

    buttons[0][1] = v.findViewById(R.id.b1_2);
    buttons[0][1].setOnClickListener(this);

    buttons[0][2] = v.findViewById(R.id.b1_3);
    buttons[0][2].setOnClickListener(this);

    buttons[1][0] = v.findViewById(R.id.b2_1);
    buttons[1][0].setOnClickListener(this);

    buttons[1][1] = v.findViewById(R.id.b2_2);
    buttons[1][1].setOnClickListener(this);

    buttons[1][2] = v.findViewById(R.id.b2_3);
    buttons[1][2].setOnClickListener(this);

    buttons[2][0] = v.findViewById(R.id.b3_1);
    buttons[2][0].setOnClickListener(this);

    buttons[2][1] = v.findViewById(R.id.b3_2);
    buttons[2][1].setOnClickListener(this);

    buttons[2][2] = v.findViewById(R.id.b3_3);
    buttons[2][2].setOnClickListener(this);

    return v;
}

И это кнопка xml:

<Button
  android:id="@+id/b1_1"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_weight="1"
  android:textColor="#000000"
  android:textSize="30dp" />

Внутри 3 LinearLayouts

расположены 9 кнопок

Ответы [ 3 ]

0 голосов
/ 12 марта 2020

Это выглядит как проблема:

int i = 0;

for (int x = 0; x < 3; x++)
    for (int y = 0; y < 3; y++)
    {
        String s = string.get(i);
        buttons[x][y].setText(s);//<--- Problem here
    }

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

Вы можете решить эту проблему, увеличив i после каждого l oop:

int i = 0;

for (int x = 0; x < 3; x++)
    for (int y = 0; y < 3; y++)
    {
        String s = string.get(i);
        buttons[x][y].setText(s);
        i++;
    }

Однако, гораздо более простой способ сделать это - позволить системе Android сохранить текст для вас. TextView, который является суперклассом Button, имеет атрибут android:freezesText. Установите значение true, и текст будет автоматически сохранен и восстановлен для вас.

<Button
  android:id="@+id/b1_1"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_weight="1"
  android:freezesText="true"           <---- add this
  android:textColor="#000000"
  android:textSize="30dp" />
0 голосов
/ 12 марта 2020

Хорошо, после некоторого теста я обнаружил, что после любого изменения ориентации действие, в котором размещены фрагменты, будет перезапущено и инициализирует 2 новых фрагмента, чтобы setText установил текст старого фрагмента, а не тот, который отображается в данный момент, это также объясните, почему android:freezesText="true" не работал. Поэтому я изменил функцию onCreate в MainActivity на:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if(savedInstanceState == null) {
        fragment1 = FragmentTris.newInstance(1)/*new FragmentTris(1)*/;
        fragment2 = FragmentTris.newInstance(2)/*new FragmentTris(2)*/;

        getSupportFragmentManager().beginTransaction()
                .replace(R.id.container1, fragment1, fragment1_tag)
                .replace(R.id.container2, fragment2, fragment2_tag)
                .commit();
    }
    else if(savedInstanceState != null)
    {
        fragment1 = (FragmentTris) getSupportFragmentManager().findFragmentByTag(fragment1_tag);
        fragment2 = (FragmentTris) getSupportFragmentManager().findFragmentByTag(fragment2_tag);
    }
    if(!fragment1.isInLayout() && !fragment2.isInLayout())
    {
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.container1, fragment1, fragment1_tag)
                .replace(R.id.container2, fragment2, fragment2_tag)
                .commit();
    }
}

Таким образом, после поворота можно будет использовать тот же экземпляр фрагментов и правильно восстановить текст на кнопках

0 голосов
/ 10 марта 2020

Вы можете попробовать onViewStateRestored(Bundle savedInstanceState) метод жизненного цикла Fragments.

Просто удалите код из onActivityCreated(Bundle b) и поместите весь код в метод onViewStateRestored(Bundle savedInstanceState).

...