
public class Ratiolayout extends VIEwGroup {private float ratio = 1.6222f; // 4 x 3 default. 1.78 is 16 x 9public 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);}@OverrIDeprotected 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);}@OverrIDeprotected 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());}} 要查看它的行动,使用这样的布局:
<relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"xmlns:tools="http://schemas.androID.com/tools"androID:layout_wIDth="match_parent"androID:layout_height="match_parent"tools:context=".MainActivity" ><com.example.Ratiolayout androID:ID="@+ID/image" androID:layout_wIDth="0dp" androID:layout_height="match_parent" androID:layout_marginBottom="100dp" androID:layout_margintop="100dp" androID:background="#FFFF00FF" /></relativeLayout>
这将是我的活动:
记录输出:
I/Ratio (9445): /onMeasureI/Ratio (9445): mw: 1087,mh: 670I/Ratio (9445): /onMeasureI/Ratio (9445): mw: 655,mh: 404I/Ratio (9445): /onLayoutI/Ratio (9445): l: 0,t: 133,r:1087,b:537I/Ratio (9445): mw: 655,mh:404I/Ratio (9445): w: 1087,mw:404 <--- NO reason this should not be 655
为什么AndroID不符合我最新的measureDWIDth,但使用较旧的版本,但最新的高度?
编辑:更新.使Ratiolayout的父级不是relativeLayout,但是linearLayout或FrameLayout给出了正确的行为.由于某些原因relativeLayout是“缓存”measureDWIDth并且不使用最新的.
编辑2:relativeLayout.onLayout中的这个评论似乎证实了我的“缓存”,我认为这是一个BUG
@OverrIDeprotected 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@OverrIDeprotected voID onMeasure(int wIDthMeasureSpec,int heightmeasureSpec) { 最后编辑好的我放弃.这是relativeLayout中的一个合法的错误.这种代码修复它,但它会导致toRightOf属性的问题.我发现的工作是将此Ratiolayout嵌入另一个VIEwGroup,如linerLayout.那些好奇的代码
@OverrIDeprotected 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);}解决方法 我实际上试图做你以前尝试做的,也就是说,使视图尽可能大,同时保留一些宽高比(即平方或4:3或类似的东西). 我的问题是当我的VIEw在一个ScrollVIEw中时,它的大小计算不正确.我无法弄清楚这一点,但是我会发布我的代码,以防万一有帮助.这与你的代码非常相似,但是我从FrameLayout继承,最后调用super.onMeasure().
我仔细检查了我正在使用的项目,实际上它是relativeLayout的直接孩子.
Java的:
/** * A FrameLayout which trIEs to be as big as possible while maintaining a given ratio between its wIDth and height. * Formula: Height = WIDth / ratio; * Usage: * 1) Set layout_wIDth and layout_height to "match_parent" * 2) For 4:3 for example,set ratio to 4/3 = 1.333333 etc. Or don't specify,and it will be square by default. */public class RatioFrameLayout extends FrameLayout{ private final static float DEFAulT_RATIO = 1f; private float ratio; private boolean measured = false; public RatioFrameLayout(Context context) { super(context); } public RatioFrameLayout(Context context,AttributeSet attrs) { super(context,attrs); readAttributes(context,attrs); } public RatioFrameLayout(Context context,int defStyle) { super(context,defStyle); readAttributes(context,attrs); } private voID readAttributes(Context context,AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.RatioFrameLayout); String value = a.getString(R.styleable.RatioFrameLayout_ratio); try { ratio = float.parsefloat(value); } catch (Exception e) { ratio = DEFAulT_RATIO; } a.recycle(); } public float getRatio() { return ratio; } public voID setRatio(float ratio) { this.ratio = ratio; } @OverrIDe protected voID onMeasure(int wIDthMeasureSpec,int heightmeasureSpec) { super.onMeasure(wIDthMeasureSpec,heightmeasureSpec); int targetWIDth = getMeasureDWIDth(); int targetHeight = Math.round((float)getMeasureDWIDth() / ratio); if (targetHeight > getMeasuredHeight() && getMeasuredHeight() != 0) { targetWIDth = Math.round(getMeasuredHeight() * ratio); targetHeight = getMeasuredHeight(); } super.onMeasure(MeasureSpec.makeMeasureSpec(targetWIDth,MeasureSpec.EXACTLY),MeasureSpec.makeMeasureSpec(targetHeight,MeasureSpec.EXACTLY)); } private voID printMeasureSpec(String description,int value) { int mode = MeasureSpec.getMode(value); String modename = mode == MeasureSpec.AT_MOST ? "AT_MOST" : mode == MeasureSpec.EXACTLY ? "EXACTLY" : "UnspecIFIED"; DLog.d(String.format("Measure spec for %s,mode = %s,size = %d",description,modename,MeasureSpec.getSize(value))); }} attrs.xml:
<resources> <declare-styleable name="RatioFrameLayout"> <attr name="ratio" format="string|reference" /> </declare-styleable></resources>总结
以上是内存溢出为你收集整理的android – RelativeLayout没有正确更新自定义视图的宽度全部内容,希望文章能够帮你解决android – RelativeLayout没有正确更新自定义视图的宽度所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)