call: allow to drag video preview
Change-Id: I49413a061fcd5bef2056656d8276b48477aa522f
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
index 97b804b..e35cf8c 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
@@ -21,6 +21,7 @@
package cx.ring.fragments;
import android.Manifest;
+import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
@@ -32,6 +33,7 @@
import android.content.pm.PackageManager;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
@@ -48,6 +50,7 @@
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.Surface;
import android.view.SurfaceHolder;
@@ -55,6 +58,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.InputMethodManager;
import android.widget.RelativeLayout;
import android.widget.Toast;
@@ -145,6 +149,10 @@
private ConfParticipantAdapter confAdapter = null;
private boolean mConferenceMode = false;
+ private PointF previewDrag = null;
+ private final ValueAnimator previewSnapAnimation = new ValueAnimator();
+ private final int[] previewMargins = new int[4];
+
@Inject
DeviceRuntimeService mDeviceRuntimeService;
@@ -322,6 +330,7 @@
}
};
+ @SuppressLint("ClickableViewAccessibility")
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
setHasOptionsMenu(true);
@@ -400,6 +409,89 @@
binding.previewSurface.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
configureTransform(mPreviewSurfaceWidth, mPreviewSurfaceHeight));
+ float margin = getResources().getDimension(R.dimen.call_preview_margin);
+ previewSnapAnimation.setDuration(250);
+ previewSnapAnimation.setFloatValues(0.f, 1.f);
+ previewSnapAnimation.setInterpolator(new DecelerateInterpolator());
+ previewSnapAnimation.addUpdateListener(animation -> {
+ RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) binding.previewContainer.getLayoutParams();
+ float f = margin * animation.getAnimatedFraction();
+ float r = 1.f - animation.getAnimatedFraction();
+ params.setMargins(
+ (int)(previewMargins[0] * r + f),
+ (int)(previewMargins[1] * r + f),
+ (int)(previewMargins[2] * r + f),
+ (int)(previewMargins[3] * r + f));
+ binding.previewContainer.setLayoutParams(params);
+ });
+
+ binding.previewContainer.setOnTouchListener((v, event) -> {
+ int action = event.getActionMasked();
+ if (action == MotionEvent.ACTION_DOWN) {
+ previewSnapAnimation.cancel();
+ previewDrag = new PointF(event.getX(), event.getY());
+ v.setElevation(v.getContext().getResources().getDimension(R.dimen.call_preview_elevation_dragged));
+ RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();
+ params.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+ params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
+ params.setMargins((int)v.getX(), (int)v.getY(), 0, 0);
+ v.setLayoutParams(params);
+ return true;
+ } else if (action == MotionEvent.ACTION_MOVE) {
+ if (previewDrag != null) {
+ RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();
+ RelativeLayout parent = (RelativeLayout) v.getParent();
+ params.setMargins(
+ Math.min(params.leftMargin + (int) (event.getX() - previewDrag.x), parent.getWidth() - v.getWidth() - (int)margin),
+ Math.min(params.topMargin + (int) (event.getY() - previewDrag.y), parent.getHeight() - v.getHeight() - (int)margin),
+ 0, 0);
+ v.setLayoutParams(params);
+ return true;
+ }
+ return false;
+ } else if (action == MotionEvent.ACTION_UP) {
+ if (previewDrag != null) {
+ previewSnapAnimation.cancel();
+ previewDrag = null;
+ v.setElevation(v.getContext().getResources().getDimension(R.dimen.call_preview_elevation));
+ RelativeLayout parent = (RelativeLayout) v.getParent();
+ RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();
+ int ml = 0, mr = 0, mt = 0, mb = 0;
+ if (params.leftMargin + (v.getWidth() / 2) > parent.getWidth() / 2) {
+ params.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
+ params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+ mr = (int) (parent.getWidth() - v.getWidth() - v.getX());
+ } else {
+ params.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+ params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
+ ml = (int) v.getX();
+ }
+ if (params.topMargin + (v.getHeight() / 2) > parent.getHeight() / 2) {
+ params.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
+ params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ mb = (int) (parent.getHeight() - v.getHeight() - v.getY());
+ } else {
+ params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ mt = (int) v.getY();
+ }
+ previewMargins[0] = ml;
+ previewMargins[1] = mt;
+ previewMargins[2] = mr;
+ previewMargins[3] = mb;
+ params.setMargins(ml, mt, mr, mb);
+ v.setLayoutParams(params);
+ previewSnapAnimation.start();
+ return true;
+ }
+ return false;
+ } else {
+ return false;
+ }
+ });
+
binding.dialpadEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
diff --git a/ring-android/app/src/main/res/layout/frag_call.xml b/ring-android/app/src/main/res/layout/frag_call.xml
index b8e3a95..6789060 100644
--- a/ring-android/app/src/main/res/layout/frag_call.xml
+++ b/ring-android/app/src/main/res/layout/frag_call.xml
@@ -51,12 +51,12 @@
android:id="@+id/preview_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
- android:layout_marginStart="12dp"
- android:layout_marginTop="12dp"
- android:layout_marginEnd="12dp"
- android:layout_marginBottom="12dp"
+ android:layout_marginLeft="@dimen/call_preview_margin"
+ android:layout_marginTop="@dimen/call_preview_margin"
+ android:layout_marginBottom="@dimen/call_preview_margin"
+ android:layout_marginRight="@dimen/call_preview_margin"
android:visibility="gone"
app:cardCornerRadius="16dp"
app:cardPreventCornerOverlap="false"
diff --git a/ring-android/app/src/main/res/values/dimens.xml b/ring-android/app/src/main/res/values/dimens.xml
index 74d5110..b48f676 100644
--- a/ring-android/app/src/main/res/values/dimens.xml
+++ b/ring-android/app/src/main/res/values/dimens.xml
@@ -69,4 +69,8 @@
<dimen name="navigation_bottom_height">60dp</dimen>
+ <dimen name="call_preview_elevation">8dp</dimen>
+ <dimen name="call_preview_elevation_dragged">16dp</dimen>
+ <dimen name="call_preview_margin">12dp</dimen>
+
</resources>
\ No newline at end of file