繁体   English   中英

为什么在恢复片段状态时 setText() 不起作用

[英]Why setText() doesn't work when restoring state of the fragment

我正在尝试完成一个井字游戏应用程序的编码,该应用程序使用同一片段的两个实例通信在一起,以便每个玩家都可以在自己的网格上播放,如下所示(每个网格都放置在一个 xml 文件中,替换主框架中的框架布局xml)。 该应用程序运行正常,但我无法在旋转后恢复应用程序的状态。 为此,我使用了位于另一个名为ArrayPersistence类中的静态ArrayList

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
                }
        }
    }
}

二维数组用于存储九个按钮的 id。 该应用程序在编译或运行时没有显示错误,我只是无法在按钮上设置保存的文本。 我添加了一些 system.out 来打印整个ArrayList以确保所有内容都被正确保存和检索,但无法弄清楚为什么setText()无法设置保存的文本


编辑#1

根据要求,这是用于获取按钮 ID 的代码

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" />

有 9 个按钮放置在 3 个LinearLayouts

您可以尝试onViewStateRestored(Bundle savedInstanceState)的生命周期方法Fragments

只需从onActivityCreated(Bundle b)删除代码并将所有代码放在onViewStateRestored(Bundle savedInstanceState)方法中。

这看起来像一个问题:

 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来解决这个问题:

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 系统为您保存文本。 TextViewButton的超类,具有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" />

好的,经过一些测试,我发现在任何方向更改后,承载片段的活动都会重新启动并初始化 2 个新片段,因此setText在旧片段上设置文本而不是当前显示的文本,这也解释了为什么android:freezesText="true"不起作用。 所以我将MainActivity onCreate函数修改为:

@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();
    }
}

这样旋转后就可以使用相同的片段实例并正确恢复按钮上的文本

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM