forked from mirrors/Fedilab
Adding media editor
This commit is contained in:
parent
422119d44d
commit
12e352c774
7 changed files with 168 additions and 285 deletions
|
@ -86,6 +86,9 @@
|
|||
android:name=".activities.ScheduledActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/scheduled" />
|
||||
<activity
|
||||
android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
|
||||
android:theme="@style/Base.Theme.AppCompat" />
|
||||
|
||||
<service
|
||||
android:name=".services.PostMessageService"
|
||||
|
|
|
@ -19,8 +19,10 @@ import static app.fedilab.android.ui.drawer.ComposeAdapter.prepareDraft;
|
|||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ClipData;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.net.Uri;
|
||||
|
@ -42,6 +44,7 @@ import androidx.appcompat.app.ActionBar;
|
|||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.work.Data;
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
|
@ -58,6 +61,7 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import app.fedilab.android.BaseMainActivity;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.client.entities.api.Attachment;
|
||||
import app.fedilab.android.client.entities.api.Context;
|
||||
import app.fedilab.android.client.entities.api.Mention;
|
||||
import app.fedilab.android.client.entities.api.ScheduledStatus;
|
||||
|
@ -103,6 +107,27 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana
|
|||
private app.fedilab.android.client.entities.api.Account accountMention;
|
||||
private String statusReplyId;
|
||||
|
||||
private final BroadcastReceiver imageReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(android.content.Context context, Intent intent) {
|
||||
String imgpath = intent.getStringExtra("imgpath");
|
||||
if (imgpath != null) {
|
||||
int position = 0;
|
||||
for (Status status : statusList) {
|
||||
if (status.media_attachments != null && status.media_attachments.size() > 0) {
|
||||
for (Attachment attachment : status.media_attachments) {
|
||||
if (attachment.local_path.equalsIgnoreCase(imgpath)) {
|
||||
composeAdapter.notifyItemChanged(position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
position++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -272,6 +297,17 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana
|
|||
|
||||
}
|
||||
MastodonHelper.loadPPMastodon(binding.profilePicture, account.mastodon_account);
|
||||
LocalBroadcastManager.getInstance(this)
|
||||
.registerReceiver(imageReceiver,
|
||||
new IntentFilter(Helper.INTENT_SEND_MODIFIED_IMAGE));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LocalBroadcastManager.getInstance(this)
|
||||
.unregisterReceiver(imageReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,34 +1,27 @@
|
|||
package app.fedilab.android.imageeditor;
|
||||
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static app.fedilab.android.imageeditor.FileSaveHelper.isSdkHigherThan28;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Typeface;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.AnticipateOvershootInterpolator;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.constraintlayout.widget.ConstraintSet;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.transition.ChangeBounds;
|
||||
import androidx.transition.TransitionManager;
|
||||
|
||||
|
@ -40,6 +33,8 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.databinding.ActivityEditImageBinding;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.imageeditor.base.BaseActivity;
|
||||
import app.fedilab.android.imageeditor.filters.FilterListener;
|
||||
import app.fedilab.android.imageeditor.filters.FilterViewAdapter;
|
||||
|
@ -48,7 +43,6 @@ import app.fedilab.android.imageeditor.tools.ToolType;
|
|||
import es.dmoral.toasty.Toasty;
|
||||
import ja.burhanrashid52.photoeditor.OnPhotoEditorListener;
|
||||
import ja.burhanrashid52.photoeditor.PhotoEditor;
|
||||
import ja.burhanrashid52.photoeditor.PhotoEditorView;
|
||||
import ja.burhanrashid52.photoeditor.PhotoFilter;
|
||||
import ja.burhanrashid52.photoeditor.SaveSettings;
|
||||
import ja.burhanrashid52.photoeditor.TextStyleBuilder;
|
||||
|
@ -60,35 +54,23 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
View.OnClickListener,
|
||||
PropertiesBSFragment.Properties,
|
||||
ShapeBSFragment.Properties,
|
||||
EmojiBSFragment.EmojiListener,
|
||||
StickerBSFragment.StickerListener, EditingToolsAdapter.OnItemSelected, FilterListener {
|
||||
EmojiBSFragment.EmojiListener, EditingToolsAdapter.OnItemSelected, FilterListener {
|
||||
|
||||
public static final String FILE_PROVIDER_AUTHORITY = "com.burhanrashid52.photoeditor.fileprovider";
|
||||
public static final String ACTION_NEXTGEN_EDIT = "action_nextgen_edit";
|
||||
public static final String PINCH_TEXT_SCALABLE_INTENT_KEY = "PINCH_TEXT_SCALABLE";
|
||||
private static final int CAMERA_REQUEST = 52;
|
||||
private static final int PICK_REQUEST = 53;
|
||||
private final int STORE_REQUEST = 54;
|
||||
|
||||
private final EditingToolsAdapter mEditingToolsAdapter = new EditingToolsAdapter(this);
|
||||
private final FilterViewAdapter mFilterViewAdapter = new FilterViewAdapter(this);
|
||||
private final ConstraintSet mConstraintSet = new ConstraintSet();
|
||||
PhotoEditor mPhotoEditor;
|
||||
@Nullable
|
||||
@VisibleForTesting
|
||||
Uri mSaveImageUri;
|
||||
private PhotoEditorView mPhotoEditorView;
|
||||
private PropertiesBSFragment mPropertiesBSFragment;
|
||||
private ShapeBSFragment mShapeBSFragment;
|
||||
private ShapeBuilder mShapeBuilder;
|
||||
private EmojiBSFragment mEmojiBSFragment;
|
||||
private StickerBSFragment mStickerBSFragment;
|
||||
private TextView mTxtCurrentTool;
|
||||
private Typeface mWonderFont;
|
||||
private RecyclerView mRvTools, mRvFilters;
|
||||
private ConstraintLayout mRootView;
|
||||
private boolean mIsFilterVisible;
|
||||
private Uri uri;
|
||||
private boolean exit;
|
||||
private FileSaveHelper mSaveFileHelper;
|
||||
|
||||
private static int exifToDegrees(int exifOrientation) {
|
||||
if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
|
||||
|
@ -101,59 +83,47 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
return 0;
|
||||
}
|
||||
|
||||
String path;
|
||||
private ActivityEditImageBinding binding;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
makeFullScreen();
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_edit_image);
|
||||
binding = ActivityEditImageBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
Bundle b = getIntent().getExtras();
|
||||
if (getSupportActionBar() != null)
|
||||
getSupportActionBar().hide();
|
||||
String path = null;
|
||||
|
||||
if (b != null)
|
||||
path = b.getString("imageUri", null);
|
||||
|
||||
if (path == null) {
|
||||
finish();
|
||||
}
|
||||
uri = Uri.parse(path);
|
||||
|
||||
|
||||
uri = Uri.parse("file://" + path);
|
||||
exit = false;
|
||||
|
||||
|
||||
initViews();
|
||||
|
||||
handleIntentImage(mPhotoEditorView.getSource());
|
||||
|
||||
mWonderFont = Typeface.createFromAsset(getAssets(), "beyond_wonderland.ttf");
|
||||
|
||||
mPropertiesBSFragment = new PropertiesBSFragment();
|
||||
mEmojiBSFragment = new EmojiBSFragment();
|
||||
mStickerBSFragment = new StickerBSFragment();
|
||||
mShapeBSFragment = new ShapeBSFragment();
|
||||
mStickerBSFragment.setStickerListener(this);
|
||||
mEmojiBSFragment.setEmojiListener(this);
|
||||
mPropertiesBSFragment.setPropertiesChangeListener(this);
|
||||
mShapeBSFragment.setPropertiesChangeListener(this);
|
||||
|
||||
LinearLayoutManager llmTools = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
|
||||
mRvTools.setLayoutManager(llmTools);
|
||||
mRvTools.setAdapter(mEditingToolsAdapter);
|
||||
binding.rvConstraintTools.setLayoutManager(llmTools);
|
||||
binding.rvConstraintTools.setAdapter(mEditingToolsAdapter);
|
||||
|
||||
LinearLayoutManager llmFilters = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
|
||||
mRvFilters.setLayoutManager(llmFilters);
|
||||
mRvFilters.setAdapter(mFilterViewAdapter);
|
||||
|
||||
// NOTE(lucianocheng): Used to set integration testing parameters to PhotoEditor
|
||||
boolean pinchTextScalable = getIntent().getBooleanExtra(PINCH_TEXT_SCALABLE_INTENT_KEY, true);
|
||||
binding.rvFilterView.setLayoutManager(llmFilters);
|
||||
binding.rvFilterView.setAdapter(mFilterViewAdapter);
|
||||
|
||||
//Typeface mTextRobotoTf = ResourcesCompat.getFont(this, R.font.roboto_medium);
|
||||
//Typeface mEmojiTypeFace = Typeface.createFromAsset(getAssets(), "emojione-android.ttf");
|
||||
Typeface mEmojiTypeFace = Typeface.createFromAsset(getAssets(), "emojione-android.ttf");
|
||||
|
||||
mPhotoEditor = new PhotoEditor.Builder(this, mPhotoEditorView)
|
||||
.setPinchTextScalable(pinchTextScalable) // set flag to make text scalable when pinch
|
||||
//.setDefaultTextTypeface(mTextRobotoTf)
|
||||
mPhotoEditor = new PhotoEditor.Builder(this, binding.photoEditorView)
|
||||
.setPinchTextScalable(true)
|
||||
.setDefaultEmojiTypeface(mEmojiTypeFace)
|
||||
.build(); // build photo editor sdk
|
||||
|
@ -163,93 +133,46 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
|
||||
//Set Image Dynamically
|
||||
try {
|
||||
mPhotoEditorView.getSource().setImageURI(uri);
|
||||
binding.photoEditorView.getSource().setImageURI(uri);
|
||||
} catch (Exception e) {
|
||||
Toasty.error(EditImageActivity.this, getString(R.string.toast_error)).show();
|
||||
}
|
||||
|
||||
if (uri != null) {
|
||||
try (InputStream inputStream = getContentResolver().openInputStream(uri)) {
|
||||
assert inputStream != null;
|
||||
ExifInterface exif = new ExifInterface(inputStream);
|
||||
int rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
|
||||
int rotationInDegrees = exifToDegrees(rotation);
|
||||
mPhotoEditorView.getSource().setRotation(rotationInDegrees);
|
||||
binding.photoEditorView.getSource().setRotation(rotationInDegrees);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Button send = findViewById(R.id.send);
|
||||
|
||||
send.setOnClickListener(v -> {
|
||||
mPhotoEditor.setFilterEffect(PhotoFilter.NONE);
|
||||
binding.send.setOnClickListener(v -> {
|
||||
exit = true;
|
||||
saveImage();
|
||||
});
|
||||
}
|
||||
|
||||
private void handleIntentImage(ImageView source) {
|
||||
Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
// NOTE(lucianocheng): Using "yoda conditions" here to guard against
|
||||
// a null Action in the Intent.
|
||||
if (Intent.ACTION_EDIT.equals(intent.getAction()) ||
|
||||
ACTION_NEXTGEN_EDIT.equals(intent.getAction())) {
|
||||
try {
|
||||
Uri uri = intent.getData();
|
||||
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
|
||||
source.setImageBitmap(bitmap);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
String intentType = intent.getType();
|
||||
if (intentType != null && intentType.startsWith("image/")) {
|
||||
Uri imageUri = intent.getData();
|
||||
if (imageUri != null) {
|
||||
source.setImageURI(imageUri);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode,
|
||||
@NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == STORE_REQUEST) {// If request is cancelled, the result arrays are empty.
|
||||
if (grantResults.length > 0
|
||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
saveImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initViews() {
|
||||
ImageView imgUndo;
|
||||
ImageView imgRedo;
|
||||
ImageView imgCamera;
|
||||
ImageView imgGallery;
|
||||
ImageView imgSave;
|
||||
ImageView imgClose;
|
||||
ImageView imgCrop;
|
||||
|
||||
mPhotoEditorView = findViewById(R.id.photoEditorView);
|
||||
mTxtCurrentTool = findViewById(R.id.txtCurrentTool);
|
||||
mRvTools = findViewById(R.id.rvConstraintTools);
|
||||
mRvFilters = findViewById(R.id.rvFilterView);
|
||||
mRootView = findViewById(R.id.rootView);
|
||||
|
||||
imgUndo = findViewById(R.id.imgUndo);
|
||||
imgUndo.setOnClickListener(this);
|
||||
|
||||
imgRedo = findViewById(R.id.imgRedo);
|
||||
imgRedo.setOnClickListener(this);
|
||||
|
||||
imgCamera = findViewById(R.id.imgCamera);
|
||||
imgCamera.setOnClickListener(this);
|
||||
|
||||
imgGallery = findViewById(R.id.imgGallery);
|
||||
imgGallery.setOnClickListener(this);
|
||||
|
||||
imgSave = findViewById(R.id.imgSave);
|
||||
imgSave.setOnClickListener(this);
|
||||
|
||||
imgClose = findViewById(R.id.imgClose);
|
||||
imgClose.setOnClickListener(this);
|
||||
|
||||
imgCrop = findViewById(R.id.imgCrop);
|
||||
imgCrop.setOnClickListener(this);
|
||||
|
||||
binding.imgUndo.setOnClickListener(this);
|
||||
binding.imgRedo.setOnClickListener(this);
|
||||
binding.imgClose.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -261,7 +184,7 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
styleBuilder.withTextColor(newColorCode);
|
||||
|
||||
mPhotoEditor.editText(rootView, inputText, styleBuilder);
|
||||
mTxtCurrentTool.setText(R.string.label_text);
|
||||
binding.txtCurrentTool.setText(R.string.label_text);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -285,100 +208,64 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
public void onTouchSourceImage(MotionEvent event) {
|
||||
}
|
||||
|
||||
@SuppressLint("NonConstantResourceId")
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
|
||||
case R.id.imgUndo:
|
||||
mPhotoEditor.undo();
|
||||
break;
|
||||
|
||||
case R.id.imgRedo:
|
||||
mPhotoEditor.redo();
|
||||
break;
|
||||
|
||||
case R.id.imgSave:
|
||||
saveImage();
|
||||
break;
|
||||
|
||||
case R.id.imgClose:
|
||||
onBackPressed();
|
||||
break;
|
||||
case R.id.imgCrop:
|
||||
shareImage();
|
||||
break;
|
||||
|
||||
case R.id.imgCamera:
|
||||
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
startActivityForResult(cameraIntent, CAMERA_REQUEST);
|
||||
break;
|
||||
|
||||
case R.id.imgGallery:
|
||||
Intent intent = new Intent();
|
||||
intent.setType("image/*");
|
||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_REQUEST);
|
||||
break;
|
||||
int id = view.getId();
|
||||
if (id == R.id.imgUndo) {
|
||||
mPhotoEditor.undo();
|
||||
} else if (id == R.id.imgRedo) {
|
||||
mPhotoEditor.redo();
|
||||
} else if (id == R.id.imgClose) {
|
||||
onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
private void shareImage() {
|
||||
if (mSaveImageUri == null) {
|
||||
//showSnackbar(getString(R.string.msg_save_image_to_share));
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("image/*");
|
||||
intent.putExtra(Intent.EXTRA_STREAM, buildFileProviderUri(mSaveImageUri));
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.msg_share_image)));
|
||||
}
|
||||
|
||||
private Uri buildFileProviderUri(@NonNull Uri uri) {
|
||||
return FileProvider.getUriForFile(this,
|
||||
FILE_PROVIDER_AUTHORITY,
|
||||
new File(uri.getPath()));
|
||||
}
|
||||
|
||||
|
||||
private void saveImage() {
|
||||
final String fileName = System.currentTimeMillis() + ".png";
|
||||
final boolean hasStoragePermission =
|
||||
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PERMISSION_GRANTED;
|
||||
if (hasStoragePermission || isSdkHigherThan28()) {
|
||||
showLoading("Saving...");
|
||||
mSaveFileHelper.createFile(fileName, (fileCreated, filePath, error, uri) -> {
|
||||
if (fileCreated) {
|
||||
SaveSettings saveSettings = new SaveSettings.Builder()
|
||||
.setClearViewsEnabled(true)
|
||||
.setTransparencyEnabled(true)
|
||||
.build();
|
||||
if (requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
showLoading(getString(R.string.saving));
|
||||
File file = new File(path);
|
||||
try {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
file.createNewFile();
|
||||
|
||||
mPhotoEditor.saveAsFile(filePath, saveSettings, new PhotoEditor.OnSaveListener() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull String imagePath) {
|
||||
mSaveFileHelper.notifyThatFileIsNowPubliclyAvailable(getContentResolver());
|
||||
hideLoading();
|
||||
showSnackbar("Image Saved Successfully");
|
||||
mSaveImageUri = uri;
|
||||
mPhotoEditorView.getSource().setImageURI(mSaveImageUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Exception exception) {
|
||||
hideLoading();
|
||||
showSnackbar("Failed to save Image");
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
hideLoading();
|
||||
showSnackbar(error);
|
||||
SaveSettings saveSettings = new SaveSettings.Builder()
|
||||
.setClearViewsEnabled(true)
|
||||
.setTransparencyEnabled(true)
|
||||
.build();
|
||||
if (ContextCompat.checkSelfPermission(EditImageActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(EditImageActivity.this,
|
||||
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
|
||||
STORE_REQUEST);
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
mPhotoEditor.saveAsFile(file.getAbsolutePath(), saveSettings, new PhotoEditor.OnSaveListener() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull String imagePath) {
|
||||
hideLoading();
|
||||
showSnackbar(getString(R.string.image_saved));
|
||||
binding.photoEditorView.getSource().setImageURI(Uri.fromFile(new File(imagePath)));
|
||||
if (exit) {
|
||||
Intent intentImage = new Intent(Helper.INTENT_SEND_MODIFIED_IMAGE);
|
||||
intentImage.putExtra("imgpath", imagePath);
|
||||
LocalBroadcastManager.getInstance(EditImageActivity.this).sendBroadcast(intentImage);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Exception exception) {
|
||||
hideLoading();
|
||||
showSnackbar(getString(R.string.save_image_failed));
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
hideLoading();
|
||||
if (e.getMessage() != null) {
|
||||
showSnackbar(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,8 +293,8 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
if (data != null && data.getExtras() != null) {
|
||||
mPhotoEditor.clearAllViews();
|
||||
Bitmap photo = (Bitmap) data.getExtras().get("data");
|
||||
mPhotoEditorView.getSource().setImageBitmap(photo);
|
||||
mPhotoEditorView.getSource().setRotation(rotationInDegrees);
|
||||
binding.photoEditorView.getSource().setImageBitmap(photo);
|
||||
binding.photoEditorView.getSource().setRotation(rotationInDegrees);
|
||||
}
|
||||
break;
|
||||
case PICK_REQUEST:
|
||||
|
@ -416,8 +303,8 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
mPhotoEditor.clearAllViews();
|
||||
Uri uri = data.getData();
|
||||
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
|
||||
mPhotoEditorView.getSource().setImageBitmap(bitmap);
|
||||
mPhotoEditorView.getSource().setRotation(rotationInDegrees);
|
||||
binding.photoEditorView.getSource().setImageBitmap(bitmap);
|
||||
binding.photoEditorView.getSource().setRotation(rotationInDegrees);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -429,8 +316,8 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
if (result != null) {
|
||||
Uri resultUri = result.getUri();
|
||||
if (resultUri != null) {
|
||||
mPhotoEditorView.getSource().setImageURI(resultUri);
|
||||
mPhotoEditorView.getSource().setRotation(rotationInDegrees);
|
||||
binding.photoEditorView.getSource().setImageURI(resultUri);
|
||||
binding.photoEditorView.getSource().setRotation(rotationInDegrees);
|
||||
if (uri != null && uri.getPath() != null) {
|
||||
File fdelete = new File(uri.getPath());
|
||||
if (fdelete.exists()) {
|
||||
|
@ -449,19 +336,19 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
@Override
|
||||
public void onColorChanged(int colorCode) {
|
||||
mPhotoEditor.setShape(mShapeBuilder.withShapeColor(colorCode));
|
||||
mTxtCurrentTool.setText(R.string.label_brush);
|
||||
binding.txtCurrentTool.setText(R.string.label_brush);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpacityChanged(int opacity) {
|
||||
mPhotoEditor.setShape(mShapeBuilder.withShapeOpacity(opacity));
|
||||
mTxtCurrentTool.setText(R.string.label_brush);
|
||||
binding.txtCurrentTool.setText(R.string.label_brush);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShapeSizeChanged(int shapeSize) {
|
||||
mPhotoEditor.setShape(mShapeBuilder.withShapeSize(shapeSize));
|
||||
mTxtCurrentTool.setText(R.string.label_brush);
|
||||
binding.txtCurrentTool.setText(R.string.label_brush);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -472,22 +359,14 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
@Override
|
||||
public void onEmojiClick(String emojiUnicode) {
|
||||
mPhotoEditor.addEmoji(emojiUnicode);
|
||||
mTxtCurrentTool.setText(R.string.label_emoji);
|
||||
binding.txtCurrentTool.setText(R.string.label_emoji);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStickerClick(Bitmap bitmap) {
|
||||
mPhotoEditor.addImage(bitmap);
|
||||
mTxtCurrentTool.setText(R.string.label_sticker);
|
||||
}
|
||||
|
||||
|
||||
private void showSaveDialog() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setMessage(getString(R.string.msg_save_image));
|
||||
builder.setPositiveButton("Save", (dialog, which) -> saveImage());
|
||||
builder.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss());
|
||||
builder.setNeutralButton("Discard", (dialog, which) -> finish());
|
||||
builder.setPositiveButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
|
||||
builder.setNegativeButton(R.string.discard, (dialog, which) -> finish());
|
||||
builder.create().show();
|
||||
|
||||
}
|
||||
|
@ -504,7 +383,7 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
mPhotoEditor.setBrushDrawingMode(true);
|
||||
mShapeBuilder = new ShapeBuilder();
|
||||
mPhotoEditor.setShape(mShapeBuilder);
|
||||
mTxtCurrentTool.setText(R.string.label_shape);
|
||||
binding.txtCurrentTool.setText(R.string.label_shape);
|
||||
showBottomSheetDialogFragment(mShapeBSFragment);
|
||||
break;
|
||||
case TEXT:
|
||||
|
@ -514,28 +393,30 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
styleBuilder.withTextColor(colorCode);
|
||||
|
||||
mPhotoEditor.addText(inputText, styleBuilder);
|
||||
mTxtCurrentTool.setText(R.string.label_text);
|
||||
binding.txtCurrentTool.setText(R.string.label_text);
|
||||
});
|
||||
break;
|
||||
case ERASER:
|
||||
mPhotoEditor.brushEraser();
|
||||
mTxtCurrentTool.setText(R.string.label_eraser_mode);
|
||||
binding.txtCurrentTool.setText(R.string.label_eraser_mode);
|
||||
break;
|
||||
case FILTER:
|
||||
mTxtCurrentTool.setText(R.string.label_filter);
|
||||
binding.txtCurrentTool.setText(R.string.label_filter);
|
||||
showFilter(true);
|
||||
break;
|
||||
case EMOJI:
|
||||
showBottomSheetDialogFragment(mEmojiBSFragment);
|
||||
break;
|
||||
case STICKER:
|
||||
showBottomSheetDialogFragment(mStickerBSFragment);
|
||||
break;
|
||||
case BRUSH:
|
||||
mPhotoEditor.setBrushDrawingMode(true);
|
||||
mTxtCurrentTool.setText(R.string.label_brush);
|
||||
binding.txtCurrentTool.setText(R.string.label_brush);
|
||||
mPropertiesBSFragment.show(getSupportFragmentManager(), mPropertiesBSFragment.getTag());
|
||||
break;
|
||||
case CROP:
|
||||
Log.v(Helper.TAG, "crop! " + uri);
|
||||
CropImage.activity(uri)
|
||||
.start(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -549,33 +430,33 @@ public class EditImageActivity extends BaseActivity implements OnPhotoEditorList
|
|||
|
||||
void showFilter(boolean isVisible) {
|
||||
mIsFilterVisible = isVisible;
|
||||
mConstraintSet.clone(mRootView);
|
||||
mConstraintSet.clone(binding.rootView);
|
||||
|
||||
if (isVisible) {
|
||||
mConstraintSet.clear(mRvFilters.getId(), ConstraintSet.START);
|
||||
mConstraintSet.connect(mRvFilters.getId(), ConstraintSet.START,
|
||||
mConstraintSet.clear(binding.rvFilterView.getId(), ConstraintSet.START);
|
||||
mConstraintSet.connect(binding.rvFilterView.getId(), ConstraintSet.START,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.START);
|
||||
mConstraintSet.connect(mRvFilters.getId(), ConstraintSet.END,
|
||||
mConstraintSet.connect(binding.rvFilterView.getId(), ConstraintSet.END,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.END);
|
||||
} else {
|
||||
mConstraintSet.connect(mRvFilters.getId(), ConstraintSet.START,
|
||||
mConstraintSet.connect(binding.rvFilterView.getId(), ConstraintSet.START,
|
||||
ConstraintSet.PARENT_ID, ConstraintSet.END);
|
||||
mConstraintSet.clear(mRvFilters.getId(), ConstraintSet.END);
|
||||
mConstraintSet.clear(binding.rvFilterView.getId(), ConstraintSet.END);
|
||||
}
|
||||
|
||||
ChangeBounds changeBounds = new ChangeBounds();
|
||||
changeBounds.setDuration(350);
|
||||
changeBounds.setInterpolator(new AnticipateOvershootInterpolator(1.0f));
|
||||
TransitionManager.beginDelayedTransition(mRootView, changeBounds);
|
||||
TransitionManager.beginDelayedTransition(binding.rootView, changeBounds);
|
||||
|
||||
mConstraintSet.applyTo(mRootView);
|
||||
mConstraintSet.applyTo(binding.rootView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (mIsFilterVisible) {
|
||||
showFilter(false);
|
||||
mTxtCurrentTool.setText(R.string.app_name);
|
||||
binding.txtCurrentTool.setText(R.string.app_name);
|
||||
} else if (!mPhotoEditor.isCacheEmpty()) {
|
||||
showSaveDialog();
|
||||
} else {
|
||||
|
|
|
@ -26,12 +26,12 @@ public class EditingToolsAdapter extends RecyclerView.Adapter<EditingToolsAdapte
|
|||
|
||||
public EditingToolsAdapter(OnItemSelected onItemSelected) {
|
||||
mOnItemSelected = onItemSelected;
|
||||
mToolList.add(new ToolModel("Crop", R.drawable.ic_crop, ToolType.CROP));
|
||||
mToolList.add(new ToolModel("Shape", R.drawable.ic_oval, ToolType.SHAPE));
|
||||
mToolList.add(new ToolModel("Text", R.drawable.ic_text, ToolType.TEXT));
|
||||
mToolList.add(new ToolModel("Eraser", R.drawable.ic_eraser, ToolType.ERASER));
|
||||
mToolList.add(new ToolModel("Filter", R.drawable.ic_photo_filter, ToolType.FILTER));
|
||||
mToolList.add(new ToolModel("Emoji", R.drawable.ic_insert_emoticon, ToolType.EMOJI));
|
||||
mToolList.add(new ToolModel("Sticker", R.drawable.ic_sticker, ToolType.STICKER));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
|
@ -12,5 +12,6 @@ public enum ToolType {
|
|||
ERASER,
|
||||
FILTER,
|
||||
EMOJI,
|
||||
STICKER
|
||||
STICKER,
|
||||
CROP
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ import androidx.preference.PreferenceManager;
|
|||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
|
@ -439,6 +440,8 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
|||
if ((attachment.type != null && attachment.type.toLowerCase().startsWith("image")) || (attachment.mimeType != null && attachment.mimeType.toLowerCase().startsWith("image"))) {
|
||||
Glide.with(composeAttachmentItemBinding.preview.getContext())
|
||||
.load(attachmentPath)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.skipMemoryCache(true)
|
||||
.into(composeAttachmentItemBinding.preview);
|
||||
} else if ((attachment.type != null && attachment.type.toLowerCase().startsWith("video")) || (attachment.mimeType != null && attachment.mimeType.toLowerCase().startsWith("video"))) {
|
||||
composeAttachmentItemBinding.buttonPlay.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
app:layout_constraintBottom_toTopOf="@+id/rvConstraintTools"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:photo_src="@drawable/blank_image" />
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgUndo"
|
||||
|
@ -46,32 +45,12 @@
|
|||
app:layout_constraintBottom_toTopOf="@+id/rvConstraintTools"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgGallery"
|
||||
android:layout_width="@dimen/top_tool_icon_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/semi_black_transparent"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_gallery"
|
||||
app:layout_constraintBottom_toTopOf="@+id/rvConstraintTools"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgCamera"
|
||||
android:layout_width="@dimen/top_tool_icon_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/semi_black_transparent"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_camera"
|
||||
app:layout_constraintBottom_toTopOf="@+id/rvConstraintTools"
|
||||
app:layout_constraintStart_toEndOf="@id/imgGallery" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgClose"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_margin="8dp"
|
||||
android:src="@drawable/ic_close"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
@ -80,7 +59,7 @@
|
|||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rvConstraintTools"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/tool_bg"
|
||||
android:orientation="horizontal"
|
||||
|
@ -118,26 +97,6 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/guideline" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgSave"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:src="@drawable/ic_save"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/guideline" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgCrop"
|
||||
android:layout_width="@dimen/top_tool_icon_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/semi_black_transparent"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_crop"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/photoEditorView"
|
||||
app:layout_constraintEnd_toStartOf="@+id/imgUndo"
|
||||
app:layout_constraintStart_toEndOf="@+id/imgCamera" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/send"
|
||||
|
@ -150,6 +109,6 @@
|
|||
android:padding="0dp"
|
||||
android:text="@string/validate"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/imgSave"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/guideline" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in a new issue