像Whatsapp个人资料一样在滚动上折叠/调整图像大小

时间:2016-08-05 20:23:40

标签: android xml android-activity scroll android-recyclerview

我正在创建一个带有recyclerview的应用程序。在RV上方我有一个图像,当我滚动时它会变小。这样可行,但RV也会滚动。我希望首先图像变小,然后recyclelerview开始滚动。但是我怎么能这样做呢?这是我的XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/b"
        android:id="@+id/test_photo"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="test"/>

    </LinearLayout>
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        app:layout_anchor="@+id/test_photo"
        android:background="@color/colorPrimary"
        app:layout_anchorGravity="bottom|start">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/colorWhite"
            android:textSize="30sp"
            android:text="username"/>
    </LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/user_view_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

这是调整图像大小的代码:

rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
                float state = 0.0f;

                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, final int dy) {
                    Log.e("Y",Integer.toString(dy));
                    state+=dy;
                    LinearLayout img = (LinearLayout) findViewById(R.id.test_photo);
                    Log.e("STATE", Float.toString(state));
                    if(state >= 500){
                        img.getLayoutParams().height = minWidth;
                        img.getLayoutParams().width = minWidth;
                        img.requestLayout();
                    }
                    if(state <= 0){
                        img.getLayoutParams().height = imgHeight;
                        img.getLayoutParams().width = imgHeight;
                        img.requestLayout();
                    }
                    if(state > 0 && state < 500){

                        //up
                        img.getLayoutParams().height = (int)(imgHeight - ((float)(imgHeight-minWidth)/500)*state);
                        img.getLayoutParams().width = (int)(imgHeight - ((float)(imgHeight-minWidth)/500)*state);
                        img.requestLayout();

                    }
                }
            });

感谢您的帮助!

编辑:

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.AppBarLayout
    android:id="@+id/app_bar"
    android:layout_width="match_parent"
    android:layout_height="320dp"
    android:fitsSystemWindows="true"
    android:theme="@style/AppTheme.AppBarOverlay">

    <com.obware.alifsto.HelpClasses.CollapsingImageLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:minHeight="108dp"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <ImageView
            android:id="@+id/background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            android:scaleType="centerCrop"
            android:src="@drawable/sunset" />

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize" />

        <ImageView
            android:id="@+id/avatar"
            android:layout_width="96dp"
            android:layout_height="96dp"
            android:layout_gravity="bottom|center_horizontal"
            android:layout_marginBottom="96dp"
            android:src="@drawable/logo_blau_weiss"
            android:transitionName="@string/transition_userview_image"/>

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center_horizontal"
            android:layout_marginBottom="48dp"
            android:text="Title"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/subtitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center_horizontal"
            android:layout_marginBottom="24dp"
            android:text="Subtitle "
            android:transitionName="@string/transition_userview_username"
            android:textAppearance="?android:attr/textAppearanceMedium" />

    </com.obware.alifsto.HelpClasses.CollapsingImageLayout>

</android.support.design.widget.AppBarLayout>


<android.support.v7.widget.RecyclerView
    android:id="@+id/user_interface_recycler"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">


</android.support.v7.widget.RecyclerView>

2 个答案:

答案 0 :(得分:4)

您希望这样做的方式是使用CoordinatorLayoutAppBarLayout并使用所有Material Design滚动优势。

基本上你所做的就是创建一个类似于CollapsingToolbarLayout的专用布局。对于我的演示,我使用该类中的代码作为灵感来使我的折叠图像布局工作。

使其有效的原因是将布局添加为AppBarLayout的直接子项,然后创建AppBarLayout.OnOffsetChangeListener并将其注册到AppBarLayout。执行此操作时,您将在用户滚动并向上滚动布局时收到通知。

另一个重要部分是设定最小高度。 AppBarLayout使用最小高度来确定何时停止滚动布局,为您留下折叠的布局区域。

