Updating a ListView inside a Fragment placed on a ViewPager on DialogFragment dismiss
2014-05-10 06:25
337 查看
Title says all. We’ll see today how to proceed in order to update a ListView that is placed inside a Fragment (not a ListFragment) placed on a ViewPager just after dismissing
aDialogFragment. Seems complicated, huh?
Well, imagine that you have an Activity which layout uses tabs (represented by Fragments) and you want to use a ViewPager so it feels better to users. With a ViewPager you
can swipe tabs, and that make users happy. Now, think about your Activity’s tabs: you may have three or four and one of them may be a ListView.
Finally, imagine that this ListView is updated every time user inputs data that is stored into a database. The user inputs data using a button that presents a Dialog with buttons or whatever the app needs to show.
When the user pushes the OK button, the Dialog will call onDismiss(). And the ListView should update here, but it won’t do unless you notify it that there are changes.
It’s really easy, but it may be confusing sometimes. We will consider that you created a project using Android Studio wizards and that you selected “Tabs+Swipe” navigation option. Take a look at your main Activity, there should be a custom FragmentPagerAdapter.
We’ll make it “remember” your fragments. You can achieve this saving all yourFragments as individual objects or use an array. For example:
You just have to override destroyItem() and edit getItem() to handle when we modify the array. Also add getRegisteredFragment() so we can access the fragment array.
Now, on your DialogFragment, declare a new interface and use it on the onDismiss() method. Like this:
Call it whatever you want and don’t forget to use onAttach() to be sure that your Activity is acting correctly. For this to happen you have to implement it on your Activity. So, add implements DialogFragmentName.OnDBChangedListener to
your Activity declaration. Also, implement your interface method and use it to call a (yet to write) public method of your ListView fragment.
Finally, add a public method to your ListView fragment or the Activity will not be able to finish the job : ) Something like this will work if you are using SQLite databases:
That’s it! Hope it helped someone : )
aDialogFragment. Seems complicated, huh?
When may we need this?
Well, imagine that you have an Activity which layout uses tabs (represented by Fragments) and you want to use a ViewPager so it feels better to users. With a ViewPager youcan swipe tabs, and that make users happy. Now, think about your Activity’s tabs: you may have three or four and one of them may be a ListView.
Finally, imagine that this ListView is updated every time user inputs data that is stored into a database. The user inputs data using a button that presents a Dialog with buttons or whatever the app needs to show.
When the user pushes the OK button, the Dialog will call onDismiss(). And the ListView should update here, but it won’t do unless you notify it that there are changes.
Nice. How do we do that?
It’s really easy, but it may be confusing sometimes. We will consider that you created a project using Android Studio wizards and that you selected “Tabs+Swipe” navigation option. Take a look at your main Activity, there should be a custom FragmentPagerAdapter.We’ll make it “remember” your fragments. You can achieve this saving all yourFragments as individual objects or use an array. For example:
1 public class MyPagerAdapter extends FragmentPagerAdapter { 2 3 SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>(); 4 5 ... 6 7 @Override 8 public Fragment getItem(int position) { 9 // getItem is called to instantiate the fragment for the given 10 // page. 11 Fragment fragment = new MyFragment(); 12 Bundle args = new Bundle(); 13 args.putInt(SectionFragment.ARG_SECTION_NUMBER, position + 1); 14 fragment.setArguments(args); 15 registeredFragments.put(position, fragment); 16 return fragment; 17 } 18 19 20 @Override 21 public void destroyItem(ViewGroup container, int position, Object object) { 22 registeredFragments.remove(position); 23 super.destroyItem(container, position, object); 24 } 25 26 public Fragment getRegisteredFragment(int position) { 27 return registeredFragments.get(position); 28 } 29 30 ... 31 32 }
You just have to override destroyItem() and edit getItem() to handle when we modify the array. Also add getRegisteredFragment() so we can access the fragment array.
Now, on your DialogFragment, declare a new interface and use it on the onDismiss() method. Like this:
1 public class MyDialogFragment extends DialogFragment implements 2 DialogInterface.OnDismissListener{ 3 4 5 private OnDBChangedListener mCallback; 6 7 ... 8 9 @Override 10 public void onDismiss(DialogInterface dialog) { 11 mCallback.onDBChanged(); 12 super.onDismiss(dialog); 13 } 14 15 // Container Activity must implement this interface 16 public interface OnDBChangedListener { 17 public void onDBChanged(); 18 } 19 20 @Override 21 public void onAttach(Activity activity) { 22 super.onAttach(activity); 23 24 // This makes sure that the container activity has implemented 25 // the callback interface. If not, it throws an exception 26 try { 27 mCallback = (OnDBChangedListener) activity; 28 } catch (ClassCastException e) { 29 throw new ClassCastException(activity.toString() + " must implement 30 OnDBChangedListener"); 31 } 32 } 33 }
Call it whatever you want and don’t forget to use onAttach() to be sure that your Activity is acting correctly. For this to happen you have to implement it on your Activity. So, add implements DialogFragmentName.OnDBChangedListener to
your Activity declaration. Also, implement your interface method and use it to call a (yet to write) public method of your ListView fragment.
1 public class MainActivity extends Activity implements ActionBar.TabListener, 2 MyDialogFragment.OnDBChangedListener{ 3 ... 4 @Override 5 public void onDBChanged() { 6 SectionFragment sFrag = 7 (SectionFragment)mSectionsPagerAdapter.getRegisteredFragment(1); 8 sFrag.updateDB(); 9 } 10 }
Finally, add a public method to your ListView fragment or the Activity will not be able to finish the job : ) Something like this will work if you are using SQLite databases:
1 public void updateDB() { 2 if(dataSource!=null) { 3 ListView lView = (ListView)rootView.findViewById(R.id.listView); 4 dataSource.open(); 5 6 List<Foo> foos = dataSource.getAllFoos(); 7 adapter = new ArrayAdapter<Foo>(context, 8 android.R.layout.simple_list_item_1, 9 foos); 10 lView.setAdapter(adapter); 11 dataSource.close(); 12 } 13 14 }
That’s it! Hope it helped someone : )
相关文章推荐
- ViewPager和Fragment的结合使用fragment里包含着listview的常见问题
- ViewPager加上Fragment 显示ListView
- ListView+Fragment+ViewPager配合,实现今日头条的效果
- viewpager中的ListView和fragment获取到设备后退键
- viewPagerFragment的子fragment的onActivityResult()无法执行调用问题解决方案
- Viewpager+Fragment滑动更改ListView数据和设置title文字的变化
- 底部弹出DialogFragment中使用ViewPager,ViewPager中使用Fragment出现Fragment does not have a view错误
- 关于Fragment中定义一个ListView,然后给这个ListView添加header(ViewPager)的问题
- ViewPager+Fragment+ListView打造新闻列表
- Android ViewPager>Fragment>Listview>addHeaderView添加轮播图隐藏bug
- scrollview+tablayout+viewpager+三个fragment+listview滑动冲突、展示不全
- 网络数据请求展示为无限轮播图 ViewPager+XListView+Fragment+ImageLoader
- viewpager+listview+fragment实现简单的滑动标签页
- 封装工具类MyTask+判断是否有网络+ViewPagerFragment+Xlistview多条目加载
- 占位布局之fragment01的布局---PullToRefreshScrollView+viewpager+listview
- Fragment+ViewPager 滑动时 onResume和onPause
- 网络请求(viewPager,Fragment,ListView)
- 用全屏DialogFragment代替Activity,结合ViewPager展示图片
- 介绍Fragment、ListView、ViewPager三者用法
- Android中ViewPager+Fragment预加载和onResume方法的问题