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

任何帮助都是感激的。


当前回答

用法:

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

其他回答

这是一个有点旧,但我自己有麻烦(需要在一个片段中创建动画对象)。这个解决方案对我来说很有效,我相信这是不言自明的。

class YourFragment: Fragment() {
    var width = 0
    var height = 0


override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // Inflate the layout for this fragment
    val root = inflater.inflate(R.layout.fragment_winner_splash, container, false)
    container?.width.let {
        if (it != null) {
            width = it
        }
    }
    container?.height.let {
        if (it != null) {
            height = it
        }
    }
    
    return root
}
 

你调用getWidth()太早了。UI还没有在屏幕上调整大小和布局。

无论如何,我怀疑您是否想要做您正在做的事情——动画小部件不会改变它们的可点击区域,因此无论它如何旋转,按钮仍然会对原始方向的点击做出响应。

也就是说,您可以使用维度资源来定义按钮大小,然后从布局文件和源代码中引用该维度资源,以避免此问题。

如果app在后台,消失的视图返回0作为高度。 这是我的代码(1oo%工作)

fun View.postWithTreeObserver(postJob: (View, Int, Int) -> Unit) {
    viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            val widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            val heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            measure(widthSpec, heightSpec)
            postJob(this@postWithTreeObserver, measuredWidth, measuredHeight)
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                @Suppress("DEPRECATION")
                viewTreeObserver.removeGlobalOnLayoutListener(this)
            } else {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        }
    })
}

你可以使用addOnLayoutChangeListener

你可以在onCreate活动或onCreateView片段中使用它

@Edit 不要忘记删除它,因为在某些情况下它会触发无限循环


myView.addOnLayoutChangeListener(object : View.OnLayoutChangeListener{
                override fun onLayoutChange(
                    v: View?, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int
                ) {
                    if (v?.width > 0 && v?.height > 0){
                        // do something
                        Log.i(TAG, "view : ${view.width}")
                        // remove after finish
                        v?.removeOnLayoutChangeListener(this) 
                    }
                }
            })

这是因为视图需要更多的时间来膨胀。所以不用调用view。宽度和视图。主线程上的高度,你应该使用视图。Post{…}以确保你的观点已经被夸大了。在芬兰湾的科特林:

view.post{width}
view.post{height}

在Java中,您还可以在Runnable中调用getWidth()和getHeight()方法,并将Runnable传递给view.post()方法。

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