24

Sto seguendo il progetto di esempio Cheesesquare per comprendere la nuova libreria di materiali di progettazione.Android CollapsingToolbarLayout con visualizzazione personalizzata

Mi chiedo se c'è un modo per utilizzare una visualizzazione personalizzata (come Telegram) con ImageView, titolo e sottotitoli al posto del semplice Titolo fornito dal widget CollapsingToolbarLayout.

Grazie.

+0

Hai provato un 'CollapsingToolbarLayout' contenente prima un 'ImageView' e poi un' LinearLayout' con 2 'TextView's? – shkschneider

+0

Ho provato, ma il mio scopo è la sostituzione del titolo con il mio CustomView per preservare l'animazione del titolo nella barra degli strumenti. – CeccoCQ

+0

@shkschneider spiegheresti un po 'di più. Voglio usare –

risposta

21

Ho avuto lo stesso problema e ho passato molte ore a cercare una soluzione. La mia soluzione era aggiungere le viste compresse (ImageView e TextView) all'interno dello CollapsingToolbarLayout e quindi gestire la transizione nel codice. In questo modo è più flessibile e più semplice dell'estensione da CollapsingToolbarLayout.

primo luogo è necessario aggiungere le vostre opinioni all'interno del CollapsingToolbarLayout con le proprietà di parallasse:

 <ImageView 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:paddingTop:"80dp" 
      android:src="@drawable/icon" 
      app:layout_collapseMode="parallax" 
      app:layout_collapseParallaxMultiplier="0.8"/> //set vertical transition here 

quindi impostare la scala delle opinioni con l'aiuto di un OnOffsetchangeListner:

private static final float SCALE_MINIMUM=0.5f; 
    appBarLayout.setOnWorkingOffsetChange(new ControllableAppBarLayout.OnWorkingOffsetChange() { 
     @Override 
     public void onOffsetChange(int offSet, float collapseDistance) { 
      imageView.setScaleX(1 + (collapseDistance * SCALE_MINIMUM)); 
      imageView.setScaleY(1 + (collapseDistance * SCALE_MINIMUM)); 

      textView.setScaleX(1 + (collapseDistance * SCALE_MINIMUM)); 
      textView.setScaleY(1 + (collapseDistance * SCALE_MINIMUM)); 

      // You can also setTransitionY/X, setAlpha, setColor etc. 
     } 
    }); 

In qualche modo il valore predefinito offsetChangedListener non ha funzionato correttamente per me (probabilmente dovresti provarlo con il listener predefinito per primo), quindi ho utilizzato lo ControllableAppBarLayout da https://gist.github.com/blipinsk/3f8fb37209de6d3eea99 e aggiunto quanto segue:

private OnWorkingOffsetChange onWorkingOffsetChange; 

@Override 
public void onOffsetChanged(AppBarLayout appBarLayout, int i) { 
    if (!isInEditMode()) { 
     onWorkingOffsetChange.onOffsetChange(i, (float) i/appBarLayout.getTotalScrollRange()); 
    } 
} 

public void setOnWorkingOffsetChange(OnWorkingOffsetChange listener) { 
    this.onWorkingOffsetChange = listener; 
} 

public interface OnWorkingOffsetChange { 
    void onOffsetChange(int offSet, float collapseDistance); 
} 

L'unico problema è che si avrebbe bisogno di impostare app:contentScrim="#00000000" (trasparente) per il vostro CollapsingToolbarLayout, in modo che le opinioni sono ancora visibili quando la barra è compressa. Se hai davvero bisogno dell'effetto background collassante, sono sicuro che potresti "simulare" questo impostando l'alfa di uno sfondo ImageView nello OffsetChangeListener. ;)

+0

spiegheresti per favore un po 'di più. Ho lo stesso problema, voglio solo usare un'icona e un titolo al centro di 'CollapsingToolBarLayout' quando scorrono verso l'alto di quanto l'icona deve volare alla sinistra della barra degli strumenti dove normalmente l'icona della app esiste e il titolo è nella parte destra di icona. –

2

Dal widget stesso non sembra essere un modo per abilitarlo direttamente, come è stato possibile aggiungere viste personalizzate alla barra degli strumenti.

Ciò che si potrebbe provare, tuttavia, è aprire la fonte di CollapsingToolbarLayout.class e verificare come viene utilizzato il set CollapsingTextHelper.class. Puoi provare a creare il tuo widget estendendolo dallo CollapsingToolbarLayout.

Questi link possono aiutare con la creazione di componenti personalizzati/viste, se non li avete creato in precedenza: Custom Views, Custom Components

non ho ancora provato questo, ma in realtà è qualcosa che stavo pensando cercando di ottenere una soluzione simile a quella che stai cercando. Passi che tihkn avrei seguito, finora: attributi

  1. Creare personalizzato per le impostazioni dei sottotitoli in attrs.xml
  2. Crea il tuo MyCollapsingToolbarLayout estendendo quella originale.
  3. Assicurarsi di chiamare super nei costruttori, in modo che il componente originale rimanga intatto.
  4. Creare un subtitleTextHelper aggiungendo un nuovo CollapsingTextHelper al componente.
  5. Ignora onDraw per disegnare effettivamente i sottotitoli.
  6. Aggiorna il layout contenente il tuo CollapingsToolbarLayout con gli attributi dei sottotitoli (stile predefinito e così, forse un testo di sottotitoli fisso).
  7. Applicare le modifiche allo Activity contenente il numero CollapsingToolbar. (Converti CollapsingToolbarlayout in MyCollapingsToolbarLayout, imposta i sottotitoli, impostazioni personalizzate extra, ecc.).
  8. Incrocio, test.

