我有一个具有两个片段的android应用,该片段将数据从fragmentA传递到fragmentB。我可以正确加载所有数据,但是当我改变屏幕方向时,它们都会重新加载。我已经在要保留状态的片段中设置了onSaveInstanceState
和onViewStateRestored
方法,但是当屏幕方向改变时,什么也不会停留。
The main problem that needs to be fixed is when text is loaded into the TextView in FragmentB - it needs to stay there when the screen orientation is changed.
MainActivity.Java
package com.example.tourguide;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
public class MainActivity extends AppCompatActivity implements FragmentA.FragmentAListener, FragmentB.FragmentBListener {
private FragmentA fragmentA;
private FragmentB fragmentB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentA = new FragmentA();
fragmentB = new FragmentB();
if(savedInstanceState == null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container_a, new FragmentA());
ft.replace(R.id.container_b, new FragmentB());
ft.commitNow();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
@Override
public void onInputASent(CharSequence input) {
fragmentB.updateEditText(input);
}
@Override
public void onInputBSent(CharSequence input) {
fragmentA.updateEditText(input);
}
}
FragmentA.Java
package com.example.tourguide;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.ListFragment;
public class FragmentA extends ListFragment implements AdapterView.OnItemClickListener {
private FragmentAListener listener;
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String[] locationList = getActivity().getResources().getStringArray(R.array.location_list);
updateEditText(locationList[position]);
listener.onInputASent(locationList[position]);
}
public interface FragmentAListener {
void onInputASent(CharSequence input);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_a, container, false);
return v;
}
@Override
public void onListItemClick(@NonNull ListView l, @NonNull View v, int position, long id) {
super.onListItemClick(l, v, position, id);
}
public void updateEditText(CharSequence newText) {
//editText.setText(newText);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof FragmentAListener) {
listener = (FragmentAListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement FragmentAListener");
}
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter arrayAdapter = ArrayAdapter.createFromResource(getActivity(), R.array.location_list, android.R.layout.simple_list_item_1);
setListAdapter(arrayAdapter);
getListView().setOnItemClickListener(this);
}
}
FragmentB.Java-这是在旋转屏幕时需要将字符串保留在TextView中的片段
package com.example.tourguide;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class FragmentB extends Fragment {
private FragmentBListener listener;
private TextView resultsFrag;
private static final String KEY_TITLE = "title_key";
private String stateObject;
public interface FragmentBListener {
void onInputBSent(CharSequence input);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_b, container, false);
resultsFrag = v.findViewById(R.id.tvFragmentB);
//I used the same if block in three different locations and none of them worked
if (savedInstanceState != null) {
String itemTo = savedInstanceState.getString(KEY_TITLE);
resultsFrag.setText(itemTo);
} else {
Toast.makeText(getActivity(), "Error 1", Toast.LENGTH_SHORT).show();
}
return v;
}
public void updateEditText(CharSequence newText) {
String newOption = newText.toString();
stateObject = newText.toString();
Resources res = getResources();
String[] locationDesc = res.getStringArray(R.array.location_description);
if (newOption.equals("Calgary")) {
resultsFrag.setText(locationDesc[0]);
} else if (newOption.equals("Victoria")) {
resultsFrag.setText(locationDesc[1]);
} else if (newOption.equals("Vancouver")) {
resultsFrag.setText(locationDesc[2]);
} else if (newOption.equals("Toronto")) {
resultsFrag.setText(locationDesc[3]);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof FragmentBListener) {
listener = (FragmentBListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement FragmentBListener");
}
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_TITLE, resultsFrag.getText().toString());
}
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
//I used the same if block in three different locations and none of them worked
if (savedInstanceState != null) {
String itemTo = savedInstanceState.getString(KEY_TITLE);
resultsFrag.setText(itemTo);
} else {
Toast.makeText(getActivity(), "Error 2", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//I used the same if block in three different locations and none of them worked
if (savedInstanceState != null) {
String itemTo = savedInstanceState.getString(KEY_TITLE);
resultsFrag.setText(itemTo);
} else {
Toast.makeText(getActivity(), "Error 3", Toast.LENGTH_SHORT).show();
}
}
}
fragment_b.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_blue_light"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvFragmentB"
android:layout_width="match_parent"
android:layout_height="602dp" />
</LinearLayout>
字符串
<resources>
<string name="app_name">Tour Guide</string>
<string-array name="location_list">
<item>Calgary</item>
<item>Victoria</item>
<item>Vancouver</item>
<item>Toronto</item>
</string-array>
<!-- Descriptions for the locations -->
<string-array name="location_description">
<item>This is a big description for CALGARY - THIS needs to load in for more information regarding CALGARY</item>
<item>This is a big description for VICTORIA - THIS needs to load in for more information regarding VICTORIA</item>
<item>This is a big description for VANCOUVER - THIS needs to load in for more information regarding VANCOUVER</item>
<item>This is a big description for TORONTO - THIS needs to load in for more information regarding TORONTO</item>
</string-array>
</resources>
fragment_a.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_green_light"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp">
<ListView
android:id="@android:id/list"
android:layout_width="wrap_content"
android:layout_height="206dp" />
</LinearLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/container_a"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@+id/container_b"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
它们已保存,但是您要替换它们。使用此
if(savedInstanceState == null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container_a, new FragmentA());
ft.replace(R.id.container_b, new FragmentB());
ft.commit();
}
请注意,片段实例化几乎是唯一可以通过这种检查产生正确和预期结果的方案。
除非保留通过findFragmentByTag
+实例化获得的片段,否则不要保留对其的引用。在这种情况下,您可能希望使用commitNow
获得可靠的结果。