繁体   English   中英

Android-将片段重新加载到ViewPager中

[英]Android - Reload Fragment into a ViewPager

我正在构建一个从SQLite本地数据库提取数据的应用程序。

我有一个Activity,在其中使用ViewPager 在此ViewPager中,有12个可滑动片段。

我想实现一个“ 重新加载 ”按钮,该按钮允许用户重新加载实际的Fragments,删除用户修改引起的任何更改并恢复Fragment的原始状态。

我尝试在myAdapter( FragmentStatePagerAdapter的扩展notifyDataSetChanged()上使用notifyDataSetChanged()方法,即使它应该重新加载整个寻呼机:此方法也可以工作(每个Fragment重新加载),但是不会删除用户修改(例如,如果我得到一个EditText)并且如果我替换了其文本,则按“重新加载”按钮不会恢复其原始状态)。

我还尝试按照建议替换getItemPosition()方法,但不能解决问题。

1)活动:

public class MyActivity extends AppCompatActivity {
//code
    ViewPager pager;
    MyAdapter adapter;
    TabLayout tabLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //...
        //Pager settings
        adapter = new Adapter(getSupportFragmentManager(),this);
        pager = (ViewPager) findViewById(R.id.pager);
        pager.setAdapter(adapter);
        //TabLayout settings
        tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
        tabLayout.setupWithViewPager(pager);
        //...
    }
    //...
    //Method called after clicking on 'Reload' button
    public void reloadFragment() {
        adapter.notifyDataSetChanged();
    }
}

2)转接器:

public class Adapter extends FragmentStatePagerAdapter {
    //...
    public Fragment getItem(int position) {
        Fragment f = null;
        switch (position) {
            case 0:
                f = new MyFragment01();
                break;
            //case from 0 to 11
        }
        return f;
    }
    //...
    @Override
    public int getItemPosition( Object object ) {
        return POSITION_NONE;
    }

3)MyFragment01(12之1):

import android.support.v4.app.Fragment;
//...
public class MyFragment01 extends Fragment {
    PopulateEditText editText01;
    public MyFragment01() {
        //Empty constructor used to load from MyActivity
    }
    @Override
    public void onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //...
        View myFragmentView = inflater.inflate(R.layout.layout_fragment_01, container, false);
        //...
        acquire(myFragmentView); //Acquire layout elements (EditTexts, Spinners, other)
        populate(); //Insert text on previous layout elements, based on SQLite data
        //...
        //'Reload' button
        ImageButton test = (ImageButton) myFragmentView.findViewById(R.id.testBtn);
        test.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((MyActivity)getActivity()).reloadFragment();
             }
            });
        }
    }
}

编辑#1 (关于用户yshahak的问题)

3b)详细的方法acquire(myFragmentView); 来自MyFragment01 ,它被称为使元素膨胀:

public void acquire(View myFragmentView) {
    editText01 = new PopulateEditText(R.id.editText01,myFragmentView);
    //...
}
public void populate() {
    //cursor is a cursor which extracts a record from SQLite Database
    //column is an attribute of this record
    editText01.initializeEditText(cursor,"column",true);
    //...
}

4)PopulateEditText类:

public class PopulateEditText {
    EditText editText;
    Activity activity;
    //Constructor
    public PopulateEditText(int elementFromLayout, View myFragmentView) {
        this.editText=(EditText) myFragmentView.findViewById(elementFromLayout);
        reset();
    }
    public void reset() {
        if(editText!=null)
            editText.setText("");
    }

    public void initializeEditText(Cursor c, String column, boolean enableEditText) {
        this.column=column;
        String s = c.getString(c.getColumnIndex(column));
        editText.setText(s);
        editText.setSelection(editText.getText().length());
        editText.setEnabled(enableEditText);
    }
}

编辑#2
当我按下“重新加载”按钮时,这些方法从MyFragment01中调用(在调试时通过一些断点检查):
1. onCreateView
2. acquire(myFragmentView)
3. populate()
并且,如果我检查了EditText的文本, ViewPager正确地将其重新加载到起始值,因此似乎已重新加载了“新片段”,但未附加到ViewPager元素上。

例:
-起始值: 文字
-修改值: 文字1234
-点击“重新加载”,实际值: 文本1234
-EditText中的getText()。toString(): 文本 (预期结果,未在实际视图中显示)

让我们尝试慢慢看一下:

当您按下“测试”按钮时,发生的事情是adpater将所有片段都带进去,并问自己如何处理它们。 如果使用FragmentPageAdapter,则因为定义了它将抛出它们(带有“ POSITION_NONE”),所以它将通过调用getItem()来重新加载所有Fragment。

但是由于使用FragmentStatePagerAdapter扩展,因此尝试使用旧的Fragments,因此保留了旧的修改。

所以基本上我认为您替换为FragmentPageAdapter的id应该可以使用。

请记住,仅因为您要更新其中一个片段,这种方法才能真正有效地重新加载所有片段。

我找到了解决问题的方法。 Adapter内部,我将FragmentManager fm添加为构造函数中的变量:

FragmentManager fm;
public Adapter(FragmentManager fm, Activity activity) {
    super(fm);
    this.fm=fm;
    this.context=activity.getApplicationContext();
    this.activity=activity;
}

MyActivity内部,我已经以这种方式编辑了reloadFragment()方法,现在FragmentManager可用了:

public void reloadFragment(int position) {
    Adapter adapter = (Adapter)pager.getAdapter();
    //This list contains a 'list' of Fragments available on ViewPager adapter. 
    List<Fragment> list = adapter.fm.getFragments();
    switch(position) {
        case 0:
            ((MyFragment01)list.get(position)).populate();
            break;
        //iterate for case from 0 to 11
    }
 }

在每个Fragment上调用我的populate()自定义方法,每个EditText(和常规元素)都将正确恢复到其原始值。

当我单击“重新加载”按钮时,将提供reloadFragment(int position)的参数position reloadFragment(int position) 我在通用类上移动了该方法,以便从我想要的每个片段中调用它。 因此,我需要在参数中添加视图和活动:

public static void reloadButton(View myFragmentView, final Activity activity, final int position) {
    ImageButton test = (ImageButton) myFragmentView.findViewById(R.id.reloadBtn);
    test.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ((MyActivity)activity).reloadFragment(position);
        }
    });
}

也许这不是有史以来最有效的解决方案,如果我能找到更好的一般解决方案,我会在这里发布

编辑#1 :我必须修改实现控件的方式,正如yshahak告诉我的那样,List并不是解决我的问题的好方法。 这就是为什么当我打开活动时,片段未按顺序(从0到11)附加,而是“按需”附加的原因。 因此,如果我打开活动并直接滑动到第11个片段,则它将是元素编号3而不是11(因为我的活动仅缓存前两个2个片段onCreate)。 我将寻找另一个解决方案,我将在这里更新

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM