アニメーションの場合、ビューからの高さを知る必要があります。問題は、ビューが描画されない限り、getHeight()メソッドが常に0を返すことです。だから、それを描画せずに高さを取得する方法はありますか?
この場合、ビューはLinearLayoutです。
編集: https://github.com/Udinic/SmallExamples/blob/master/ExpandAnimationExample/src/com/udinic/expand_animation_example/ExpandAnimation.Java からエキスパンドアニメーションを適応させようとしています。
それを使用して、リストアイテムの情報をさらに拡張します。 xmlを介して同じ効果を達成することができませんでした。現時点では、アニメーションを描画する前にレイアウトサイズがわかっている場合にのみ機能します。
高さを取得したいが、表示される前にビューを非表示にしたいようです。
ビューの可視性を可視または非可視に設定して開始します(高さが作成されるように)。以下に示すように、コード内で非表示/非表示に変更することを心配しないでください。
private int mHeight = 0;
private View mView;
class...
// onCreate or onResume or onStart ...
mView = findViewByID(R.id.someID);
mView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener(){
@Override
public void onGlobalLayout() {
// gets called after layout has been done but before display
// so we can get the height then hide the view
mHeight = mView.getHeight(); // Ahaha! Gotcha
mView.getViewTreeObserver().removeGlobalOnLayoutListener( this );
mView.setVisibility( View.GONE );
}
});
同様の状況で同様の問題が発生しました。
アニメーションの対象となるview
の高さを必要とするアニメーションを作成する必要がありました。 view
であるLinearLayout
は、TextView
型の子ビューになる場合があります。 TextView
は複数行であり、実際に必要な行数は異なります。
私が何をしたとしても、TextView
が1行だけであるかのように、ビューの測定された高さを取得しました。テキストがたまたま1行の長さになるたびにこれがうまく機能したのは不思議ではありませんが、テキストが行よりも長い場合は失敗しました。
私はこの答えを考えました: https://stackoverflow.com/a/6157820/854396 しかし、埋め込みTextView
にアクセスできないので、それは私にとってあまりうまく機能しませんでしたここから直接。 (ただし、子ビューのツリーを反復処理することもできました。)
今のところ動作する私のコードを見てください:
view
は、アニメーション化されるビューです。これはLinearLayout
です(最終的な解決策は、ここでもう少し型を保存します)this
は、view
を含み、LinearLayout
から継承するカスタムビューです。
private void expandView( final View view ) {
view.setVisibility(View.VISIBLE);
LayoutParams parms = (LayoutParams) view.getLayoutParams();
final int width = this.getWidth() - parms.leftMargin - parms.rightMargin;
view.measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
final int targetHeight = view.getMeasuredHeight();
view.getLayoutParams().height = 0;
Animation anim = new Animation() {
@Override
protected void applyTransformation( float interpolatedTime, Transformation trans ) {
view.getLayoutParams().height = (int) (targetHeight * interpolatedTime);
view.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
anim.setDuration( ANIMATION_DURATION );
view.startAnimation( anim );
}
これはほぼそれでしたが、私は別の間違いを犯しました。ビュー階層内には、LinearLayout
のサブクラスである2つのカスタムビューが含まれ、それらのxmlはxmlルートタグとしてmerge
タグにマージされます。これらのmerge
タグのいずれかで、Android:orientation
属性をvertical
に。このマージされたViewGroup
の中にはただ1つの子ViewGroup
があり、そのため実際には画面上で間違った方向を見ることができなかったため、レイアウト自体にはあまり気にしませんでした。しかし、そこにあり、このレイアウト測定ロジックを少し壊しました。
上記に加えて、ビュー階層内のLinearLayout
sおよびサブクラスに関連付けられたすべてのパディングを取り除くことが必要になる場合があります。同じように見えるように別のレイアウトをラップする必要がある場合でも、マージンで置き換えます。
技術的には、ビューでmeasure
メソッドを呼び出し、getMeasureHeight
を介してその高さを取得できます。詳細はこちらをご覧ください: https://developer.Android.com/guide/topics/ui/how-Android-draws.html 。ただし、MeasureSpec
を指定する必要があります。
しかし実際には、ビューのサイズはその親レイアウトの影響を受けるため、実際に描画されるときとは異なるサイズになる場合があります。
また、RELATIVE_TO_SELF
アニメーションの値。
static void getMeasurments(View v) {
v.measure(View.MeasureSpec.makeMeasureSpec(PARENT_VIEW.getWidth(),
View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED));
final int targetHeight = v.getMeasuredHeight();
final int targetWidth = v.getMesauredWidth();
}
更新された投稿については、次のことが役立ちます。 Animation#initialize method。コンストラクタの代わりに初期化を配置するだけで、必要なサイズがすべて揃います。
親がそのサイズを決定しない場合は、自分で測定します。
常にあなたのためにそれを行うためのビュー上のkotlin拡張があります:
fun View.getMeasurments(): Pair<Int, Int> {
measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
val width = measuredWidth
val height = measuredHeight
return width to height
}