我正在动态地创建我的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();
}
});
如果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)
}
}
})
}
正如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.
这是一个有点旧,但我自己有麻烦(需要在一个片段中创建动画对象)。这个解决方案对我来说很有效,我相信这是不言自明的。
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
}
用法:
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)
}
}
}