139

アクティビティが作成された後、Androidアプリのビューにアニメーションを適用しようとしています。これを行うには、ビューの現在のサイズを決定してから、現在のサイズから新しいサイズに拡大縮小するアニメーションを設定する必要があります。ビューはユーザーからの入力に応じてさまざまなサイズに拡大縮小されるため、この部分は実行時に実行する必要があります。私のレイアウトはXMLで定義されています。

これは簡単な作業のように思えます。明らかに私の問題を解決したものはありませんが、これに関しては多くのSOの質問があります。だからおそらく私は明らかな何かを見逃しています。私は自分の見解を次のように把握しています。

ImageView myView = (ImageView) getWindow().findViewById(R.id.MyViewID);

これは正常に機能しますが、、、、などを呼び出すとgetWidth()getHeight()すべて0が返されます。ビューを手動で呼び出してからを呼び出すことも試みましたが、効果はありません。getMeasuredWidth()getLayoutParams().widthmeasure()getMeasuredWidth()

onCreate()これらのメソッドを呼び出して、デバッガーのアクティビティーとでオブジェクトを調べてみましたonPostCreate()。実行時にこのビューの正確な寸法を把握するにはどうすればよいですか?

4

13 に答える 13

190

ビューでViewTreeObserverを使用して、最初のレイアウトを待ちます。最初のレイアウトの後でのみ、getWidth()/ getHeight()/ getMeasuredWidth()/ getMeasuredHeight()が機能します。

ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
  viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
      view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
      viewWidth = view.getWidth();
      viewHeight = view.getHeight();
    }
  });
}
于 2011-07-04T08:54:48.787 に答える
78

シナリオに応じて、実際には複数のソリューションがあります。

  1. 安全な方法は、レイアウトフェーズが終了した後、ビューを描画する直前に機能します。
public static void runJustBeforeBeingDrawn(final View view, final Runnable runnable) {
    final OnPreDrawListener preDrawListener = new OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            view.getViewTreeObserver().removeOnPreDrawListener(this);
            runnable.run();
            return true;
        }
    };
    view.getViewTreeObserver().addOnPreDrawListener(preDrawListener); 
}

使用例:

    ViewUtil.runJustBeforeBeingDrawn(yourView, new Runnable() {
        @Override
        public void run() {
            //Here you can safely get the view size (use "getWidth" and "getHeight"), and do whatever you wish with it
        }
    });
  1. 場合によっては、ビューのサイズを手動で測定するだけで十分です。
view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
int width=view.getMeasuredWidth(); 
int height=view.getMeasuredHeight();

コンテナのサイズがわかっている場合:

    val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxWidth, View.MeasureSpec.AT_MOST)
    val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxHeight, View.MeasureSpec.AT_MOST)
    view.measure(widthMeasureSpec, heightMeasureSpec)
    val width=view.measuredWidth
    val height=view.measuredHeight
  1. 拡張したカスタムビューがある場合は、「onMeasure」メソッドでそのサイズを取得できますが、一部のケースでのみうまく機能すると思います。
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
    final int newHeight= MeasureSpec.getSize(heightMeasureSpec);
    final int newWidth= MeasureSpec.getSize(widthMeasureSpec);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
  1. Kotlinで作成する場合は、次の関数を使用できます。この関数は、runJustBeforeBeingDrawn私が作成したものとまったく同じように機能します。

     view.doOnPreDraw { actionToBeTriggered() }
    

これをgradleに追加する必要があることに注意してください(ここにあります):

