При добавлении вкладок в OnCreate проблем нет, вкладки добавляются нормально, но при добавлении вкладок в вызове onChange пакета LiveDataObserver ничего не происходит.
У меня есть ViewPager с 2 фрагментами внутри2-й фрагмент У меня есть второй Viewpgaer с еще 2 Fragemnts, этот второй виртуальный вице-президент имеет com.google.android.material.tabs.TabLayout, но TabLayout НЕ связан через .setupWithViewPager ().
EDIT: Конфигурация будет выглядеть примерно так:
MainActivity (Nav) -> MainFrag (ViewPager) -> ChildFrag (в 1-й позиции) ... <- это TabLayout </p>
Продолжить :
Этот TabLayout показывает только содержимое второго самого внутреннего viewPager, это означает, что он должен отображать только 2 вкладки, не более того.
Но яЯ хочу добавить эти две вкладки с помощью обратных вызовов LiveData.
Я особенно не хочу, чтобы они (viewpager и tablayout) были связаны, потому что я хочу, чтобы фрагменты были созданы один раз, но ятакже хочу, чтобы вкладки выглядели так, как если бы пользователь создавал их на лету.
Если я создаю Fragemtns, с единственной целью добавления вкладок, я рискую получать информацию из БД каждый раз, когда это происходит. Готово, даже если пользователь выбирает одну и ту же опцию дважды.
Кроме того, если фрагменты уже созданы, разбиение на страницы становится плавным. Любой ценой я избегаю использования notifyDataSetChanged (), потому что мне не нравится, как данные перемещаются с этой опцией, это главная причина.
Так что я хочу .addTab () в onChange LiveData, поэтомучто я могу создавать вкладки с заголовками, которые предоставляет 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));
}
});
}
}
РЕДАКТИРОВАТЬ:
Моя SharedViewModel:
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 (тот, который использует getChildFragmentManager ())
Важно отметить, что это viewPager НИЖЕ TabLayout, НО Фрагмент TabLayout имеет родителя, который является другим ViewPager и имеет идентичную конфигурацию .... FragmentPagerAdapter, "BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT" и Фрагменты, инициализированные в конструкторе, вы можетевижу, что 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 (в 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 (в 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 (в 1) (subViewPgaer + TabLayout) / Frag (в 0) <- AKA: SessionsFragment </p>
@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);
}
});
}
Сообщения об ошибках отсутствуют, вкладки добавляются, но не отображаются.