为什么 setText() 在恢复片段状态时不起作用
Why setText() doesn't work when restoring state of the fragment
我正在尝试完成井字应用程序的编码,该应用程序使用同一片段的两个实例一起通信,以便每个玩家都可以在自己的网格上玩 as show here(每个网格都放在 xml 文件替换主 xml) 中的框架布局。
该应用程序运行正常,但我无法在旋转后恢复应用程序的状态。
为此,我使用了位于另一个名为 ArrayPersistence
:
的 class 中的静态 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" />
3个里面放了9个按钮LinearLayouts
您可以尝试使用 Fragments
的 onViewStateRestored(Bundle savedInstanceState)
生命周期方法。
只需删除 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 系统为您保存文本。 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" />
好的,经过一些测试,我发现在任何方向改变后,托管片段的 activity 将重新启动并初始化 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();
}
}
这样在旋转后可以使用相同的片段实例并正确恢复按钮上的文本
我正在尝试完成井字应用程序的编码,该应用程序使用同一片段的两个实例一起通信,以便每个玩家都可以在自己的网格上玩 as show here(每个网格都放在 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" />
3个里面放了9个按钮LinearLayouts
您可以尝试使用 Fragments
的 onViewStateRestored(Bundle savedInstanceState)
生命周期方法。
只需删除 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 系统为您保存文本。 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" />
好的,经过一些测试,我发现在任何方向改变后,托管片段的 activity 将重新启动并初始化 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();
}
}
这样在旋转后可以使用相同的片段实例并正确恢复按钮上的文本