I'm trying to do a simple android application with 2 fragments. First fragment is to enter the message, second fragment is to display the message.
I need to show one fragment at a time in portrait mode, both fragments in landscape mode. For that I have 2 layout files for the main activity, one for portrait(normal) mode with empty FrameLayout, second one for landscape mode with both fragments are embedded in the xml layout itself.
When I rotate the screen to landscape mode, I see that the "onCreateView()" method called twice for the first fragment.
I could not figure out how to fix this. Any thought on this would be helpful for me !!
I have already went through the same questions here in stackoverflow, but it didn't help as those questions are with viewPager, tabs, adapters.
Further details:
MainActivity.java
public class MainActivity extends Activity implements MyFragment1.MyFragment1Interface{
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState){
Log.d(TAG,"On create called");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(findViewById(R.id.my_fragment_container) != null){
if(savedInstanceState != null)
return;
Log.d(TAG,"creating fragment1 and adding");
MyFragment1 myFragment1 = new MyFragment1();
getFragmentManager().beginTransaction().add(R.id.my_fragment_container,myFragment1).commit();
}
}
@Override
public void showMessage(String message) {
MyFragment2 myFragment2 = (MyFragment2) getFragmentManager().findFragmentById(R.id.fragment2);
if(myFragment2 != null)
myFragment2.displayMessage(message);
else{
myFragment2 = new MyFragment2();
Bundle args = new Bundle();
args.putString(MyFragment1.ARG_MESSAGE,message);
myFragment2.setArguments(args);
getFragmentManager().beginTransaction().replace(R.id.my_fragment_container,myFragment2).addToBackStack(null).commit();
}
}
}
res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/my_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
res/layout-land/activity_main.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="match_parent"
android:orientation="horizontal">
<fragment android:name="com.example.emanickam.sampleapp.MyFragment1"
android:id="@+id/fragment1"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"/>
<fragment android:name="com.example.emanickam.sampleapp.MyFragment2"
android:id="@+id/fragment2"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"/>
</LinearLayout>
MyFragment1.java
public class MyFragment1 extends Fragment {
MyFragment1Interface mMyFragment1Interface;
public static final String ARG_MESSAGE = "arg.message";
private static final String TAG = "MyFragment1";
public interface MyFragment1Interface
{
public void showMessage(String message);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_fragment1, container, false);
Button button = (Button) view.findViewById(R.id.send_message);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
sendMessage(v);
}
});
Log.d(TAG,"oncreatview is called");
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mMyFragment1Interface = (MyFragment1Interface) context;
}
public void sendMessage(View view)
{
EditText message = (EditText) getActivity().findViewById(R.id.message);
mMyFragment1Interface.showMessage(message.getText().toString());
}
}
MyFragment2.java
public class MyFragment2 extends Fragment {
public static final String ARG_MESSAGE = "arg.message";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_fragment2, container, false);
if(getArguments() != null) {
TextView displayMessage = (TextView) view.findViewById(R.id.display_message);
displayMessage.setText(getArguments().getString(ARG_MESSAGE));
}
return view;
}
public void displayMessage(String message)
{
TextView displayMessage = (TextView) getActivity().findViewById(R.id.display_message);
displayMessage.setText(message);
}
}
res/layout/fragment_my_fragment1.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter a message" />
<Button
android:id="@+id/send_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send Message"/>
</LinearLayout>
res/layout/fragment_my_fragment2.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/display_message"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
Logs:
> D/MainActivity: On create called
> D/MainActivity: creating fragment1 and adding
> D/MyFragment1: oncreatview is called
--screen rotated to landscape here
> D/MainActivity: On create called
> D/MyFragment1: oncreatview is called
> D/MyFragment1: oncreatview is called
Update:
I have got few links of suggested answers to look into for same kind of question. for instance, the answer for the following stackoverflow question,
Android Orientation changes calls onCreate
suggests that we need to add the configChanges attribute in the activity in the manifest file.
<activity android:name=".MainActivity" android:configChanges="keyboardHidden|orientation|screenSize">
This means that android system will not handle the orientation changes and the activity will handle it by itself. When I used this, the layout file I have defined for landscape mode (res/layout-land/activity_main.xml) is completely ignored and it took the portrait layout file in the landscape mode also which is completely different from what i'm trying to achieve. of-course, I understand why. this is because of the android:configChanges attribute. But this is not my intention.
I don't want to disable the android's screen rotation handling for my activity. I'm OK with the default behavior of destroying the activity and recreating it when rotation happens as I can store and retrieve necessary data to handle the destruction. I only want to know how to fix this problem of fragment onCreateView() called twice without disabling the rotation handling as per this Answer by user hackbod