【问题标题】:Fragment methods are not getting called片段方法没有被调用
【发布时间】:2015-12-21 15:57:41
【问题描述】:

我已经实现了Android Studio 1.5.1 中给出的导航抽屉

  • 我有 5 个导航抽屉项目,每个项目都有一个片段。每个 Fragment 都有 Share 方法(不常见)。
  • 在第一个导航抽屉项目的片段中,可以说 OldStory 片段,我正在使用 Viewpager 进行滑动视图,该视图由 3 个片段和 FragmentStatePagerAdapter 组成。它有 Share 方法。

问题 - Story Fragment 的共享方法每次都会被调用,即使屏幕上显示了其他片段。调试后,我知道 Story 片段中的方法被调用了。 - 如果我禁用 OldStory Fragment,那么一切正常。

我无法解决这个问题。我读了很多问题/答案,但它们与活动和片段方法有关。请帮我解决这个问题。

注意 - OldStory 片段具有扩展 FragmentStatePagerAdapter 类的内部类。此类创建许多故事片段。其他实现方式相同。

public class OldStory extends Fragment {

private StoryPagerAdapter storyPagerAdapter;
private InfiniteViewPager viewPager;
SharedPreferences sharedPreferences;
private int TotalCount;

public OldStory() {
    // Required empty public constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Notify the system to allow an options menu for this fragment.

}



@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    final View rootView = inflater.inflate(R.layout.fragment_old_story, container, false);
    viewPager = (InfiniteViewPager) rootView.findViewById(R.id.pager);
    viewPager.setOffscreenPageLimit(0);
    sharedPreferences = getActivity().getSharedPreferences(Startup.PreferenceSETTINGS, Context.MODE_PRIVATE);
    TotalCount = sharedPreferences.getInt(Startup.StoryCount, 4);
    storyPagerAdapter = new StoryPagerAdapter(getFragmentManager());
    PagerAdapter wrappedAdapter = new InfinitePagerAdapter(storyPagerAdapter);
    viewPager.setAdapter(wrappedAdapter);
    viewPager.setCurrentItem(TotalCount-1);

    return rootView;
}

public class StoryPagerAdapter extends FragmentStatePagerAdapter {
    public StoryPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {

        return Story.newInstance(position+1);
    }

    @Override
    public int getCount() {
        return TotalCount;
    }
}
}

故事片段方法实现 -

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    menu.clear();
    inflater.inflate(R.menu.story, menu);
    getActivity().getMenuInflater().inflate(R.menu.main, menu);
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.Refresh:
            // We make sure that the SwipeRefreshLayout is displaying it's refreshing indicator
            if(!visiblity) {
                if (!RefreshLayout.isRefreshing()) {
                    ErrorLayout.setVisibility(View.GONE);
                    RefreshLayout.setRefreshing(true);
                }

                // Start our refresh background task
                initiateRequest(Today);
            }
            return true;

        case R.id.Share:
            //InShort = sharedPreferences.getString(Startup.InShort, null);
            Toast.makeText(getContext(), "Stories", Toast.LENGTH_SHORT).show();
            if (InShort!= null && !InShort.isEmpty())
            {

                Intent sendIntent = new Intent(Intent.ACTION_SEND);
                sendIntent.putExtra(Intent.EXTRA_TEXT, "Hi From Story");
                sendIntent.setType("text/plain");
                startActivity(sendIntent);
            }

            return true;

        default:
            return super.onOptionsItemSelected(item);
    }


}

MainActivity用于切换片段。

public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    displayView(item.getItemId());

    return true;
}

//method to replace Views in ID = content_frame in content_main
public void displayView(int viewID)
{
    fragment = null;
    title = getString(R.string.app_name);

    switch (viewID)
    {
        case R.id.nav_frag0:
            fragment = new OldStory();
            title = getString(R.string.story);
            viewIsAtHome = true;
            break;

        case R.id.nav_frag1:
            fragment = new Fragment1();
            title = getString(R.string.fragment1);
            viewIsAtHome = false;
            break;

        case R.id.nav_frag2:
            fragment = new Fragment2();
            title = getString(R.string.fragment2);
            viewIsAtHome = false;
            break;

        case R.id.nav_frag3:
            fragment = new Fragment3();
            title = getString(R.string.fragment3);
            viewIsAtHome = false;
            break;

        case R.id.nav_frag4:
            fragment = new Fragment4();
            viewIsAtHome = false;
            title = getString(R.string.fragment4);
            break;

        case R.id.nav_share:
            fragment = new Fragment5();
            title = getString(R.string.fragment5);
            viewIsAtHome = false;
            break;

    }

    if (fragment != null)
    {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.content_frame,fragment);
        ft.commit();
    }

    //set the toolbar title
    if(getSupportActionBar() != null)
    {
        getSupportActionBar().setTitle(title);
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
}

【问题讨论】:

  • 你能添加你如何初始化和切换片段的代码吗?我是对的,问题是一旦您通过 NavigationDrawer 切换到另一个片段,嵌套在 ViewPager 片段中仍然会得到onOptionsItemSelected 调用?
  • 到目前为止,您似乎面临同样的问题,如下所示:stackoverflow.com/a/34401646/1658267 不过,最好有更多的上下文来确定
  • 还有一件事 - 你如何使用setHasOptionsMenu()
  • @KonstantinLoginov 我已经用 MainActivity 代码更新了我的问题。
  • 没有 setHasOptionsMenu() 你永远不会得到菜单被夸大。但是在代码 sn-ps 中,我没有看到这个方法被调用。如果你愿意,我可以上传带有 viewpagers、不同 Fragment 和 NavigationDrawer 的测试项目,这样你就可以尝试看看可能的差异..