android {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

implementation 'androidx.core:core-ktx:#.#'
于 2015-01-25T11:48:05.100 に答える
22

getWidth()ビューが実際に画面に表示される前に電話をかけていますか?

新しいAndroid開発者が犯すよくある間違いは、コンストラクター内でビューの幅と高さを使用することです。ビューのコンストラクターが呼び出されると、Androidはビューの大きさをまだ認識していないため、サイズはゼロに設定されます。実際のサイズは、レイアウト段階で計算されます。これは、構築後、何かが描画される前に発生します。メソッドを使用してonSizeChanged()、値がわかったときに値を通知することも、メソッド内などで後でメソッドgetWidth()と メソッドを使用することもできます。getHeight()onDraw()

于 2010-09-23T14:29:58.880 に答える
17

@mbairdのアドバイスに基づいて、ImageViewクラスをサブクラス化し、をオーバーライドすることで、実行可能な解決策を見つけましたonLayout()。次に、アクティビティが実装するオブザーバーインターフェイスを作成し、それ自体への参照をクラスに渡しました。これにより、アクティビティが実際にサイズ設定を終了したときにアクティビティに通知できるようになりました。

これが最善の解決策であると100%確信しているわけではありませんが(したがって、この回答をまだ正しいとマークしていません)、それは機能し、ドキュメントによると、ビューの実際のサイズを見つけるのは初めてです。

于 2010-09-24T10:00:13.153 に答える
10

API <11の場合にビューをオーバーライドしてレイアウトを取得するためのコードは次のとおりです(API 11にはView.OnLayoutChangedListener機能が含まれています)。

public class CustomListView extends ListView
{
    private OnLayoutChangedListener layoutChangedListener;

    public CustomListView(Context context)
    {
        super(context);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        if (layoutChangedListener != null)
        {
            layoutChangedListener.onLayout(changed, l, t, r, b);
        }
        super.onLayout(changed, l, t, r, b);
    }

    public void setLayoutChangedListener(
        OnLayoutChangedListener layoutChangedListener)
    {
        this.layoutChangedListener = layoutChangedListener;
    }
}
public interface OnLayoutChangedListener
{
    void onLayout(boolean changed, int l, int t, int r, int b);
}
于 2010-10-22T19:55:07.413 に答える
7

この質問を確認できます。Viewpost()メソッドを使用できます。

于 2011-07-09T15:30:39.277 に答える
5

これは私の中で私のために働きますonClickListener

yourView.postDelayed(new Runnable() {               
    @Override
    public void run() {         
        yourView.invalidate();
        System.out.println("Height yourView: " + yourView.getHeight());
        System.out.println("Width yourView: " + yourView.getWidth());               
    }
}, 1);
于 2013-04-04T09:57:51.643 に答える
5

以下のコードを使用して、ビューのサイズを指定します。

@Override
public void onWindowFocusChanged(boolean hasFocus) {
       super.onWindowFocusChanged(hasFocus);
       Log.e("WIDTH",""+view.getWidth());
       Log.e("HEIGHT",""+view.getHeight());
}
于 2017-02-10T17:42:57.873 に答える
4

私も迷子にgetMeasuredWidth()なりgetMeasuredHeight() getHeight()getWidth()長い間..........後で、ビューの幅と高さを取得することonSizeChanged()がこれを行うための最良の方法であることがわかりました........動的に実行できますonSizeChanged()メソッドをオーバーライドして、ビューの現在の幅と現在の高さを取得します。

手の込んだコードスニペットがあるこれを見てみたいかもしれません。新しいブログ投稿:AndroidでcustomViewの幅と高さの寸法を取得する方法(ビューを拡張)http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.html

于 2011-02-27T20:48:54.640 に答える
0

画面上のビューの位置と寸法の両方を取得できます

 val viewTreeObserver: ViewTreeObserver = videoView.viewTreeObserver;

if (viewTreeObserver.isAlive) {
    viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            //Remove Listener
            videoView.viewTreeObserver.removeOnGlobalLayoutListener(this);

            //View Dimentions
            viewWidth = videoView.width;
            viewHeight = videoView.height;

            //View Location
            val point = IntArray(2)
            videoView.post {
                videoView.getLocationOnScreen(point) // or getLocationInWindow(point)
                viewPositionX = point[0]
                viewPositionY = point[1]
            }

        }
    });
}
于 2020-04-09T07:49:15.110 に答える
0

Kotlinファイルで、それに応じて変更します

 Handler().postDelayed({

           Your Code

        }, 1)
于 2020-11-05T09:23:16.910 に答える
0

描画された直後にビューのサイズを知る必要がある場合は、そのビューでpost()を呼び出すだけで、必要なものを実行するRunnableをそこに送信できます。これは、ViewTreeObserverやglobalLayoutよりも優れたソリューションです。これは、一度だけではなく繰り返し呼び出されるためです。このRunnsbleは1回だけ実行され、ビューのサイズがわかります。

于 2021-04-25T18:13:48.930 に答える
-2

私のために完璧に動作します:

 protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        CTEditor ctEdit = Element as CTEditor;
        if (ctEdit == null) return;           
        if (e.PropertyName == "Text")
        {
            double xHeight = Element.Height;
            double aHaight = Control.Height;
            double height;                
            Control.Measure(LayoutParams.MatchParent,LayoutParams.WrapContent);
            height = Control.MeasuredHeight;
            height = xHeight / aHaight * height;
            if (Element.HeightRequest != height)
                Element.HeightRequest = height;
        }
    }
于 2017-09-08T07:03:04.883 に答える