这是一段代码摘录:

    class OnOffsetChangedListener implements AppBarLayout.OnOffsetChangedListener {

        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {

            final int insetTop = mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0;
            final int scrollRange = appBarLayout.getTotalScrollRange();
            float offsetFactor = (float) (-verticalOffset) / (float) scrollRange;
            Log.d(TAG, "onOffsetChanged(), offsetFactor = " + offsetFactor);


            int childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = getChildAt(i);
                final ViewOffsetHelper offsetHelper = getViewOffsetHelper(child);

                if (child instanceof Toolbar) {
                    if (getHeight() - insetTop + verticalOffset >= child.getHeight()) {
                        offsetHelper.setTopAndBottomOffset(-verticalOffset); // pin
                    }
                }

                if (child.getId() == R.id.background) {
                    int offset = Math.round(-verticalOffset * .5F);
                    offsetHelper.setTopAndBottomOffset(offset); // parallax
                }

                if (child.getId() == R.id.avatar) {

                    float scaleFactor = 1F - offsetFactor * .5F ;
                    child.setScaleX(scaleFactor);
                    child.setScaleY(scaleFactor);

                    int topOffset = (int) ((mImageTopCollapsed - mImageTopExpanded) * offsetFactor) - verticalOffset;
                    int leftOffset = (int) ((mImageLeftCollapsed - mImageLeftExpanded) * offsetFactor);
                    child.setPivotX(0);
                    child.setPivotY(0);
                    offsetHelper.setTopAndBottomOffset(topOffset);
                    offsetHelper.setLeftAndRightOffset(leftOffset);
                }

                if (child.getId() == R.id.title) {

                    int topOffset = (int) ((mTitleTopCollapsed - mTitleTopExpanded) * offsetFactor) - verticalOffset;
                    int leftOffset = (int) ((mTitleLeftCollapsed - mTitleLeftExpanded) * offsetFactor);
                    offsetHelper.setTopAndBottomOffset(topOffset);
                    offsetHelper.setLeftAndRightOffset(leftOffset);
                    Log.d(TAG, "onOffsetChanged(), offsetting title top = " + topOffset + ", left = " + leftOffset);
                    Log.d(TAG, "onOffsetChanged(), offsetting title mTitleLeftCollapsed = " + mTitleLeftCollapsed + ", mTitleLeftExpanded = " + mTitleLeftExpanded);
                }

                if (child.getId() == R.id.subtitle) {

                    int topOffset = (int) ((mSubtitleTopCollapsed - mSubtitleTopExpanded) * offsetFactor) - verticalOffset;
                    int leftOffset = (int) ((mSubtitleLeftCollapsed - mSubtitleLeftExpanded) * offsetFactor);
                    offsetHelper.setTopAndBottomOffset(topOffset);
                    offsetHelper.setLeftAndRightOffset(leftOffset);
                }
            }
        }
    }

child.setScaleX()child.setScaleY()是实际更改图片大小的代码。

演示应用程序位于https://github.com/klarson2/Collapsing-Image的GitHub上。享受。

编辑:添加TabLayout后,我意识到我在布局中犯了一个错误,即将AppBarLayout设置为固定高度,然后使自定义折叠组件高度为match_parent 。这使得您无法看到添加到应用栏的TabLayout。我更改了布局,以使AppBarLayout高度为wrap_content,并且自定义折叠组件具有固定高度。这样就可以向TabLayout添加AppBarLayout之类的其他组件。这已在GitHub的最新版本中得到纠正。

答案 1 :(得分:0)

使用以下代码,我根据滚动调整图像的大小。这样您就可以在AppBar中看到它的折叠状态。

在折叠AppBar时播放动画的持续时间值和缩放值。

就我而言,我的工具栏是透明的,我在运行时管理AppBar元素的颜色。

@Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
        /**
        * Collapsed
         */
        if (Math.abs(verticalOffset) == appBarLayout.getTotalScrollRange()) {
            myImage.animate().scaleX((float)0.4).setDuration(3000);
            myImage.animate().scaleY((float)0.4).setDuration(3000);
            myImage.animate().alpha(1).setDuration(0);

            /**
             * EXPANDED
             */
        } else if (verticalOffset == 0) {
            myImage.animate().scaleX((float)1).setDuration(100);
            myImage.animate().scaleY((float)1).setDuration(100);
            myImage.animate().alpha(1).setDuration(0);
            /**
             * Somewhere in between
             */
        } else {
            final int scrollRange = appBarLayout.getTotalScrollRange();
            float offsetFactor = (float) (-verticalOffset) / (float) scrollRange;
            float scaleFactor = 1F - offsetFactor * .5F;
            myImage.animate().scaleX(scaleFactor);
            myImage.animate().scaleY(scaleFactor);
        }
    }

PD:无论图像是否超出AppBar的限制,该功能都可以工作,就像图像是浮动按钮一样。

GL

来源