为什么旋转事业的Andr​​oid片段置换失败? [英] Why does rotation cause Android fragment replacement to fail?

查看:139
本文介绍了为什么旋转事业的Andr​​oid片段置换失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经把使用片段置换一个活动,两个片段一个简单的程序。一个片段具有一个按钮,即当pressed,替换为第二个片段的片段。

这工作,如果该应用程序已启动,单击此按钮预期。

如果该应用程序被启动时,该装置被转动(无论是横向或持续回画像),并且按钮被点击,则与被同时显示两个片段的片段替换失败。

这是怎么回事呢?有片段生命周期的问题,我没有解决?

MainActivity.java

 包edu.mindlab.fragmenttest;

进口android.app.FragmentTransaction;
进口android.support.v7.app.ActionBarActivity;
进口android.os.Bundle;
进口android.view.Menu;
进口android.view.MenuItem;
进口android.view.View;


公共类MainActivity扩展ActionBarActivity {
    私人MainActivityFragment startingFragment;
    私人ReplacementFragment replacementFragment;

    @覆盖
    保护无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_main);
        startingFragment =新MainActivityFragment();
        replacementFragment =新ReplacementFragment();

        FragmentTransaction T = getFragmentManager()的BeginTransaction()。
        t.add(R.id.fragment_container,startingFragment,开始)提交()。
    }


    @覆盖
    公共布尔onCreateOptionsMenu(功能菜单){
        //充气菜单;这增加了项目操作栏,如果它是present。
        。getMenuInflater()膨胀(R.menu.menu_main,菜单);
        返回true;
    }

    @覆盖
    公共布尔onOptionsItemSelected(菜单项项){
        //处理动作栏项目点击这里。将操作栏
        //自动在主/向上按钮操作的点击,只要
        //你在AndroidManifest.xml中指定一个父活动。
        INT的id = item.getItemId();

        // noinspection SimplifiableIfStatement
        如果(ID == R.id.action_settings){
            返回true;
        }

        返回super.onOptionsItemSelected(项目);
    }

    公共无效replaceFragment(查看视图){
        如果(!replacementFragment.isAdded()){
            FragmentTransaction T = getFragmentManager()的BeginTransaction()。
            。t.replace(R.id.fragment_container,replacementFragment,replacementTest)提交();
        }
    }
}
 

MainActivityFragment.java

 包edu.mindlab.fragmenttest;

进口android.app.Fragment;
进口android.os.Bundle;
进口android.view.LayoutInflater;
进口android.view.View;
进口android.view.ViewGroup;

公共类MainActivityFragment扩展片段{
    公共MainActivityFragment(){
    }

    @覆盖
    公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,
                             捆绑savedInstanceState){
        查看查看= inflater.inflate(R.layout.fragment_main,集装箱,假);

        返回查看;
    }
}
 

ReplacementFragment.java

 包edu.mindlab.fragmenttest;

进口android.app.Activity;
进口android.net.Uri;
进口android.os.Bundle;
进口android.app.Fragment;
进口android.view.LayoutInflater;
进口android.view.View;
进口android.view.ViewGroup;

公共类ReplacementFragment扩展片段{

    公共静态ReplacementFragment的newInstance(){
        ReplacementFragment片段=新ReplacementFragment();
        返回片段;
    }

    公共ReplacementFragment(){
        //要求空公共构造
    }

    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
    }

    @覆盖
    公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,
                             捆绑savedInstanceState){
        //充气的布局该片段
        返回inflater.inflate(R.layout.fragment_replacement,集装箱,假);
    }

    @覆盖
    公共无效onAttach(活动活动){
        super.onAttach(活动);
    }

    @覆盖
    公共无效onDetach(){
        super.onDetach();
    }

}
 

activity_main.xml

 <的FrameLayout的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
         机器人:layout_width =match_parent
         机器人:layout_height =match_parent
         机器人:ID =@ + ID / fragment_container>
< /的FrameLayout>
 

fragment_main.xml

 < RelativeLayout的的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
            的xmlns:工具=htt​​p://schemas.android.com/tool​​s
            机器人:layout_width =match_parent
            机器人:layout_height =match_parent
            机器人:以下属性来=@扪/ activity_horizo​​ntal_margin
            机器人:paddingRight =@扪/ activity_horizo​​ntal_margin
            机器人:paddingTop =@扪/ activity_vertical_margin
            机器人:paddingBottom会=@扪/ activity_vertical_margin
            工具:上下文=MainActivityFragment。>

