Подтвердить что ты не робот

Android - Карусель, как виджет, который отображает часть левого и правого элементов

Итак, я искал высокий и низкий, но не смог найти ответа на мой вопрос. В основном я нуждаюсь в поведении Android ViewFlipper или ViewPager, но я хочу отображать части левого и правого представлений, чтобы указать, что у пользователя есть элементы для прокрутки, вместо того, чтобы выбранное представление занимало весь экран.

Я также хотел бы добавить некоторые эффекты в левый и боковой виды, например, затемнение и масштабирование, а затем немного. Можно ли это сделать с помощью запаса ViewFlipper или ViewPager или мне нужно развернуть свою собственную группу просмотра, à la cover flow (http://www.inter-fuser.com/2010/01/android-coverflow-widget.html)?

(P.S. Я не хочу использовать виджет Gallery, этот компонент сосет).

Это то, что нам нужно отобразить после выбора вида (слева и справа видны все еще):

view switcher

Поворот влево или вправо приведет к переходу основного вида, уменьшению яркости и уменьшению его, а наоборот, к следующему или предыдущему виду.

4b9b3361

Ответ 1

Я хотел бы дать обновление всем, кто может захотеть такую ​​же функцию. Был достигнут большой прогресс в реализации этой функции до сих пор, и теперь представление работает именно так, как нам нужно.

В ViewPager есть метод, называемый setPageMargin(). Этот метод может получить отрицательное значение, которое сделает фрагменты/представления перекрывающимися друг с другом. Чтобы достичь желаемого расположения, мы сначала динамически вычисляли левое и правое поля на процент от экрана. Это также можно сделать статически, но поскольку мы будем ориентироваться на различные размеры экрана, это, по-видимому, лучший подход.

Позже мы установили маркер страницы ViewPager в 2 раза по размеру боковых полей. Это позволяет просматривать снимки вместе. Однако в это время ViewPager будет отображаться более одного вида.

Все, что вам осталось сделать, - либо применить преобразование (масштаб) к представлениям влево и вправо (Android 3.0+), либо добавить дополнительные поля вокруг них, чтобы сжать их до нужного размера (до 3.0).

OnPageChangeListener.onPageScrolled() может использоваться для отслеживания прокрутки ViewPager. Гладкий трансформация может быть достигнута. Код выглядит следующим образом:

private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {

    @Override
    public void onPageSelected(int position) {
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        // positionOffset varies from 0 to 1 and indicates how far the view is
        // from the center of the ViewPager. When a view is selected (centered), this
        // value is 0.

        // Fades the text in an out while the ViewPager scrolls from one view to another.
        // On our final design the text views are fixed to the center of the screen and
        // do not scroll along with the views.
        if (positionOffset < 0.5) {
            setTextViewAlpha(1 - positionOffset * 2);
        } else {
            setTextViewAlpha((positionOffset - 0.5f) * 2);
        }

        // It surprisingly complicated to get the current object being displayed by
        // a ViewPager (there no getCurrentObject method). ScaleableFragment is just
        // a custom class to allow an adapter to cache it internally and also correctly
        // manage a fragment lifecycle and restore from a saved state.
        ScaleableFragment sampleFragment = (ScaleableFragment) ((ShowHeroShotImageFragmentPagerAdapter) pager
                .getAdapter()).getItem(position);

        // Calculates by how much the current view will be scaled down. The RATIO_SCALE
        // is 0.3 in our case, which makes the side views 70% of the size of the
        // center view. When centered, the scale will be 1. When
        // fully scrolled, the scale will be 0.7.
        float scale = 1 - (positionOffset * RATIO_SCALE);

        // Just a shortcut to findViewById(R.id.image).setScale(scale);
        sampleFragment.scaleImage(scale);


        // Now, if not in the last element, scale the next one up (in opposite direction).
        if (position + 1 < pager.getAdapter().getCount()) {
            sampleFragment = (ScaleableFragment) ((ShowHeroShotImageFragmentPagerAdapter) pager.getAdapter())
                    .getItem(position + 1);
            scale = positionOffset * RATIO_SCALE + (1 - RATIO_SCALE);
            sampleFragment.scaleImage(scale);
        }
    }

    // Once scrolling is done. Make sure the views are in the right scale (1 for center,
    // 0.7 for sides). Required as the onPageScrolled() method does not guarantee it
    // will interpolate to 1.0 precisely.
    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == ViewPager.SCROLL_STATE_IDLE) {
            setTextViewAlpha(1);
            ScaleableFragment sampleFragment = (ScaleableFragment) ((ShowHeroShotImageFragmentPagerAdapter) pager
                    .getAdapter()).getItem(pager.getCurrentItem());
            sampleFragment.scaleImage(1);
            sampleFragment.enableClicks();

            if (pager.getCurrentItem() > 0) {
                sampleFragment = (ScaleableFragment) ((ShowHeroShotImageFragmentPagerAdapter) pager.getAdapter())
                        .getItem(pager.getCurrentItem() - 1);
                sampleFragment.scaleImage(1 - RATIO_SCALE);
                sampleFragment.disableClicks();
            }

            if (pager.getCurrentItem() + 1 < pager.getAdapter().getCount()) {
                sampleFragment = (ScaleableFragment) ((ShowHeroShotImageFragmentPagerAdapter) pager.getAdapter())
                        .getItem(pager.getCurrentItem() + 1);
                sampleFragment.scaleImage(1 - RATIO_SCALE);
                sampleFragment.disableClicks();
            }
        }
    }
};

