From 06deba4bd4d7702e12fec98c7d7ffa12efeffd89 Mon Sep 17 00:00:00 2001 From: goapunk <goapunk@riseup.net> Date: Thu, 31 May 2018 14:25:27 +0200 Subject: [PATCH] Create a dedicated qrCodeView --- .../android/activity/ActivityComponent.java | 4 +- .../android/keyagreement/CameraView.java | 28 ++- .../keyagreement/KeyAgreementActivity.java | 4 +- ...ragment.java => KeyAgreementFragment.java} | 181 +++++++----------- .../briar/android/view/QrCodeView.java | 61 ++++++ .../layout-land/fragment_keyagreement_qr.xml | 110 ----------- .../res/layout/fragment_keyagreement_qr.xml | 41 +--- .../src/main/res/layout/qr_code_view.xml | 43 +++++ 8 files changed, 202 insertions(+), 270 deletions(-) rename briar-android/src/main/java/org/briarproject/briar/android/keyagreement/{ShowQrCodeFragment.java => KeyAgreementFragment.java} (71%) create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/view/QrCodeView.java delete mode 100644 briar-android/src/main/res/layout-land/fragment_keyagreement_qr.xml create mode 100644 briar-android/src/main/res/layout/qr_code_view.xml diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java index 50b5416877..1d92a31f30 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java @@ -29,7 +29,7 @@ import org.briarproject.briar.android.introduction.IntroductionMessageFragment; import org.briarproject.briar.android.keyagreement.ContactExchangeActivity; import org.briarproject.briar.android.keyagreement.IntroFragment; import org.briarproject.briar.android.keyagreement.KeyAgreementActivity; -import org.briarproject.briar.android.keyagreement.ShowQrCodeFragment; +import org.briarproject.briar.android.keyagreement.KeyAgreementFragment; import org.briarproject.briar.android.login.AuthorNameFragment; import org.briarproject.briar.android.login.ChangePasswordActivity; import org.briarproject.briar.android.login.DozeFragment; @@ -188,7 +188,7 @@ public interface ActivityComponent { void inject(IntroFragment fragment); - void inject(ShowQrCodeFragment fragment); + void inject(KeyAgreementFragment fragment); void inject(ContactChooserFragment fragment); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/CameraView.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/CameraView.java index aa6ba31ac1..d9cf8d01f7 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/CameraView.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/CameraView.java @@ -9,10 +9,12 @@ import android.hardware.Camera.Size; import android.support.annotation.Nullable; import android.support.annotation.UiThread; import android.util.AttributeSet; +import android.view.Display; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; +import android.view.WindowManager; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; @@ -21,6 +23,7 @@ import java.io.IOException; import java.util.List; import java.util.logging.Logger; +import static android.content.Context.WINDOW_SERVICE; import static android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK; import static android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT; import static android.hardware.Camera.Parameters.FLASH_MODE_OFF; @@ -97,7 +100,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, } @UiThread - public void start(int rotationDegrees) throws CameraException { + public void start() throws CameraException { LOG.info("Opening camera"); try { int cameras = Camera.getNumberOfCameras(); @@ -122,7 +125,7 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, } catch (RuntimeException e) { throw new CameraException(e); } - setDisplayOrientation(rotationDegrees); + setDisplayOrientation(getScreenRotationDegrees()); // Use barcode scene mode if it's available Parameters params = camera.getParameters(); params = setSceneMode(camera, params); @@ -157,6 +160,27 @@ public class CameraView extends SurfaceView implements SurfaceHolder.Callback, camera = null; } + /** + * See {@link Camera#setDisplayOrientation(int)}. + */ + private int getScreenRotationDegrees() { + WindowManager wm = + (WindowManager) getContext().getSystemService(WINDOW_SERVICE); + Display d = wm.getDefaultDisplay(); + switch (d.getRotation()) { + case Surface.ROTATION_0: + return 0; + case Surface.ROTATION_90: + return 90; + case Surface.ROTATION_180: + return 180; + case Surface.ROTATION_270: + return 270; + default: + throw new AssertionError(); + } + } + @UiThread private void startPreview(SurfaceHolder holder) throws CameraException { LOG.info("Starting preview"); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java index 9ec105ac2b..0a25f92377 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java @@ -193,8 +193,8 @@ public abstract class KeyAgreementActivity extends BriarActivity implements continueClicked = false; // FIXME #824 FragmentManager fm = getSupportFragmentManager(); - if (fm.findFragmentByTag(ShowQrCodeFragment.TAG) == null) { - BaseFragment f = ShowQrCodeFragment.newInstance(); + if (fm.findFragmentByTag(KeyAgreementFragment.TAG) == null) { + BaseFragment f = KeyAgreementFragment.newInstance(); fm.beginTransaction() .replace(R.id.fragmentContainer, f, f.getUniqueTag()) .addToBackStack(f.getUniqueTag()) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ShowQrCodeFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementFragment.java similarity index 71% rename from briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ShowQrCodeFragment.java rename to briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementFragment.java index 2c38043fbb..4c4623d09d 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/ShowQrCodeFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementFragment.java @@ -2,18 +2,12 @@ package org.briarproject.briar.android.keyagreement; import android.content.Context; import android.graphics.Bitmap; -import android.hardware.Camera; -import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.UiThread; import android.util.DisplayMetrics; -import android.view.Display; import android.view.LayoutInflater; -import android.view.Surface; import android.view.View; import android.view.ViewGroup; -import android.view.animation.AlphaAnimation; -import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.TextView; @@ -41,6 +35,7 @@ import org.briarproject.briar.R; import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.fragment.BaseEventFragment; import org.briarproject.briar.android.fragment.ErrorFragment; +import org.briarproject.briar.android.view.QrCodeView; import java.io.IOException; import java.nio.charset.Charset; @@ -63,10 +58,10 @@ import static org.briarproject.bramble.util.LogUtils.logException; @MethodsNotNullByDefault @ParametersNotNullByDefault -public class ShowQrCodeFragment extends BaseEventFragment - implements QrCodeDecoder.ResultCallback { +public class KeyAgreementFragment extends BaseEventFragment + implements QrCodeDecoder.ResultCallback, QrCodeView.FullscreenListener { - static final String TAG = ShowQrCodeFragment.class.getName(); + static final String TAG = KeyAgreementFragment.class.getName(); private static final Logger LOG = Logger.getLogger(TAG); private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); @@ -84,21 +79,18 @@ public class ShowQrCodeFragment extends BaseEventFragment EventBus eventBus; private CameraView cameraView; + private LinearLayout cameraOverlay; private View statusView; + private QrCodeView qrCodeView; private TextView status; - private View qrCodeContainer; - private ImageView qrCode; - private boolean fullscreen = false; private boolean gotRemotePayload; private volatile boolean gotLocalPayload; private KeyAgreementTask task; - public static ShowQrCodeFragment newInstance() { - + public static KeyAgreementFragment newInstance() { Bundle args = new Bundle(); - - ShowQrCodeFragment fragment = new ShowQrCodeFragment(); + KeyAgreementFragment fragment = new KeyAgreementFragment(); fragment.setArguments(args); return fragment; } @@ -118,7 +110,6 @@ public class ShowQrCodeFragment extends BaseEventFragment public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_keyagreement_qr, container, false); } @@ -126,45 +117,17 @@ public class ShowQrCodeFragment extends BaseEventFragment @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - cameraView = view.findViewById(R.id.camera_view); + cameraOverlay = view.findViewById(R.id.camera_overlay); statusView = view.findViewById(R.id.status_container); status = view.findViewById(R.id.connect_status); - qrCodeContainer = view.findViewById(R.id.qr_code_container); - qrCode = view.findViewById(R.id.qr_code); - ImageView fullscreenButton = view.findViewById(R.id.fullscreen_button); - fullscreenButton.setOnClickListener(v -> { - LinearLayout cameraOverlay = view.findViewById(R.id.camera_overlay); - LayoutParams statusParams, qrCodeParams; - if (fullscreen) { - // Shrink the QR code container to fill half its parent - if (cameraOverlay.getOrientation() == HORIZONTAL) { - statusParams = new LayoutParams(0, MATCH_PARENT, 1f); - qrCodeParams = new LayoutParams(0, MATCH_PARENT, 1f); - } else { - statusParams = new LayoutParams(MATCH_PARENT, 0, 1f); - qrCodeParams = new LayoutParams(MATCH_PARENT, 0, 1f); - } - fullscreenButton.setImageResource( - R.drawable.ic_fullscreen_black_48dp); - } else { - // Grow the QR code container to fill its parent - statusParams = new LayoutParams(0, 0, 0f); - qrCodeParams = new LayoutParams(MATCH_PARENT, MATCH_PARENT, 1f); - fullscreenButton.setImageResource( - R.drawable.ic_fullscreen_exit_black_48dp); - } - statusView.setLayoutParams(statusParams); - qrCodeContainer.setLayoutParams(qrCodeParams); - cameraOverlay.invalidate(); - fullscreen = !fullscreen; - }); + qrCodeView = view.findViewById(R.id.qr_code_view); + qrCodeView.setFullscreenListener(this); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - getActivity().setRequestedOrientation(SCREEN_ORIENTATION_NOSENSOR); cameraView.setPreviewConsumer(new QrCodeDecoder(this)); } @@ -173,30 +136,33 @@ public class ShowQrCodeFragment extends BaseEventFragment public void onStart() { super.onStart(); try { - cameraView.start(getScreenRotationDegrees()); + cameraView.start(); } catch (CameraException e) { logCameraExceptionAndFinish(e); } startListening(); } - /** - * See {@link Camera#setDisplayOrientation(int)}. - */ - private int getScreenRotationDegrees() { - Display d = getActivity().getWindowManager().getDefaultDisplay(); - switch (d.getRotation()) { - case Surface.ROTATION_0: - return 0; - case Surface.ROTATION_90: - return 90; - case Surface.ROTATION_180: - return 180; - case Surface.ROTATION_270: - return 270; - default: - throw new AssertionError(); + @Override + public void toggleFullscreen(boolean fullscreen) { + LinearLayout.LayoutParams statusParams, qrCodeParams; + if (fullscreen) { + // Grow the QR code view to fill its parent + statusParams = new LayoutParams(0, 0, 0f); + qrCodeParams = new LayoutParams(MATCH_PARENT, MATCH_PARENT, 1f); + } else { + // Shrink the QR code view to fill half its parent + if (cameraOverlay.getOrientation() == HORIZONTAL) { + statusParams = new LayoutParams(0, MATCH_PARENT, 1f); + qrCodeParams = new LayoutParams(0, MATCH_PARENT, 1f); + } else { + statusParams = new LayoutParams(MATCH_PARENT, 0, 1f); + qrCodeParams = new LayoutParams(MATCH_PARENT, 0, 1f); + } } + statusView.setLayoutParams(statusParams); + qrCodeView.setLayoutParams(qrCodeParams); + cameraOverlay.invalidate(); } @Override @@ -242,7 +208,7 @@ public class ShowQrCodeFragment extends BaseEventFragment // If we've stopped the camera view, restart it if (gotRemotePayload) { try { - cameraView.start(getScreenRotationDegrees()); + cameraView.start(); } catch (CameraException e) { logCameraExceptionAndFinish(e); return; @@ -299,51 +265,10 @@ public class ShowQrCodeFragment extends BaseEventFragment KeyAgreementAbortedEvent event = (KeyAgreementAbortedEvent) e; keyAgreementAborted(event.didRemoteAbort()); } else if (e instanceof KeyAgreementFinishedEvent) { - runOnUiThreadUnlessDestroyed(() -> { - statusView.setVisibility(VISIBLE); - status.setText(R.string.exchanging_contact_details); - }); + keyAgreementFinished(); } } - @UiThread - private void generateBitmapQR(Payload payload) { - // Get narrowest screen dimension - Context context = getContext(); - if (context == null) return; - DisplayMetrics dm = context.getResources().getDisplayMetrics(); - new AsyncTask<Void, Void, Bitmap>() { - - @Override - @Nullable - protected Bitmap doInBackground(Void... params) { - byte[] payloadBytes = payloadEncoder.encode(payload); - if (LOG.isLoggable(INFO)) { - LOG.info("Local payload is " + payloadBytes.length - + " bytes"); - } - // Use ISO 8859-1 to encode bytes directly as a string - String content = new String(payloadBytes, ISO_8859_1); - return QrCodeUtils.createQrCode(dm, content); - } - - @Override - protected void onPostExecute(@Nullable Bitmap bitmap) { - if (bitmap != null && !isDetached()) { - qrCode.setImageBitmap(bitmap); - // Simple fade-in animation - AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f); - anim.setDuration(200); - qrCode.startAnimation(anim); - } - } - }.execute(); - } - - private void setQrCode(Payload localPayload) { - runOnUiThreadUnlessDestroyed(() -> generateBitmapQR(localPayload)); - } - private void keyAgreementFailed() { runOnUiThreadUnlessDestroyed(() -> { reset(); @@ -353,25 +278,25 @@ public class ShowQrCodeFragment extends BaseEventFragment }); } - private void keyAgreementWaiting() { - runOnUiThreadUnlessDestroyed( - () -> status.setText(R.string.waiting_for_contact_to_scan)); - } - private void keyAgreementStarted() { runOnUiThreadUnlessDestroyed(() -> { - qrCodeContainer.setVisibility(INVISIBLE); + qrCodeView.setVisibility(INVISIBLE); statusView.setVisibility(VISIBLE); status.setText(R.string.authenticating_with_device); }); } + private void keyAgreementWaiting() { + runOnUiThreadUnlessDestroyed( + () -> status.setText(R.string.waiting_for_contact_to_scan)); + } + private void keyAgreementAborted(boolean remoteAborted) { runOnUiThreadUnlessDestroyed(() -> { reset(); - qrCodeContainer.setVisibility(VISIBLE); + qrCodeView.setVisibility(VISIBLE); statusView.setVisibility(INVISIBLE); - status.setText(null); + status.setText(""); // TODO show abort somewhere persistent? Toast.makeText(getActivity(), remoteAborted ? R.string.connection_aborted_remote : @@ -380,6 +305,30 @@ public class ShowQrCodeFragment extends BaseEventFragment }); } + private void keyAgreementFinished() { + runOnUiThreadUnlessDestroyed(() -> { + statusView.setVisibility(VISIBLE); + status.setText(R.string.exchanging_contact_details); + }); + } + + private void setQrCode(Payload localPayload) { + Context context = getContext(); + if (context == null) return; + DisplayMetrics dm = context.getResources().getDisplayMetrics(); + ioExecutor.execute(() -> { + byte[] payloadBytes = payloadEncoder.encode(localPayload); + if (LOG.isLoggable(INFO)) { + LOG.info("Local payload is " + payloadBytes.length + + " bytes"); + } + // Use ISO 8859-1 to encode bytes directly as a string + String content = new String(payloadBytes, ISO_8859_1); + Bitmap qrCode = QrCodeUtils.createQrCode(dm, content); + runOnUiThreadUnlessDestroyed(() -> qrCodeView.setQrCode(qrCode)); + }); + } + @Override public void handleResult(Result result) { runOnUiThreadUnlessDestroyed(() -> { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/QrCodeView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/QrCodeView.java new file mode 100644 index 0000000000..c4649cf4fd --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/view/QrCodeView.java @@ -0,0 +1,61 @@ +package org.briarproject.briar.android.view; + +import android.content.Context; +import android.graphics.Bitmap; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.UiThread; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.animation.AlphaAnimation; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import org.briarproject.briar.R; + +public class QrCodeView extends FrameLayout { + + private final ImageView qrCodeImageView; + private boolean fullscreen = false; + private FullscreenListener listener; + + public QrCodeView(@NonNull Context context, + @Nullable AttributeSet attrs) { + super(context, attrs); + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.qr_code_view, this, true); + qrCodeImageView = findViewById(R.id.qr_code); + ImageView fullscreenButton = findViewById(R.id.fullscreen_button); + fullscreenButton.setOnClickListener(v -> { + fullscreen = !fullscreen; + if (!fullscreen) + fullscreenButton.setImageResource( + R.drawable.ic_fullscreen_black_48dp); + else + fullscreenButton.setImageResource( + R.drawable.ic_fullscreen_exit_black_48dp); + if (listener != null) + listener.toggleFullscreen(fullscreen); + } + ); + } + + public void setQrCode(Bitmap qrCode) { + qrCodeImageView.setImageBitmap(qrCode); + // Simple fade-in animation + AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f); + anim.setDuration(200); + qrCodeImageView.startAnimation(anim); + } + + @UiThread + public void setFullscreenListener(FullscreenListener listener) { + this.listener = listener; + } + + public interface FullscreenListener { + void toggleFullscreen(boolean isFullscreen); + } + +} diff --git a/briar-android/src/main/res/layout-land/fragment_keyagreement_qr.xml b/briar-android/src/main/res/layout-land/fragment_keyagreement_qr.xml deleted file mode 100644 index 9d378e5ba3..0000000000 --- a/briar-android/src/main/res/layout-land/fragment_keyagreement_qr.xml +++ /dev/null @@ -1,110 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<FrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <org.briarproject.briar.android.keyagreement.CameraView - android:id="@+id/camera_view" - android:layout_width="match_parent" - android:layout_height="match_parent"/> - - <LinearLayout - android:id="@+id/camera_overlay" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal" - android:baselineAligned="false"> - - <LinearLayout - android:id="@+id/status_container" - android:layout_width="0dp" - android:layout_height="match_parent" - android:layout_weight="1" - android:background="@android:color/background_light" - android:gravity="center" - android:orientation="vertical" - android:padding="@dimen/margin_medium" - android:visibility="invisible"> - - <ProgressBar - style="?android:attr/progressBarStyleLarge" - android:layout_width="wrap_content" - android:layout_height="wrap_content"/> - - <TextView - android:id="@+id/connect_status" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="center" - android:paddingTop="@dimen/margin_large" - tools:text="Connection failed"/> - </LinearLayout> - - <FrameLayout - android:id="@+id/qr_code_container" - android:layout_width="0dp" - android:layout_height="match_parent" - android:layout_weight="1" - android:background="@android:color/white"> - - <ProgressBar - style="?android:attr/progressBarStyleLarge" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center"/> - - <RelativeLayout - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <ImageView - android:id="@+id/qr_code" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_centerInParent="true" - android:contentDescription="@string/qr_code" - android:scaleType="fitCenter"/> - - <ImageView - android:id="@+id/fullscreen_button" - android:background="?selectableItemBackground" - android:src="@drawable/ic_fullscreen_black_48dp" - android:alpha="0.54" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_margin="@dimen/margin_small" - android:layout_alignParentBottom="true" - android:layout_alignParentRight="true" - android:layout_alignParentEnd="true" - android:contentDescription="@string/show_qr_code_fullscreen"/> - </RelativeLayout> - </FrameLayout> - </LinearLayout> - - <RelativeLayout - android:id="@+id/container_progress" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@android:color/white" - android:visibility="invisible"> - - <ProgressBar - android:id="@+id/progress_bar" - style="?android:attr/progressBarStyleLarge" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_above="@+id/title_progress_bar" - android:layout_centerHorizontal="true"/> - - <TextView - android:id="@+id/title_progress_bar" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_centerInParent="true" - android:gravity="center" - android:paddingTop="@dimen/margin_large" - tools:text="@string/waiting_for_contact_to_scan"/> - </RelativeLayout> -</FrameLayout> diff --git a/briar-android/src/main/res/layout/fragment_keyagreement_qr.xml b/briar-android/src/main/res/layout/fragment_keyagreement_qr.xml index d9527df8fd..f992ee2035 100644 --- a/briar-android/src/main/res/layout/fragment_keyagreement_qr.xml +++ b/briar-android/src/main/res/layout/fragment_keyagreement_qr.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> @@ -43,45 +42,11 @@ tools:text="Connection failed"/> </LinearLayout> - <FrameLayout - android:id="@+id/qr_code_container" + <org.briarproject.briar.android.view.QrCodeView + android:id="@+id/qr_code_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" - android:background="@android:color/white"> - - <ProgressBar - style="?android:attr/progressBarStyleLarge" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center"/> - - <RelativeLayout - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <ImageView - android:id="@+id/qr_code" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_centerInParent="true" - android:contentDescription="@string/qr_code" - android:scaleType="fitCenter" - tools:src="@drawable/startup_lock"/> - - <ImageView - android:id="@+id/fullscreen_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_alignParentEnd="true" - android:layout_alignParentRight="true" - android:layout_margin="@dimen/margin_small" - android:alpha="0.54" - android:background="?selectableItemBackground" - android:contentDescription="@string/show_qr_code_fullscreen" - android:src="@drawable/ic_fullscreen_black_48dp"/> - </RelativeLayout> - </FrameLayout> + android:background="@android:color/white"/> </LinearLayout> </FrameLayout> diff --git a/briar-android/src/main/res/layout/qr_code_view.xml b/briar-android/src/main/res/layout/qr_code_view.xml new file mode 100644 index 0000000000..eb690fe976 --- /dev/null +++ b/briar-android/src/main/res/layout/qr_code_view.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<merge + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + tools:showIn="@layout/list_item_forum"> + + <ProgressBar + style="?android:attr/progressBarStyleLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"/> + + <android.support.constraint.ConstraintLayout + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ImageView + android:id="@+id/qr_code" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:contentDescription="@string/qr_code" + android:scaleType="fitCenter" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:src="@drawable/startup_lock"/> + + <ImageView + android:id="@+id/fullscreen_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="@dimen/margin_small" + android:alpha="0.54" + android:background="?selectableItemBackground" + android:contentDescription="@string/show_qr_code_fullscreen" + android:src="@drawable/ic_fullscreen_black_48dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintRight_toRightOf="parent"/> + </android.support.constraint.ConstraintLayout> +</merge> -- GitLab