【问题标题】:Group in ConstraintLayout prevents setting ProgressBar visibilityConstraintLayout 中的组阻止设置 ProgressBar 可见性
【发布时间】:2018-11-29 16:55:12
【问题描述】:

我正在通过使用新的 ConstraintLayout (1.1.2) 来扁平化我的布局,但我无法再控制 ProgressBar 在组中时的可见性。这是我的布局 XML 文件的最简单版本,它重现了该问题:

    <android.support.constraint.ConstraintLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <!-- This group prevents me from hiding ProgressBar -->
        <android.support.constraint.Group
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:constraint_referenced_ids="imageLoadingSpinner" />

        <ProgressBar
            android:id="@+id/imageLoadingSpinner"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </android.support.constraint.ConstraintLayout>

我引入了 Group 是为了控制一些布局,但为了简单起见,我将所有这些都省略了。该bug的本质是引入组阻止我将ProgressBar的可见性设置为GONE

以下代码不再隐藏 ProgressBar:

    find(R.id.imageLoadingSpinner).setVisibility(GONE);

要明确一点,如果我删除组,如下图,我可以将ProgressBar的可见性设置为GONE

    <android.support.constraint.ConstraintLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <!-- Commenting out this group allows me to hide ProgressBar -->
        <!--<android.support.constraint.Group-->
            <!--android:layout_width="wrap_content"-->
            <!--android:layout_height="wrap_content"-->
            <!--app:constraint_referenced_ids="imageLoadingSpinner" />-->

        <ProgressBar
            android:id="@+id/imageLoadingSpinner"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </android.support.constraint.ConstraintLayout>

我找不到有关此问题的任何信息。 ProgressBar visibility issue 无关。

【问题讨论】:

    标签: android android-layout android-constraintlayout


    【解决方案1】:

    虽然如前所述,您无法仅更改单个 Group 子项的可见性(为此我发现此小部件的帮助和乐趣都少得多),但您始终可以设置其 alpha 属性。

    因此,如果您不以任何方式弄乱要隐藏的视图的 alpha 值,则可以执行以下操作:

    find(R.id.imageLoadingSpinner).setAlpha(0);
    

    我找不到不这样做的理由,除了视图可能仍会被渲染,然后所有渲染的像素将被转换为 0-alpha,因此会变得不可见,浪费一些时钟的周期,但在大多数情况下,将其视为问题未免有些夸张。

    【讨论】:

    • 聪明的主意,谢谢。我同意您的观点,即 Group 小部件的帮助要小得多,因为您无法独立于 Group 控制其子项的可见性。我更喜欢使用 setVisibility 控制可见性的解决方案,因为它更易于维护(特别是,项目的未来开发人员可以比使用 setAlpha 的技巧更快地理解它)。不过谢谢!
    • "...为此,我发现这个小部件的帮助和乐趣要少得多" - 你可以再说一遍!这种有点违反直觉的行为只花了我 2 个小时......
    【解决方案2】:

    我不认为这是一个问题,因为根据docs,基本上这是使用Group

    该类控制一组引用小部件的可见性。

    还有:

    组的可见性将应用于引用的小部件。这是一种轻松隐藏/显示一组小部件的便捷方式,无需以编程方式维护该组。

    因此,您必须设置组本身的可见性。我不知道您使用该组做什么,因为您没有指定,但也许您应该重组以更好地利用它,或者完全摆脱它。

    【讨论】:

    • 我明白了,我认为组的可见性不会优先于子级,因为我正在转换的布局有一个 LinearLayout 而不是一个组,并且可见性逻辑有效。所以我想我会使用屏障而不是组。
    • @MichaelOsofsky 是的,视图一侧的障碍约束也可以工作。
    • 这种行为看起来既错误又愚蠢。感谢您的正确回答。
    【解决方案3】:

    只是为了添加各种解决方案 - 您可以扩展 Group 并使其行为符合您的预期。如果您经常使用组并且您期望在可见性方面正常的父子行为,这会更方便一些。

    public class LayoutGroup extends Group {
        public LayoutGroup(Context context) {
            super(context);
        }
    
        public LayoutGroup(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public LayoutGroup(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        public void updatePreLayout(ConstraintLayout container) {
            int visibility = this.getVisibility();
            float elevation = 0.0F;
            if (Build.VERSION.SDK_INT >= 21) {
                elevation = this.getElevation();
            }
    
            for(int i = 0; i < this.mCount; ++i) {
                int id = this.mIds[i];
                View view = container.getViewById(id);
                if (view != null) {
                    // If the group is visible, let the child control visibility
                    view.setVisibility(visibility == VISIBLE ? view.getVisibility() : visibility);
                    if (elevation > 0.0F && Build.VERSION.SDK_INT >= 21) {
                        view.setElevation(elevation);
                    }
                }
            }
        }
    }
    

    作为参考,这里是来自基类(组)的代码:

      for(int i = 0; i < this.mCount; ++i) {
            int id = this.mIds[i];
            View view = container.getViewById(id);
            if (view != null) {
                view.setVisibility(visibility);
                if (elevation > 0.0F && VERSION.SDK_INT >= 21) {
                    view.setElevation(elevation);
                }
            }
        }
    

    然后在你的布局文件中当然使用你自己的组件:

       <yourpackage.LayoutGroup
                android:id="@+id/group_id"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:constraint_referenced_ids="view1,view2,view3"/>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多