标签: android android-fragments android-viewpager


【解决方案1】:

我不确定这是否真的是您问题的答案,但我注意到您的代码中有一个错误:

storyPagerAdapter = new StoryPagerAdapter(getFragmentManager());

将无法正常工作,因为您需要使用getChildFragmentManager() 来管理片段中的片段。

【讨论】:

    【解决方案2】:

    我试图重现您的问题并编写了这个应用程序,据我所知,这是复制您应用程序的行为:

    我已将它的源代码上传到我的 Dropbox - feel free to check it out

    如您所见,片段可以正确处理分享按钮的点击。 总是有机会,我没有完全理解你的问题,但我是这样做的:

    膨胀此菜单的所有片段(但具有不同的onOptionsItemSelected):

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <item
            android:id="@+id/nav_share"
            android:icon="@drawable/ic_menu_share"
            app:showAsAction="always"
            android:title="Share" />
    </menu>
    

    FragmentA 中我的 SubFragment 类(我在 ViewPager 中使用的类):

    public class SubFragment extends Fragment {
    
        String msg;
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.subfragmnet, container, false);
            setHasOptionsMenu(true);
            rootView.findViewById(R.id.subfragmentFrameLayout).setBackgroundColor(getArguments().getInt("background"));
            msg = getArguments().getString("msg");
            return rootView;
        }
    
        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            inflater.inflate(R.menu.menu_fragment, menu);
            super.onCreateOptionsMenu(menu, inflater);
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            if (item.getItemId() == R.id.nav_share) {
                Snackbar.make(getView(), "Hello from SubFragment " + msg, Snackbar.LENGTH_LONG).show();
            }
    
            return super.onOptionsItemSelected(item);
        }
    }
    

    FragmentA,第一个Fragment,承载ViewPager并嵌套Fragments:

    public class FragmentA extends Fragment {
    
        PagerAdapter pagerAdapter;
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_a, container, false);
    
            Bundle bundle1 = new Bundle();
            bundle1.putInt("background", Color.RED);
            bundle1.putString("msg", "page 1");
    
            Bundle bundle2 = new Bundle();
            bundle2.putInt("background", Color.YELLOW);
            bundle2.putString("msg", "page 2");
    
            Bundle bundle3 = new Bundle();
            bundle3.putInt("background", Color.BLUE);
            bundle3.putString("msg", "page 3");
    
            Fragment[] fragments = {
                    Fragment.instantiate(getContext(), SubFragment.class.getName(), bundle1),
                    Fragment.instantiate(getContext(), SubFragment.class.getName(), bundle2),
                    Fragment.instantiate(getContext(), SubFragment.class.getName(), bundle3),
            };
    
            if (pagerAdapter == null) {
                pagerAdapter = new PagerAdapter(getChildFragmentManager(), fragments);
            }
    
            ViewPager viewPager = (ViewPager)rootView.findViewById(R.id.viewPager);
            viewPager.setAdapter(pagerAdapter);
    
            return rootView;
        }
    }
    

    FragmentB(和FragmentC几乎一样):

    public class FragmentB extends Fragment {
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            setHasOptionsMenu(true);
            return inflater.inflate(R.layout.fragment_b, container, false);
        }
    
        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            inflater.inflate(R.menu.menu_fragment, menu);
            super.onCreateOptionsMenu(menu, inflater);
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            if (item.getItemId() == R.id.nav_share) {
                Toast.makeText(getContext(), "Hello from Fragment B", Toast.LENGTH_LONG).show();
            }
    
            return super.onOptionsItemSelected(item);
        }
    }
    

    Hosting Activity 是标准 NavigationDrawer Activity,它在 Drawer 的项目点击时切换 Fragments。

    public class MainActivity extends AppCompatActivity
            implements NavigationView.OnNavigationItemSelectedListener {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
    
            ....
    
            getSupportFragmentManager().beginTransaction().replace(R.id.container, Fragment.instantiate(this, FragmentA.class.getName())).commit();
        }
    
        ...
    
        @SuppressWarnings("StatementWithEmptyBody")
        @Override
        public boolean onNavigationItemSelected(MenuItem item) {
            int id = item.getItemId();
    
            if (id == R.id.nav_camera) {
                getSupportFragmentManager().beginTransaction().replace(R.id.container, Fragment.instantiate(this, FragmentA.class.getName())).commit();
            } else if (id == R.id.nav_gallery) {
                getSupportFragmentManager().beginTransaction().replace(R.id.container, Fragment.instantiate(this, FragmentB.class.getName())).commit();
            } else if (id == R.id.nav_slideshow) {
                getSupportFragmentManager().beginTransaction().replace(R.id.container, Fragment.instantiate(this, FragmentC.class.getName())).commit();
            }
    
            DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
            drawer.closeDrawer(GravityCompat.START);
            return true;
        }
    }
    

    如果我正确理解了您的问题,请告诉我!

    无论如何,我希望它会有所帮助。

    【讨论】:

    • 实际上与这个问题一起的确切问题在这里:stackoverflow.com/questions/34349728/…
    • @Roon13 我不明白。我的示例中没有菜单重复? (即使我将 PagerAdapterFragmentPagerAdapter 更改为 FragmentStatePagerAdapter
    • 是的,但我在相同的实现中遇到了这个问题。这就是为什么我很难理解。
    • @Roon13 您可以浏览我的代码 - 它非常简单,因此您可以将其用作指南。例如,据我所见,您在 StoryFragment 中膨胀了两次,而我只做了一次。
    • 我只对 StoryFragment 进行了一次膨胀。如果我在某个地方错过了,你能指出来吗??
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 2014-06-02
    相关资源
    最近更新 更多