在 ViewPager 的不同页面访问不同的 children

accessing different children in different pages of ViewPager

我的 StartupPreference 的布局只用一个 ViewPager 定义为:

<?xml version="1.0" encoding="utf-8"?>

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

和关联的 activity 将其关联为:

public class StartupPreference extends AppCompatActivity implements StartupPrefFrag_interfaces{
    private final static int no_of_prefs = 2;
    private LinearLayout dot_animation_holder;
    private static int temp_count = 0;

    public void ViewUpdater(View updatedView){
        dot_animation_holder = (LinearLayout) updatedView;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_startup_preference);
        //we're not using the layout natively, but using Fragment's layout
        //but setContentView is required -> it is accessed by : R.id.startPref_pager

        dot_animation_holder= findViewById(R.id.dot_animation_holder);

        StartPrefPagerAdapter prefPagerAdapter =
                new StartPrefPagerAdapter(getSupportFragmentManager());

        ViewPager StartPref_Viewpager = findViewById(R.id.startPref_pager);
        StartPref_Viewpager.setAdapter(prefPagerAdapter);




        StartPref_Viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                    ((ImageView)(findViewById(R.id.dot_animation_holder).findViewById(R.id.page1))).setImageResource(R.drawable.active_dot);
                    ((ImageView)(findViewById(R.id.dot_animation_holder).findViewById(R.id.page2))).setImageResource(R.drawable.inactive_dot);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });




    }


    private class StartPrefPagerAdapter extends FragmentPagerAdapter {
        public StartPrefPagerAdapter(FragmentManager fm){
            super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
        }

        @Override
        public int getCount(){
            return StartupPreference.no_of_prefs;//no. of preference pages
        }

        @Override
        public Fragment getItem(int position) {
            switch (position){
                case 0:
                    return new Frag_StartPref_Layout();
                case 1:
                    return new Frag_StartPref_Theme();
            }
            return null;
        }

    }

}

我遇到的问题是我不知道如何访问与 ViewPager 关联的不同 View。由于 fragmentlayout 都包含一个使用 <include...> 标记的名为 dot_animation.xml 的公共 layout,但是 中的代码 onPageSelected 上面的方法只更新第一页,如果我在 <include...> 中使用不同的 ids,比如:

fragment_startpref_layout.xml:

...

<include
        layout="@layout/dot_animation"
        android="@+id/dot_animation_holder1"
        />
...  

fragment_startpref_theme.xml

...
    <include
            layout="@layout/dot_animation"
            android="@+id/dot_animation_holder2"
    />

...  

并且我使用这些 id 更新 ImageView 然后我得到一个 NullPointer 异常。(我使用 activity 中的代码)

那么,我怎样才能访问 ViewPager 的各个页面中的不同 View
片段的布局如下:
fragment_startpref_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout

    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/C_startPref_layout"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    >

    <ImageView
        android:id="@+id/startPref_Layout"
        android:layout_width="0dp"
        android:layout_height="0dp"

        android:scaleType="centerCrop"
        app:layout_constraintBottom_toTopOf="@+id/startPref_layout_info"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@mipmap/ic_launcher" />


    <TextView
        android:id="@+id/startPref_layout_info"
        android:layout_width="0dp"
        android:layout_height="0dp"

        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:gravity="center"
        android:text="@string/Frag_startPref_layout_info"

        android:textSize="25sp"
        app:layout_constraintBottom_toTopOf="@+id/startPref_layout_select1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent=".125"
        app:layout_constraintStart_toStartOf="parent" />

    <RadioGroup
        android:id="@+id/startPref_layout_select1"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"

        android:layout_marginEnd="8dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toTopOf="@+id/dot_animation_holder"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent=".125"
        app:layout_constraintStart_toStartOf="parent">

        <RadioButton
            android:id="@+id/radioButton1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:checked="true"
            android:text="@string/Frag_startPref_Radio1"
            android:textSize="15sp" />

        <RadioButton
            android:id="@+id/radioButton2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="@string/Frag_startPref_Radio2"
            android:textSize="15sp" />
    </RadioGroup>

    <include
        layout="@layout/dot_animation"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_theme_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/C_startPref_theme"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    >

    <ImageView
        android:id="@+id/startPref_Theme"
        android:layout_width="0dp"
        android:layout_height="0dp"

        android:scaleType="centerCrop"
        app:layout_constraintBottom_toTopOf="@+id/startPref_layout_info"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@mipmap/ic_launcher" />


    <TextView
        android:id="@+id/startPref_layout_info"
        android:layout_width="0dp"
        android:layout_height="0dp"

        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:gravity="center"
        android:text="@string/Frag_startPref_layout_info"

        android:textSize="25sp"
        app:layout_constraintBottom_toTopOf="@+id/startPref_layout_select2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent=".125"
        app:layout_constraintStart_toStartOf="parent" />

    <RadioGroup
        android:id="@+id/startPref_layout_select2"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"

        android:layout_marginEnd="8dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toTopOf="@+id/dot_animation_holder"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent=".125"
        app:layout_constraintStart_toStartOf="parent">

        <RadioButton
            android:id="@+id/radioButton1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:checked="true"
            android:text="@string/Frag_startPref_Radio1"
            android:textSize="15sp" />

        <RadioButton
            android:id="@+id/radioButton2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="@string/Frag_startPref_Radio2"
            android:textSize="15sp" />
    </RadioGroup>


    <include
        layout="@layout/dot_animation"
        />


</androidx.constraintlayout.widget.ConstraintLayout>

首先,您需要在 onViewCreated 上更新 fragmnet 中的 view。 您无法更新其他视图的原因是 viewpager 仅显示当前 fragment.and nullpointexception 的原因也是其他视图未被 viewpager 加载到 activity。(您可能还想检查如果在 onCreateView 方法中调用了正确的布局。)如果你想加载所有它们,即使它们不在屏幕上,你可以使用 viewPager.setOffscreenPageLimit(); 但这失去了 viewpager 的目的。所以我的建议是创建回调以与您的片段通信并通过回调发送数据并更新您在片段内的视图。这也让你的 activity 不那么凌乱。

更新:

example of using ViewPager with multiple layouts

Document About setOffscreenPageLimit

Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state. Pages beyond this limit will be recreated from the adapter when needed.

This is offered as an optimization. If you know in advance the number of pages you will need to support or have lazy-loading mechanisms in place on your pages, tweaking this setting can have benefits in perceived smoothness of paging animations and interaction. If you have a small number of pages (3-4) that you can keep active all at once, less time will be spent in layout for newly created view subtrees as the user pages back and forth.

You should keep this limit low, especially if your pages have complex layouts. This setting defaults to 1.