public class MultiAudioLayout extends ViewGroup implements IUserUpdateCallback {
private Context context;
private int childVerticalSpace;
private int childHorizontalSpace;
private int maxColumnNum;
private int maxRowNum;
private int childWidth;
private int childHeight;
private Map<String, AudioItemView> audioItemMap;
private OnClickMoreMemberListener listener;
private List<String> hideData;
public MultiAudioLayout(Context context) {
this(context, null);
}
public MultiAudioLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
audioItemMap = new HashMap<>();
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.MultiVideoLayout);
if (attributes != null) {
childVerticalSpace = attributes.getDimensionPixelSize(R.styleable.MultiVideoLayout_childVerticalSpace, 0);
maxColumnNum = attributes.getInt(R.styleable.MultiVideoLayout_maxColumnNum, 0);
maxRowNum = attributes.getInt(R.styleable.MultiVideoLayout_maxRowNum, 0);
attributes.recycle();
}
MeetingManager.getInstance().addUserUpdateCallback(this.getClass(), this);
hideData = new ArrayList<>();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int childCount = getChildCount();
if (childCount == 0) {
setMeasuredDimension(0, 0);
} else {
measureChildren(widthMeasureSpec, heightMeasureSpec);
childWidth = getChildAt(0).getMeasuredWidth();
childHeight = getChildAt(0).getMeasuredHeight();
childHorizontalSpace = (width - maxColumnNum * childWidth) / (maxColumnNum - 1);
int realWidth = width;
int realHeight;
if (childCount < maxColumnNum) {
realWidth = childCount * childWidth + ((childCount - 1) * childHorizontalSpace);
}
int rowCount = childCount / maxColumnNum + (childCount % maxColumnNum != 0 ? 1 : 0);
realHeight = rowCount * childHeight + (rowCount - 1) * childVerticalSpace;
if (realHeight > height) {
realHeight = height;
}
setMeasuredDimension(realWidth, realHeight);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left;
int top;
for (int i = 0; i < getChildCount(); i++) {
AudioItemView audioItemView = (AudioItemView) getChildAt(i);
left = (i % maxColumnNum) * (childWidth + childHorizontalSpace);
top = (i / maxRowNum) * (childHeight + childVerticalSpace);
audioItemView.layout(left, top, left + childWidth, top + childHeight);
}
}
@Override
public void addUser(String userId) {
if (!isExistUser(userId)) {
if (!isMax()) {
AudioItemView audioItemView = new AudioItemView(context);
audioItemView.bindUser(userId);
this.addView(audioItemView);
audioItemMap.put(userId, audioItemView);
} else {
AudioItemView lastAudioItemView = (AudioItemView) getChildAt(getChildCount() - 1);
if (!TextUtils.isEmpty(lastAudioItemView.getUserId())) {
lastAudioItemView.setMoreView();
lastAudioItemView.setOnClickListener(v -> {
if (listener != null) {
listener.clickMoreMember();
}
});
hideData.add(lastAudioItemView.getUserId());
audioItemMap.remove(lastAudioItemView.getUserId());
lastAudioItemView.bindUser("");
}
hideData.add(userId);
}
}
}
@Override
public void updateUser(String userId) {
if (audioItemMap.get(userId) != null) {
audioItemMap.get(userId).updateUser();
}
}
@Override
public void removeUser(String userId) {
if (isExistUser(userId)) {
AudioItemView removeItem = audioItemMap.get(userId);
int position = indexOfChild(removeItem);
this.removeView(removeItem);
audioItemMap.remove(userId);
AudioItemView lastAudioItemView = (AudioItemView) getChildAt(getChildCount() - 1);
if (TextUtils.isEmpty(lastAudioItemView.getUserId())) {
if (hideData.size() > 0 && hideData.size() <= 2) {
lastAudioItemView.bindUser(hideData.get(0));
lastAudioItemView.updateUser();
lastAudioItemView.setOnClickListener(null);
audioItemMap.put(hideData.get(0), lastAudioItemView);
hideData.remove(0);
if (hideData.size() > 0) {
AudioItemView audioItemView = new AudioItemView(context);
audioItemView.bindUser(hideData.get(0));
audioItemView.updateUser();
this.addView(audioItemView);
audioItemMap.put(hideData.get(0), audioItemView);
hideData.clear();
}
} else if (hideData.size() > 2) {
AudioItemView audioItemView = new AudioItemView(context);
audioItemView.bindUser(hideData.get(0));
audioItemView.updateUser();
this.addView(audioItemView, position);
audioItemMap.put(hideData.get(0), audioItemView);
hideData.remove(0);
}
}
} else if (hideData.contains(userId)) {
for (int i = 0; i < hideData.size(); i++) {
if (userId.equals(hideData.get(i))) {
hideData.remove(i);
}
}
if (hideData.size() == 1) {
AudioItemView lastAudioItemView = (AudioItemView) getChildAt(getChildCount() - 1);
if (TextUtils.isEmpty(lastAudioItemView.getUserId())) {
lastAudioItemView.bindUser(hideData.get(0));
lastAudioItemView.updateUser();
lastAudioItemView.setOnClickListener(null);
audioItemMap.put(hideData.get(0), lastAudioItemView);
hideData.clear();
}
}
}
}
@Override
public void userCameraStateUpdate(String userId) {
}
@Override
public void userMicStateUpdate(String userId) {
}
@Override
public void onStreamUpdate(String userId, boolean isAdd) {
if (!isAdd) {
MeetingManager.getInstance().stopPlay(userId);
}
}
@Override
public void onVideoStreamUpdate(String userId, boolean isAvailable) {
}
public AudioItemView getUser(String userId) {
return isExistUser(userId) ? audioItemMap.get(userId) : null;
}
public boolean isExistUser(String userId) {
return audioItemMap.containsKey(userId);
}
public boolean isMax() { return getChildCount() >= maxColumnNum * maxRowNum; }
public void setActiveVoice(String userId) {
if (isExistUser(userId)) {
for (Map.Entry<String, AudioItemView> entry : audioItemMap.entrySet()) {
if (entry.getKey().equals(userId)) {
entry.getValue().setMaxVoice(true);
} else {
entry.getValue().setMaxVoice(false);
}
}
} else {
for (Map.Entry<String, AudioItemView> entry : audioItemMap.entrySet()) {
entry.getValue().setMaxVoice(false);
}
}
}
public void setVisible(boolean isVisible) {
if (isVisible) {
if (isVisible()) {
return;
}
setVisibility(View.VISIBLE);
} else {
if (!isVisible()) {
return;
}
setVisibility(View.GONE);
}
}
public boolean isVisible() {
return getVisibility() == View.VISIBLE;
}
public void setOnClickMoreMemberListener(OnClickMoreMemberListener listener) {
this.listener = listener;
}
public interface OnClickMoreMemberListener {
void clickMoreMember();
}
}