diff options
3 files changed, 98 insertions, 72 deletions
diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml index 2a055fc8252f..8f3345f9d85c 100644 --- a/packages/SystemUI/res/layout/long_screenshot.xml +++ b/packages/SystemUI/res/layout/long_screenshot.xml @@ -22,35 +22,82 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + <Button + android:id="@+id/save" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/save" + app:layout_constraintEnd_toStartOf="@id/cancel" + app:layout_constraintHorizontal_chainStyle="packed" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/guideline" /> + + <Button + android:id="@+id/cancel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/cancel" + app:layout_constraintEnd_toStartOf="@id/edit" + app:layout_constraintStart_toEndOf="@id/save" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/guideline" /> + + <Button + android:id="@+id/edit" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/screenshot_edit_label" + app:layout_constraintEnd_toStartOf="@id/share" + app:layout_constraintStart_toEndOf="@id/cancel" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/guideline" /> + + <Button + android:id="@+id/share" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@*android:string/share" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/edit" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/guideline" /> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + app:layout_constraintGuide_percent="0.1" /> + <ImageView android:id="@+id/preview" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginVertical="8dp" + android:layout_marginBottom="24dp" android:layout_marginHorizontal="48dp" android:adjustViewBounds="true" app:layout_constrainedHeight="true" app:layout_constrainedWidth="true" - app:layout_constraintBottom_toBottomOf="@id/guideline" + app:layout_constraintTop_toBottomOf="@id/guideline" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" tools:background="?android:colorBackground" tools:minHeight="100dp" tools:minWidth="100dp" /> <com.android.systemui.screenshot.CropView android:id="@+id/crop_view" - android:visibility="gone" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginVertical="8dp" + android:layout_marginBottom="24dp" app:layout_constrainedHeight="true" app:layout_constrainedWidth="true" - app:layout_constraintBottom_toBottomOf="@id/guideline" + app:layout_constraintTop_toBottomOf="@id/guideline" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" app:handleThickness="3dp" app:handleColor="@*android:color/accent_device_default" app:scrimColor="#9444" @@ -58,46 +105,5 @@ tools:minHeight="100dp" tools:minWidth="100dp" /> - <androidx.constraintlayout.widget.Guideline - android:id="@+id/guideline" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal" - app:layout_constraintGuide_percent="0.9" /> - - <Button - android:id="@+id/close" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_margin="8dp" - android:text="Close" - app:layout_constraintEnd_toStartOf="@+id/edit" - app:layout_constraintHorizontal_bias="0.5" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="@+id/guideline" /> - - <Button - android:id="@+id/edit" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_margin="8dp" - android:text="Edit" - app:layout_constraintEnd_toStartOf="@+id/share" - app:layout_constraintHorizontal_bias="0.5" - app:layout_constraintStart_toEndOf="@+id/close" - app:layout_constraintTop_toTopOf="@+id/guideline" /> - - <Button - android:id="@+id/share" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_margin="8dp" - android:text="Share" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.5" - app:layout_constraintStart_toEndOf="@+id/edit" - app:layout_constraintTop_toTopOf="@+id/guideline" /> - </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java b/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java index 8ff66f548172..20f845103723 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageTileSet.java @@ -108,6 +108,15 @@ class ImageTileSet { } Bitmap toBitmap() { + return toBitmap(new Rect(0, 0, getWidth(), getHeight())); + } + + /** + * @param bounds Selected portion of the tile set's bounds (equivalent to tile bounds coord + * space). For example, to get the whole doc, use Rect(0, 0, getWidth(), + * getHeight()). + */ + Bitmap toBitmap(Rect bounds) { if (mTiles.isEmpty()) { return null; } @@ -115,6 +124,9 @@ class ImageTileSet { output.setPosition(0, 0, getWidth(), getHeight()); RecordingCanvas canvas = output.beginRecording(); canvas.translate(-getLeft(), -getTop()); + // Additional translation to account for the requested bounds + canvas.translate(-bounds.left, -bounds.top); + canvas.clipRect(bounds); for (ImageTile tile : mTiles) { canvas.save(); canvas.translate(tile.getLeft(), tile.getTop()); @@ -122,7 +134,7 @@ class ImageTileSet { canvas.restore(); } output.endRecording(); - return HardwareRenderer.createHardwareBitmap(output, getWidth(), getHeight()); + return HardwareRenderer.createHardwareBitmap(output, bounds.width(), bounds.height()); } int getLeft() { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java index db295332bbdd..18c379a4650f 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java @@ -21,6 +21,7 @@ import android.annotation.UiThread; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.graphics.Rect; import android.net.Uri; import android.os.UserHandle; import android.text.TextUtils; @@ -54,7 +55,8 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener // TODO: Support saving without additional action. private enum PendingAction { SHARE, - EDIT + EDIT, + SAVE } public static final int MAX_PAGES = 5; @@ -74,9 +76,11 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener private RequestCallback mCallback; private Window mWindow; private ImageView mPreview; - private View mClose; + private View mSave; + private View mCancel; private View mEdit; private View mShare; + private CropView mCropView; public ScrollCaptureController(Context context, Connection connection, Executor uiExecutor, Executor bgExecutor, ImageExporter exporter, UiEventLogger uiEventLogger) { @@ -111,11 +115,14 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener .addOnComputeInternalInsetsListener(this); mPreview = findViewById(R.id.preview); - mClose = findViewById(R.id.close); + mSave = findViewById(R.id.save); + mCancel = findViewById(R.id.cancel); mEdit = findViewById(R.id.edit); mShare = findViewById(R.id.share); + mCropView = findViewById(R.id.crop_view); - mClose.setOnClickListener(this::onClicked); + mSave.setOnClickListener(this::onClicked); + mCancel.setOnClickListener(this::onClicked); mEdit.setOnClickListener(this::onClicked); mShare.setOnClickListener(this::onClicked); @@ -130,7 +137,8 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener } void disableButtons() { - mClose.setEnabled(false); + mSave.setEnabled(false); + mCancel.setEnabled(false); mEdit.setEnabled(false); mShare.setEnabled(false); } @@ -139,19 +147,17 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener Log.d(TAG, "button clicked!"); int id = v.getId(); - if (id == R.id.close) { - v.setPressed(true); - disableButtons(); + v.setPressed(true); + disableButtons(); + if (id == R.id.save) { + startExport(PendingAction.SAVE); + } else if (id == R.id.cancel) { doFinish(); } else if (id == R.id.edit) { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT); - v.setPressed(true); - disableButtons(); startExport(PendingAction.EDIT); } else if (id == R.id.share) { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_SHARE); - v.setPressed(true); - disableButtons(); startExport(PendingAction.SHARE); } } @@ -165,8 +171,13 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener } private void startExport(PendingAction action) { + Rect croppedPortion = new Rect( + 0, + (int) (mImageTileSet.getHeight() * mCropView.getTopBoundary()), + mImageTileSet.getWidth(), + (int) (mImageTileSet.getHeight() * mCropView.getBottomBoundary())); ListenableFuture<ImageExporter.Result> exportFuture = mImageExporter.export( - mBgExecutor, mRequestId, mImageTileSet.toBitmap(), mCaptureTime); + mBgExecutor, mRequestId, mImageTileSet.toBitmap(croppedPortion), mCaptureTime); exportFuture.addListener(() -> { try { ImageExporter.Result result = exportFuture.get(); @@ -191,24 +202,21 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener } intent.setType("image/png"); intent.setData(uri); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - Intent sharingChooserIntent = Intent.createChooser(intent, null) - .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK) - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK + | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - mContext.startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT); + mContext.startActivityAsUser(intent, UserHandle.CURRENT); } private void doShare(Uri uri) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("image/png"); intent.setData(uri); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK + | Intent.FLAG_GRANT_READ_URI_PERMISSION); Intent sharingChooserIntent = Intent.createChooser(intent, null) - .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK) - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_GRANT_READ_URI_PERMISSION); mContext.startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT); } |