web-dev-qa-db-ja.com

Android RecyclerViewのスムーズなスクロールで、高さをアニメーション化して表示します

展開可能な子ビューを備えたRecyclerViewがあります。子ViewGroupをクリックすると、次のgifのように、ViewGroupの高さを0から測定されたビューグループの高さまでアニメーション化するビューの量が膨らみます。

example

問題は次のとおりです。recyclerViewでsmoothScrollToPositionを呼び出しています。ビュー位置までスムーズにスクロールしますが、recyclerviewのアンダービューで触れている上記のgifで、まだ展開されていない現在のビューの高さを考慮します。ビューがすでに表示されているため、位置にスクロールしませんが、もう一度タッチすると(smoothscrolltopositionを再度呼び出す)、ビューが既に展開されているため、ビューを正しい位置にスクロールします。

ビューを画面の一番上までスクロールする方法、または単にスクロールしてコンテンツを表示する方法はありますか?

参考までに:これは、ビューを膨らませるために呼び出されるメソッドです。

collapsible_content.removeAllViews();
for(int i = 0; i < 5; i++) {
        View link_view = getLayoutInflater().inflate(R.layout.list_item_timeline_step_link, collapsible_content, false);
        TextView text = (TextView) link_view.findViewById(R.id.step_link_text);
        text.setText("Test");
        collapsible_content.addView(link_view);
    }

そして、これは私の拡張方法です。

public void toggle() {
        collapsible_content.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        Animation a;
        if (mExpanded) {
            a = new ExpandAnimation(collapsible_content.getLayoutParams().height, 0);
        } else {
            a = new ExpandAnimation(collapsible_content.getLayoutParams().height, getMeasuredHeight());
        }
        a.setDuration(mAnimationDuration);
        collapsible_content.startAnimation(a);
        mExpanded = !mExpanded;
    }

そしてアニメーション:

private class ExpandAnimation extends Animation {
        private final int mStartHeight;
        private final int mDeltaHeight;

        public ExpandAnimation(int startHeight, int endHeight) {
            mStartHeight = startHeight;
            mDeltaHeight = endHeight - startHeight;
        }

        @Override
        protected void applyTransformation(float interpolatedTime,
                                           Transformation t) {
            final int newHeight = (int) (mStartHeight + mDeltaHeight *
                    interpolatedTime);
            collapsible_content getLayoutParams().height = newHeight;

            if (newHeight <= 0) {
                collapsible_content setVisibility(View.GONE);
            } else {
                collapsible_content setVisibility(View.VISIBLE);
            }
            collapsible_content requestLayout();
        }


        @Override
        public boolean willChangeBounds() {
            return true;
        }
    }
8
Yuri Heupa

私の解決策は、applyTransformationメソッド内でビューの下部を常にチェックし、それをRecyclerViewの高さと比較することでした。下部がRVの高さよりも高くなった場合は、差分値でスクロールします。

final int bottom = collapsible_content.getBottom();
final int listViewHeight = mRecyclerView.getHeight();
if (bottom > listViewHeight) {
    final int top = collapsible_content.getTop();
    if (top > 0) {
        mRecyclerView.smoothScrollBy(0, Math.min(bottom - listViewHeight + mRecyclerView.getPaddingBottom(), top));
    }
}

秘訣は、Math.minを使用してビューの上部を取得することでした。これにより、上にスクロールして上部が表示されなくなります。

ListViewAnimations に基づくソリューション

8
Yuri Heupa

アニメーションリスナーを追加し、アニメーションの展開が終了したら、リサイクラービューのスクロールを開始します。

0
Mann