我正在动态地创建我的android项目中的所有元素。我试图获得一个按钮的宽度和高度,以便我可以旋转该按钮。我只是想学习如何使用android语言。但是,它返回0。

我做了一些研究,我看到它需要在其他地方而不是在onCreate()方法中完成。如果有人能给我一个如何做这件事的例子,那就太好了。

这是我当前的代码:

package com.animation;

import android.app.Activity;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.Button;
import android.widget.LinearLayout;

public class AnimateScreen extends Activity {


//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    LinearLayout ll = new LinearLayout(this);

    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(30, 20, 30, 0);

    Button bt = new Button(this);
    bt.setText(String.valueOf(bt.getWidth()));

    RotateAnimation ra = new RotateAnimation(0,360,bt.getWidth() / 2,bt.getHeight() / 2);
    ra.setDuration(3000L);
    ra.setRepeatMode(Animation.RESTART);
    ra.setRepeatCount(Animation.INFINITE);
    ra.setInterpolator(new LinearInterpolator());

    bt.startAnimation(ra);

    ll.addView(bt,layoutParams);

    setContentView(ll);
}

任何帮助都是感激的。


当前回答

最简洁的方法是使用post method of view:

科特林:

  view.post{
      var width = view.width
      var height = view.height
  }

Java:

view.post(new Runnable() {
    @Override
    public void run() {
        int width = view.getWidth();
        int height = view.getHeight();
    }
});

其他回答

正如Ian在这篇Android开发者文章中所述:

Anyhow, the deal is that layout of the contents of a window happens after all the elements are constructed and added to their parent views. It has to be this way, because until you know what components a View contains, and what they contain, and so on, there's no sensible way you can lay it out. Bottom line, if you call getWidth() etc. in a constructor, it will return zero. The procedure is to create all your view elements in the constructor, then wait for your View's onSizeChanged() method to be called -- that's when you first find out your real size, so that's when you set up the sizes of your GUI elements. Be aware too that onSizeChanged() is sometimes called with parameters of zero -- check for this case, and return immediately (so you don't get a divide by zero when calculating your layout, etc.). Some time later it will be called with the real values.

我使用了这个解决方案,我认为它比onWindowFocusChanged()更好。如果你打开一个对话片段,然后旋转电话,onWindowFocusChanged将被调用只有当用户关闭对话框):

    yourView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            // Ensure you call it only once :
            yourView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

            // Here you can get the size :)
        }
    });

编辑:由于removeGlobalOnLayoutListener已弃用,你现在应该做:

@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {

    // Ensure you call it only once :
    if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
        yourView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
    else {
        yourView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    }

    // Here you can get the size :)
}

用法:

imageView.size { width, height ->
            //your code
        }

延伸:


fun <T : View> T.size(function: (Int, Int) -> Unit) {
    if (isLaidOut && height != 0 && width != 0) {
        function(width, height)
    } else {
        if (height == 0 || width == 0) {
            var onLayoutChangeListener: View.OnLayoutChangeListener? = null
            var onGlobalLayoutListener: ViewTreeObserver.OnGlobalLayoutListener? = null

            onGlobalLayoutListener = object : ViewTreeObserver.OnGlobalLayoutListener {
                override fun onGlobalLayout() {
                    if (isShown) {
                        removeOnLayoutChangeListener(onLayoutChangeListener)
                        viewTreeObserver.removeOnGlobalLayoutListener(this)
                        function(width, height)
                    }
                }
            }

            onLayoutChangeListener = object : View.OnLayoutChangeListener {
                override fun onLayoutChange(
                    v: View?,
                    left: Int,
                    top: Int,
                    right: Int,
                    bottom: Int,
                    oldLeft: Int,
                    oldTop: Int,
                    oldRight: Int,
                    oldBottom: Int
                ) {
                    val width = v?.width ?: 0
                    val height = v?.height ?: 0
                    if (width > 0 && height > 0) {
                        // remove after finish
                        viewTreeObserver.removeOnGlobalLayoutListener(onGlobalLayoutListener)
                        v?.removeOnLayoutChangeListener(this)
                        function(width, height)
                    }
                }
            }

            viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
            addOnLayoutChangeListener(onLayoutChangeListener)
        } else {
            function(width, height)
        }
    }
}

也许这能帮助到一些人:

为View类创建一个扩展函数

文件名:ViewExt.kt

fun View.afterLayout(what: () -> Unit) {
    if(isLaidOut) {
        what.invoke()
    } else {
        viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                what.invoke()
            }
        })
    }
}

这可以用在任何视图:

view.afterLayout {
    do something with view.height
}

如果您正在使用Kotlin

  customView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {

            override fun onGlobalLayout() {

                if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
                    customView.viewTreeObserver.removeOnGlobalLayoutListener(this)
                }
                else {
                    customView.viewTreeObserver.removeGlobalOnLayoutListener(this)
                }

                // Here you can get the size :)
                viewWidth = customView.width
            }
        })