Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

从ViewPager迁移到ViewPager2中遇到的问题 #253

Open
ou2356 opened this issue Feb 13, 2023 · 0 comments
Open

从ViewPager迁移到ViewPager2中遇到的问题 #253

ou2356 opened this issue Feb 13, 2023 · 0 comments

Comments

@ou2356
Copy link

ou2356 commented Feb 13, 2023

我的ViewPager2中管理着3个Fragment,其中两个Fragment都有RecyclerView,这两个RecyclerView都管理着同样的实时更新的item数据,但是我发现在ViewPager2中当RecyclerView有item数据实时更新出来时所有的item都会闪烁或者发生奇怪的偏移。但是这一系列的现象在ViewPager中都没有出现到,我对这个现象进行了一系列的追溯,有了一点眉目,但不知道该如何解决这个问题,下面展示3种我调试的现象,欢迎大家来参观讨论,我挺期待用上ViewPager2的:

现象1(ViewPager2的问题现象):

Clipchamp.mp4
    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/Theme.AppCompat.DayNight"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toTopOf="@+id/view_pager2">

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="20dp" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="horizontal"
        app:layout_constraintTop_toBottomOf="@+id/app_bar_layout"
        app:layout_constraintBottom_toTopOf="@+id/sendMsgEt"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />
        viewPager2 = findViewById(R.id.view_pager2);
        tabLayout = findViewById(R.id.tab_layout);
        //禁止ViewPager的左右滑动
        viewPager2.setUserInputEnabled(false);
        viewPager2.setOffscreenPageLimit(3);
        viewPager2.setAdapter(new FragmentStateAdapter(supportFragmentManager, getLifecycle()) {
            @NonNull
            @Override
            public Fragment createFragment(int position) {
                switch (position){
                    case 0 :
                        chatFragment = new mChatFragment();
                        return chatFragment;
                    case 1 :
                        terminalFragment = new mTerminalFragment();
                        return terminalFragment;
                    case 2 :
                        controlFragment = new mControlFragment();
                        return controlFragment;
                    default:
                        return null;
                }
            }
            @Override
            public int getItemCount() {
                return 3;
            }
        });
        tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
            @Override
            public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
                //ViewPager选中时对Tab执行的代码
                switch (position){
                    case 0 :
                        tab.setText("对话模式");
                        break;
                    case 1 :
                        tab.setText("终端模式");
                        break;
                    case 2 :
                        tab.setText("控件模式");
                        break;
                    default: break;
                }
            }
        });
        tabLayoutMediator.attach();
        messageRecyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                Log.e("RecyclerViewLayout","newTop:"+top+"\tnewBottom:"+bottom);
            }
        });

OnLayoutChangeListener中捕获的日志如下(RecyclerView每新增一个item其中的newBottom都会发生两次改变先是0后面变成1953,我认为导致这个问题的原因就在于newBottom改变成了0):
图片
于是我对令newBottom变成0的代码经行了追溯,发现下面两处有可能是导致newBottom变成0的代码(我能力有限,只能debug后建立断点后一点点往回看,希望理解),令我好奇的是下面两处代码在newBottom变成1953时并没有被执行,这也让我更加肯定下面两处代码把newBottom变成了0:
图片
图片

现象2(把xml布局文件中ViewPager2的layout_height="0dp"修改成固定的"350dp",其它部分代码同上)

Clipchamp.mp4

修改后的xml代码如下

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager2"
        android:layout_width="match_parent"
        android:layout_height="350dp"
        android:orientation="horizontal"
        app:layout_constraintTop_toBottomOf="@+id/app_bar_layout"
        app:layout_constraintBottom_toTopOf="@+id/sendMsgEt"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

捕获日志如下(可见RecyclerView每新增一个item其中的newBottom只更新了一次,且都为963,可以说没有改变,一切正常,但这样的固定值的布局显然不是我想要的):
图片

现象3(把ViewPager2改回用ViewPager)

Clipchamp.mp4
    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/Theme.AppCompat.DayNight"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toTopOf="@+id/view_pager">

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="20dp" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="horizontal"
        app:layout_constraintTop_toBottomOf="@+id/app_bar_layout"
        app:layout_constraintBottom_toTopOf="@+id/sendMsgEt"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>
        ViewPager viewPager = findViewById(R.id.view_pager);
        viewPager.setOffscreenPageLimit(3);
        viewPager.setAdapter(new FragmentPagerAdapter(supportFragmentManager) {
            @NonNull
            @Override
            public Fragment getItem(int position) {
                switch (position){
                    case 0 :
                        chatFragment = new mChatFragment();
                        return chatFragment;
                    case 1 :
                        terminalFragment = new mTerminalFragment();
                        return terminalFragment;
                    case 2 :
                        controlFragment = new mControlFragment();
                        return controlFragment;
                    default:
                        return null;
                }
            }
            @Override
            public int getCount() {
                return 3;
            }
            @Override
            public CharSequence getPageTitle(int position){
                switch (position){
                    case 0 :
                        return "对话模式";
                    case 1 :
                        return "终端模式";
                    case 2 :
                        return "控件模式";
                    default:
                        return null;
                }
            }
        });
        TabLayout tabLayout = findViewById(R.id.tab_layout);
        tabLayout.setupWithViewPager(viewPager);

捕获日志如下(一切正常):
图片

最后贴上RecyclerView的item更新代码

    private void refreshMsgUI(){
        ((AppCompatActivity)context).runOnUiThread(()->{
            terminalFragment.recyclerViewAdapter.notifyItemInserted(terminalFragment.recyclerViewAdapter.getItemCount()-1);
            if (isTerScrollToBottom) {
                terminalFragment.messageRecyclerView.scrollToPosition(terminalFragment.recyclerViewAdapter.getItemCount()-1);
            }
            chatFragment.recyclerViewAdapter.notifyItemInserted(chatFragment.recyclerViewAdapter.getItemCount()-1);
            if (isChatScrollToBottom) {
                chatFragment.messageRecyclerView.scrollToPosition(chatFragment.recyclerViewAdapter.getItemCount()-1);
            }
        });
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant