屏幕旋转后使用不同布局重绘片段
Redraw fragment after screen rotation with different layout
我正在实现一个应用程序的 registration/login 部分,我试图通过使用不同的片段进行登录和注册来在一个 activity 中实现它。
我有两种不同的纵向和横向布局,基本上是纵向纵向布局和横向横向布局,都有徽标和包含片段的 FrameLayout(让我们考虑登录的那个).
该片段由 xml 资源文件扩充并以编程方式插入 activity onCreate() 方法中,方法如下:
fragmentManager = this.getFragmentManager();
ViewGroup root = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
LinearLayout linearLayout = (LinearLayout) root.getChildAt(0);
frameLayout = (FrameLayout) linearLayout.getChildAt(1);
loginFragment = (LoginFragment) fragmentManager.findFragmentByTag("loginFragment");
if (loginFragment == null) {
// If fragment wasn't saved, create new one
Log.d("DEBUG", "Fragment is null");
loginFragment = new LoginFragment();
}
else
Log.d("DEBUG", "Fragment is not null");
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(frameLayout.getId(), loginFragment, "loginFragment");
transaction.commit();
一切正常,直到我旋转屏幕,然后我得到以下信息:
java.lang.IllegalStateException: Can't change container ID of fragment
LoginFragment{19d136ec #0 id=0x7f090040 loginFragment}: was 2131296320
now 2131296322
我尝试在提交后放置 fragmentManager.executePendingTransactions();
,但仍然是同样的问题。实在不知道还有什么可以尝试的,希望得到一些提示。
编辑:这是布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:layout_gravity="center_horizontal"
android:src="@drawable/jobsharklogo"
android:layout_weight="1" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/frameLayout"
android:layout_weight="1" />
</LinearLayout>
和
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView2"
android:layout_gravity="center_vertical"
android:src="@drawable/jobsharklogo" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frameLayout2"
android:layout_weight="1" />
</LinearLayout>
和LoginFragment代码:
public class LoginFragment extends Fragment implements View.OnClickListener {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnLoginFragmentInteractionListener mListener;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment LoginFragment.
*/
// TODO: Rename and change types and number of parameters
public static LoginFragment newInstance(String param1, String param2) {
LoginFragment fragment = new LoginFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public LoginFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_login, container, false);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1);
params.gravity = Gravity.CENTER;
view.setLayoutParams(params);
Button loginButton = (Button) view.findViewById(R.id.loginButton);
Button signupButton = (Button) view.findViewById(R.id.signupButton);
loginButton.setOnClickListener(this);
signupButton.setOnClickListener(this);
return view;
}
public void onClick(View button) {
if (mListener != null) {
mListener.onLoginFragmentInteraction(button.getId());
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnLoginFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnLoginFragmentInteractionListener {
public void onLoginFragmentInteraction(int id);
}
}
问题可能在于您正在尝试替换通过 XML 添加的片段。
参见:IllegalStateException when replacing a Fragment 进行讨论。
编辑 2:
我也使用横向模式,并且可以旋转它并更改布局。
好的,我实现了您的代码(使用我可以从您的代码中找出的内容)。我只是通过使用 findViewBy()
.
改变了我定位元素的方式
在activity中:
public class LoginActivity extends Activity implements LoginFragment.OnLoginFragmentInteractionListener {
private FragmentManager fragmentManager;
private FrameLayout frameLayout;
private LoginFragment loginFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
fragmentManager = this.getFragmentManager();
ViewGroup root = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
frameLayout = (FrameLayout) root.findViewById(R.id.frameLayout);
loginFragment = (LoginFragment) fragmentManager.findFragmentByTag("loginFragment");
if (loginFragment == null) {
// If fragment wasn't saved, create new one
Log.d("DEBUG", "Fragment is null");
loginFragment = new LoginFragment().newInstance("param1", "param2");
}
else
Log.d("DEBUG", "Fragment is not null");
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(frameLayout.getId(), loginFragment, "loginFragment");
transaction.commit();
}
@Override
public void onLoginFragmentInteraction(int id) {
Log.e("DEBuG", "id: "+id);
}
}
其中 main.xml
是:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:id="@+id/linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="#f0498a">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/frameLayout"
android:layout_weight="1" />
在任何旋转模式下点击按钮,我得到:
E/DEBuG﹕ id: 2131296322
E/DEBuG﹕ id: 2131296321
我用的xml横屏模式(输入layout-land
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:id="@+id/linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="@color/material_blue_grey_900">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frameLayout"
android:layout_weight="1" />
<Button
android:id="@+id/loginButton"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="login"/>
<Button
android:id="@+id/signupButton"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="sing in"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView2"
android:layout_gravity="center_vertical"
android:src="@drawable/jobsharklogo" />
和纵向模式(就在 layout
文件夹中)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:id="@+id/linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="#f0498a">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/frameLayout"
android:layout_weight="1" />
<Button
android:id="@+id/loginButton"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="login"/>
<Button
android:id="@+id/signupButton"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="sing in"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:layout_gravity="center_horizontal"
android:src="@drawable/jobsharklogo"
android:layout_weight="1" />
我正在实现一个应用程序的 registration/login 部分,我试图通过使用不同的片段进行登录和注册来在一个 activity 中实现它。
我有两种不同的纵向和横向布局,基本上是纵向纵向布局和横向横向布局,都有徽标和包含片段的 FrameLayout(让我们考虑登录的那个).
该片段由 xml 资源文件扩充并以编程方式插入 activity onCreate() 方法中,方法如下:
fragmentManager = this.getFragmentManager();
ViewGroup root = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
LinearLayout linearLayout = (LinearLayout) root.getChildAt(0);
frameLayout = (FrameLayout) linearLayout.getChildAt(1);
loginFragment = (LoginFragment) fragmentManager.findFragmentByTag("loginFragment");
if (loginFragment == null) {
// If fragment wasn't saved, create new one
Log.d("DEBUG", "Fragment is null");
loginFragment = new LoginFragment();
}
else
Log.d("DEBUG", "Fragment is not null");
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(frameLayout.getId(), loginFragment, "loginFragment");
transaction.commit();
一切正常,直到我旋转屏幕,然后我得到以下信息:
java.lang.IllegalStateException: Can't change container ID of fragment LoginFragment{19d136ec #0 id=0x7f090040 loginFragment}: was 2131296320 now 2131296322
我尝试在提交后放置 fragmentManager.executePendingTransactions();
,但仍然是同样的问题。实在不知道还有什么可以尝试的,希望得到一些提示。
编辑:这是布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:layout_gravity="center_horizontal"
android:src="@drawable/jobsharklogo"
android:layout_weight="1" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/frameLayout"
android:layout_weight="1" />
</LinearLayout>
和
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView2"
android:layout_gravity="center_vertical"
android:src="@drawable/jobsharklogo" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frameLayout2"
android:layout_weight="1" />
</LinearLayout>
和LoginFragment代码:
public class LoginFragment extends Fragment implements View.OnClickListener {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnLoginFragmentInteractionListener mListener;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment LoginFragment.
*/
// TODO: Rename and change types and number of parameters
public static LoginFragment newInstance(String param1, String param2) {
LoginFragment fragment = new LoginFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public LoginFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_login, container, false);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1);
params.gravity = Gravity.CENTER;
view.setLayoutParams(params);
Button loginButton = (Button) view.findViewById(R.id.loginButton);
Button signupButton = (Button) view.findViewById(R.id.signupButton);
loginButton.setOnClickListener(this);
signupButton.setOnClickListener(this);
return view;
}
public void onClick(View button) {
if (mListener != null) {
mListener.onLoginFragmentInteraction(button.getId());
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnLoginFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnLoginFragmentInteractionListener {
public void onLoginFragmentInteraction(int id);
}
}
问题可能在于您正在尝试替换通过 XML 添加的片段。
参见:IllegalStateException when replacing a Fragment 进行讨论。
编辑 2:
我也使用横向模式,并且可以旋转它并更改布局。
好的,我实现了您的代码(使用我可以从您的代码中找出的内容)。我只是通过使用 findViewBy()
.
在activity中:
public class LoginActivity extends Activity implements LoginFragment.OnLoginFragmentInteractionListener {
private FragmentManager fragmentManager;
private FrameLayout frameLayout;
private LoginFragment loginFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
fragmentManager = this.getFragmentManager();
ViewGroup root = (ViewGroup) getWindow().getDecorView().findViewById(android.R.id.content);
frameLayout = (FrameLayout) root.findViewById(R.id.frameLayout);
loginFragment = (LoginFragment) fragmentManager.findFragmentByTag("loginFragment");
if (loginFragment == null) {
// If fragment wasn't saved, create new one
Log.d("DEBUG", "Fragment is null");
loginFragment = new LoginFragment().newInstance("param1", "param2");
}
else
Log.d("DEBUG", "Fragment is not null");
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(frameLayout.getId(), loginFragment, "loginFragment");
transaction.commit();
}
@Override
public void onLoginFragmentInteraction(int id) {
Log.e("DEBuG", "id: "+id);
}
}
其中 main.xml
是:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:id="@+id/linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="#f0498a">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/frameLayout"
android:layout_weight="1" />
在任何旋转模式下点击按钮,我得到:
E/DEBuG﹕ id: 2131296322
E/DEBuG﹕ id: 2131296321
我用的xml横屏模式(输入layout-land
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:id="@+id/linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="@color/material_blue_grey_900">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frameLayout"
android:layout_weight="1" />
<Button
android:id="@+id/loginButton"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="login"/>
<Button
android:id="@+id/signupButton"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="sing in"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView2"
android:layout_gravity="center_vertical"
android:src="@drawable/jobsharklogo" />
和纵向模式(就在 layout
文件夹中)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:id="@+id/linear"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="#f0498a">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/frameLayout"
android:layout_weight="1" />
<Button
android:id="@+id/loginButton"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="login"/>
<Button
android:id="@+id/signupButton"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="sing in"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:layout_gravity="center_horizontal"
android:src="@drawable/jobsharklogo"
android:layout_weight="1" />