我正在动态地创建我的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);
}

任何帮助都是感激的。


当前回答

public final class ViewUtils {

    public interface ViewUtilsListener {
        void onDrawCompleted();
    }

    private ViewUtils() {
    }

    public static void onDraw(View view, ViewUtilsListener listener) {
        view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (view.getHeight() != 0 && view.getWidth() != 0) {
                    if (listener != null) {
                        listener.onDrawCompleted();
                    }
                    view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                }
            }
        });
    }
}

你可以这样用;

ViewUtils.onDraw(view, new ViewUtils.ViewUtilsListener() {
                @Override
                public void onDrawCompleted() {
                    int width = view.getWidth();
                    int height = view.getHeight();
                }
            });

其他回答

我宁愿使用OnPreDrawListener()而不是addOnGlobalLayoutListener(),因为它被调用得比其他侦听器早一点。

    view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
    {
        @Override
        public boolean onPreDraw()
        {
            if (view.getViewTreeObserver().isAlive())
                view.getViewTreeObserver().removeOnPreDrawListener(this);
            
            // put your code here
            return true;
        }
    });

根据@Pang的评论调整了代码onPreDraw方法应返回true以继续当前的绘图过程。

如果需要在屏幕上显示某个小部件之前获取它的宽度,可以使用getMeasuredWidth()或getMeasuredHeight()。

myImage.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
int width = myImage.getMeasuredWidth();
int height = myImage.getMeasuredHeight();
public final class ViewUtils {

    public interface ViewUtilsListener {
        void onDrawCompleted();
    }

    private ViewUtils() {
    }

    public static void onDraw(View view, ViewUtilsListener listener) {
        view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (view.getHeight() != 0 && view.getWidth() != 0) {
                    if (listener != null) {
                        listener.onDrawCompleted();
                    }
                    view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                }
            }
        });
    }
}

你可以这样用;

ViewUtils.onDraw(view, new ViewUtils.ViewUtilsListener() {
                @Override
                public void onDrawCompleted() {
                    int width = view.getWidth();
                    int height = view.getHeight();
                }
            });

也许这能帮助到一些人:

为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
}

AndroidX在AndroidX .core.view中有多个扩展函数可以帮助你完成这类工作

为此,您需要使用Kotlin。

最适合这里的是doOnLayout:

在布局此视图时执行给定的操作。如果视图已经布局并且它没有请求布局,操作将立即执行,否则,操作将在视图下一次布局后执行。 该操作只会在下一个布局中被调用一次,然后被删除。

在你的例子中:

bt.doOnLayout {
    val ra = RotateAnimation(0,360,it.width / 2,it.height / 2)
    // more code
}

依赖:androidx.core: core-ktx: 1.0.0