繁体   English   中英

addTab() 未在回调中添加任何 TabLayout.Tab

[英]addTab() not adding any TabLayout.Tab on callback

在 OnCreate 上添加选项卡时没有问题,正常添加选项卡,但是在 LiveDataObserver 的 onChange 回调上添加选项卡时..没有任何反应。

我有一个带有 2 个片段的 ViewPager,在第二个片段内我有一个带有另外 2 个片段的第二个 Viewpgaer,这第二个 vp 有一个 com.google.android.material.tabs.TabLayout 但 TabPageLayout.不是通过.setup()耦合

编辑:配置将是这样的:

MainActivity (Nav) -> MainFrag (ViewPager) -> ChildFrag (at 1st pos)...<- 这是 TabLayout

继续

此 TabLayout 仅显示第二个最内部 viewPager 的内容,这意味着它应该只显示 2 个选项卡,仅此而已。

但我想通过 LiveData 回调添加这两个选项卡。

我特别不希望它们(viewpager 和 tablayout )耦合,因为我希望片段被创建一次,但我也希望标签看起来好像用户正在动态创建它们。

如果我创建 Fragemtns 的唯一目的是添加选项卡,那么每次完成时我都会冒着从数据库中获取信息的风险,即使用户选择了两次相同的选项。

此外,如果片段已经构建,则分页会变得平滑。 我不惜一切代价避免使用 notifyDataSetChanged() 因为我不喜欢使用该选项传输数据的方式,这是主要原因。

所以我想在 LiveData 的 onChange 中添加 .addTab() ,这样我就可以创建带有 LiveData 提供的标题的选项卡。

然而什么也没发生

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        app:tabSelectedTextColor="@android:color/white"


        app:layout_constraintBottom_toTopOf="@id/guideline"
        app:layout_constraintTop_toTopOf="parent"
        app:tabTextColor="@android:color/black"
        >

那就是 XML

public class FlyHighSubFragment extends Fragment {




    private WeakReference<FlyHighActivity> mContextWeakReference;
    private MySubFragmentPagerAdapter mAdapter;
    private FragmentFlyhighSubBinding binding;


    private TabLayout mTabLayout;

    private SharedViewModel mSharedViewModel;



    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        if (context instanceof FlyHighActivity) {

            mContextWeakReference = new WeakReference<>((FlyHighActivity)context);

        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {



        binding = DataBindingUtil.inflate(inflater,
                R.layout.fragment_flyhigh_sub, container, false);


        mAdapter = new MySubFragmentPagerAdapter(getChildFragmentManager());

        binding.mainContainer.setAdapter(mAdapter);



        mTabLayout = binding.tablayout;

        mTabLayout.addOnTabSelectedListener(new TabLayout.BaseOnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                binding.mainContainer.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

        binding.mainContainer.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
}

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mSharedViewModel = ViewModelProviders.of(mContextWeakReference.get()).get(SharedViewModel.class);
/*called on the process of going from page [0][0] to page [1][0]*/
        mSharedViewModel.getUserName().observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String s) {

                mTabLayout.addTab(mTabLayout.newTab().setText(s));




            }
        });
/*called on the process of going from [1][0] to [1][1]*/
        mSharedViewModel.getSessionTitle().observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String s) {
            mTabLayout.addTab(mTabLayout.newTab().setText(s));
            }
        });

    }

}

编辑:

我的共享视图模型:

public class SharedViewModel extends ViewModel {

    private static final String TAG = "SharedViewModel";

/*Each one of this Strings are passed from Fragment to Fragment, some of them trigger a Firebase listener, others provide view data for the Fragment.*/

/*All of them do their job properly, even the ones called inside the FlyHighSubFragment which is the Fragment that shelters the TabLayout*/

    private MutableLiveData<String> uId = new MutableLiveData<>();
    private MutableLiveData<String> userName = new MutableLiveData<>();
    private MutableLiveData<String> chatRef = new MutableLiveData<>();
    private MutableLiveData<String> sessionTitle = new MutableLiveData<>();
    private MutableLiveData<Sessions> session = new MutableLiveData<>();

    public SharedViewModel() {

    }

    public MutableLiveData<Sessions> getSession() {
        return session;
    }

    public void setSession(Sessions session) {
        this.session.setValue(session);
    }

    public MutableLiveData<String> getSessionTitle() {
        return sessionTitle;
    }

    public void setSessionTitle(String sessionTitle) {
        this.sessionTitle.setValue(sessionTitle);
    }

    public MutableLiveData<String> getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName.setValue(userName);
    }

    public LiveData<String> getUid() {
        return uId;
    }

    public void setUid(String input) {
        uId.setValue(input);
    }

    public MutableLiveData<String> getChatRef() {
        return chatRef;
    }

    public void setChatRef(String chatRef) {
        this.chatRef.setValue(chatRef);
    }

}

这是我的 SubFragmentPagerAdapter,它是最里面的 ViewPager 的 Adapter(使用 getChildFragmentManager() 的那个)

