android 自定义relativelayout,android – RelativeLayout没有正确更新自定义视图的宽度

我有这个容器类,用于制作其他尺寸的一个尺寸,宽度或高度,其他尺寸的比例.例如,我想要一个16:9布局容器,其宽度为“match_parent”.但是,当将高度用作“match_parent”时,Android似乎没有正确的重新发送.当我将高度设置为一个比例的宽度一切都很好!反之亦然,它不起作用.这是怎么回事?

public class RatioLayout extends ViewGroup {

private float ratio = 1.6222f; // 4 x 3 default. 1.78 is 16 x 9

public float getRatio() { return ratio; }

public void setRatio(float ratio) {

this.ratio = ratio;

requestLayout();

}

public RatioLayout(Context context) {

this(context,null);

}

public RatioLayout(Context context,AttributeSet attrs) {

this(context,attrs,0);

}

public RatioLayout(Context context,AttributeSet attrs,int defStyle) {

super(context,defStyle);

}

@Override

protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec) {

Log.i("Ratio","/onMeasure");

int width = MeasureSpec.getSize(widthMeasureSpec);

int height = MeasureSpec.getSize(heightMeasureSpec);

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

// int exactly = MeasureSpec.EXACTLY; // 1073741824

// int atMost = MeasureSpec.AT_MOST; // -2147483648

// int unspec = MeasureSpec.UNSPECIFIED; // 0

width = Math.round(height * ratio);

widthMeasureSpec = MeasureSpec.makeMeasureSpec(width,MeasureSpec.EXACTLY);

heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,MeasureSpec.EXACTLY);

setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);

int mw = getMeasuredWidth();

int mh = getMeasuredHeight();

Log.i("Ratio","mw: " + mw + ",mh: " + mh);

}

@Override

protected void onLayout(boolean changed,int l,int t,int r,int b) {

Log.i("Ratio","/onLayout");

Log.i("Ratio","l: " + l + ",t: " + t + ",r:" + r + ",b:" + b);

Log.i("Ratio","mw: " + getMeasuredWidth() + ",mh:" + getMeasuredHeight());

Log.i("Ratio","w: " + getWidth() + ",mw:" + getHeight());

}

}

要查看它的行动,使用这样的布局:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity" >

android:id="@+id/image"

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_marginBottom="100dp"

android:layout_marginTop="100dp"

android:background="#FFFF00FF" />

这将是我的活动:

记录输出:

I/Ratio (9445): /onMeasure

I/Ratio (9445): mw: 1087,mh: 670

I/Ratio (9445): /onMeasure

I/Ratio (9445): mw: 655,mh: 404

I/Ratio (9445): /onLayout

I/Ratio (9445): l: 0,t: 133,r:1087,b:537

I/Ratio (9445): mw: 655,mh:404

I/Ratio (9445): w: 1087,mw:404

为什么Android不符合我最新的measuredWidth,但使用较旧的版本,但最新的高度?

编辑:更新.使RatioLayout的父级不是RelativeLayout,但是LinearLayout或FrameLayout给出了正确的行为.由于某些原因RelativeLayout是“缓存”measuredWidth并且不使用最新的.

编辑2:RelativeLayout.onLayout中的这个评论似乎证实了我的“缓存”,我认为这是一个bug

@Override

protected void onLayout(boolean changed,int b) {

// The layout has actually already been performed and the positions

// cached. Apply the cached values to the children.

int count = getChildCount();

// TODO: we need to find another way to implement RelativeLayout

// This implementation cannot handle every case

@Override

protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec) {

最后编辑好的我放弃.这是RelativeLayout中的一个合法的错误.这种代码修复它,但它会导致toRightOf属性的问题.我发现的工作是将此RatioLayout嵌入另一个ViewGroup,如LinerLayout.那些好奇的代码

@Override

protected void onMeasure(int widthMeasureSpec,heightMeasureSpec);

if (getParent() instanceof RelativeLayout) {

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)getLayoutParams();

Class> clazz = RelativeLayout.LayoutParams.class;

try {

Field left = clazz.getDeclaredField("mLeft");

Field right = clazz.getDeclaredField("mRight");

left.setAccessible(true);

right.setAccessible(true);

int l = left.getInt(params);

if (l == -1) l = params.leftMargin; // if the value is uninitialized,set it to 0;

if (l == -1) l = 0; // if the value is uninitialized,set it to 0;

// setting this seems to break the layout_marginLeft properties.

right.setInt(params,l + getMeasuredWidth());

} catch (NoSuchFieldException e) {

Log.e("Ration","error",e);

} catch (IllegalArgumentException e) {

Log.e("Ration",e);

} catch (IllegalAccessException e) {

Log.e("Ration",e);

}

}

int mw = getMeasuredWidth();

int mh = getMeasuredHeight();

lastWidth = mw;

Log.i("Ratio",mh: " + mh);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值