bar*_*ide 141 android android-adapter android-fragments android-viewpager android-listfragment
我正在使用Android中的v4兼容性ViewPager.我的FragmentActivity有一堆数据,可以在我的ViewPager中的不同页面上以不同的方式显示.到目前为止,我只有3个相同的ListFragment实例,但将来我将有3个不同的ListFragments实例.ViewPager位于垂直电话屏幕上,列表不是并排的.
现在,ListFragment上的一个按钮启动一个单独的整页活动(通过FragmentActivity),它返回并且FragmentActivity修改数据,保存数据,然后尝试更新其ViewPager中的所有视图.就在这里,我被卡住了.
public class ProgressMainActivity extends FragmentActivity
{
MyAdapter mAdapter;
ViewPager mPager;
@Override
public void onCreate(Bundle savedInstanceState)
{
...
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.viewpager);
mPager.setAdapter(mAdapter);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
...
updateFragments();
...
}
public void updateFragments()
{
//Attempt 1:
//mAdapter.notifyDataSetChanged();
//mPager.setAdapter(mAdapter);
//Attempt 2:
//HomeListFragment fragment = (HomeListFragment) getSupportFragmentManager().findFragmentById(mAdapter.fragId[0]);
//fragment.updateDisplay();
}
public static class MyAdapter extends FragmentPagerAdapter implements
TitleProvider
{
int[] fragId = {0,0,0,0,0};
public MyAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public String getTitle(int position){
return titles[position];
}
@Override
public int getCount(){
return titles.length;
}
@Override
public Fragment getItem(int position)
{
Fragment frag = HomeListFragment.newInstance(position);
//Attempt 2:
//fragId[position] = frag.getId();
return frag;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE; //To make notifyDataSetChanged() do something
}
}
public class HomeListFragment extends ListFragment
{
...
public static HomeListFragment newInstance(int num)
{
HomeListFragment f = new HomeListFragment();
...
return f;
}
...
Run Code Online (Sandbox Code Playgroud)
现在你可以看到,我的第一次尝试是整个FragmentPagerAdapter上的notifyDataSetChanged,这有时会显示更新数据,但是其他人我得到了IllegalStateException:在onSaveInstanceState之后无法执行此操作.
我的第二次尝试调用我的ListFragment中调用更新函数,但getItem中的getId返回0.根据我尝试过的文档
使用findFragmentById()或findFragmentByTag()从FragmentManager获取对Fragment的引用
但我不知道我的碎片的标签或ID!我有一个用于ViewPager的android:id ="@ + id/viewpager",以及一个用于ListFragment布局中我的ListView的android:id ="@ android:id/list",但我不认为这些是有用的.
那么,我怎么能:a)一次性安全地更新整个ViewPager(理想情况下将用户返回到之前的页面) - 用户可以看到视图更改.或者最好是,b)在每个受影响的ListFragment中调用一个函数来手动更新ListView.
任何帮助都将被感激地接受!
Pēt*_*une 253
Barkside的答案适用FragmentPagerAdapter但不起作用FragmentStatePagerAdapter,因为它没有在传递给它的片段上设置标签FragmentManager.
随着FragmentStatePagerAdapter我们似乎可以得到通过,使用其instantiateItem(ViewGroup container, int position)电话.它返回对位置的片段的引用position.如果FragmentStatePagerAdapter已经存在对有问题的片段的引用,instantiateItem则只返回对该片段的引用,并且不再调用getItem()它来实例化它.
所以,假设我正在查看片段#50,并希望访问片段#49.由于它们很接近,#49很可能已经被实例化.所以,
ViewPager pager = findViewById(R.id.viewpager);
FragmentStatePagerAdapter a = (FragmentStatePagerAdapter) pager.getAdapter();
MyFragment f49 = (MyFragment) a.instantiateItem(pager, 49)
Run Code Online (Sandbox Code Playgroud)
bar*_*ide 153
好吧,我想我已经找到了一种在我自己的问题中执行请求b)的方法,所以我会分享其他人的利益.一个ViewPager内部片段的标记的形式为"android:switcher:VIEWPAGER_ID:INDEX",其中VIEWPAGER_ID是R.id.viewpager在XML布局,并且指数为viewpager的位置.因此,如果位置已知(例如0),我可以执行updateFragments():
HomeListFragment fragment =
(HomeListFragment) getSupportFragmentManager().findFragmentByTag(
"android:switcher:"+R.id.viewpager+":0");
if(fragment != null) // could be null if not instantiated yet
{
if(fragment.getView() != null)
{
// no need to call if fragment's onDestroyView()
//has since been called.
fragment.updateDisplay(); // do what updates are required
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道这是否是一种有效的方式,但它会做到更好的建议.
fay*_*lon 58
每次实例化Fragement时尝试记录标记.
public class MPagerAdapter extends FragmentPagerAdapter {
private Map<Integer, String> mFragmentTags;
private FragmentManager mFragmentManager;
public MPagerAdapter(FragmentManager fm) {
super(fm);
mFragmentManager = fm;
mFragmentTags = new HashMap<Integer, String>();
}
@Override
public int getCount() {
return 10;
}
@Override
public Fragment getItem(int position) {
return Fragment.instantiate(mContext, AFragment.class.getName(), null);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Object obj = super.instantiateItem(container, position);
if (obj instanceof Fragment) {
// record the fragment tag here.
Fragment f = (Fragment) obj;
String tag = f.getTag();
mFragmentTags.put(position, tag);
}
return obj;
}
public Fragment getFragment(int position) {
String tag = mFragmentTags.get(position);
if (tag == null)
return null;
return mFragmentManager.findFragmentByTag(tag);
}
}
Run Code Online (Sandbox Code Playgroud)
Fra*_*ank 35
如果你问我,下面的第二个解决方案,跟踪所有"活动"片段页面,更好:http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part -ii.html
来自barkside的答案对我来说太难了.
您可以跟踪所有"活动"片段页面.在这种情况下,您将跟踪ViewPager使用的FragmentStatePagerAdapter中的片段页面.
private final SparseArray<Fragment> mPageReferences = new SparseArray<Fragment>();
public Fragment getItem(int index) {
Fragment myFragment = MyFragment.newInstance();
mPageReferences.put(index, myFragment);
return myFragment;
}
Run Code Online (Sandbox Code Playgroud)
为了避免保留对"非活动"片段页面的引用,我们需要实现FragmentStatePagerAdapter的destroyItem(...)方法:
public void destroyItem(View container, int position, Object object) {
super.destroyItem(container, position, object);
mPageReferences.remove(position);
}
Run Code Online (Sandbox Code Playgroud)
...当您需要访问当前可见的页面时,您可以调用:
int index = mViewPager.getCurrentItem();
MyAdapter adapter = ((MyAdapter)mViewPager.getAdapter());
MyFragment fragment = adapter.getFragment(index);
Run Code Online (Sandbox Code Playgroud)
... MyAdapter的getFragment(int)方法如下所示:
public MyFragment getFragment(int key) {
return mPageReferences.get(key);
}
Run Code Online (Sandbox Code Playgroud)
"
Rya*_*n R 13
好的,在上面的@barkside测试方法后,我无法使用我的应用程序.然后我记得IOSched2012应用程序也使用了一个viewpager,这就是我找到解决方案的地方.它不使用任何片段ID或标签,因为它们不viewpager以易于访问的方式存储.
以下是IOSched应用HomeActivity 的重要部分.特别注意评论,其中有关键:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Since the pager fragments don't have known tags or IDs, the only way to persist the
// reference is to use putFragment/getFragment. Remember, we're not persisting the exact
// Fragment instance. This mechanism simply gives us a way to persist access to the
// 'current' fragment instance for the given fragment (which changes across orientation
// changes).
//
// The outcome of all this is that the "Refresh" menu button refreshes the stream across
// orientation changes.
if (mSocialStreamFragment != null) {
getSupportFragmentManager().putFragment(outState, "stream_fragment",
mSocialStreamFragment);
}
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (mSocialStreamFragment == null) {
mSocialStreamFragment = (SocialStreamFragment) getSupportFragmentManager()
.getFragment(savedInstanceState, "stream_fragment");
}
}
Run Code Online (Sandbox Code Playgroud)
并将您的实例存储Fragments在FragmentPagerAdapter类似的内容中:
private class HomePagerAdapter extends FragmentPagerAdapter {
public HomePagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return (mMyScheduleFragment = new MyScheduleFragment());
case 1:
return (mExploreFragment = new ExploreFragment());
case 2:
return (mSocialStreamFragment = new SocialStreamFragment());
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
此外,请记住保护您的Fragment电话:
if (mSocialStreamFragment != null) {
mSocialStreamFragment.refresh();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
70278 次 |
| 最近记录: |