10

Я пытаюсь поместить ImageView в CollapsingToolbarLayout, в котором он загружает весь экран при загрузке, а при прокрутке содержимого ширина изображения с разрешением 16x9 изменяется до размера изображения занимает всю ширину экрана. В этот момент я хотел бы изображение параллакса с app:layout_collapseParallaxMultiplier от 0,5Проблема с CoordinatorLayout и ImageView, которая регулирует ширину при прокрутке

Используя этот XML Layout:

<?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> 

выполняет следующие:

enter image description here

, который показывает следующие каковы фактические границы изображения:

enter image description here

Как я перечисляю, я хотел бы больше ширины изображения, чтобы показать, как высота изображения сжимается и приводит следующее:

enter image description here

После того, как я добраться до этой точки, это где я хотел бы, чтобы коллапс-параллаксный множитель 0,5 вступил в силу.

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

Должен ли я создать свой собственный CoordinatorLayout.Behavior для этого?

+0

Можете ли вы показать эффект прокрутки вашего фактического xml (некоторый фрейм или анимированный gif)? – GPack

ответ

12

Вы можете достичь того, чего хотите, отслеживая вертикальное смещение AppBarLayout. Он имеет красивый метод addOnOffsetChangedListener, поэтому вы можете масштабировать изображение в зависимости от смещения AppBarLayout.

Итак, есть три вещей, которые вы должны сделать, чтобы заставить его работать:

  1. Вы должны поместить изображение в drawable-nodpi папку, чтобы предотвратить Android от его масштабировании для различных размеров экрана ,
  2. Меняйте ImageView «ы собственности scaleType к matrix - это необходимо, как мы будем менять матрицу этого ImageView сами.
  3. Реализовать addOnOffsetChangedListener для вас AppBarLayout по следующему пути:

    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 «s исходный код для определения границ, когда он имеет centerCrop тип шкалы, а затем просто вычислить масштаб и перевод матрицы в зависимости от verticalOffset. Если значение шкалы меньше 1.0f, мы только достигли точки, в которой соотношение сторон нашего представления равно отношению к размеру drawable, и нам не нужно масштабировать больше.

Примечание:

  1. Она будет работать, как вы хотите, только с изображением, ширина> высота, в противном случае его поведение будет таким же, как centerCrop
  2. Это будет работать только если ваш parallaxMultiplier находится между 0 и 1.

Как это выглядит для меня:

enter image description here

+0

Были ли какие-либо другие изменения для XML, которые я предоставил, кроме изменения scaleType в Matrix? Я добавил слушателя, но он не сделал его похожим на вашу анимацию, просто изменил образ изображения и все еще выполняет предыдущий параллаксинг. – hooked82

+0

Хм, странно. Да, мой XML полностью равен вашему, просто с одним изменением - 'android: scaleType =" matrix ". Я также разместил свой XML с помощью редактирования, проверьте это. Может быть, вы забыли что-нибудь – rom4ek

+0

Какое у вас решение получилось? – rom4ek