<的TextView
    机器人:文本=@字符串/ start_string
    机器人:layout_width =WRAP_CONTENT
    机器人:layout_height =WRAP_CONTENT
    机器人:ID =@ + ID / TextView的/>

<按钮
    机器人:layout_width =WRAP_CONTENT
    机器人:layout_height =WRAP_CONTENT
    机器人:文本=@字符串/ replacement_fragment
    机器人:ID =@ + ID /按钮
    机器人:layout_below =@ + ID / TextView的
    机器人:layout_alignParentLeft =真
    机器人:layout_alignParentStart =真
    机器人:layout_marginTop =56dp
    机器人:的onClick =replaceFragment/>


< / RelativeLayout的>
 

fragment_replacement.xml

 <的FrameLayout的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
         的xmlns:工具=htt​​p://schemas.android.com/tool​​s
         机器人:layout_width =match_parent
         机器人:layout_height =match_parent
         工具:上下文=edu.mindlab.fragmenttest.ReplacementFragment>

<的TextView
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    机器人:文本=@字符串/ replacement_fragment/>

< /的FrameLayout>
 

解决方案

答案很简单。 UI状态保持整个屏幕旋转意思是,如果你什么也不做,屏幕仍然显示第二个片段,一旦你旋转。既然你在你的活动添加的第一个片段onCreate方法将被添加到什么是已经因此显示的两个片段重叠。

您可以做这样的事情:

  FragmentManager经理= getFragmentManager();
如果(mgr.findFragmentByTag(开始)== NULL和放大器;&安培;
    mgr.findFragmentByTag(replacementTest)== NULL){

    FragmentTransaction T = mgr.beginTransaction();
    t.add(R.id.fragment_container,startingFragment,开始)提交()。

}
 

I have put together a simple program that uses fragment replacement with a single activity and two fragments. One fragment has a button, that when pressed, replaces the fragment with a second fragment.

This works as expected if the application is started and the button is clicked.

If the application is started, the device is rotated (either to landscape or continuing back to portrait), and the button is clicked, then the fragment replacement fails with both fragments being displayed simultaneously.

What is going on here? Is there fragment lifecycle issue I am failing to address?

MainActivity.java

package edu.mindlab.fragmenttest;

import android.app.FragmentTransaction;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;


public class MainActivity extends ActionBarActivity{
    private MainActivityFragment startingFragment;
    private ReplacementFragment replacementFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startingFragment = new MainActivityFragment();
        replacementFragment = new ReplacementFragment();

        FragmentTransaction t = getFragmentManager().beginTransaction();
        t.add(R.id.fragment_container, startingFragment, "start").commit();
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void replaceFragment(View view){
        if(!replacementFragment.isAdded()) {
            FragmentTransaction t = getFragmentManager().beginTransaction();
            t.replace(R.id.fragment_container, replacementFragment, "replacementTest").commit();
        }
    }
}

MainActivityFragment.java

package edu.mindlab.fragmenttest;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MainActivityFragment extends Fragment {
    public MainActivityFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_main, container, false);

        return view;
    }
}

ReplacementFragment.java

package edu.mindlab.fragmenttest;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class ReplacementFragment extends Fragment {

    public static ReplacementFragment newInstance() {
        ReplacementFragment fragment = new ReplacementFragment();
        return fragment;
    }

    public ReplacementFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_replacement, container, false);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

}

activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:id="@+id/fragment_container">
</FrameLayout>

fragment_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            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=".MainActivityFragment">

<TextView
    android:text="@string/start_string"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/textView"/>

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/replacement_fragment"
    android:id="@+id/button"
    android:layout_below="@+id/textView"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_marginTop="56dp"
    android:onClick="replaceFragment"/>


</RelativeLayout>

fragment_replacement.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:tools="http://schemas.android.com/tools"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         tools:context="edu.mindlab.fragmenttest.ReplacementFragment">

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="@string/replacement_fragment"/>

</FrameLayout>

解决方案

The answer is simple. UI state is retained across screen rotations meaning if you do nothing the screen would still show the second fragment once you rotate. Since you add the first fragment in your Activity onCreate method it will be added to what is already shown hence the two fragments overlap.

You could do something like this:

FragmentManager mgr = getFragmentManager();
if (mgr.findFragmentByTag("start") == null &&
    mgr.findFragmentByTag("replacementTest") == null) {

    FragmentTransaction t = mgr.beginTransaction();
    t.add(R.id.fragment_container, startingFragment, "start").commit();             

}

这篇关于为什么旋转事业的Andr​​oid片段置换失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