Это он. Я не опубликовал полное решение, но надеюсь, что этого достаточно, чтобы заставить кого-то начать.

P.S. В 3.0+ включить аппаратное ускорение. Без него прокрутка выглядела изменчивой на вкладке галактики samsung 10.1.

Ответ 2

Я играл с ним, и мое решение довольно простое. Я размещаю его здесь, если кто-то заинтересован.

Во-первых, макет для каждого фрагмента должен допускать некоторые пробелы с обеих сторон. самый простой способ, который я нашел, это использовать вес:

<LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="0.1" />

<LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="0.8"
    android:orientation="vertical" >

    <!-- fragment contents go here -->

</LinearLayout>

<LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="0.1" />

Это даст хороший 10% -ный запас с обеих сторон. Не забудьте установить фон на них, так как он будет охватывать соседние фрагменты. Теперь для самого пейджера: вам нужно использовать отрицательные поля, как объяснил AngraX, но также обязательно предварительно загрузите последующие фрагменты, так как они будут видны до того, как они будут регулярно. Я получил хорошие результаты:

    mPager = (ViewPager) findViewById(R.id.pager);
    mPager.setAdapter(mAdapter);
    mPager.setPageMargin(getResources().getDisplayMetrics().widthPixels / -7);
    mPager.setOffscreenPageLimit(2);

значение -7 оставляет краю следующего фрагмента видимым, поиграйте со своей конкретной композицией. Я также рекомендую кадрировать каждый фрагмент.

Ответ 3

Ну, вот потенциальный ответ, который может быть близок к тому, что вы ищете, но не совсем то, что вы ищете: существует проект под названием ViewFlow, который, как я думаю, дает возможность уведомить пользователя о том, что на экране есть больше просмотров через индикаторы. Он также обеспечивает возможность буферизации представлений слева и справа от вашего текущего вида, поэтому вы могли бы вытолкнуть код, чтобы отображать небольшие части из них, в основном уменьшая то, что он рассматривает как его доступный размер экрана.

Править: Глупо меня; Прежде чем ответить, я должен прочитать последний вопрос.:) Я не думаю, что вы можете сделать это с помощью ViewFlipper или Viewpager, к сожалению.

Ответ 4

Просто используйте ViewPager и играйте с шириной фрагментов и полей. Я сделал это, и все работает нормально.