1

我有一个屏幕,用户按下一个按钮来调出一个DialogFragment带有EditText. 他们输入信息,然后按Ok。如果他们再次按下按钮,我已经做到了,因此EditText将显示他们刚刚输入的信息,并且一切正常。

但是,如果他们输入信息,按Ok,然后使用选项菜单去查看另一个屏幕/ ,一旦他们再次按该按钮fragment,信息将不会显示在其中。EditText

即使用户暂时离开该屏幕,我如何保存信息?我认为它需要newInstance片段类中的方法,然后调用托管活动newInstance而不是构造函数。但我不确定如何实现它。任何帮助表示赞赏。谢谢!

SingleFragmentActivity

public abstract class SingleFragmentActivity extends FragmentActivity
{
    protected abstract Fragment createFragment();

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);

        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);

        if (fragment == null)
        {
            fragment = createFragment();
            fm.beginTransaction()
                .add(R.id.fragmentContainer, fragment)
                .commit();
        }
    }
}

托管活动的相关代码,AdviceActivity:

public class AdviceActivity extends SingleFragmentActivity
{
    @Override
    protected Fragment createFragment()
    {
        return new AdviceFragment();
    }
}

托管片段 AdviceFragment 中的相关代码:

private boolean isTextButtonFirstClick = true;

...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
    mTextButton = (Button) v.findViewById(R.id.textButton);
    mTextButton.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v)
        {
            if (isTextButtonFirstClick)
            {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputTextFragment dialog = InputTextFragment.newInstance("", isTextButtonFirstClick);
                dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                dialog.show(fm, DIALOG_TEXT);
                isTextButtonFirstClick = false;
            }
            else
            {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputTextFragment dialog = InputTextFragment.newInstance(mAdvice.getText(), isTextButtonFirstClick);
                dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                dialog.show(fm, DIALOG_TEXT);
            }
        }
    });
...
}

来自 DialogFragment InputTextFragment 的相关代码:

public static InputTextFragment newInstance(String text, boolean isTextButtonFirstClick)
{
    Bundle args = new Bundle();
    args.putSerializable(EXTRA_TEXTBUTTON_FIRSTCLICK, isTextButtonFirstClick);
    args.putSerializable(EXTRA_TEXT, text);

    InputTextFragment fragment = new InputTextFragment();
    fragment.setArguments(args);

    return fragment;
}

...

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    ...

    boolean isTextButtonFirstClick = getArguments().getBoolean(EXTRA_TEXTBUTTON_FIRSTCLICK);

    final EditText editText = (EditText) v.findViewById(R.id.dialogInputEditText);
    if (!isTextButtonFirstClick)
    {
        editText.setText(text);
        editText.setSelection(text.length());
    }

    ...
}

XML 活动片段:

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

</RelativeLayout>
4

1 回答 1

1

听起来好像布尔值 isTextButtonFirstClick 被错误地设置为 false。

这意味着在导航期间创建了一个新的 Advice Fragment 实例。

尝试

  • 在 Advice Fragment 的 onCreate 中设置 setRetainInstance(true) 以保持布尔值。

  • 如果 R.id.fragmentContainer 是 XML 中的片段标记,则将其更改为 LinearLayout 或 RelativeLayout (无论如何您都在顶部添加片段,我怀疑 findFragmentById 总是返回 null)

  • 将 Activity 中的代码更改为:

    FragmentManager fm = getSupportFragmentManager();
    Fragment fragment = fm.findFragmentByTag("singleFragment");
    
    if (fragment == null)
    {
        fragment = createFragment();
    }
    
       fm.beginTransaction()
            .replace(R.id.fragmentContainer, fragment,  "singleFragment" )
            .commit();
    

通常在以编程方式添加片段时,您使用标签,而在 XML 中定义片段让 Android 框架处理生命周期时,您可以通过 id 找到它。

在我看来,好像您处于中间解决方案中,试图同时做这两个,但这不会按预期工作。

希望这可以帮助,如果有格式问题,请提前道歉。答案是通过电话写的:-)

编辑:

如果您只想保存简单类型的信息(例如布尔值),我会在这里向您指出我的旧答案之一:在旋转屏幕时将文本视图保存在片段中

您的最后一条评论显示您有一些复杂的信息(文本、照片、视频等)需要保留。

使所有这些 Parcelable 将是一个巨大的痛苦,所以这是我的第二个建议:

  1. 将 EventBus 添加到您的项目https://github.com/greenrobot/EventBus
  2. 为信息创建一个持有者类,例如

    public class AdviceHolder {
        private boolean isTextButtonFirstClick;
        private String text;
        private BitMap image;
        ... 
    
       // setter and getter methods (if using eclipse alt+shit+s 'create setter and getters from fields') 
    }
    
  3. 现在在启动 AdviceActivity 时,您准备了一个新的 AdviceHolder

    public class AdviceActivity extends SingleFragmentActivity
    {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            // make a new AdviceHolder if none existed
            AdviceHolder holder = new AdviceHolder();
            AdviceHolder existingHolder = EventBus.getDefault().getStickyEvent(AdviceHolder.class);
            if (existingHolder == null) {        
                 EventBus.getDefault().postSticky(holder);
            }
    
            super.onCreate(savedInstanceState);
        }
    
        @Override
        protected Fragment createFragment()
        {
            return new AdviceFragment();
        }
    }
    

此步骤将使 AdviceHolder 对象在您的代码中的任何位置都可用。将其视为一个全局存储库。

这意味着无论您如何在 Activites 或 Fragments 之间移动,它们都可以访问 AdviceHolder 并可以对其进行编辑。

因此,例如在您的 AdviceFragment 中:

private AdviceHolder holder;

...
@Override
public void onCreate (Bundle savedInstanceState) {
    AdviceHolder holder = (AdviceHolder)EventBus.getDefault().getStickyEvent(AdviceHolder.class);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
    // read isTextButtonFirstClick from holder
    boolean isTextButtonFirstClick = holder.isTextButtonFirstClick();

    mTextButton = (Button) v.findViewById(R.id.textButton);
    mTextButton.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v)
        {
            if (isTextButtonFirstClick)
            {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputTextFragment dialog = InputTextFragment.newInstance("", isTextButtonFirstClick);
                dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                dialog.show(fm, DIALOG_TEXT);

                // update isTextButtonFirstClick in holder
                holder.setTextButtonFirstClick(false);
                EventBus.getDefault().postStickyEvent(holder);
            }
            else
            {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputTextFragment dialog = InputTextFragment.newInstance(mAdvice.getText(), isTextButtonFirstClick);
                dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                dialog.show(fm, DIALOG_TEXT);
            }
        }
    });
...
}

当您在某个时候完成填充AdviceHolder(并将其发送到服务器或任何计划)时,将其从 EventBus 中删除以启用在AdviceActivity.

EventBus.getDefault().removeStickyEvent(AdviceHolder.class);

有关 EventBus 的其他示例,请查看http://www.stevenmarkford.com/passing-objects-between-android-activities/

这都是很多信息,希望不要太混乱。

于 2014-10-02T01:31:54.107 回答