Java Android中的片段和ViewPager

Java Android中的片段和ViewPager,java,android,android-viewpager,fragment,Java,Android,Android Viewpager,Fragment,我有一个ViewPager,允许用户在5个不同的视图之间滑动,每个“视图”扩展片段 我有自己的适配器,它扩展了FragmentPagerAdapter,并将getItem()实现为 这很好,用户可以在5个不同的视图之间滑动。但问题来了:前4个视图中的每一个都包含用户可以交互的视图,如Button和EditText 然后我希望最后一页(第5页)显示前4页(片段)中所有视图中的所有用户输入值。我该怎么做 我找不到任何方法从前面的片段中读取用户输入值。视图可能不再存在(但如果用户返回,将重新创建) 我

我有一个ViewPager,允许用户在5个不同的视图之间滑动,每个“视图”扩展片段

我有自己的适配器,它扩展了FragmentPagerAdapter,并将getItem()实现为

这很好,用户可以在5个不同的视图之间滑动。但问题来了:前4个视图中的每一个都包含用户可以交互的视图,如Button和EditText

然后我希望最后一页(第5页)显示前4页(片段)中所有视图中的所有用户输入值。我该怎么做

我找不到任何方法从前面的片段中读取用户输入值。视图可能不再存在(但如果用户返回,将重新创建)


我似乎无法得到现有的碎片

2个解决方案浮现在我脑海中

第一个是在调用前4个片段的onpause()方法时保存用户输入数据。您可以将数据保存到首选项,然后从第5个片段中检索它

第二种方法是在刷卡时保留碎片。这样刷卡会更快更干净,每次刷卡时都要重新创建碎片:

yourcustomviewpager.setOffscreenPageLimit(5);
关于setOffscreenPageLimit发件人:

设置在空闲状态下视图层次结构中当前页面两侧应保留的页数。超出此限制的页面将在需要时从适配器重新创建。 这是作为一种优化提供的。如果您事先知道需要支持的页面数量,或者页面上有延迟加载机制,调整此设置可以提高页面动画和交互的平滑度。如果您有少量页面(3-4个)可以同时保持活动状态,则在用户页面来回移动时,新创建的视图子树的布局所花费的时间将更少。 您应该将此限制保持在较低的水平,尤其是在页面布局复杂的情况下。此设置默认为1


我想到了两个解决办法

第一个是在调用前4个片段的onpause()方法时保存用户输入数据。您可以将数据保存到首选项,然后从第5个片段中检索它

第二种方法是在刷卡时保留碎片。这样刷卡会更快更干净,每次刷卡时都要重新创建碎片:

yourcustomviewpager.setOffscreenPageLimit(5);
关于setOffscreenPageLimit发件人:

设置在空闲状态下视图层次结构中当前页面两侧应保留的页数。超出此限制的页面将在需要时从适配器重新创建。 这是作为一种优化提供的。如果您事先知道需要支持的页面数量,或者页面上有延迟加载机制,调整此设置可以提高页面动画和交互的平滑度。如果您有少量页面(3-4个)可以同时保持活动状态,则在用户页面来回移动时,新创建的视图子树的布局所花费的时间将更少。 您应该将此限制保持在较低的水平,尤其是在页面布局复杂的情况下。此设置默认为1


我会考虑使用一个自定义对象来保持每个片段的数据填充。比如:

public class FillerData implements Parcelable {
    private String page0$data0;
    private String page0$data1;
    private String page0$data2;

    // getters and setters if you wish

    // implement Parcelable interface as this object will be managed by host activity
}
您只有一个这样的对象由父活动管理,父活动将实现一个用于公开此对象的接口:

public static interface FillerDataExposer {
    public FillerData exposeFiller();
}

public class MyFragmentHostActivity extends FragmentActivity implements FillerDataExposer {
    private static final String FILLER_KEY = "FILLER_KEY";
    private FillerData myFillerData;

    protected void onCreate(Bundle savedInstance) {
        .......
        if(savedInstance != null) {
            myFillerData = (FillerData) savedInstance.getParcelable(FILLER_KEY);
        } else {
            myFillerData = new FillerData();
        }
    }

    protected void onSaveInstanceState(Bundle savedInstance) {
        super.onSaveInstanceState();
        savedInstance.putExtra(FILLER_KEY, myFillerData);
    }

    public FillerData exposeFiller() {
        return this.myFillerData;
    }
}
现在,您的每个片段都可以通过父活动访问该集中式数据填充对象。为了减少代码的重量,您的所有片段都可以从提供对
FillerDataExposer
实现(实际上是父活动)的访问的基本片段类扩展:

只应记录填充数据的片段可能如下所示:

public class Page1Fragment extends AbstractFillerFragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = // inflate XML resource ...
        yourEditText = (EditText) view.findViewById(...);
        // other relevant code ....
    }

    public void onViewCreated(View view, Bundle savedInstanceState) {
       yourEditText.setText(dataExposer.exposeFiller.setPageX$DataY());
       // some code for EditText.addTextChangedListener(new TextWatcher() could look like:
        yourEditText.addTextChangedListener(new TextWatcher() {

          public void afterTextChanged(Editable s) {

            dataExposer.exposeFiller().setPage1$Data0(s.toString());

          }

          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          public void onTextChanged(CharSequence s, int start, int before, int count) {}
       });
    }
}
public class FinalFragment extends AbstractFillerFragment {
    public void collectAllData() {
        DataFiller allDataCollectedObject = dataExposer.exposeFiller();
        // by calling get...() you should have access to collected data.
    }
}
而需要访问所有存储数据的片段可能如下所示:

