Не обрезайте страницы ViewPager

Я не могу заставить мой ViewPager не обрезать содержимое своих страниц.

В настоящее время я использую ViewPager с FragmentStatePagerAdapter в своем приложении. У меня 3 страницы, каждая страница показывает другой фрагмент. Все работает отлично, но теперь я хочу иметь возможность рисовать за пределами границ моих страниц, как на этом изображении:

What I Want

Я установил clipChildren и clipToPadding в false в моих родителях всех представлений, которые должны рисовать вне их границ, но вот что я получаю: мои представления обрезаются в соответствии с границами страниц.

What I get

Дополнительная информация: Чтобы исправить эту проблему, я использовал hierarchyviewer для проверки моей иерархии представлений и выяснения того, может ли какое-либо представление "под капотом" иметь поведение отсечения. И бинго: каждый из корневых представлений моих фрагментов добавляется под NoSaveStateFrameLayout. Я подозреваю, что этот парень закрепил своих детей...

Является ли мое последнее предположение правильным на ваш взгляд? Как сделать, чтобы получить незакрепленные страницы?

Ответ 1

Существует несколько разных представлений, для которых требуется отключить отсечение. Во-первых, FrameLayout, находящийся в корневой части ViewPager, должен отключить обрезку. Вы можете сделать это везде, где вы инициализируете свой плейер. Вам также необходимо установить ограничение на закрытие страницы на 2, чтобы можно было загрузить дополнительный фрагмент во время салфетки. Без этого вы увидите поп, идущий от 1- > 2 до 3-х нагрузок, и добавляет, что он переполняет содержимое до 2, когда 2 закончили загрузку (это загружает как 2, так и 3 раньше времени).

mViewPager.setClipChildren(false);
mViewPager.setClipToPadding(false);
mViewPager.setOffscreenPageLimit(2);

Во-вторых, XML, который вы надуваете в своем FragmentStatePagerAdapter, должен включать соответствующие теги, или это может быть сделано программно. Наконец, вам нужно заставить NoSaveStateFrameLayout также не зажимать. Это можно сделать после создания представления в onViewCreated. Вот фрагмент примера:

public static class PlaceholderFragment extends Fragment {

    public static PlaceholderFragment newInstance() {
        PlaceholderFragment fragment = new PlaceholderFragment();
        return fragment;
    }

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        LinearLayout rootView = (LinearLayout) inflater.inflate(R.layout.fragment_main, container, false);
        //This can be done in XML
        rootView.setClipChildren(false);
        rootView.setClipToPadding(false);
        return rootView;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        //This is the NoSaveStateFrameLayout - force it to not clip
        FrameLayout frameLayout = (FrameLayout) getView();
        frameLayout.setClipChildren(false);
        frameLayout.setClipToPadding(false);
    }
}

Я тестировал это решение и уверен, что он работает.

Пример полной активности: https://gist.github.com/grantamos/d664f01a30f9ad97ba53

Ответ 2

Вы пытались использовать отрицательное значение для поля между страницами (используя ViewPager.setPageMargin(int))? Вам также необходимо установить ограничение на экранную страницу как минимум на 2 (используя ViewPager.setOffscreenPageLimit(int)).

Ответ 3

У меня была та же проблема. Я исправил это, добавив

android:clipChildren="false"
android:clipToPadding="false"

to ViewPager и ViewGroup, который является родительским элементом ViewPager

Например, если у вас есть такой макет:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:clipChildren="false"
            android:clipToPadding="false"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.v4.view.ViewPager
                android:clipChildren="false"
                android:clipToPadding="false"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>
    </FrameLayout>
</RelativeLayout>

тогда только LinearLayout и ViewPager должны иметь

android:clipChildren="false"
android:clipToPadding="false"