gpt4 book ai didi

java - addTab() 在回调中不添加任何 TabLayout.Tab

转载 作者:行者123 更新时间:2023-12-01 22:08:30 27 4
gpt4 key购买 nike

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

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

编辑:配置如下:

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));
}
});

}

}

编辑:

我的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() 的适配器)

需要提到的一件重要的事情是,这是 TabLayout 下面的 viewPager,但是 TabLayout 的 Fragment 有一个父级,它是另一个 ViewPager 并且具有相同的配置....FragmentPagerAdapter、“BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT”和在构造函数中初始化的 Fragments ,你可以看到没有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) <- 又名: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 没有从其父级获取所需正确 View 的选项,或者问题可能直接依赖于 TabLayout 本身,而没有安装正确 FragmentManager 的选项。或者也许有但我还没有找到它,我认为这是主要问题。

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

关于java - addTab() 在回调中不添加任何 TabLayout.Tab,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58675186/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com