public class Page1Fragment extends AbstractFillerFragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = // inflate XML resource ...
        yourEditText = (EditText) view.findViewById(...);
        // other relevant code ....
    }

    public void onViewCreated(View view, Bundle savedInstanceState) {
       yourEditText.setText(dataExposer.exposeFiller.setPageX$DataY());
       // some code for EditText.addTextChangedListener(new TextWatcher() could look like:
        yourEditText.addTextChangedListener(new TextWatcher() {

          public void afterTextChanged(Editable s) {

            dataExposer.exposeFiller().setPage1$Data0(s.toString());

          }

          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          public void onTextChanged(CharSequence s, int start, int before, int count) {}
       });
    }
}
public class FinalFragment extends AbstractFillerFragment {
    public void collectAllData() {
        DataFiller allDataCollectedObject = dataExposer.exposeFiller();
        // by calling get...() you should have access to collected data.
    }
}
这只是个草图,但你会明白的。这样做的目的是在活动重新启动时管理活动中的单个对象,并通过接口使其可访问,这样您就可以尊重活动模式的片段


<>希望有意义…

我会考虑使用一个自定义对象来保持每个片段的数据填充。比如:

public class FillerData implements Parcelable {
    private String page0$data0;
    private String page0$data1;
    private String page0$data2;

    // getters and setters if you wish

    // implement Parcelable interface as this object will be managed by host activity
}
您只有一个这样的对象由父活动管理,父活动将实现一个用于公开此对象的接口:

public static interface FillerDataExposer {
    public FillerData exposeFiller();
}

public class MyFragmentHostActivity extends FragmentActivity implements FillerDataExposer {
    private static final String FILLER_KEY = "FILLER_KEY";
    private FillerData myFillerData;

    protected void onCreate(Bundle savedInstance) {
        .......
        if(savedInstance != null) {
            myFillerData = (FillerData) savedInstance.getParcelable(FILLER_KEY);
        } else {
            myFillerData = new FillerData();
        }
    }

    protected void onSaveInstanceState(Bundle savedInstance) {
        super.onSaveInstanceState();
        savedInstance.putExtra(FILLER_KEY, myFillerData);
    }

    public FillerData exposeFiller() {
        return this.myFillerData;
    }
}
现在,您的每个片段都可以通过父活动访问该集中式数据填充对象。为了减少代码的重量,您的所有片段都可以从提供对
FillerDataExposer
实现(实际上是父活动)的访问的基本片段类扩展:

只应记录填充数据的片段可能如下所示:

public class Page1Fragment extends AbstractFillerFragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = // inflate XML resource ...
        yourEditText = (EditText) view.findViewById(...);
        // other relevant code ....
    }

    public void onViewCreated(View view, Bundle savedInstanceState) {
       yourEditText.setText(dataExposer.exposeFiller.setPageX$DataY());
       // some code for EditText.addTextChangedListener(new TextWatcher() could look like:
        yourEditText.addTextChangedListener(new TextWatcher() {

          public void afterTextChanged(Editable s) {

            dataExposer.exposeFiller().setPage1$Data0(s.toString());

          }

          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          public void onTextChanged(CharSequence s, int start, int before, int count) {}
       });
    }
}
public class FinalFragment extends AbstractFillerFragment {
    public void collectAllData() {
        DataFiller allDataCollectedObject = dataExposer.exposeFiller();
        // by calling get...() you should have access to collected data.
    }
}
而需要访问所有存储数据的片段可能如下所示:

public class Page1Fragment extends AbstractFillerFragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = // inflate XML resource ...
        yourEditText = (EditText) view.findViewById(...);
        // other relevant code ....
    }

    public void onViewCreated(View view, Bundle savedInstanceState) {
       yourEditText.setText(dataExposer.exposeFiller.setPageX$DataY());
       // some code for EditText.addTextChangedListener(new TextWatcher() could look like:
        yourEditText.addTextChangedListener(new TextWatcher() {

          public void afterTextChanged(Editable s) {

            dataExposer.exposeFiller().setPage1$Data0(s.toString());

          }

          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          public void onTextChanged(CharSequence s, int start, int before, int count) {}
       });
    }
}
public class FinalFragment extends AbstractFillerFragment {
    public void collectAllData() {
        DataFiller allDataCollectedObject = dataExposer.exposeFiller();
        // by calling get...() you should have access to collected data.
    }
}
这只是个草图,但你会明白的。这样做的目的是在活动重新启动时管理活动中的单个对象,并通过接口使其可访问,这样您就可以尊重活动模式的片段


希望它有意义……

onpause技巧不起作用,因为在查看第4页(最后一页)时,第3页没有调用onpause。你说得对。因此,您可以在每次更改输入时保存输入(您应该为您的文本视图设置侦听器)。我真正需要的是一个fragmentNotVisibleAnymore()方法。我想我会尝试使用setOnPageChangeListener,它可以在每个片段中调用一个方法来收集所有数据。第二个方法只需一行代码,不需要将数据保存到首选项,也可以使滑动更加平滑。不管怎样,这是你的决定。按您认为最好的方式执行:)几乎正确,但第二种方法需要多4行代码,因为它还需要我缓存在m中创建的对象