CoordinatorLayout和ImageView在滚动时会调整宽度的问题 [英] Issue with CoordinatorLayout and ImageView that adjusts width while scrolling

本文介绍了CoordinatorLayout和ImageView在滚动时会调整宽度的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将ImageView放在CollapsingToolbarLayout中,使其在加载时占据全屏,并且在滚动内容时,将调整16x9分辨率图像的宽度,直到图像占满整个屏幕的宽度.屏幕.那时,我希望图像的app:layout_collapseParallaxMultiplier为视差

I'm attempting to put an ImageView in a CollapsingToolbarLayout in which it takes up the full screen on load and as you scroll the content, the 16x9 resolution image width resizes until the image takes up the full width of the screen. At that point, I'd like the image to parallax with a app:layout_collapseParallaxMultiplier of 0.5

使用此XML布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

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

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/img_hero"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:scaleType="centerCrop"
                android:src="@drawable/lake"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.5"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="none"
                app:popupTheme="@style/AppTheme.PopupOverlay"/>

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

    <include layout="@layout/content_scrolling"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|end"
        app:srcCompat="@android:drawable/ic_dialog_email"/>

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

完成以下操作:

以下内容显示了图像的实际边界:

Which the following shows what the actual boundaries of the image are:

在滚动时,我希望随着图像高度的缩小而显示更多的图像宽度,并产生以下结果:

As I scroll, I would like more of the image width to show as the height of the image shrinks and results in the following:

到这一点,这就是我希望折叠视差倍数0.5生效的地方.

Once I get to this point, this is where I would like the collapse parallax multiplier of 0.5 to take effect.

我搞砸了许多不同的滚动行为,尝试了所有ImageView scrollTypes,但无济于事.有谁知道这是否可能,如果可以,可以提供任何指示我做错了还是没有做的事情.

I've messed with many different scroll behaviors, tried all of the ImageView scrollTypes, to no avail. Does anybody know if this is possible and if so, can provide any pointers into what I'm either doing wrong or not doing.

我需要创建自己的自定义CoordinatorLayout.Behavior来完成此操作吗?

Do I need to create my own custom CoordinatorLayout.Behavior to accomplish this?

推荐答案

您可以通过跟踪AppBarLayout的垂直偏移量来实现所需的功能.它具有漂亮的方法addOnOffsetChangedListener,因此您可以根据AppBarLayout的偏移量缩放图像.

You can achieve what you want by tracking vertical offset of AppBarLayout. It has beautiful method addOnOffsetChangedListener, so you can scale your image depending on offset of AppBarLayout.

因此,要使其正常运行,您需要执行件事:

So, there are three things that you have to do to get it working:

  1. 您需要将图片放置在drawable-nodpi文件夹中,以防止Android将其缩放为不同的屏幕尺寸.
  2. 将您的ImageView的属性scaleType更改为matrix-这是必需的,因为我们将自己更改此ImageView的矩阵.
  3. 通过以下方式为您AppBarLayout实施addOnOffsetChangedListener:

  1. You need to place your image into drawable-nodpi folder, to prevent Android from scaling it for different screen sizes.
  2. Change your ImageView's property scaleType to matrix - it's needed as we will change matrix of this ImageView by ourselves.
  3. Implement addOnOffsetChangedListener for you AppBarLayout by next way:

final ImageView imageView = (ImageView) findViewById(R.id.img_hero);
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.app_bar);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
        Matrix matrix = new Matrix(imageView.getImageMatrix());

        //get image's width and height
        final int dwidth = imageView.getDrawable().getIntrinsicWidth();
        final int dheight = imageView.getDrawable().getIntrinsicHeight();

        //get view's width and height
        final int vwidth = imageView.getWidth() - imageView.getPaddingLeft() - imageView.getPaddingRight();
        int vheight = imageView.getHeight() - imageView.getPaddingTop() - imageView.getPaddingBottom();

        float scale;
        float dx = 0, dy = 0;
        float parallaxMultiplier = ((CollapsingToolbarLayout.LayoutParams) imageView.getLayoutParams()).getParallaxMultiplier();

        //maintain the image's aspect ratio depending on offset
        if (dwidth * vheight > vwidth * dheight) {
            vheight += (verticalOffset); //calculate view height depending on offset
            scale = (float) vheight / (float) dheight; //calculate scale
            dx = (vwidth - dwidth * scale) * 0.5f; //calculate x value of the center point of scaled drawable
            dy = -verticalOffset * (1 - parallaxMultiplier); //calculate y value by compensating parallaxMultiplier
        } else {
            scale = (float) vwidth / (float) dwidth;
            dy = (vheight - dheight * scale) * 0.5f;
        }

        int currentWidth = Math.round(scale * dwidth); //calculate current intrinsic width of the drawable

        if (vwidth <= currentWidth) { //compare view width and drawable width to decide, should we scale more or not
            matrix.setScale(scale, scale);
            matrix.postTranslate(Math.round(dx), Math.round(dy));
            imageView.setImageMatrix(matrix);
        }
    }
});

我在这里所做的只是获取ImageView的源代码,以确定其具有centerCrop比例类型时的范围,然后仅根据verticalOffset计算比例和矩阵平移.如果比例值小于1.0f,那么我们就达到了视图的纵横比等于可绘制对象的纵横比的程度,并且不需要缩放更多.

What I did here is just get ImageView's source code to determine bounds when it has centerCrop scale type and then just calculate the scale and translation of matrix depending on verticalOffset. If scale value is less than 1.0f then we've just reached the point where our view's aspect ratio is equal to the drawable's aspect ratio, and we don't need to scale more.

注意 :

Note:

  1. 它将仅按宽度>高度的图像工作,否则其行为将与centerCrop
  2. 相同
  3. 仅当您的parallaxMultiplier介于0和1之间时,它才有效.
  1. It would work as you wish, only with the image whose width > height, otherwise its behavior would be the same as centerCrop
  2. It would work only if your parallaxMultiplier is in between 0 and 1.

对我的感觉如何

这篇关于CoordinatorLayout和ImageView在滚动时会调整宽度的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