我正在尝试在创建活动后将动画应用到我的Android应用中的视图。为此,我需要确定视图的当前大小,然后设置动画以从当前大小缩放到新大小。此部分必须在运行时完成,因为视图根据用户的输入缩放到不同的大小。我的布局是用XML定义的。
这似乎是一件容易的事,虽然没有一个能解决我的问题,但很多问题都存在。所以也许我错过了一些明显的东西。我通过以下方式处理了我的观点:
ImageView myView = (ImageView)getWindow().findViewById(R.id.MyViewID);
这样做很好,但是在调用getWidth()
,getHeight()
,getMeasuredWidth()
,getLayoutParams().width
等时,它们都返回0.我还尝试手动调用{{ 1}}在视图上跟随调用measure()
,但这没有效果。
我尝试调用这些方法并在我的活动getMeasuredWidth()
和onCreate()
中检查调试器中的对象。如何在运行时确定此视图的确切尺寸?
答案 0 :(得分:173)
使用View上的ViewTreeObserver等待第一个布局。只有在第一个布局后才能使用getWidth()/ getHeight()/ getMeasuredWidth()/ getMeasuredHeight()。
ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
viewWidth = view.getWidth();
viewHeight = view.getHeight();
}
});
}
答案 1 :(得分:51)
实际上有多种解决方案,具体取决于具体情况:
public static void runJustBeforeBeingDrawn(final View view, final Runnable runnable) { final OnPreDrawListener preDrawListener = new OnPreDrawListener() { @Override public boolean onPreDraw() { view.getViewTreeObserver().removeOnPreDrawListener(this); runnable.run(); return true; } }; view.getViewTreeObserver().addOnPreDrawListener(preDrawListener); }
样本用法:
ViewUtil.runJustBeforeBeingDrawn(yourView, new Runnable() {
@Override
public void run() {
//Here you can safely get the view size (use "getWidth" and "getHeight"), and do whatever you wish with it
}
});
view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); int width=view.getMeasuredWidth(); int height=view.getMeasuredHeight();
如果你知道容器的大小:
val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxWidth, View.MeasureSpec.AT_MOST)
val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(maxHeight, View.MeasureSpec.AT_MOST)
view.measure(widthMeasureSpec, heightMeasureSpec)
val width=view.measuredWidth
val height=view.measuredHeight
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final int newHeight= MeasureSpec.getSize(heightMeasureSpec); final int newWidth= MeasureSpec.getSize(widthMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); }
如果你在Kotlin写作,你可以使用下一个函数,它在幕后的工作方式与我写的runJustBeforeBeingDrawn
完全相同:
view.doOnPreDraw { actionToBeTriggered() }
请注意,您需要将其添加到gradle(通过here找到):
implementation 'androidx.core:core-ktx:#.#'
答案 2 :(得分:19)
您是否在视图实际显示在屏幕上之前调用getWidth()
?
新Android开发人员常犯的错误是使用宽度 和构造函数中的视图高度。当一个视图的时候 调用构造函数,Android还不知道视图有多大 是的,因此大小设置为零。实际尺寸是在计算期间计算的 布局阶段,在施工后但在任何事情之前发生 绘制。您可以使用
onSizeChanged()
方法进行通知 知道它们时的值,或者您可以使用getWidth()
和。{ 稍后getHeight()
种方法,例如onDraw()
方法。
答案 3 :(得分:17)
基于@ mbaird的建议,我通过继承ImageView
类并覆盖onLayout()
找到了一个可行的解决方案。然后我创建了一个我的活动实现的观察器接口,并将对它自己的引用传递给了类,这允许它在实际完成大小调整时告诉活动。
我不是100%确信这是最好的解决方案(因此我没有将此答案标记为正确),但它确实有效并且根据文档是第一次可以找到实际的大小一个观点。
答案 4 :(得分:10)
以下是通过覆盖视图来获取布局的代码,如果API< 11(API 11包括View.OnLayoutChangedListener功能):
public class CustomListView extends ListView
{
private OnLayoutChangedListener layoutChangedListener;
public CustomListView(Context context)
{
super(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
if (layoutChangedListener != null)
{
layoutChangedListener.onLayout(changed, l, t, r, b);
}
super.onLayout(changed, l, t, r, b);
}
public void setLayoutChangedListener(
OnLayoutChangedListener layoutChangedListener)
{
this.layoutChangedListener = layoutChangedListener;
}
}
public interface OnLayoutChangedListener
{
void onLayout(boolean changed, int l, int t, int r, int b);
}
答案 5 :(得分:6)
您可以查看this question。您可以使用View
的{{3}}方法。
答案 6 :(得分:5)
这适用于我的onClickListener
:
yourView.postDelayed(new Runnable() {
@Override
public void run() {
yourView.invalidate();
System.out.println("Height yourView: " + yourView.getHeight());
System.out.println("Width yourView: " + yourView.getWidth());
}
}, 1);
答案 7 :(得分:4)
我也在getMeasuredWidth()
和getMeasuredHeight()
getHeight()
以及getWidth()
长时间迷路..........后来我发现得到了view onSizeChanged()
中的视图宽度和高度是执行此操作的最佳方式........您可以通过覆盖onSizeChanged(
)方法动态获取视图的CURRENT宽度和CURRENT高度。< / p>
可能想看看这个有精心设计的代码片段。 新博文:如何获取Android http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.html中的customView(扩展视图)的宽度和高度尺寸
答案 8 :(得分:4)
使用下面的代码,它给出了视图的大小。
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Log.e("WIDTH",""+view.getWidth());
Log.e("HEIGHT",""+view.getHeight());
}
答案 9 :(得分:0)
val viewTreeObserver: ViewTreeObserver = videoView.viewTreeObserver;
if (viewTreeObserver.isAlive) {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
//Remove Listener
videoView.viewTreeObserver.removeOnGlobalLayoutListener(this);
//View Dimentions
viewWidth = videoView.width;
viewHeight = videoView.height;
//View Location
val point = IntArray(2)
videoView.post {
videoView.getLocationOnScreen(point) // or getLocationInWindow(point)
viewPositionX = point[0]
viewPositionY = point[1]
}
}
});
}
答案 10 :(得分:0)
在Kotlin文件中,进行相应更改
Handler().postDelayed({
Your Code
}, 1)
答案 11 :(得分:0)
如果您需要在绘制后立即知道 View 的尺寸,您可以简单地在给定的 View 上调用 post() 并发送一个 Runnable 来执行您需要的任何内容。 它是比 ViewTreeObserver 和 globalLayout 更好的解决方案,因为它被重复调用而不仅仅是一次。 这个 Runnsble 只会执行一次,你就会知道视图的大小。
答案 12 :(得分:-1)
对我来说是完美的:
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
CTEditor ctEdit = Element as CTEditor;
if (ctEdit == null) return;
if (e.PropertyName == "Text")
{
double xHeight = Element.Height;
double aHaight = Control.Height;
double height;
Control.Measure(LayoutParams.MatchParent,LayoutParams.WrapContent);
height = Control.MeasuredHeight;
height = xHeight / aHaight * height;
if (Element.HeightRequest != height)
Element.HeightRequest = height;
}
}