14

そのため、高低を検索しましたが、質問に対する答えが見つかりませんでした。基本的に必要なのは、Android の ViewFlipper または ViewPager によって提供される動作ですが、選択したビューが画面全体を占めるのではなく、スクロールする要素があることをユーザーに示すために、左右のビューの一部を表示したいと考えています。

また、左側と側面のビューにいくつかの効果を追加したいと思います。たとえば、減光や縮小などです。ストックのViewFlipperまたはViewPagerでそれを行うことは可能ですか、それともカバーフローのように独自のビューグループを展開する必要がありますか( http://www.inter-fuser.com/2010/01/android-coverflow-widget .html )?

(PS ギャラリー ウィジェットは使いたくありません。そのコンポーネントは最悪です)。

これは、ビューが選択されたら表示する必要があるものです (左右のビューは引き続き表示されます)。

ビュースイッチャー

左または右にフリングすると、メイン ビューが外側に移行し、少し暗くなって小さくなり、次または前のビューで反対のことが行われます。

4

4 に答える 4

16

同じ機能が必要な人にアップデートを提供したいと思います。これまでのところ、この機能の実装には多くの進歩があり、現在、ビューは必要に応じて正確に機能しています。

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's surprisingly complicated to get the current object being displayed by
        // a ViewPager (there's no getCurrentObject method). ScaleableFragment is just
        // a custom class to allow an adapter to cache it internally and also correctly
        // manage a fragment's 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();
            }
        }
    }
};

これだよ。私は完全な解決策を投稿しませんでしたが、これが他の誰かを始めるのに十分であることを願っています。

PS On 3.0+は、ハードウェアアクセラレーションを有効にします。それがないと、サムスンギャラクシータブ10.1でスクロールが途切れ途切れに見えました。

于 2012-05-04T04:25:25.690 に答える
4

私はそれでいくつか遊んだ、そして私の解決策はかなり単純である。誰かが興味を持った場合に備えて、ここに投稿します。

まず、各フラグメントのレイアウトでは、両側にいくつかのギャップを設ける必要があります。これを行うために私が見つけた最も簡単な方法は、重みを使用することです。

<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の値は、次のフラグメントのエッジを表示したままにし、特定のコンポジションで遊んでください。また、各フラグメントをフレーミングすることをお勧めします。

于 2012-09-24T13:58:58.433 に答える
2

さて、これはあなたが探しているものに近いかもしれないが、あなたが探しているものとは異なる可能性のある答えです: ViewFlowと呼ばれるプロジェクトがあり、インジケーターを介してより多くのビューがあることをユーザーに通知する機能を提供すると思います画面上。また、現在のビューの左右にビューをバッファリングする機能も提供するため、コードを突っ込んで、表示されるものを利用可能な画面サイズとして基本的に縮小することで、それらの小さな部分をレンダリングできる場合があります。

編集:愚かな私; 答える前に最後の質問を読むべきです。:)残念ながら、ViewFlipperまたはViewpagerでこれを行うことはできないと思います。

于 2012-04-03T21:21:13.790 に答える
1

ViewPager を使用して、フラグメントとマージンの幅で遊んでください。私はそうしました、そしてそれはうまくいきます。

于 2012-05-14T20:05:14.827 に答える