use of org.telegram.ui.Components.voip.VoIPTextureView in project Telegram-FOSS by Telegram-FOSS-Team.
the class VoIPFragment method createView.
public View createView(Context context) {
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
accessibilityManager = ContextCompat.getSystemService(context, AccessibilityManager.class);
FrameLayout frameLayout = new FrameLayout(context) {
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH && lastInsets != null) {
canvas.drawRect(0, 0, getMeasuredWidth(), lastInsets.getSystemWindowInsetTop(), overlayPaint);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH && lastInsets != null) {
canvas.drawRect(0, getMeasuredHeight() - lastInsets.getSystemWindowInsetBottom(), getMeasuredWidth(), getMeasuredHeight(), overlayBottomPaint);
}
}
float pressedX;
float pressedY;
boolean check;
long pressedTime;
@Override
public boolean onTouchEvent(MotionEvent ev) {
/* === pinch to zoom === */
if (!canZoomGesture && !isInPinchToZoomTouchMode && !zoomStarted && ev.getActionMasked() != MotionEvent.ACTION_DOWN) {
finishZoom();
return false;
}
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
canZoomGesture = false;
isInPinchToZoomTouchMode = false;
zoomStarted = false;
}
VoIPTextureView currentTextureView = getFullscreenTextureView();
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN || ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
AndroidUtilities.rectTmp.set(currentTextureView.getX(), currentTextureView.getY(), currentTextureView.getX() + currentTextureView.getMeasuredWidth(), currentTextureView.getY() + currentTextureView.getMeasuredHeight());
AndroidUtilities.rectTmp.inset((currentTextureView.getMeasuredHeight() * currentTextureView.scaleTextureToFill - currentTextureView.getMeasuredHeight()) / 2, (currentTextureView.getMeasuredWidth() * currentTextureView.scaleTextureToFill - currentTextureView.getMeasuredWidth()) / 2);
if (!GroupCallActivity.isLandscapeMode) {
AndroidUtilities.rectTmp.top = Math.max(AndroidUtilities.rectTmp.top, ActionBar.getCurrentActionBarHeight());
AndroidUtilities.rectTmp.bottom = Math.min(AndroidUtilities.rectTmp.bottom, currentTextureView.getMeasuredHeight() - AndroidUtilities.dp(90));
} else {
AndroidUtilities.rectTmp.top = Math.max(AndroidUtilities.rectTmp.top, ActionBar.getCurrentActionBarHeight());
AndroidUtilities.rectTmp.right = Math.min(AndroidUtilities.rectTmp.right, currentTextureView.getMeasuredWidth() - AndroidUtilities.dp(90));
}
canZoomGesture = AndroidUtilities.rectTmp.contains(ev.getX(), ev.getY());
if (!canZoomGesture) {
finishZoom();
// return maybeSwipeToBackGesture;
}
}
if (!isInPinchToZoomTouchMode && ev.getPointerCount() == 2) {
pinchStartDistance = (float) Math.hypot(ev.getX(1) - ev.getX(0), ev.getY(1) - ev.getY(0));
pinchStartCenterX = pinchCenterX = (ev.getX(0) + ev.getX(1)) / 2.0f;
pinchStartCenterY = pinchCenterY = (ev.getY(0) + ev.getY(1)) / 2.0f;
pinchScale = 1f;
pointerId1 = ev.getPointerId(0);
pointerId2 = ev.getPointerId(1);
isInPinchToZoomTouchMode = true;
}
} else if (ev.getActionMasked() == MotionEvent.ACTION_MOVE && isInPinchToZoomTouchMode) {
int index1 = -1;
int index2 = -1;
for (int i = 0; i < ev.getPointerCount(); i++) {
if (pointerId1 == ev.getPointerId(i)) {
index1 = i;
}
if (pointerId2 == ev.getPointerId(i)) {
index2 = i;
}
}
if (index1 == -1 || index2 == -1) {
getParent().requestDisallowInterceptTouchEvent(false);
finishZoom();
// return maybeSwipeToBackGesture;
}
pinchScale = (float) Math.hypot(ev.getX(index2) - ev.getX(index1), ev.getY(index2) - ev.getY(index1)) / pinchStartDistance;
if (pinchScale > 1.005f && !zoomStarted) {
pinchStartDistance = (float) Math.hypot(ev.getX(index2) - ev.getX(index1), ev.getY(index2) - ev.getY(index1));
pinchStartCenterX = pinchCenterX = (ev.getX(index1) + ev.getX(index2)) / 2.0f;
pinchStartCenterY = pinchCenterY = (ev.getY(index1) + ev.getY(index2)) / 2.0f;
pinchScale = 1f;
pinchTranslationX = 0f;
pinchTranslationY = 0f;
getParent().requestDisallowInterceptTouchEvent(true);
//
zoomStarted = true;
isInPinchToZoomTouchMode = true;
}
float newPinchCenterX = (ev.getX(index1) + ev.getX(index2)) / 2.0f;
float newPinchCenterY = (ev.getY(index1) + ev.getY(index2)) / 2.0f;
float moveDx = pinchStartCenterX - newPinchCenterX;
float moveDy = pinchStartCenterY - newPinchCenterY;
pinchTranslationX = -moveDx / pinchScale;
pinchTranslationY = -moveDy / pinchScale;
invalidate();
} else if ((ev.getActionMasked() == MotionEvent.ACTION_UP || (ev.getActionMasked() == MotionEvent.ACTION_POINTER_UP && checkPointerIds(ev)) || ev.getActionMasked() == MotionEvent.ACTION_CANCEL)) {
getParent().requestDisallowInterceptTouchEvent(false);
finishZoom();
}
fragmentView.invalidate();
switch(ev.getAction()) {
case MotionEvent.ACTION_DOWN:
pressedX = ev.getX();
pressedY = ev.getY();
check = true;
pressedTime = System.currentTimeMillis();
break;
case MotionEvent.ACTION_CANCEL:
check = false;
break;
case MotionEvent.ACTION_UP:
if (check) {
float dx = ev.getX() - pressedX;
float dy = ev.getY() - pressedY;
long currentTime = System.currentTimeMillis();
if (dx * dx + dy * dy < touchSlop * touchSlop && currentTime - pressedTime < 300 && currentTime - lastContentTapTime > 300) {
lastContentTapTime = System.currentTimeMillis();
if (emojiExpanded) {
expandEmoji(false);
} else if (canHideUI) {
showUi(!uiVisible);
previousState = currentState;
updateViewState();
}
}
check = false;
}
break;
}
return canZoomGesture || check;
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (child == callingUserPhotoView && (currentUserIsVideo || callingUserIsVideo)) {
return false;
}
if (child == callingUserPhotoView || child == callingUserTextureView || (child == currentUserCameraFloatingLayout && currentUserCameraIsFullscreen)) {
if (zoomStarted || zoomBackAnimator != null) {
canvas.save();
canvas.scale(pinchScale, pinchScale, pinchCenterX, pinchCenterY);
canvas.translate(pinchTranslationX, pinchTranslationY);
boolean b = super.drawChild(canvas, child, drawingTime);
canvas.restore();
return b;
}
}
return super.drawChild(canvas, child, drawingTime);
}
};
frameLayout.setClipToPadding(false);
frameLayout.setClipChildren(false);
frameLayout.setBackgroundColor(0xff000000);
updateSystemBarColors();
fragmentView = frameLayout;
frameLayout.setFitsSystemWindows(true);
callingUserPhotoView = new BackupImageView(context) {
int blackoutColor = ColorUtils.setAlphaComponent(Color.BLACK, (int) (255 * 0.3f));
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(blackoutColor);
}
};
callingUserTextureView = new VoIPTextureView(context, false, true, false, false);
callingUserTextureView.renderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
callingUserTextureView.renderer.setEnableHardwareScaler(true);
callingUserTextureView.renderer.setRotateTextureWithScreen(true);
callingUserTextureView.scaleType = VoIPTextureView.SCALE_TYPE_FIT;
// callingUserTextureView.attachBackgroundRenderer();
frameLayout.addView(callingUserPhotoView);
frameLayout.addView(callingUserTextureView);
final BackgroundGradientDrawable gradientDrawable = new BackgroundGradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] { 0xFF1b354e, 0xFF255b7d });
final BackgroundGradientDrawable.Sizes sizes = BackgroundGradientDrawable.Sizes.ofDeviceScreen(BackgroundGradientDrawable.Sizes.Orientation.PORTRAIT);
gradientDrawable.startDithering(sizes, new BackgroundGradientDrawable.ListenerAdapter() {
@Override
public void onAllSizesReady() {
callingUserPhotoView.invalidate();
}
});
overlayBackground = new VoIPOverlayBackground(context);
overlayBackground.setVisibility(View.GONE);
callingUserPhotoView.getImageReceiver().setDelegate((imageReceiver, set, thumb, memCache) -> {
ImageReceiver.BitmapHolder bmp = imageReceiver.getBitmapSafe();
if (bmp != null) {
overlayBackground.setBackground(bmp);
}
});
callingUserPhotoView.setImage(ImageLocation.getForUserOrChat(callingUser, ImageLocation.TYPE_BIG), null, gradientDrawable, callingUser);
currentUserCameraFloatingLayout = new VoIPFloatingLayout(context);
currentUserCameraFloatingLayout.setDelegate((progress, value) -> currentUserTextureView.setScreenshareMiniProgress(progress, value));
currentUserCameraFloatingLayout.setRelativePosition(1f, 1f);
currentUserCameraIsFullscreen = true;
currentUserTextureView = new VoIPTextureView(context, true, false);
currentUserTextureView.renderer.setIsCamera(true);
currentUserTextureView.renderer.setUseCameraRotation(true);
currentUserCameraFloatingLayout.setOnTapListener(view -> {
if (currentUserIsVideo && callingUserIsVideo && System.currentTimeMillis() - lastContentTapTime > 500) {
AndroidUtilities.cancelRunOnUIThread(hideUIRunnable);
hideUiRunnableWaiting = false;
lastContentTapTime = System.currentTimeMillis();
callingUserMiniFloatingLayout.setRelativePosition(currentUserCameraFloatingLayout);
currentUserCameraIsFullscreen = true;
cameraForceExpanded = true;
previousState = currentState;
updateViewState();
}
});
currentUserTextureView.renderer.setMirror(true);
currentUserCameraFloatingLayout.addView(currentUserTextureView);
callingUserMiniFloatingLayout = new VoIPFloatingLayout(context);
callingUserMiniFloatingLayout.alwaysFloating = true;
callingUserMiniFloatingLayout.setFloatingMode(true, false);
callingUserMiniTextureRenderer = new TextureViewRenderer(context);
callingUserMiniTextureRenderer.setEnableHardwareScaler(true);
callingUserMiniTextureRenderer.setIsCamera(false);
callingUserMiniTextureRenderer.setFpsReduction(30);
callingUserMiniTextureRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
View backgroundView = new View(context);
backgroundView.setBackgroundColor(0xff1b1f23);
callingUserMiniFloatingLayout.addView(backgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
callingUserMiniFloatingLayout.addView(callingUserMiniTextureRenderer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
callingUserMiniFloatingLayout.setOnTapListener(view -> {
if (cameraForceExpanded && System.currentTimeMillis() - lastContentTapTime > 500) {
AndroidUtilities.cancelRunOnUIThread(hideUIRunnable);
hideUiRunnableWaiting = false;
lastContentTapTime = System.currentTimeMillis();
currentUserCameraFloatingLayout.setRelativePosition(callingUserMiniFloatingLayout);
currentUserCameraIsFullscreen = false;
cameraForceExpanded = false;
previousState = currentState;
updateViewState();
}
});
callingUserMiniFloatingLayout.setVisibility(View.GONE);
frameLayout.addView(currentUserCameraFloatingLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
frameLayout.addView(callingUserMiniFloatingLayout);
frameLayout.addView(overlayBackground);
bottomShadow = new View(context);
bottomShadow.setBackground(new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] { Color.TRANSPARENT, ColorUtils.setAlphaComponent(Color.BLACK, (int) (255 * 0.5f)) }));
frameLayout.addView(bottomShadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 140, Gravity.BOTTOM));
topShadow = new View(context);
topShadow.setBackground(new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] { ColorUtils.setAlphaComponent(Color.BLACK, (int) (255 * 0.4f)), Color.TRANSPARENT }));
frameLayout.addView(topShadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 140, Gravity.TOP));
emojiLayout = new LinearLayout(context) {
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setVisibleToUser(emojiLoaded);
}
};
emojiLayout.setOrientation(LinearLayout.HORIZONTAL);
emojiLayout.setPadding(0, 0, 0, AndroidUtilities.dp(30));
emojiLayout.setClipToPadding(false);
emojiLayout.setOnClickListener(view -> {
if (System.currentTimeMillis() - lastContentTapTime < 500) {
return;
}
lastContentTapTime = System.currentTimeMillis();
if (emojiLoaded) {
expandEmoji(!emojiExpanded);
}
});
emojiRationalTextView = new TextView(context);
emojiRationalTextView.setText(LocaleController.formatString("CallEmojiKeyTooltip", R.string.CallEmojiKeyTooltip, UserObject.getFirstName(callingUser)));
emojiRationalTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
emojiRationalTextView.setTextColor(Color.WHITE);
emojiRationalTextView.setGravity(Gravity.CENTER);
emojiRationalTextView.setVisibility(View.GONE);
for (int i = 0; i < 4; i++) {
emojiViews[i] = new ImageView(context);
emojiViews[i].setScaleType(ImageView.ScaleType.FIT_XY);
emojiLayout.addView(emojiViews[i], LayoutHelper.createLinear(22, 22, i == 0 ? 0 : 4, 0, 0, 0));
}
statusLayout = new LinearLayout(context) {
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
final VoIPService service = VoIPService.getSharedInstance();
final CharSequence callingUserTitleText = callingUserTitle.getText();
if (service != null && !TextUtils.isEmpty(callingUserTitleText)) {
final StringBuilder builder = new StringBuilder(callingUserTitleText);
builder.append(", ");
if (service.privateCall != null && service.privateCall.video) {
builder.append(LocaleController.getString("VoipInVideoCallBranding", R.string.VoipInVideoCallBranding));
} else {
builder.append(LocaleController.getString("VoipInCallBranding", R.string.VoipInCallBranding));
}
final long callDuration = service.getCallDuration();
if (callDuration > 0) {
builder.append(", ");
builder.append(LocaleController.formatDuration((int) (callDuration / 1000)));
}
info.setText(builder);
}
}
};
statusLayout.setOrientation(LinearLayout.VERTICAL);
statusLayout.setFocusable(true);
statusLayout.setFocusableInTouchMode(true);
callingUserPhotoViewMini = new BackupImageView(context);
callingUserPhotoViewMini.setImage(ImageLocation.getForUserOrChat(callingUser, ImageLocation.TYPE_SMALL), null, Theme.createCircleDrawable(AndroidUtilities.dp(135), 0xFF000000), callingUser);
callingUserPhotoViewMini.setRoundRadius(AndroidUtilities.dp(135) / 2);
callingUserPhotoViewMini.setVisibility(View.GONE);
callingUserTitle = new TextView(context);
callingUserTitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 24);
callingUserTitle.setText(ContactsController.formatName(callingUser.first_name, callingUser.last_name));
callingUserTitle.setShadowLayer(AndroidUtilities.dp(3), 0, AndroidUtilities.dp(.666666667f), 0x4C000000);
callingUserTitle.setTextColor(Color.WHITE);
callingUserTitle.setGravity(Gravity.CENTER_HORIZONTAL);
callingUserTitle.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
statusLayout.addView(callingUserTitle, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 6));
statusTextView = new VoIPStatusTextView(context);
ViewCompat.setImportantForAccessibility(statusTextView, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
statusLayout.addView(statusTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 6));
statusLayout.setClipChildren(false);
statusLayout.setClipToPadding(false);
statusLayout.setPadding(0, 0, 0, AndroidUtilities.dp(15));
frameLayout.addView(callingUserPhotoViewMini, LayoutHelper.createFrame(135, 135, Gravity.CENTER_HORIZONTAL, 0, 68, 0, 0));
frameLayout.addView(statusLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 68, 0, 0));
frameLayout.addView(emojiLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 17, 0, 0));
frameLayout.addView(emojiRationalTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 24, 32, 24, 0));
buttonsLayout = new VoIPButtonsLayout(context);
for (int i = 0; i < 4; i++) {
bottomButtons[i] = new VoIPToggleButton(context);
buttonsLayout.addView(bottomButtons[i]);
}
acceptDeclineView = new AcceptDeclineView(context);
acceptDeclineView.setListener(new AcceptDeclineView.Listener() {
@Override
public void onAccept() {
if (currentState == VoIPService.STATE_BUSY) {
Intent intent = new Intent(activity, VoIPService.class);
intent.putExtra("user_id", callingUser.id);
intent.putExtra("is_outgoing", true);
intent.putExtra("start_incall_activity", false);
intent.putExtra("video_call", isVideoCall);
intent.putExtra("can_video_call", isVideoCall);
intent.putExtra("account", currentAccount);
try {
activity.startService(intent);
} catch (Throwable e) {
FileLog.e(e);
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && activity.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[] { Manifest.permission.RECORD_AUDIO }, 101);
} else {
if (VoIPService.getSharedInstance() != null) {
VoIPService.getSharedInstance().acceptIncomingCall();
if (currentUserIsVideo) {
VoIPService.getSharedInstance().requestVideoCall(false);
}
}
}
}
}
@Override
public void onDecline() {
if (currentState == VoIPService.STATE_BUSY) {
windowView.finish();
} else {
if (VoIPService.getSharedInstance() != null) {
VoIPService.getSharedInstance().declineIncomingCall();
}
}
}
});
acceptDeclineView.setScreenWasWakeup(screenWasWakeup);
frameLayout.addView(buttonsLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM));
frameLayout.addView(acceptDeclineView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 186, Gravity.BOTTOM));
backIcon = new ImageView(context);
backIcon.setBackground(Theme.createSelectorDrawable(ColorUtils.setAlphaComponent(Color.WHITE, (int) (255 * 0.3f))));
backIcon.setImageResource(R.drawable.ic_ab_back);
backIcon.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16));
backIcon.setContentDescription(LocaleController.getString("Back", R.string.Back));
frameLayout.addView(backIcon, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.LEFT));
speakerPhoneIcon = new ImageView(context) {
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(ToggleButton.class.getName());
info.setCheckable(true);
VoIPService service = VoIPService.getSharedInstance();
if (service != null) {
info.setChecked(service.isSpeakerphoneOn());
}
}
};
speakerPhoneIcon.setContentDescription(LocaleController.getString("VoipSpeaker", R.string.VoipSpeaker));
speakerPhoneIcon.setBackground(Theme.createSelectorDrawable(ColorUtils.setAlphaComponent(Color.WHITE, (int) (255 * 0.3f))));
speakerPhoneIcon.setPadding(AndroidUtilities.dp(12), AndroidUtilities.dp(12), AndroidUtilities.dp(12), AndroidUtilities.dp(12));
frameLayout.addView(speakerPhoneIcon, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.RIGHT));
speakerPhoneIcon.setOnClickListener(view -> {
if (speakerPhoneIcon.getTag() == null) {
return;
}
if (VoIPService.getSharedInstance() != null) {
VoIPService.getSharedInstance().toggleSpeakerphoneOrShowRouteSheet(activity, false);
}
});
backIcon.setOnClickListener(view -> {
if (!lockOnScreen) {
onBackPressed();
}
});
if (windowView.isLockOnScreen()) {
backIcon.setVisibility(View.GONE);
}
notificationsLayout = new VoIPNotificationsLayout(context);
notificationsLayout.setGravity(Gravity.BOTTOM);
notificationsLayout.setOnViewsUpdated(() -> {
previousState = currentState;
updateViewState();
});
frameLayout.addView(notificationsLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 200, Gravity.BOTTOM, 16, 0, 16, 0));
tapToVideoTooltip = new HintView(context, 4);
tapToVideoTooltip.setText(LocaleController.getString("TapToTurnCamera", R.string.TapToTurnCamera));
frameLayout.addView(tapToVideoTooltip, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 8));
tapToVideoTooltip.setBottomOffset(AndroidUtilities.dp(4));
tapToVideoTooltip.setVisibility(View.GONE);
updateViewState();
VoIPService service = VoIPService.getSharedInstance();
if (service != null) {
if (!isVideoCall) {
isVideoCall = service.privateCall != null && service.privateCall.video;
}
initRenderers();
}
return frameLayout;
}
Aggregations