【问题标题】:Cannot set visibility on individual items in a ConstraintLayout.Group无法设置 ConstraintLayout.Group 中单个项目的可见性
【发布时间】:2018-11-27 21:27:34
【问题描述】:

我有一个这样定义的ConstraintLayout.Group

    <android.support.constraint.Group
        android:id="@+id/someGroup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:constraint_referenced_ids="
        textView1,
        textView2,
        button1" />

我将此组的可见性从 GONE 更改为 VISIBLE:

someGroup.visibility = VISIBLE

但是当我尝试通过指定该组中一个视图的可见性来覆盖它时:

button1.visibility = GONE

...它不起作用。我将此可见性记录到 logcat,它显示 8 (GONE)但我仍然可以看到视图

有什么想法可能在这里发生吗?我尝试在该组上调用requestLayoutupdatePreLayout,我尝试更改几次可见性,可见、不可见然后消失。我什至重建了整个项目,因为一些 stackoverflow 回答说它可能有助于解决 ConstraintLayout 中的可见性问题。我还尝试了 1.1.3 和 2.2.0-alpha 版本。没有任何效果。它总是可见的。

【问题讨论】:

    标签: android android-layout android-constraintlayout


    【解决方案1】:

    更新:组内单个视图可见性的行为已更改,并在 ConstraintLayout 版本 2.0.0 beta 6 中报告为已修复。请参阅 bug fixes for ConstraintLayout 2.0.0 beta 6


    您看到了正确的行为。在组中放置视图时,您放弃了更改单个视图可见性的能力。我认为机制是视图的可见性是(由您)设置的,然后根据组成员身份(由系统)分配组的可见性。

    解决方法取决于您的需要:

    1. 保留要控制的视图在组外的可见性;
    2. 管理自己的群组逻辑,忘记系统提供的群组;
    3. 使用setReferencedIds管理群组成员。

    我认为这是一个常见的投诉,但我也认为它不太可能得到解决。 (恕我直言)


    我刚刚评论了关于这个确切问题的另一个问题,所以我冒昧地在这里发布(尽管答案已经被接受)一个简单的类,这将有助于管理 ConstraintLayout 组。

    ManagedGroup.java

    /**
     * Manage a ConstraintLayout Group view membership as a view's visibility is changed. Calling
     * {@link #setVisibility(View, int)} will set a view's visibility and remove it from the group.
     * Other methods here provide explicit means to manage a group's view membership.
     * <p>
     * Usage: In XML define
     * <pre>{@code
     * <[Package].ManagedGroup
     *         android:id="@+id/group"
     *         android:layout_width="wrap_content"
     *         android:layout_height="wrap_content"
     *         android:visibility="visible"
     *         app:constraint_referenced_ids="id1,id2,id3..." />}
     * </pre>
     */
    public class ManagedGroup extends Group {
        private final Set<Integer> mRemovedRefIds = new HashSet<>();
    
        public ManagedGroup(Context context) {
            super(context);
        }
    
        public ManagedGroup(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public ManagedGroup(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        /**
         * Set the reference ids for the group and clear the removed id array.
         *
         * @param ids All identifiers in the group.
         */
        @Override
        public void setReferencedIds(@NonNull int[] ids) {
            super.setReferencedIds(ids);
            mRemovedRefIds.clear();
        }
    
        /**
         * Set visibility for  view and remove the view's id from the group.
         *
         * @param view       View for visibility change
         * @param visibility View.VISIBLE, View.INVISIBLE or View.GONE.
         */
        public void setVisibility(@NonNull View view, int visibility) {
            removeReferencedIds(view.getId());
            view.setVisibility(visibility);
        }
    
        /**
         * Add all removed views back into the group.
         */
        public void resetGroup() {
            setReferencedIds(getAllReferencedIds());
        }
    
        /**
         * Remove reference ids from the group. This is done automatically when
         * setVisibility(View view, int visibility) is called.
         *
         * @param idsToRemove All the ids to remove from the group.
         */
        public void removeReferencedIds(int... idsToRemove) {
            for (int id : idsToRemove) {
                mRemovedRefIds.add(id);
            }
    
            int[] refIds = getReferencedIds();
            Set<Integer> newRefIdSet = new HashSet<>();
    
            for (int id : refIds) {
                if (!mRemovedRefIds.contains(id)) {
                    newRefIdSet.add(id);
                }
            }
            super.setReferencedIds(copySetToIntArray(newRefIdSet));
        }
    
        /**
         * Add reference ids to the group.
         *
         * @param idsToAdd Identifiers to add to the group.
         */
        public void addReferencedIds(int... idsToAdd) {
            for (int id : idsToAdd) {
                mRemovedRefIds.remove(id);
            }
            super.setReferencedIds(joinArrays(getReferencedIds(), idsToAdd));
        }
    
        /**
         * Return int[] of all ids in the group plus those removed.
         *
         * @return All current ids in group plus those removed.
         */
        @NonNull
        public int[] getAllReferencedIds() {
            return joinArrays(getReferencedIds(), copySetToIntArray(mRemovedRefIds));
        }
    
        @NonNull
        private int[] copySetToIntArray(Set<Integer> fromSet) {
            int[] toArray = new int[fromSet.size()];
            int i = 0;
    
            for (int id : fromSet) {
                toArray[i++] = id;
            }
    
            return toArray;
        }
    
        @NonNull
        private int[] joinArrays(@NonNull int[] array1, @NonNull int[] array2) {
            int[] joinedArray = new int[array1.length + array2.length];
    
            System.arraycopy(array1, 0, joinedArray, 0, array1.length);
            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
            return joinedArray;
        }
    }
    

    【讨论】:

    • 我担心这可能是答案。让我等几天,如果没有人回复任何不同的内容,我会标记为正确。
    • 没错。并且是一个非常愚蠢的 API。仅仅因为一个人将一个组分配给一个视图并不意味着他们想通过它来唯一地控制可见性。我不相信谷歌实际上是这样设计的,并认为这是个好主意。
    • ConstraintLayout 2.0.0 beta 6 允许为单个视图设置可见性,但仅当您以编程方式设置可见性时才有效
    猜你喜欢
    • 2015-06-27
    • 1970-01-01
    • 2016-07-09
    • 2010-12-09
    • 2015-05-02
    • 1970-01-01
    • 2015-08-18
    • 2022-01-18
    • 2010-09-27
    相关资源
    最近更新 更多