Android 单击按钮时刷新片段视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12606831/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:10:55  来源:igfitidea点击:

Refresh fragment view when button is clicked

androidviewandroid-fragments

提问by a.p.

I have a fragment activity that uses a ViewPager to display a set of fragments. On the fragment activity I have a button that when clicked, it sends a message to the current fragment to refresh its contents. Everything works ok (activity / current fragment communication) except the fact that I cannot refresh the fragment's view. Accessing the current view by getView() does not work as this function returns null; it seems that after the fragment is created (on ViewCreated is called) getView gets destroyed. Am I missing something here? How to I cause a fragment to redraw its contents programmatically? It seems that the only way this works is when the fragment is created from the parent activity. Do I have to remove and re-add the fragment again to do this?

我有一个片段活动,它使用 ViewPager 来显示一组片段。在片段活动中,我有一个按钮,单击该按钮后,它会向当前片段发送一条消息以刷新其内容。一切正常(活动/当前片段通信),除了我无法刷新片段的视图。通过 getView() 访问当前视图不起作用,因为此函数返回 null;似乎在创建片段后(在 ViewCreated 上调用)getView 被销毁。我在这里错过了什么吗?如何使片段以编程方式重绘其内容?似乎唯一有效的方法是从父活动创建片段。我是否必须再次删除并重新添加片段才能执行此操作?

Here is the code:

这是代码:

The main activity:

主要活动:

public class MainActivity extends FragmentActivity {

    private MyAdapter mAdapter;
    private static ViewPager mPager;

        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                setupViewPager();
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                getMenuInflater().inflate(R.menu.activity_main, menu);
                return true;
        }

        @Override
        public boolean onPrepareOptionsMenu(Menu menu) {
                return super.onPrepareOptionsMenu(menu);
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
                switch (item.getItemId()) {

                case R.id.menu_test:
                        updateFragment();
                        return true;

                default: return true;
                }
        }

        private void updateFragment() {
                for (int i=0; i< mAdapter.getCount(); i++) {
                        SampleFragment fragment = (SampleFragment) mAdapter.getItem(i);
                        fragment.update();
                }
        }

        private void setupViewPager() {
                try {
                        mAdapter = new MyAdapter(getSupportFragmentManager());

                        mPager = (ViewPager) findViewById(R.id.pager);
                        mPager.setAdapter(this.mAdapter);

                } catch (Exception e) {
                        e.printStackTrace();
                }
        }

        public class MyAdapter extends FragmentPagerAdapter {

                public MyAdapter(FragmentManager fm) {
                        super(fm);
                }

                @Override
                public Fragment getItem(int position) {
                        SampleFragment fragment = new SampleFragment(position); 
                        return fragment;
                }

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

and the fragment class:

和片段类:

public class SampleFragment extends Fragment{

        private int myPosition = -1;

        public SampleFragment(int position) {
                this.myPosition = position;
        }

        @Override
        public void onAttach(Activity activity) {
                super.onAttach(activity);
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                View view = inflater.inflate(R.layout.fragment, container, false);
                update(view, "Updated from onCreateView");
                return view;
        }

        @Override
        public void onActivityCreated(Bundle bundle) {
                super.onActivityCreated(bundle);
        }

        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
                super.onViewCreated(view, savedInstanceState);

                view.findViewById(R.id.textTitle).setOnClickListener(myClickListener);
        }

        private OnClickListener myClickListener = new OnClickListener() {
                @Override
                public void onClick(View v) {
                        switch (v.getId()) {

                        case R.id.textTitle:
                                break;

                        }
                }
        };

        public void update() {
                update(getView(), "Updated from main");
        }

        private void update(View view, String subtitleText) {
                TextView title = (TextView) view.findViewById(R.id.textTitle);
                TextView subtitle = (TextView) view.findViewById(R.id.textSubtitle);

                title.setText("Fragment " + myPosition);
                subtitle.setText(subtitleText);
        }
}

The error happens on view.FindViewById (view is null) when called from the menu item in the main activity.

当从主活动中的菜单项调用时,错误发生在 view.FindViewById(视图为空)上。

回答by UgglyNoodle

You can take a look at this articlewhich explains how to keep references to the fragments in your ViewPager.

你可以看看这篇文章,它解释了如何在你的 ViewPager 中保留对片段的引用。

There are two methods described on the page. The first one involves setting a tag when you add the fragment using the FragmentManager. Then you can retrieve the fragment using findFragmentByTag(). However, I did not see how to make this work using FragmentPagerAdapter or FragmentStatePagerAdapter, since these implementations add the fragments for you. If you are using your own custom PagerAdapter, this may work for you.

页面上描述了两种方法。第一个涉及在使用 FragmentManager 添加片段时设置标签。然后,您可以使用 检索片段findFragmentByTag()。但是,我没有看到如何使用 FragmentPagerAdapter 或 FragmentStatePagerAdapter 来完成这项工作,因为这些实现为您添加了片段。如果您使用自己的自定义 PagerAdapter,这可能对您有用。

The other method, which does work for FragmentPagerAdapter or FragmentStatePagerAdapter, involves keeping a map of all your fragments, updating inside your getItem()and destroyItem()implementations. This method has worked for me.

另一种对 FragmentPagerAdapter 或 FragmentStatePagerAdapter 有效的方法涉及保留所有片段的映射,在您的getItem()destroyItem()实现中更新。这个方法对我有用。

Once you have a reference to the current fragment, you can just call a method in your fragment to refresh its view.

获得对当前片段的引用后,您只需在片段中调用一个方法即可刷新其视图。