Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/191.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 自定义视图组在LinearLayout内部工作,而不是在RelativeLayout内部工作_Android_Layout_Custom View - Fatal编程技术网

Android 自定义视图组在LinearLayout内部工作,而不是在RelativeLayout内部工作

Android 自定义视图组在LinearLayout内部工作,而不是在RelativeLayout内部工作,android,layout,custom-view,Android,Layout,Custom View,我想创建一个自定义LinearLayout,然后创建一个自定义ImageButton,该按钮可以基于其父对象的大小为大小的两个维度获取百分比值,而不管父对象类型是Relative还是Linear。我在看这篇文章:,这很有帮助,但我有一个问题,这些答案并没有解决 当我将自定义LinearLayout放置在另一个LinearLayout中时,一切正常。在下面的示例中,我的自定义LinearLayout覆盖了父级宽度的80%的预期空间 然而,如果我把它放在一个相对的窗口中,我的屏幕总是显示为空的,我不

我想创建一个自定义LinearLayout,然后创建一个自定义ImageButton,该按钮可以基于其父对象的大小为大小的两个维度获取百分比值,而不管父对象类型是Relative还是Linear。我在看这篇文章:,这很有帮助,但我有一个问题,这些答案并没有解决

当我将自定义LinearLayout放置在另一个LinearLayout中时,一切正常。在下面的示例中,我的自定义LinearLayout覆盖了父级宽度的80%的预期空间

然而,如果我把它放在一个相对的窗口中,我的屏幕总是显示为空的,我不知道为什么会发生这种情况

这是我的班级:

public class ButtonPanel extends LinearLayout {

    public ButtonPanel(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int newWidth = (int) Math.ceil(parentWidth * 0.8);

        this.setMeasuredDimension(newWidth, parentHeight);
        this.setLayoutParams(new RelativeLayout.LayoutParams(newWidth,parentHeight));

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}
这是我的活动测试布局

<RelativeLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="horizontal"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent">

        <com.android.tests.views.ButtonPanel
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="horizontal"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="@drawable/inner_panel"
                android:gravity="center_horizontal"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true">
        </com.android.tests.views.ButtonPanel>
    </RelativeLayout>
在我的活动中,我所做的就是将内容视图设置为上述布局

顺便提一下,现在有人知道我如何动态地获取父对象的类型以设置新的LayoutParameters了吗?在上面,您将看到父类型RelativeLayout硬编码到自定义视图onMeasure函数中


提前感谢您的帮助

这是一个问题吗

this.setLayoutParams(new RelativeLayout.LayoutParams(newWidth,parentHeight)); // <-- a RelativeLayout params?

在onMeasure函数中,您可以使用类似的方法来了解视图的父类是什么

this.getParent().getClass().getName()
这也应该起作用

a instanceof B

当使用instanceof时,您需要在编译时知道B的类。使用isAssignableFrom时,它可以是动态的,并且在运行时会发生更改


如果你不擅长字符串比较,你也可以使用枚举。

我在这篇文章中的两个问题比预期的更相关

我意识到,通过将视图的LayoutParams设置为一个全新的实例,我覆盖了相对布局定位视图所需的布局定位信息

通过“归零”这些信息,我的视图具有正确的尺寸,但布局不知道将其放置在何处,因此它根本不知道

以下新onMeasure的代码显示了如何直接修改已附加到视图的LayoutParams的高度和宽度,从而避免覆盖布局位置信息和基于父对象类型创建新的LayoutParams

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int specWidth = MeasureSpec.getSize(widthMeasureSpec);
        int specHeight = MeasureSpec.getSize(heightMeasureSpec);

        int newWidth = (int) Math.ceil(parentWidth * 0.8);
        int newHeight = (int) Math.ceil(parentHeight * 0.8);

        this.setMeasuredDimension(newWidth, newHeight);

        this.getLayoutParams().height = newHeight;
        this.getLayoutParams().width = newWidth;

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
现在,我要诚实地说,这段代码仍然不是没有bug的。多次将活动置于前台和后台会不断减小此自定义视图的大小。每次启动活动时,都会反复应用0.8折减系数。我怀疑LayoutParams的设置与此有关,实际上可能没有必要,但我没有时间进行测试


但是,这仍然回答了关于这篇文章的问题,即为什么我的观点没有出现,尽管有正确的维度。

我不知道你的意思。诚然,我正在实现这一半盲设计,从这一行中我知道,任何给定视图或视图组的布局参数都必须是其父容器的布局参数的实例。正是关于这一行,我在最后问了我的小问题,这样我就不必硬编码RelativeLayout作为父类型。看来blessenm给了我答案。谢谢,我今天晚些时候会尝试。尝试了这个,但是做了一个小小的修改,getSimpleName只得到类名,结果getName得到了整个包android.widget.RelativeLayout。对我来说,这似乎很奇怪,我不得不借助字符串比较来区分父母双方,但我想就我的目的而言,这是可行的。谢谢你的指点!我已经更新了我的答案。如果这有帮助,upvote,如果它解决了你的问题,接受答案。嗨,谢谢你提供的额外信息,但是通过进一步的测试和修复我遇到的主要错误,我发现我真的不需要知道父类型。事实证明,我可以直接编辑视图的LayoutParams的高度和宽度,而不必实例化新的LayoutParams对象。无论如何,我都不接受这个答案,因为你的解决方案虽然肯定很有帮助,但只针对我遇到的小问题,而不是我发布的主要问题。我已经更新了帖子,以反映对我遇到的主要问题的修复。再次感谢!
@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int specWidth = MeasureSpec.getSize(widthMeasureSpec);
        int specHeight = MeasureSpec.getSize(heightMeasureSpec);

        int newWidth = (int) Math.ceil(parentWidth * 0.8);
        int newHeight = (int) Math.ceil(parentHeight * 0.8);

        this.setMeasuredDimension(newWidth, newHeight);

        this.getLayoutParams().height = newHeight;
        this.getLayoutParams().width = newWidth;

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }