我正在动态地创建我的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);
}
任何帮助都是感激的。
如果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)
}
}
})
}
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
带post的答案是不正确的,因为大小可能无法重新计算。
另一个重要的事情是视图和所有它的祖先必须是可见的。为此,我使用属性view . isshows。
下面是我的kotlin函数,它可以放在utils中的某个地方:
fun View.onInitialized(onInit: () -> Unit) {
viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (isShown) {
viewTreeObserver.removeOnGlobalLayoutListener(this)
onInit()
}
}
})
}
用法是:
myView.onInitialized {
Log.d(TAG, "width is: " + myView.width)
}
这是一个有点旧,但我自己有麻烦(需要在一个片段中创建动画对象)。这个解决方案对我来说很有效,我相信这是不言自明的。
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
}
我使用了这个解决方案,我认为它比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 :)
}