无法在ConstraintLayout.Group中的单个项目上设置可见性

时间:2018-11-27 21:27:35

标签: android android-layout android-constraintlayout

我有一个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" />

我将该群组的可见性从“消失”更改为“可见”:

someGroup.visibility = VISIBLE

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

button1.visibility = GONE

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

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

1 个答案:

答案 0 :(得分:7)

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

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

  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;
    }
}