2015-12-08 17 views
10

collapseTextViewsのうち、次の2つの方法をScrollViewに「TextView」をクリックして使用します。Expand/Collapseアニメーション:スモールラグ|| MeasureSpecが間違った値を返します

擬似レイアウト構造:

<ScrollView> 
    <LinearLayout> 
     <LinearLayout> 
      <!-- some other stuff here --> 
     </LinearLayout> 
     <TextView "header1"/> 
     <View "fancydivider"/> 
     <TextView "content1"> 
     <TextView "header2"/> 
     <View "fancydivider"/> 
     <TextView "content2"> 
    </LinearLayout> 
</ScrollView> 

除算が単純View1dpheightセットです。たContent TextViewsスタイルが含まれています:

<item name="android:layout_height">0dp</item> 
    <item name="android:layout_width">match_parent</item> 

とある程度のマージン&パディングを。ここ

方法:ここ

public static void expand(final View v) { 

    //v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); 

    int matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec(((View) v.getParent()).getWidth(), View.MeasureSpec.EXACTLY); 
    int wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); 
    v.measure(matchParentMeasureSpec, wrapContentMeasureSpec); 

    final int targetHeight = v.getMeasuredHeight(); 

    // Older versions of android (pre API 21) cancel animations for views with a height of 0. 
    v.getLayoutParams().height = 1; 
    v.setVisibility(View.VISIBLE); 
    Animation a = new Animation() { 
     @Override 
     protected void applyTransformation(float interpolatedTime, Transformation t) { 
      v.getLayoutParams().height = interpolatedTime == 1 
        ? ViewGroup.LayoutParams.WRAP_CONTENT 
        : (int) (targetHeight * interpolatedTime); 
      scrollView.smoothScrollTo(0, (int) (targetHeight * interpolatedTime)); 
      v.requestLayout(); 
     } 

     @Override 
     public boolean willChangeBounds() { 
      return true; 
     } 
    }; 

    a.setInterpolator(easeInOutQuart); 
    a.setDuration(computeDurationFromHeight(v)); 
    v.startAnimation(a); 

} 

public static void collapse(final View v) { 
    final int initialHeight = v.getMeasuredHeight(); 

    Animation a = new Animation() { 
     @Override 
     protected void applyTransformation(float interpolatedTime, Transformation t) { 
      if (interpolatedTime == 1) { 
       v.setVisibility(View.GONE); 
      } else { 
       v.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime); 
       v.requestLayout(); 
      } 
     } 

     @Override 
     public boolean willChangeBounds() { 
      return true; 
     } 
    }; 

    a.setInterpolator(easeInOutQuart); 
    a.setDuration(computeDurationFromHeight(v)); 
    v.startAnimation(a); 
} 

private static int computeDurationFromHeight(View view) { 
    // 1dp/ms * multiplier 
    return (int) (view.getMeasuredHeight()/view.getContext().getResources().getDisplayMetrics().density) * 4; 
} 

問題:すべてが正常に動作します - expand animationは、テキストの最後の行に到達するまで - characters少なすぎるがそれに存在する場合、それはは、に遅れるジャンプ爆発する?完全に展開されるまで、あなたはそれを呼びたいと思っています。

Collapsingうまくいくようです。

私は他のInterpolator値を試しました。方法の別の乗数はcomputeDurationFromHeightでした。

いくつかのテスト:

    • 4行、4行目のすべてのは、以上の17の文字が18文字より少ない、正常に動作し、それが遅れています。

    • 最後の行の3行と無関係な量の文字が正常に動作します。

    • animationは、最初にexpandで動作しますが、2番目では動作しません。

    • TextViewが正しく計算されていないようです。私はexpandにいくつかのtextsmoothScrollToを削除する次のヘッダTextView
    • 上< 0.5秒間アップplopping見てきた高multiplierと(もちろんスクロールを除く。)何も変更しない
    • 他の補間も「しゃっくり」を持っています(下記参照)トンに私を得たapplyTransformation

    • いくつかのログ:重要

    、より短いです彼はポイント、私はfinal heightが表示されていることを確認2回 - 正確に50ポイント(ピクセル? dp?)の違い。 //smoothly increasing height and then: final height = 202 height = 252 final height = 252私はtargetHeight = 203を取得していますが、heightは最初に間違って計算されますが、その後にいくつかの魔法が発生しますか?


@Override 
protected void applyTransformation(float interpolatedTime, Transformation t) { 
    v.getLayoutParams().height = interpolatedTime == 1 
        ? ViewGroup.LayoutParams.WRAP_CONTENT 
        : (int) (targetHeight * interpolatedTime); 
    v.requestLayout(); 

    scrollView.smoothScrollTo(0, interpolatedTime == 1 
        ? v.getHeight() : (int) (targetHeight * interpolatedTime)); 

    Log.d("Anim", "height = " + v.getHeight()); 
    if (interpolatedTime == 1){ 
     Log.d("Anim", "final height = " + v.getHeight()); 
    } 
} 

誰もが私が行方不明です何を指摘することはできますか?

+0

補間された時刻が1かどうかを確認してから、高さをWRAP_CONTENTに設定する理由はありますか?なぜこれを行うのですか?高さが常にinterpolatedTime * targetHeightと等しいというだけではないのですか?補間された時間= 1の場合、高さはtargetHeightになります。私は終わりにWRAP_CONTENTに高さを設定することは、スタッターを引き起こしているものだと思う。 –

+0

私は上記のリンクから答えを取り出しました。もし 'interpolatedTime * targetHeight'だけを使うと最後の行はまったく表示されません。私はすでにこの問題が 'height'の間違った計算によって引き起こされていることを発見しました。:/ – yennsarah

+0

' v.requestLayout(); 'ビューを親に呼び出すlayout()メソッドとすべての子を再度レイアウトにします。連続した呼び出しは遅れにつながる可能性があります。レイアウトパラメータの代わりにRectをアニメーション化しようとします。 –

答えて

0

最後の要素を消費すると、レイアウトの高さが大きくなっているため、スクロールトリガする可能性があるので、それはディスプレイがダウン

ので、「プッシュ」、引き起こす可能性が20dpの高さと下部のでframeLayoutを追加し、しようとしてみてくださいオブザーバーそれはどんな違い

+0

残念ながら、これは何も変わりません。 – yennsarah

0

を行う場合、私はあなたが(アニメーションさTextViewの)<item name="android:layout_height">0dp</item>を変更する必要があることを99%確信しているwrap_contentなると、これはあなたが崩壊アニメーションの後、最終的な状態であると(GONEには、初期状態だ設定します)。

+0

これは動作しません。 :/ – yennsarah

関連する問題