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

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

概述我有这个容器类,用于制作其他尺寸的一个尺寸,宽度或高度,其他尺寸的比例.例如,我想要一个16:9布局容器,其宽度为“match_parent”.但是,当将高度用作“match_parent”时, Android似乎没有正确的重新发送.当我将高度设置为一个比例的宽度一切都很好!反之亦然,它不起作用.这是怎么回事? public class RatioLayout extends ViewGroup 我有这个容器类,用于制作其他尺寸的一个尺寸,宽度或高度,其他尺寸的比例.例如,我想要一个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 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没有正确更新自定义视图的宽度所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1132866.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-30
下一篇2022-05-30

发表评论

登录后才能评论

评论列表(0条)

    保存