【问题标题】:Redraw fragment after screen rotation with different layout屏幕旋转后用不同的布局重绘片段
【发布时间】:2015-04-18 18:45:37
【问题描述】:

我正在实现应用程序的注册/登录部分,并尝试通过使用不同的片段进行登录和注册,在一个活动中实现它。

我有两种不同的纵向和横向布局,基本上是纵向布局的垂直布局和横向布局的水平布局,都带有徽标和包含片段的 FrameLayout(让我们只考虑登录的那个)。

片段被一个 xml 资源文件膨胀,并以这种方式以编程方式插入到活动的 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:无法更改片段的容器 ID LoginFragment{19d136ec #0 id=0x7f090040 loginFragment}:是 2131296320 现在是 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);
}

}

【问题讨论】:

    标签: java android android-layout android-fragments screen-rotation


    【解决方案1】:

    问题可能在于您试图替换通过 XML 添加的片段。

    请参阅:IllegalStateException when replacing a Fragment 进行讨论。

    编辑 2:

    我也使用横向模式,并且能够旋转它并更改布局。 好的,我实现了你的代码(我可以从你的代码中弄清楚)。我只是改变了使用findViewBy()定位元素的方式。

    在活动中:

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

    【讨论】:

    • 片段是通过代码添加的(我在我的问题中发布的最后三行),只有片段布局是从 XML 膨胀的。
    • 好的,可能需要查看您的 LoginFragment 代码。是否还在 LoginFragment 中添加了空的默认构造函数?
    • 用 XML 布局和 LoginFragment 更新了问题
    • 仅使用纵向布局旋转也对我有用,问题是当您对横向模式使用不同的布局时。
    • 我在旋转时实际上使用了不同的布局 - 但我已经更新了完整的代码(LoginFragment 除外)。
    猜你喜欢
    • 2012-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多