Andare a dare un'occhiata ora.

+0

È stato davvero un duro lavoro. CollapsingToolbarLayout è un widget terribile. – CeccoCQ

+1

@ StingRay5 Puoi aiutarmi cosa fare all'interno di onDraw()? Oppure condividi il tuo codice. – Max

2

Andando a modificare un po 'la risposta di Christopher per mostrare come è possibile ottenere la visualizzazione personalizzata per non scomparire crollo:

primo luogo è necessario aggiungere le vostre opinioni all'interno del CollapsingToolbarLayout con le proprietà di parallasse:

 <ImageView 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:paddingTop:"80dp" 
      android:src="@drawable/icon" 
      app:layout_collapseMode="parallax" 
      app:layout_collapseParallaxMultiplier="0.8"/> //set vertical transition here 

Invece aggiungere della visualizzazione personalizzata a livello di codice e non scomparirà il collasso. Per esempio qui è una vista che contiene un titolo e un sottotitolo:

final FrameLayout frameLayout = new FrameLayout(mActivity); 
    FrameLayout.LayoutParams frameLayoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, 
      FrameLayout.LayoutParams.MATCH_PARENT); 
    frameLayout.setLayoutParams(frameLayoutParams); 


    // Create new LinearLayout 
    final LinearLayout linearLayout = new LinearLayout(mActivity); 
    frameLayoutParams =new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, dpToPixels(78)); 
    frameLayoutParams.gravity = Gravity.BOTTOM; 
    linearLayout.setLayoutParams(frameLayoutParams); 
    linearLayout.setOrientation(LinearLayout.VERTICAL); 


    // Add textviews 
    final TextView textView1 = new TextView(mActivity); 
    LinearLayout.LayoutParams linearLayoutParams =new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 
      LinearLayout.LayoutParams.WRAP_CONTENT); 
    frameLayoutParams.gravity = Gravity.BOTTOM; 
    textView1.setLayoutParams(linearLayoutParams); 
    textView1.setText("Title"); 
    textView1.setTextColor(ContextCompat.getColor(mActivity, R.color.colorWhite)); 
    textView1.setTextSize(TypedValue.COMPLEX_UNIT_SP, 40); 
    linearLayout.addView(textView1); 


    final TextView textView2 = new TextView(mActivity); 
    linearLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 
      LinearLayout.LayoutParams.WRAP_CONTENT); 
    textView2.setLayoutParams(linearLayoutParams); 
    textView2.setText("Subtitle"); 
    textView2.setTextColor(ContextCompat.getColor(mActivity, R.color.colorWhite)); 
    textView2.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20); 
    linearLayout.addView(textView2); 

    frameLayout.addView(linearLayout); 


    collapsingToolbar.addView(frameLayout); 
    final float SCALE_MIN=0.4f; 
    AppBarLayout appBarLayout = (AppBarLayout) mActivity.findViewById(R.id.appBarLayout); 
    appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { 
     @Override 
     public void onOffsetChanged(AppBarLayout appBarLayout, int offSet) { 
      float collapsedRatio = (float) offSet/appBarLayout.getTotalScrollRange(); 
      linearLayout.setScaleX(1 + (collapsedRatio * SCALE_MIN)); 
      linearLayout.setScaleY(1 + (collapsedRatio * SCALE_MIN)); 
      FrameLayout.LayoutParams frameLayoutParams =new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, dpToPixels(78)); 
      frameLayoutParams.gravity = Gravity.BOTTOM; 
      frameLayoutParams.setMargins(Math.round(dpToPixels(48) * (1+collapsedRatio)), 0, 0, Math.round(dpToPixels(15) * collapsedRatio)); 
      linearLayout.setLayoutParams(frameLayoutParams); 
      // You can also setTransitionY/X, setAlpha, setColor etc. 
     } 
    }); 

/////

float lastCollapsedRatio = -2; 

////

private int dpToPixels(int padding_in_dp){ 
    final float scale = getResources().getDisplayMetrics().density; 
    int padding_in_px = (int) (padding_in_dp * scale + 0.5f); 
    return padding_in_px; 
} 
+0

Grande trucco. Solo che improvvisamente ho ottenuto i miei registri pieni di quanto segue. Qualche idea su come evitarlo? (Gah, perché i commenti SO non possono supportare le interruzioni di riga?) 'requestLayout() impropriamente chiamato da android.support.design.widget.CollapsingToolbarLayout {a9c7244 V.ED ..... ...... I. 0,0-1440,405 # 7f1100fb app: id/collapsingToolbarLayout} durante il layout: esecuzione del secondo passaggio di layout' 'requestLayout() chiamato in modo errato da android.widget.LinearLayout {4058f2d VE ..... ...... IO. 168,132-1440,405} durante il layout: esecuzione del secondo passaggio di layout' –

+0

Ho aggiunto un controllo per vedere se 'collapsedRatio' è stato effettivamente modificato e solo in questi casi viene eseguito il ridimensionamento.Ciò ha fatto sparire tutte le lamentele sul secondo passaggio di layout. –

+0

Non ho usato questo codice da un po '. Ma ricordo di averlo incontrato. Dove hai aggiunto l'assegno? Posso aggiornare la mia risposta. @RoySolberg – luca992