Android: FragmentPagerAdapter не работает с ViewPager и материалом TabLayout - PullRequest
1 голос
/ 29 марта 2020

Я настраиваю ViewPager, который будет отображать фрагменты в зависимости от выбранной вкладки в TabLayout из материала. У меня есть фрагмент, который будет представлять все это как родительское представление (которое я не знаю, может ли это быть причиной.), И я делаю весь этот поток, потому что я хотел бы установить поток данных как Master Detail flow, в котором действие покажет 2 фрагмента, один из которых будет иметь пейджер, отображающий другой фрагмент в ViewPager

, поэтому фрагмент, который имеет как TabLayout, так и ViewPager, имеет класс, определенный следующим образом:

public class InstructionsFragment extends Fragment {
    private static final String TAG = InstructionsFragment.class.getSimpleName();

    private TabLayout instructionsTab;
    private ViewPager instructionsPager;

    private int recipeIndex;

    public InstructionsFragment(int recipeIndex) {
        this.recipeIndex = recipeIndex;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_instructions, container, false);

        this.loadViews(rootView);

        return rootView;
    }

    @Override
    public void onStart() {
        super.onStart();

        this.loadPager();
    }

    private void loadViews(View view) {
        Log.i(TAG, "Loading views");

        this.instructionsTab = view.findViewById(R.id.recipe_instructions_tabs);
        this.instructionsPager = view.findViewById(R.id.recipe_instructions_pager);

        this.instructionsTab.setupWithViewPager(this.instructionsPager);
    }

    private void loadPager() {
        Log.i(TAG, "Loading pager");

        FragmentManager fragmentManager = this.getFragmentManager();
        IngredientsFragment ingredientsFragment = new IngredientsFragment(recipeIndex);

        InstructionsPagerAdapter instructionsAdapter = new InstructionsPagerAdapter(fragmentManager, 0);
        instructionsAdapter.addFragment(ingredientsFragment);

        this.instructionsPager.setAdapter(instructionsAdapter);
    }

Этот фрагмент использует макет, определенный следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/instructions_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/recipe_instructions_tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="@string/recipe_detail_tab_ingredients_label" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="@string/recipe_detail_tab_steps_label" />
    </com.google.android.material.tabs.TabLayout>

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/recipe_instructions_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

Так что в основном есть две вкладки * stati c, и я хочу протестировать только с один, потому что даже когда я удаляю одну из вкладок, она все равно не работает.

FragmentPagerAdater определяется в таком классе:

public class InstructionsPagerAdapter extends FragmentPagerAdapter {
    private List<Fragment> fragments = new ArrayList<>();

    public InstructionsPagerAdapter(@NonNull FragmentManager fm, int behavior) {
        super(fm, behavior);
    }

    public void addFragment(Fragment fragment) {
        this.fragments.add(fragment);
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
        return this.fragments.get(position);
    }

    @Override
    public int getCount() {
        return this.fragments.size();
    }
}

При переходе к занятию который отображает InstructionsFragment, вкладки по какой-то причине не отображаются, а также фрагмент не выбран по умолчанию. Я сделал некоторую отладку, чтобы увидеть, есть ли ошибка или запущен выбранный фрагмент с помощью viewPager, и я не вижу никаких журналов ошибок в logcat, а выбранный фрагмент фактически работает, поэтому я не знаю как продолжить.

Вот как на экране отображается весь код, который я реализовал: Image loading the pager

И вот как это выглядит без загрузки код пейджера: Image without loading the pager code

Я запускаю приложение на Android 9, и это зависимости в моем проекте:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'com.google.code.gson:gson:2.8.6'
    implementation 'com.google.android.material:material:1.1.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

Ответы [ 2 ]

0 голосов
/ 29 марта 2020

Мне удалось заставить его работать, динамически добавляя вкладки, похоже, что TabsLayout из материала не поддерживает наличие набора c вкладок в макете при использовании ViewPager. ViewPager должен иметь адаптер, который передает заголовок вкладки для выбранного фрагмента для отображения в ViewPager.

Код конца для FragmentPagerAdapter выглядит следующим образом:

public class InstructionsPagerAdapter extends FragmentPagerAdapter {
    private List<Fragment> fragments = new ArrayList<>();
    private List<String> pageTitles = new ArrayList<>();

    public InstructionsPagerAdapter(@NonNull FragmentManager fm, int behavior) {
        super(fm, behavior);
    }

    public void addFragment(Fragment fragment, String tabTitle) {
        this.fragments.add(fragment);
        this.pageTitles.add(tabTitle);
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
        return this.fragments.get(position);
    }

    @Override
    public int getCount() {
        return this.fragments.size();
    }

    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        return this.pageTitles.get(position);
    }
}

Добавление списка заголовков для фрагментов и выбор его при выделении фрагмента.

0 голосов
/ 29 марта 2020

, так как я не могу опубликовать код в комментарии, вот как я делаю то же самое, и он работает во фрагменте

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         adapter = new ViewPagerAdapter(getChildFragmentManager());
        adapter.addFragment(new PickPowerballTickets(), getResources().getString(R.string.powerball));
        adapter.addFragment(new PickMegaMillionsTickets(), getResources().getString(R.string.megamillions));
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view =  inflater.inflate(R.layout.fragment_pick_my_tickets, container, false);
        viewPager = (ViewPager) view.findViewById(R.id.pager);
        viewPager.setAdapter(adapter);
        viewPager.setOffscreenPageLimit(2);
        tabLayout = (TabLayout) view.findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
        return view;
    }

вот мой адаптер пейджера

public class ViewPagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }
}
...