10

Próbuję wstawić ImageView w postaci , w której zajmuje on cały ekran podczas ładowania, a podczas przewijania zawartości szerokość obrazu o rozmiarze 16x9 zmienia się do momentu, aż obraz zajmuje całą szerokość ekranu. W tym momencie chciałbym obraz do paralaksy z app:layout_collapseParallaxMultiplier 0,5Problem z funkcją CoordinatorLayout i ImageView dostosowującą szerokość podczas przewijania

Stosując ten układ 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> 

realizuje następujące:

enter image description here

których następujące programy jakie są rzeczywiste granice obrazu:

enter image description here

Jak przewijać, chciałbym więcej szerokości obrazu, aby pokazać, jak wysokość obrazu kurczy i wyniki w następujących przypadkach:

enter image description here

Raz dostać się do tego punktu, to gdzie Chciałbym, aby mnożnik paralaksy zwinięcia wynosił 0,5.

Złamałem wiele różnych stylów przewijania, wypróbowałem wszystkie typy przewijania ImageView, bez rezultatu. Czy ktokolwiek wie, czy jest to możliwe, a jeśli tak, to może dostarczyć wszelkich wskazówek do tego, co robię źle lub nie robię.

Czy muszę wykonać własne zamówienie CoordinatorLayout.Behavior, aby to wykonać?

+0

Czy możesz pokazać efekt przewijania rzeczywistego xml (niektóre klatki lub animowany gif)? – GPack

Odpowiedz

12

Możesz osiągnąć to, co chcesz, śledząc przesunięcie pionowe AppBarLayout. Ma piękną metodę: addOnOffsetChangedListener, więc możesz skalować obraz w zależności od przesunięcia AppBarLayout.

Tak, istnieje trzy rzeczy, które trzeba zrobić, aby dostać pracy:

  1. Trzeba umieścić obraz w drawable-nodpi folderu, aby zapobiec Android od skalowanie go do różnych rozmiarów ekranu .
  2. zmienić ImageView „s własności scaleType do matrix - jest to potrzebne, gdyż będziemy zmieniać macierz tego ImageView sami.
  3. Wdrożenie addOnOffsetChangedListener dla Ciebie AppBarLayout przez następny sposób:

    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); 
         } 
        } 
    }); 
    

co zrobiłem tutaj jest po prostu ImageView „s kodu źródłowego w celu określenia granic, gdy ma centerCrop rodzaju skali, a następnie po prostu obliczyć skalę i tłumaczenie macierzy w zależności od verticalOffset. Jeśli wartość skali jest mniejsza niż 1,0f, właśnie osiągnęliśmy punkt, w którym współczynnik proporcji naszego widoku jest równy współczynnikowi proporcji rysowania i nie musimy skalować więcej.

Uwaga:

  1. będzie działać jak chcesz, tylko z obrazem, którego szerokość> wysokość, w przeciwnym razie jego zachowanie będzie taka sama jak centerCrop
  2. będzie działać tylko wtedy, gdy parallaxMultiplier jest między 0 i 1.

Jak to wygląda dla mnie:

enter image description here

+0

Czy były jakieś inne modyfikacje XML-a, które dostarczyłem, poza zmianą scaleType na Matrix? Dodałem słuchacza, ale nie sprawiło to, że wygląda jak twoja animacja, tylko zmieniło wygląd obrazu i nadal robi poprzednie paralaksy. – hooked82

+0

Hm, to dziwne. Tak, mój XML jest całkowicie równy twojemu, z jedną zmianą - 'android: scaleType =" matrix "'. Opublikowaliśmy również mój XML wraz z edycją, sprawdź to. Może zapomniałeś o czymś – rom4ek

+0

Jaka jest twoja rozdzielczość obrazu? – rom4ek

Powiązane problemy