[英]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.