【问题标题】:findFragmentById returns null after implementing ViewPager实现 ViewPager 后 findFragmentById 返回 null
【发布时间】:2020-02-26 11:57:16
【问题描述】:

我按照本教程实现 ViewPager(不创建 tablayout):https://www.javacodegeeks.com/2013/04/android-tutorial-using-the-viewpager.html

它有效,但我遇到了麻烦:

当我尝试执行 findFragmentById(R.id.my_fragment) 时,它返回 null。而且我认为这是因为在我的activity_main.xml 中除了 ViewPager 没有别的东西

我尝试在我的activity_main.xml 中添加一个<fragment>,现在我可以使用findFragmentById(R.id.my_fragment) 访问我的片段,但我的 ViewPager 现在无法工作

有办法访问我的 Fragment 吗?我需要访问他的视图。

这是我的activity_main.xml:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.viewpager.widget.ViewPager
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>`enter code here`

这是我的 MainActivity 的 onCreate


public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView((int) R.layout.activity_main);
        scan_fragment = (ScanFragment) getSupportFragmentManager().findFragmentById(R.id.scan_fragment);
        nfcButton = (ImageButton) findViewById(R.id.nfc_button);
        integrator = new IntentIntegrator(this);
        pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        //
        anim = ObjectAnimator.ofFloat(this.nfcButton, "scaleX", new float[]{0.9f});
        anim2 = ObjectAnimator.ofFloat(this.nfcButton, "scaleY", new float[]{0.9f});
        List<Fragment> fragments = getFragments();
        pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
        ViewPager pager = (ViewPager) findViewById(R.id.viewpager);
        pager.setAdapter(pageAdapter);
    }

    private List<Fragment> getFragments() {
        List<Fragment> fList = new ArrayList<Fragment>();
        fList.add(ScanFragment.newInstance("Fragment 1"));
        fList.add(WebFragment.newInstance("Fragment 2"));
        return fList;
    }

我的页面适配器


class MyPageAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;

    public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }

    @Override
    public Fragment getItem(int position) {
        return this.fragments.get(position);
    }


    @Override
    public int getCount() {
        return this.fragments.size();
    }
}

我的 Fragment 的重要部分:


    public interface OnButtonClickedListener {
        public void onButtonClicked(View view);
    }

    public static final ScanFragment newInstance(String message)
    {
        ScanFragment f = new ScanFragment();
        Bundle bdl = new Bundle(1);
        bdl.putString(EXTRA_MESSAGE, message);
        f.setArguments(bdl);
        return f;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_scan, container, false);
        mainActivity = (MainActivity) getActivity();
        MainActivity.display = 0;
        qrButton = (ImageButton) view.findViewById(R.id.main_button);
        nfcButton = (ImageButton) view.findViewById(R.id.nfc_button);
        anim = ObjectAnimator.ofFloat(this.nfcButton, "scaleX", new float[]{0.9f});
        anim2 = ObjectAnimator.ofFloat(this.nfcButton, "scaleY", new float[]{0.9f});
        nfcButton.setOnClickListener(this);
        qrButton.setOnClickListener(this);
        return view;
    }

而我的片段的 XML 只包含几个按钮和图像

【问题讨论】:

  • 请发布您的 xml 和片段/活动代码
  • 是的,我已经编辑了我的帖子 :)
  • 你可以直接使用view_pager当前项目而不是通过id查找
  • 怎么样?例如,从我的 MainActivity 中,我想访问我在 Fragment 中使用的文本(例如),如下所示:scan_fragment = (ScanFragment) getSupportFragmentManager().findFragmentById(R.id.scan_fragment); 然后:scan.fragment.my_text = 'foo';
  • 我试过这个List&lt;Fragment&gt; frags = getFragments(); scan_fragment = (ScanFragment) frags.get(0); 但还是不行

标签: java android android-fragments android-viewpager


【解决方案1】:

很抱歉让您失望了,但是您所遵循的教程已损坏,您不应该遵循它。

.

class MyFragmentPagerAdapter(
    private val context: Context,
    fragmentManager: FragmentManager
) : FragmentPagerAdapter(fragmentManager) {
    override fun getCount() = 2

    override fun getItem(position: Int) = when(position) {
        0 -> FirstFragment()
        1 -> SecondFragment()
        else -> throw IllegalStateException("Unexpected position $position")
    }

    override fun getPageTitle(position: Int): CharSequence = when(position) {
        0 -> context.getString(R.string.first)
        1 -> context.getString(R.string.second)
        else -> throw IllegalStateException("Unexpected position $position")
    }
}

class ParentFragment: Fragment() {
    override fun onCreateView(...) = ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewPager.adapter = MyFragmentPagerAdapter(requireContext(), childFragmentManager)
        tabLayout.setupWithViewPager(viewPager)
    }
}

Fragment fragment = childFragmentManager.findFragmentByTag("android:switcher:" + viewPager.getId() + ":" + fragmentPosition);

【讨论】:

    【解决方案2】:

    可能发生错误是因为 ViewPager 没有保持所有片段处于活动状态,在 onPause() 中只有当前一个和另一个 2 在其旁边。其他的没有为 Activity 创建的视图,但是我们可以通过 ViewPager 访问它们,因为 Fragments 的实例已经保存。

    希望下面的代码可以帮助到你:

    /******************************************/
        //Your ADAPTER.
        class MyPageAdapter extends FragmentPagerAdapter {
    
            private List<Fragment> fragments;
    
            //Your code...
    
    
            /**
             * Use this method for get the fragments list.
             */
            public List<Fragment> getFragments(){
                return fragments;
            }
    
        }
    
    
        /******************************************/
        //In your ACTIVITY.
        private List<Fragment> getFragments() {
            pageAdapter.getFragments();
        }
    
        /**
        * Use this to find a view and cast for your needs.
        */
        private View findById(int fragmentIndex, int viewId){
            Fragment fragment = this.getFragments().get(fragmentIndex);
            View view = ((YourFragment) fragment).getView(); //Casting to YourFragment and catching root view.
            return view.findViewById(viewId);
        }
    
    
    
        /******************************************/
        //In your FRAGMENTS.
        //Must save fragment rootView to access to findById() method. For example:
        public class YourFragment extends Fragment{
    
            private View view;
    
            @Override
                public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                         Bundle savedInstanceState) {
                    view = inflater.inflate(R.layout.fragment_scan, container, false);
                    //Your code....
                    return view;
            }
    
            public View getView(){
                return view;
            }
    
        }
    

    【讨论】:

    • 感谢您的帮助,但就我而言,我只有一项活动,实际上我的活动中只使用了一个片段
    • 任何适配器中的任何List&lt;Fragment&gt; 只会导致潜在的崩溃。
    猜你喜欢
    • 1970-01-01
    • 2014-06-14
    • 2013-06-27
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    相关资源
    最近更新 更多