要提到的一件重要的事情是,这是 TabLayout 下方的 viewPager,但是 TabLayout 的 Fragment 有一个父级,它是另一个 ViewPager 并且具有相同的配置....看到没有 notifyDatasetChanged() 因为我通过 LiveData 回调管理所有信息:

public class MySubFragmentPagerAdapter extends FragmentPagerAdapter {

    private ChatFragment mChatFragment;
    private SessionsFragment mSessionsFragment;

    public MySubFragmentPagerAdapter(@NonNull FragmentManager fm,
                                     FlyHighUser flyHighUser,
                                     MyPagerController.FragmentPager fragmentPagerController) {
        super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);

        mChatFragment = ChatFragment.newInstance(flyHighUser);
        mSessionsFragment = new SessionsFragment();

/*This is a listener I made that allows the Fragments to be able to change the pages of their parent viewPgaer.*/
        mSessionsFragment.setSessionFragmentInterface(fragmentPagerController);


    }


    private static final int NUMBER_OF_FRAGMENTS = 2;

    @NonNull
    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return mSessionsFragment;
            case 1:
                return  mChatFragment;
        }
        return null;
    }


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




}

完整的过程应该是这样的:

MainActivity(Nav) / MainFrag(viewPager) / Frag(at 0)

@Override
public void onItemClick(String uID, String userName) {


/*Set the values that Fragment at position 1 should solve, this include connecting the FireBase Listener with the uid, and getting the userName String*/
        mSharedViewModel.setUid(uID);
        mSharedViewModel.setUserName(userName);

/* this changes the page to position 1*/

    fragmentPagerController.scrollToFragment(1);
}

当页面变为 1 时,必须同时发生两件事,必须添加一个选项卡,以及 SessionsFragment(在初始化时创建),必须添加一个 Firebase 监听器到给定的引用

MainActivity(Nav) / MainFrag(viewPager) / Frag(at 1)(subViewPgaer + TabLayout)。

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mSharedViewModel = ViewModelProviders.of(mContextWeakReference.get()).get(SharedViewModel.class);
        mSharedViewModel.getUserName().observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String s) {
/*The Tab is added but not drawn*/
                mTabLayout.addTab(mTabLayout.newTab().setText(s));




            }
        });
        mSharedViewModel.getSessionTitle().observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String s) {
/* The Tab is added but not drawn*/
            mTabLayout.addTab(mTabLayout.newTab().setText(s));
            }
        });
}

MainActivity(Nav) / MainFrag(viewPager) / Frag(at 1)(subViewPgaer + TabLayout) / Frag(at 0) <- AKA: SessionsFragment

            @Override
            public void onActivityCreated(@Nullable Bundle savedInstanceState) {
                super.onActivityCreated(savedInstanceState);
                mSharedViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
                mSharedViewModel.getUid().observe(getViewLifecycleOwner(), new Observer<String>() {
                    @Override
                    public void onChanged(String s) {

                        uid = s;
        /*this works perfectly fine, I wanted the Firebase data to be bound by the MainActivity LifeCycle.
Observer is added only once, and there is only one Firebase Listener at any given moment (italian chef kiss) BTW observeUserSessions() is a LiveData setter for the observer, lifeCycleOwner and Firebase reference*/
                        mContextWeakReference.get().observeUserSessions(mObserver, "sessions/" + s);


                    }
                });
                mSharedViewModel.getUserName().observe(getViewLifecycleOwner(), new Observer<String>() {
                    @Override
                    public void onChanged(String s) {
                        clientName = s;
    /*this is viewDataBinding*/
                        binding.setClientName(clientName);

                    }
                });
            }

没有错误消息,选项卡已添加但未显示。

这不是一个真正的答案,但我想发生这种情况的原因与我们在另一个 Viewpager 中使用 ViewPager 时需要使用 getChildFragmentManager() 的原因相同。

可能是因为生命周期是分层的,没有机会在初始化过程之外绘制选项卡,可能片段的容器找不到可以附加到自己的东西,可能是充气器?容器? 我真的对 Android 架构一无所知,如果我不会遇到这个问题的话。

问题是 Tablayout.Tab 没有选项可以从其父级获取所需的正确视图,或者问题可能直接依赖于 TabLayout 本身,而没有安装正确 FragmentManager 的选项。 或者也许它有,但我还没有找到它,我认为这是主要问题。

无论如何,如果这个问题是故意的,我会完全理解,毕竟我承认 android.os 的小部件和组件提供的一些工具确实足以构建完全定制的东西,因为只要对它们的使用的了解会扩展,并且它们的行为会在不明显的情况下保持不变,问题是幕后发生的事情太多了,知道如何使用它们只意味着知道如何使用它们它们的使用方式,实际上意味着一个人根本一无所知....而且我个人认为,如果有人对 android 有肤浅的了解,这对花了多年时间掌握系统的人来说是不公平的架构组件和小部件可以构建同等水平的东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM