我正在动态创建我的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);
}
任何帮助表示赞赏 .
10 回答
你太早叫了
getWidth()
. UI尚未在屏幕上进行调整大小和布局 .我怀疑你想要做你正在做的事情,无论如何 - 动画小工具不会改变它们的可点击区域,因此按钮仍然会响应原始方向的点击,无论它如何旋转 .
话虽这么说,您可以使用dimension resource来定义按钮大小,然后从布局文件和源代码中引用该维度资源,以避免此问题 .
我使用这个解决方案,我认为它比onWindowFocusChanged()更好 . 如果打开DialogFragment,然后旋转手机,只有当用户关闭对话框时才会调用onWindowFocusChanged):
编辑:由于不推荐使用removeGlobalOnLayoutListener,您现在应该:
如果应用程序在后台,则视图返回0作为高度 . 我的代码(1oo%有效)
我们可以用
我宁愿使用
OnPreDrawListener()
而不是addOnGlobalLayoutListener()
,因为它之前被称为 .如果您使用RxJava&RxBindings,请使用一个班轮 . 没有样板的类似方法 . 这也解决了hack压制警告的问题,如Tim Autin所述 .
就是这个 . 即使从未打过电话,也无需取消订阅 .
基本问题是,您必须等待实际测量的绘制阶段(尤其是动态值,如
wrap_content
或match_parent
),但通常此阶段尚未完成onResume()
. 所以你需要一个等待这个阶段的解决方法 . 有一个不同的可能的解决方案:1.收听绘图/布局事件:ViewTreeObserver
ViewTreeObserver会因不同的绘图事件而被触发 . 通常OnGlobalLayoutListener是您想要获得测量的,因此在布局阶段之后将调用侦听器中的代码,因此测量准备就绪:
注意:将立即删除侦听器,否则将触发每个布局事件 . 如果您必须支持应用SDK Lvl <16,请使用此方法取消注册侦听器:
public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)
2.将一个runnable添加到布局队列:View.post()
不太知名和我最喜欢的解决方案 . 基本上只需使用View的post方法和您自己的runnable . 这基本上在视图的度量,布局等之后将代码排队,如Romain Guy所述:
例:
优于
ViewTreeObserver
:您的代码只执行一次,您不必在执行后禁用Observer,这可能很麻烦
更简洁的语法
参考文献:
https://stackoverflow.com/a/3602144/774398
https://stackoverflow.com/a/3948036/774398
3.覆盖视图的onLayout方法
这在逻辑可以封装在视图本身中的某些情况下才是实用的,否则这是一种非常冗长和繁琐的语法 .
还要注意,onLayout会被多次调用,所以要考虑你在方法中做了什么,或者在第一次之后禁用你的代码
4.检查是否已通过布局阶段
如果您在创建UI时有多次执行代码,则可以使用以下支持v4 lib方法:
附加:获取静态定义的测量值
如果只需获得静态定义的高度/宽度就足够了,您可以这样做:
View.getMeasuredWidth()
View.getMeasuredHeigth()
但请注意,这可能与绘图后的实际宽度/高度不同 . javadoc完美地描述了这种差异:
正如伊恩在this Android Developers thread中所述:
如果您需要在屏幕上显示某些小部件的宽度之前获取其宽度,则可以使用getMeasuredWidth()或getMeasuredHeight() .
扩展以动态获得Kotlin的高度 .
用法:
执行: