更新:组内单个视图可见性的行为已更改,并在 ConstraintLayout 版本 2.0.0 beta 6 中报告为已修复。请参阅 bug fixes for ConstraintLayout 2.0.0 beta 6 。
您看到了正确的行为。在组中放置视图时,您放弃了更改单个视图可见性的能力。我认为机制是视图的可见性是(由您)设置的,然后根据组成员身份(由系统)分配组的可见性。
解决方法取决于您的需要:
- 保留要控制的视图在组外的可见性;
- 管理自己的群组逻辑,忘记系统提供的群组;
- 使用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;
}
}