From 1067e2ff443d4a68e1692e1e8afd2de3034053a0 Mon Sep 17 00:00:00 2001
From: Yaser El Dabete Arribas <34303875+yasmanets@users.noreply.github.com>
Date: Fri, 22 Apr 2022 14:59:28 +0200
Subject: [PATCH 1/9] Translation of "Camera" and "Gallery" added in some
languages (#358)
---
CHANGELOG.md | 2 ++
cropper/src/main/res/values-ar/strings.xml | 4 ++--
cropper/src/main/res/values-de/strings.xml | 4 ++--
cropper/src/main/res/values-es-rGT/strings.xml | 2 ++
cropper/src/main/res/values-es/strings.xml | 6 ++++--
cropper/src/main/res/values-fr/strings.xml | 2 ++
cropper/src/main/res/values-it/strings.xml | 3 ++-
cropper/src/main/res/values-nl/strings.xml | 4 ++--
8 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f5feee05..341f0a74 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- `Security` in case of vulnerabilities.
## [x.x.x] - unreleased
+### Fixed
+- The translation of `Camera` and `Gallery` does not exist in some languages.
## [4.2.1] - 04/04/2022
### Added
diff --git a/cropper/src/main/res/values-ar/strings.xml b/cropper/src/main/res/values-ar/strings.xml
index 5f5fe5a4..94e5c568 100644
--- a/cropper/src/main/res/values-ar/strings.xml
+++ b/cropper/src/main/res/values-ar/strings.xml
@@ -8,9 +8,9 @@
اقلب
اقلب أفقيًا
اقلب رأسيًا
-
اختر مصدرًا
-
+ الة تصوير
+ صالة عرض
إلغاء؛ الأذونات المطلوبة غير ممنوحة
diff --git a/cropper/src/main/res/values-de/strings.xml b/cropper/src/main/res/values-de/strings.xml
index a4eacd34..d24e6599 100644
--- a/cropper/src/main/res/values-de/strings.xml
+++ b/cropper/src/main/res/values-de/strings.xml
@@ -8,9 +8,9 @@
spiegeln
horizontal spiegeln
vertikal spiegeln
-
Quelle wählen
-
+ Kamera
+ Galerie
Vorgang wird abgebrochen, benötigte Berechtigungen wurden nicht erteilt.
diff --git a/cropper/src/main/res/values-es-rGT/strings.xml b/cropper/src/main/res/values-es-rGT/strings.xml
index e299d8d5..2b639955 100644
--- a/cropper/src/main/res/values-es-rGT/strings.xml
+++ b/cropper/src/main/res/values-es-rGT/strings.xml
@@ -8,5 +8,7 @@
Voltear horizontalmente
Voltear verticalmente
Seleccionar fuente
+ Cámara
+ Galería
Cancelando, los permisos requeridos no se otorgaron
\ No newline at end of file
diff --git a/cropper/src/main/res/values-es/strings.xml b/cropper/src/main/res/values-es/strings.xml
index a8bc1e7f..f7446cc6 100644
--- a/cropper/src/main/res/values-es/strings.xml
+++ b/cropper/src/main/res/values-es/strings.xml
@@ -5,8 +5,10 @@
Rotar a la derecha
Cortar
Dar la vuelta
- Voltear horizontalmente
- Voltear verticalmente
+ Girar horizontalmente
+ Girar verticalmente
Seleccionar fuente
+ Cámara
+ Galería
Cancelando, los permisos requeridos no han sido otorgados
\ No newline at end of file
diff --git a/cropper/src/main/res/values-fr/strings.xml b/cropper/src/main/res/values-fr/strings.xml
index e6168923..c3f50bf2 100644
--- a/cropper/src/main/res/values-fr/strings.xml
+++ b/cropper/src/main/res/values-fr/strings.xml
@@ -8,5 +8,7 @@
Retourner horizontalement
Retourner verticalement
Sélectionner la source
+ Appareil photo
+ Galerie
Annulation, il manque des permissions requises
diff --git a/cropper/src/main/res/values-it/strings.xml b/cropper/src/main/res/values-it/strings.xml
index 77545864..01602e12 100644
--- a/cropper/src/main/res/values-it/strings.xml
+++ b/cropper/src/main/res/values-it/strings.xml
@@ -10,7 +10,8 @@
Capovolgi verticalmente
Seleziona origine
-
+ Fotocamera
+ Galleria
Annullamento in corso, autorizzazione richieste non concesse
diff --git a/cropper/src/main/res/values-nl/strings.xml b/cropper/src/main/res/values-nl/strings.xml
index b69dda00..cc8b5910 100644
--- a/cropper/src/main/res/values-nl/strings.xml
+++ b/cropper/src/main/res/values-nl/strings.xml
@@ -8,9 +8,9 @@
Spiegelen
Horizontaal spiegelen
Verticaal spiegelen
-
Bron selecteren
-
+ Camera
+ Galerij
Wordt geannuleerd, vereiste machtigingen zijn niet toegekend
From 31499a255b4793ebf8f4bb017253eb69eb4a8eea Mon Sep 17 00:00:00 2001
From: Fahad Kassim
Date: Mon, 25 Apr 2022 12:37:17 +0300
Subject: [PATCH 2/9] Updated Read Me (#360)
It points to the discussion's link that many Java Developers are stuck.
Great for a quick solution.
---
README.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/README.md b/README.md
index 35cb20aa..cb2f9c40 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,10 @@
[Java Sample Code](https://github.com/CanHub/Android-Image-Cropper/tree/main/sample/src/main/java/com/canhub/cropper/sample/crop_image_java)
+Still stuck? Try This Discussion here to a **Plug and Play** Solution to get you started.
+
+[🚨 Calling an Activity Directly To Handle this using Java](https://github.com/CanHub/Android-Image-Cropper/discussions/236)
+
Wanna help the project? Amazing!
- [Contributing Guide](https://github.com/CanHub/Android-Image-Cropper/blob/main/CONTRIBUTING.md)
From 983191dd24d56fbb86e9e63a1f6faa86522ee22d Mon Sep 17 00:00:00 2001
From: Canato
Date: Sun, 8 May 2022 14:51:32 +0100
Subject: [PATCH 3/9] Make samples simpler (#361)
* Add dependabot configs
* Simplify crop image
* Simplify crop image java sample
* Simplify image view sample
* Simplify sample extend activity
* Rename samples files
* Refactor options dialog
---
.github/dependabot.yml | 7 +
sample/src/main/AndroidManifest.xml | 4 +-
.../{SMainActivity.kt => MainActivity.kt} | 25 +-
.../SCropImageFragment.kt => SampleCrop.kt} | 76 +++---
...eFragmentJava.java => SampleCropJava.java} | 48 ++--
...endActivity.kt => SampleCustomActivity.kt} | 62 ++---
...esultActivity.kt => SampleResultScreen.kt} | 4 +-
...iewFragment.kt => SampleUsingImageView.kt} | 48 ++--
.../crop_image/domain/SCropImageContract.kt | 24 --
.../presenter/SCropImagePresenter.kt | 69 -----
.../domain/SCropImageContractJava.java | 27 --
.../presenter/SCropImagePresenterJava.java | 59 -----
.../domain/SCropImageViewContract.kt | 15 --
.../presenter/SCropImageViewPresenter.kt | 38 ---
.../extend_activity/domain/SExtendContract.kt | 14 --
.../presenter/SExtendPresenter.kt | 25 --
...omSheet.kt => SampleOptionsBottomSheet.kt} | 238 +++++++++---------
...ptionsDomain.kt => SampleOptionsEntity.kt} | 4 +-
.../app/SOptionsServiceLocator.kt | 10 -
.../options_dialog/domain/SOptionsContract.kt | 34 ---
.../presenter/SOptionsPresenter.kt | 95 -------
sample/src/main/res/layout/activity_main.xml | 2 +-
.../res/layout/fragment_crop_image_view.xml | 2 +-
23 files changed, 251 insertions(+), 679 deletions(-)
create mode 100644 .github/dependabot.yml
rename sample/src/main/java/com/canhub/cropper/sample/{SMainActivity.kt => MainActivity.kt} (52%)
rename sample/src/main/java/com/canhub/cropper/sample/{crop_image/app/SCropImageFragment.kt => SampleCrop.kt} (86%)
rename sample/src/main/java/com/canhub/cropper/sample/{crop_image_java/app/SCropImageFragmentJava.java => SampleCropJava.java} (87%)
rename sample/src/main/java/com/canhub/cropper/sample/{extend_activity/app/SExtendActivity.kt => SampleCustomActivity.kt} (63%)
rename sample/src/main/java/com/canhub/cropper/sample/{SCropResultActivity.kt => SampleResultScreen.kt} (94%)
rename sample/src/main/java/com/canhub/cropper/sample/{crop_image_view/app/SCropImageViewFragment.kt => SampleUsingImageView.kt} (82%)
delete mode 100644 sample/src/main/java/com/canhub/cropper/sample/crop_image/domain/SCropImageContract.kt
delete mode 100644 sample/src/main/java/com/canhub/cropper/sample/crop_image/presenter/SCropImagePresenter.kt
delete mode 100644 sample/src/main/java/com/canhub/cropper/sample/crop_image_java/domain/SCropImageContractJava.java
delete mode 100644 sample/src/main/java/com/canhub/cropper/sample/crop_image_java/presenter/SCropImagePresenterJava.java
delete mode 100644 sample/src/main/java/com/canhub/cropper/sample/crop_image_view/domain/SCropImageViewContract.kt
delete mode 100644 sample/src/main/java/com/canhub/cropper/sample/crop_image_view/presenter/SCropImageViewPresenter.kt
delete mode 100644 sample/src/main/java/com/canhub/cropper/sample/extend_activity/domain/SExtendContract.kt
delete mode 100644 sample/src/main/java/com/canhub/cropper/sample/extend_activity/presenter/SExtendPresenter.kt
rename sample/src/main/java/com/canhub/cropper/sample/options_dialog/{app/SOptionsDialogBottomSheet.kt => SampleOptionsBottomSheet.kt} (68%)
rename sample/src/main/java/com/canhub/cropper/sample/options_dialog/{domain/SOptionsDomain.kt => SampleOptionsEntity.kt} (87%)
delete mode 100644 sample/src/main/java/com/canhub/cropper/sample/options_dialog/app/SOptionsServiceLocator.kt
delete mode 100644 sample/src/main/java/com/canhub/cropper/sample/options_dialog/domain/SOptionsContract.kt
delete mode 100644 sample/src/main/java/com/canhub/cropper/sample/options_dialog/presenter/SOptionsPresenter.kt
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..c49b62bb
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,7 @@
+version: 2
+updates:
+ - package-ecosystem: gradle
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ open-pull-requests-limit: 1
\ No newline at end of file
diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
index 110804c6..6247b07c 100644
--- a/sample/src/main/AndroidManifest.xml
+++ b/sample/src/main/AndroidManifest.xml
@@ -8,7 +8,7 @@
android:label="@string/app_name"
android:theme="@style/Theme.Sample">
@@ -17,7 +17,7 @@
-
+
+ when {
+ result.isSuccessful -> {
+ Log.v("Bitmap", result.bitmap.toString())
+ Log.v("File Path", context?.let { result.getUriFilePath(it) }.toString())
+ handleCropImageResult(result.uriContent.toString())
+ }
+ result is CropImage.CancelledResult -> {
+ showErrorMessage("cropping image was cancelled by the user")
+ }
+ else -> {
+ showErrorMessage("cropping image failed")
+ }
+ }
}
private val customCropImage = registerForActivityResult(CropImageContract()) {
- presenter.onCustomCropImageResult(outputUri)
+ handleCropImageResult(it.uriContent.toString())
}
override fun onCreateView(
@@ -64,39 +73,23 @@ internal class SCropImageFragment : Fragment(), SCropImageContract.View {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- presenter.bind(this)
- binding.takePictureBeforeCallLibraryWithUri.setOnClickListener { startTakePicture() }
+ binding.takePictureBeforeCallLibraryWithUri.setOnClickListener {
+ setupOutputUri()
+ takePicture.launch(outputUri)
+ }
binding.callLibraryWithoutUri.setOnClickListener {
- startCameraWithoutUri(
- includeCamera = true,
- includeGallery = true,
- )
+ startCameraWithoutUri(includeCamera = true, includeGallery = true)
}
binding.callLibraryWithoutUriCameraOnly.setOnClickListener {
- startCameraWithoutUri(
- includeCamera = true,
- includeGallery = false,
- )
+ startCameraWithoutUri(includeCamera = true, includeGallery = false)
}
binding.callLibraryWithoutUriGalleryOnly.setOnClickListener {
- startCameraWithoutUri(
- includeCamera = false,
- includeGallery = true,
- )
+ startCameraWithoutUri(includeCamera = false, includeGallery = true)
}
-
- presenter.onCreate(activity, context)
- }
-
- override fun onDestroyView() {
- presenter.unbind()
- super.onDestroyView()
}
private fun startCameraWithoutUri(includeCamera: Boolean, includeGallery: Boolean) {
- setupOutputUri()
-
customCropImage.launch(
options {
setImageSource(
@@ -131,7 +124,6 @@ internal class SCropImageFragment : Fragment(), SCropImageContract.View {
setMaxCropResultSize(99999, 99999)
setActivityTitle("")
setActivityMenuIconColor(0)
- setOutputUri(outputUri)
setOutputCompressFormat(Bitmap.CompressFormat.JPEG)
setOutputCompressQuality(90)
setRequestedSize(0, 0)
@@ -146,7 +138,6 @@ internal class SCropImageFragment : Fragment(), SCropImageContract.View {
setAllowRotation(true)
setNoOutputImage(false)
setFixAspectRatio(false)
-
// Odd Settings
// setScaleType(CropImageView.ScaleType.CENTER)
// setCropShape(CropImageView.CropShape.OVAL)
@@ -202,7 +193,7 @@ internal class SCropImageFragment : Fragment(), SCropImageContract.View {
)
}
- override fun startCameraWithUri() {
+ private fun startCameraWithUri() {
cropImage.launch(
options(outputUri) {
setScaleType(CropImageView.ScaleType.FIT_CENTER)
@@ -251,18 +242,13 @@ internal class SCropImageFragment : Fragment(), SCropImageContract.View {
)
}
- override fun showErrorMessage(message: String) {
+ private fun showErrorMessage(message: String) {
Log.e("Camera Error:", message)
Toast.makeText(activity, "Crop failed: $message", Toast.LENGTH_SHORT).show()
}
- private fun startTakePicture() {
- setupOutputUri()
- takePicture.launch(outputUri)
- }
-
- override fun handleCropImageResult(uri: String) {
- SCropResultActivity.start(this, null, Uri.parse(uri), null)
+ private fun handleCropImageResult(uri: String) {
+ SampleResultScreen.start(this, null, Uri.parse(uri.replace("file:", "")), null)
}
private fun setupOutputUri() {
diff --git a/sample/src/main/java/com/canhub/cropper/sample/crop_image_java/app/SCropImageFragmentJava.java b/sample/src/main/java/com/canhub/cropper/sample/SampleCropJava.java
similarity index 87%
rename from sample/src/main/java/com/canhub/cropper/sample/crop_image_java/app/SCropImageFragmentJava.java
rename to sample/src/main/java/com/canhub/cropper/sample/SampleCropJava.java
index 6af40a50..32a13068 100644
--- a/sample/src/main/java/com/canhub/cropper/sample/crop_image_java/app/SCropImageFragmentJava.java
+++ b/sample/src/main/java/com/canhub/cropper/sample/SampleCropJava.java
@@ -1,4 +1,4 @@
-package com.canhub.cropper.sample.crop_image_java.app;
+package com.canhub.cropper.sample;
import static android.graphics.Color.RED;
import static android.graphics.Color.WHITE;
@@ -14,32 +14,27 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
-
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
-
+import com.canhub.cropper.CropImage;
import com.canhub.cropper.CropImageContract;
import com.canhub.cropper.CropImageContractOptions;
import com.canhub.cropper.CropImageOptions;
import com.canhub.cropper.CropImageView;
-import com.canhub.cropper.sample.SCropResultActivity;
-import com.canhub.cropper.sample.crop_image_java.domain.SCropImageContractJava;
-import com.canhub.cropper.sample.crop_image_java.presenter.SCropImagePresenterJava;
import com.example.croppersample.R;
import com.example.croppersample.databinding.FragmentCameraBinding;
-
import org.jetbrains.annotations.NotNull;
-
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Locale;
+import java.util.Objects;
-public class SCropImageFragmentJava extends Fragment implements SCropImageContractJava.View {
+public class SampleCropJava extends Fragment {
static final String DATE_FORMAT = "yyyyMMdd_HHmmss";
static final String FILE_NAMING_PREFIX = "JPEG_";
@@ -48,18 +43,17 @@ public class SCropImageFragmentJava extends Fragment implements SCropImageContra
static final String AUTHORITY_SUFFIX = ".cropper.fileprovider";
private FragmentCameraBinding binding;
- private final SCropImageContractJava.Presenter presenter = new SCropImagePresenterJava();
private Uri outputUri;
private final ActivityResultLauncher takePicture =
- registerForActivityResult(new ActivityResultContracts.TakePicture(), presenter::onTakePictureResult);
+ registerForActivityResult(new ActivityResultContracts.TakePicture(), this::onTakePictureResult);
private final ActivityResultLauncher cropImage =
- registerForActivityResult(new CropImageContract(), presenter::onCropImageResult);
+ registerForActivityResult(new CropImageContract(), this::onCropImageResult);
- public static SCropImageFragmentJava newInstance() {
- return new SCropImageFragmentJava();
+ public static SampleCropJava newInstance() {
+ return new SampleCropJava();
}
@Nullable
@@ -73,17 +67,13 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- presenter.bind(this);
binding.takePictureBeforeCallLibraryWithUri.setOnClickListener(v -> startTakePicture());
binding.callLibraryWithoutUri.setOnClickListener(v -> startCameraWithoutUri());
-
- presenter.onCreate(getActivity(), getContext());
}
@Override
public void onDestroyView() {
- presenter.unbind();
super.onDestroyView();
}
@@ -135,7 +125,6 @@ private void startCameraWithoutUri() {
cropImage.launch(options);
}
- @Override
public void startCameraWithUri() {
CropImageContractOptions options = new CropImageContractOptions(outputUri, new CropImageOptions())
.setScaleType(CropImageView.ScaleType.FIT_CENTER)
@@ -183,7 +172,6 @@ public void startCameraWithUri() {
cropImage.launch(options);
}
- @Override
public void showErrorMessage(@NotNull String message) {
Log.e("Camera Error:", message);
Toast.makeText(getActivity(), "Crop failed: " + message, Toast.LENGTH_SHORT).show();
@@ -200,9 +188,8 @@ private void startTakePicture() {
}
}
- @Override
public void handleCropImageResult(@NotNull String uri) {
- SCropResultActivity.Companion.start(this, null, Uri.parse(uri), null);
+ SampleResultScreen.Companion.start(this, null, Uri.parse(uri), null);
}
private File createImageFile() throws IOException {
@@ -214,4 +201,21 @@ private File createImageFile() throws IOException {
storageDir
);
}
+
+ public void onCropImageResult(@NonNull CropImageView.CropResult result) {
+ if (result.isSuccessful()) {
+ handleCropImageResult(Objects.requireNonNull(result.getUriContent())
+ .toString()
+ .replace("file:", ""));
+ } else if (result.equals(CropImage.CancelledResult.INSTANCE)) {
+ showErrorMessage("cropping image was cancelled by the user");
+ } else {
+ showErrorMessage("cropping image failed");
+ }
+ }
+
+ public void onTakePictureResult(boolean success) {
+ if (success) { startCameraWithUri(); }
+ else { showErrorMessage("taking picture failed"); }
+ }
}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/extend_activity/app/SExtendActivity.kt b/sample/src/main/java/com/canhub/cropper/sample/SampleCustomActivity.kt
similarity index 63%
rename from sample/src/main/java/com/canhub/cropper/sample/extend_activity/app/SExtendActivity.kt
rename to sample/src/main/java/com/canhub/cropper/sample/SampleCustomActivity.kt
index 442633b4..d1b6a290 100644
--- a/sample/src/main/java/com/canhub/cropper/sample/extend_activity/app/SExtendActivity.kt
+++ b/sample/src/main/java/com/canhub/cropper/sample/SampleCustomActivity.kt
@@ -1,4 +1,4 @@
-package com.canhub.cropper.sample.extend_activity.app
+package com.canhub.cropper.sample
import android.app.Activity
import android.content.Intent
@@ -10,41 +10,33 @@ import android.view.View
import androidx.core.app.ActivityCompat
import com.canhub.cropper.CropImage
import com.canhub.cropper.CropImageActivity
-import com.canhub.cropper.sample.extend_activity.domain.SExtendContract
-import com.canhub.cropper.sample.extend_activity.presenter.SExtendPresenter
import com.example.croppersample.R
import com.example.croppersample.databinding.ExtendedActivityBinding
-internal class SExtendActivity : CropImageActivity(), SExtendContract.View {
+internal class SampleCustomActivity : CropImageActivity() {
companion object {
fun start(activity: Activity) {
ActivityCompat.startActivity(
activity,
- Intent(activity, SExtendActivity::class.java),
+ Intent(activity, SampleCustomActivity::class.java),
null
)
}
}
private lateinit var binding: ExtendedActivityBinding
- private val presenter: SExtendContract.Presenter = SExtendPresenter()
+ private var counter = 0
override fun onCreate(savedInstanceState: Bundle?) {
binding = ExtendedActivityBinding.inflate(layoutInflater)
super.onCreate(savedInstanceState)
- presenter.bindView(this)
+ updateRotationCounter(counter.toString())
- binding.saveBtn.setOnClickListener {
- cropImage() // CropImageActivity.cropImage()
- }
- binding.backBtn.setOnClickListener {
- onBackPressed() // CropImageActivity.onBackPressed()
- }
- binding.rotateText.setOnClickListener {
- presenter.onRotateClick()
- }
+ binding.saveBtn.setOnClickListener { cropImage() } // CropImageActivity.cropImage()
+ binding.backBtn.setOnClickListener { onBackPressed() } // CropImageActivity.onBackPressed()
+ binding.rotateText.setOnClickListener { onRotateClick() }
setCropImageView(binding.cropImageView)
}
@@ -59,25 +51,14 @@ internal class SExtendActivity : CropImageActivity(), SExtendContract.View {
super.setContentView(binding.root)
}
- override fun onDestroy() {
- presenter.unbindView()
- super.onDestroy()
- }
-
- override fun rotate(counter: Int) {
- binding.cropImageView.rotateImage(counter)
- }
-
- override fun updateRotationCounter(counter: String) {
+ private fun updateRotationCounter(counter: String) {
binding.rotateText.text = getString(R.string.rotation_value, counter)
}
override fun onPickImageResult(resultUri: Uri?) {
super.onPickImageResult(resultUri)
- if (resultUri != null) {
- binding.cropImageView.setImageUriAsync(resultUri)
- }
+ if (resultUri != null) binding.cropImageView.setImageUriAsync(resultUri)
}
// Override this to add more information into the intent
@@ -88,14 +69,14 @@ internal class SExtendActivity : CropImageActivity(), SExtendContract.View {
override fun setResult(uri: Uri?, error: Exception?, sampleSize: Int) {
val result = CropImage.ActivityResult(
- binding.cropImageView.imageUri,
- uri,
- error,
- binding.cropImageView.cropPoints,
- binding.cropImageView.cropRect,
- binding.cropImageView.rotatedDegrees,
- binding.cropImageView.wholeImageRect,
- sampleSize
+ originalUri = binding.cropImageView.imageUri,
+ uriContent = uri,
+ error = error,
+ cropPoints = binding.cropImageView.cropPoints,
+ cropRect = binding.cropImageView.cropRect,
+ rotation = binding.cropImageView.rotatedDegrees,
+ wholeImageRect = binding.cropImageView.wholeImageRect,
+ sampleSize = sampleSize
)
Log.v("File Path", result.getUriFilePath(this).toString())
@@ -114,4 +95,11 @@ internal class SExtendActivity : CropImageActivity(), SExtendContract.View {
)
super.updateMenuItemIconColor(menu, itemId, color)
}
+
+ private fun onRotateClick() {
+ counter += 90
+ binding.cropImageView.rotateImage(90)
+ if (counter == 360) counter = 0
+ updateRotationCounter(counter.toString())
+ }
}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/SCropResultActivity.kt b/sample/src/main/java/com/canhub/cropper/sample/SampleResultScreen.kt
similarity index 94%
rename from sample/src/main/java/com/canhub/cropper/sample/SCropResultActivity.kt
rename to sample/src/main/java/com/canhub/cropper/sample/SampleResultScreen.kt
index 6383ab1a..ef60b3c1 100644
--- a/sample/src/main/java/com/canhub/cropper/sample/SCropResultActivity.kt
+++ b/sample/src/main/java/com/canhub/cropper/sample/SampleResultScreen.kt
@@ -11,11 +11,11 @@ import androidx.fragment.app.Fragment
import com.example.croppersample.R
import com.example.croppersample.databinding.ActivityCropResultBinding
-class SCropResultActivity : Activity() {
+class SampleResultScreen : Activity() {
companion object {
fun start(fragment: Fragment, imageBitmap: Bitmap?, uri: Uri?, sampleSize: Int?) {
- val intent = Intent(fragment.context, SCropResultActivity::class.java)
+ val intent = Intent(fragment.context, SampleResultScreen::class.java)
.putExtra(SAMPLE_SIZE, sampleSize)
.putExtra(URI, uri)
diff --git a/sample/src/main/java/com/canhub/cropper/sample/crop_image_view/app/SCropImageViewFragment.kt b/sample/src/main/java/com/canhub/cropper/sample/SampleUsingImageView.kt
similarity index 82%
rename from sample/src/main/java/com/canhub/cropper/sample/crop_image_view/app/SCropImageViewFragment.kt
rename to sample/src/main/java/com/canhub/cropper/sample/SampleUsingImageView.kt
index a29e617c..a214897a 100644
--- a/sample/src/main/java/com/canhub/cropper/sample/crop_image_view/app/SCropImageViewFragment.kt
+++ b/sample/src/main/java/com/canhub/cropper/sample/SampleUsingImageView.kt
@@ -1,4 +1,4 @@
-package com.canhub.cropper.sample.crop_image_view.app
+package com.canhub.cropper.sample
import android.graphics.Rect
import android.net.Uri
@@ -18,29 +18,24 @@ import com.canhub.cropper.CropImageView
import com.canhub.cropper.CropImageView.CropResult
import com.canhub.cropper.CropImageView.OnCropImageCompleteListener
import com.canhub.cropper.CropImageView.OnSetImageUriCompleteListener
-import com.canhub.cropper.sample.SCropResultActivity
-import com.canhub.cropper.sample.crop_image_view.domain.SCropImageViewContract
-import com.canhub.cropper.sample.crop_image_view.presenter.SCropImageViewPresenter
-import com.canhub.cropper.sample.options_dialog.app.SOptionsDialogBottomSheet
-import com.canhub.cropper.sample.options_dialog.domain.SOptionsDomain
+import com.canhub.cropper.sample.options_dialog.SampleOptionsBottomSheet
+import com.canhub.cropper.sample.options_dialog.SampleOptionsEntity
import com.example.croppersample.R
import com.example.croppersample.databinding.FragmentCropImageViewBinding
-internal class SCropImageViewFragment :
+internal class SampleUsingImageView :
Fragment(),
- SCropImageViewContract.View,
- SOptionsDialogBottomSheet.Listener,
+ SampleOptionsBottomSheet.Listener,
OnSetImageUriCompleteListener,
OnCropImageCompleteListener {
companion object {
- fun newInstance() = SCropImageViewFragment()
+ fun newInstance() = SampleUsingImageView()
}
private lateinit var binding: FragmentCropImageViewBinding
- private val presenter = SCropImageViewPresenter()
- private var options: SOptionsDomain? = null
+ private var options: SampleOptionsEntity? = null
private val openPicker =
registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
binding.cropImageView.setImageUriAsync(uri)
@@ -59,8 +54,7 @@ internal class SCropImageViewFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- presenter.bind(this)
- presenter.onViewCreated()
+ setOptions()
binding.cropImageView.let {
it.setOnSetImageUriCompleteListener(this)
@@ -69,7 +63,7 @@ internal class SCropImageViewFragment :
}
binding.settings.setOnClickListener {
- SOptionsDialogBottomSheet.show(childFragmentManager, options, this)
+ SampleOptionsBottomSheet.show(childFragmentManager, options, this)
}
binding.searchImage.setOnClickListener {
@@ -91,7 +85,7 @@ internal class SCropImageViewFragment :
}
}
- override fun onOptionsApplySelected(options: SOptionsDomain) {
+ override fun onOptionsApplySelected(options: SampleOptionsEntity) {
this.options = options
binding.cropImageView.apply {
@@ -170,7 +164,7 @@ internal class SCropImageViewFragment :
result.bitmap?.let { CropImage.toOvalBitmap(it) }
else result.bitmap
context?.let { Log.v("File Path", result.getUriFilePath(it).toString()) }
- SCropResultActivity.start(this, imageBitmap, result.uriContent, result.sampleSize)
+ SampleResultScreen.start(this, imageBitmap, result.uriContent, result.sampleSize)
} else {
Log.e("AIC", "Failed to crop image", result?.error)
Toast
@@ -179,8 +173,24 @@ internal class SCropImageViewFragment :
}
}
- override fun setOptions(options: SOptionsDomain) {
+ private fun setOptions() {
binding.cropImageView.cropRect = Rect(100, 300, 500, 1200)
- onOptionsApplySelected(options)
+ onOptionsApplySelected(defaultOptions)
}
+
+ private val defaultOptions: SampleOptionsEntity = SampleOptionsEntity(
+ scaleType = CropImageView.ScaleType.FIT_CENTER,
+ cropShape = CropImageView.CropShape.RECTANGLE,
+ cornerShape = CropImageView.CropCornerShape.RECTANGLE,
+ guidelines = CropImageView.Guidelines.ON,
+ ratio = Pair(1, 1),
+ autoZoom = true,
+ maxZoomLvl = 2,
+ multiTouch = true,
+ centerMove = true,
+ showCropOverlay = true,
+ showProgressBar = true,
+ flipHorizontal = false,
+ flipVertically = false
+ )
}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/crop_image/domain/SCropImageContract.kt b/sample/src/main/java/com/canhub/cropper/sample/crop_image/domain/SCropImageContract.kt
deleted file mode 100644
index 29f1404e..00000000
--- a/sample/src/main/java/com/canhub/cropper/sample/crop_image/domain/SCropImageContract.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.canhub.cropper.sample.crop_image.domain
-
-import android.content.Context
-import android.net.Uri
-import androidx.fragment.app.FragmentActivity
-import com.canhub.cropper.CropImageView
-
-internal interface SCropImageContract {
-
- interface View {
- fun showErrorMessage(message: String)
- fun handleCropImageResult(uri: String)
- fun startCameraWithUri()
- }
-
- interface Presenter {
- fun bind(view: View)
- fun unbind()
- fun onCreate(activity: FragmentActivity?, context: Context?)
- fun onCropImageResult(result: CropImageView.CropResult)
- fun onCustomCropImageResult(customUri: Uri?)
- fun onTakePictureResult(success: Boolean)
- }
-}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/crop_image/presenter/SCropImagePresenter.kt b/sample/src/main/java/com/canhub/cropper/sample/crop_image/presenter/SCropImagePresenter.kt
deleted file mode 100644
index c783a3e7..00000000
--- a/sample/src/main/java/com/canhub/cropper/sample/crop_image/presenter/SCropImagePresenter.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.canhub.cropper.sample.crop_image.presenter
-
-import android.Manifest
-import android.app.Activity
-import android.content.Context
-import android.content.pm.PackageManager
-import android.net.Uri
-import android.util.Log
-import androidx.core.app.ActivityCompat
-import androidx.fragment.app.FragmentActivity
-import com.canhub.cropper.CropImage
-import com.canhub.cropper.CropImageView
-import com.canhub.cropper.sample.crop_image.domain.SCropImageContract
-
-internal class SCropImagePresenter : SCropImageContract.Presenter {
-
- private var view: SCropImageContract.View? = null
- private var request = false
- private var hasSystemFeature = false
- private var context: Context? = null
-
- override fun bind(view: SCropImageContract.View) {
- this.view = view
- }
-
- override fun unbind() {
- view = null
- }
-
- override fun onCreate(activity: FragmentActivity?, context: Context?) {
- if (activity == null || context == null) {
- view?.showErrorMessage("onCreate activity and/or context are null")
- return
- }
- this.context = context
-
- request = ActivityCompat.shouldShowRequestPermissionRationale(
- activity as Activity,
- Manifest.permission.CAMERA
- )
- hasSystemFeature = context.packageManager
- ?.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY) ?: false
- }
-
- override fun onCropImageResult(result: CropImageView.CropResult) {
- when {
- result.isSuccessful -> {
- Log.v("Bitmap", result.bitmap.toString())
- Log.v("File Path", context?.let { result.getUriFilePath(it) }.toString())
- view?.handleCropImageResult(result.uriContent.toString().replace("file:", ""))
- }
- result is CropImage.CancelledResult -> {
- view?.showErrorMessage("cropping image was cancelled by the user")
- }
- else -> {
- view?.showErrorMessage("cropping image failed")
- }
- }
- }
-
- override fun onCustomCropImageResult(customUri: Uri?) {
- view?.handleCropImageResult(customUri.toString().replace("file:", ""))
- }
-
- override fun onTakePictureResult(success: Boolean) {
- if (success) view?.startCameraWithUri()
- else view?.showErrorMessage("taking picture failed")
- }
-}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/crop_image_java/domain/SCropImageContractJava.java b/sample/src/main/java/com/canhub/cropper/sample/crop_image_java/domain/SCropImageContractJava.java
deleted file mode 100644
index 449c536e..00000000
--- a/sample/src/main/java/com/canhub/cropper/sample/crop_image_java/domain/SCropImageContractJava.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.canhub.cropper.sample.crop_image_java.domain;
-
-import android.content.Context;
-import android.net.Uri;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.FragmentActivity;
-
-import com.canhub.cropper.CropImageView;
-
-public interface SCropImageContractJava {
-
- interface View {
- void showErrorMessage(String message);
- void handleCropImageResult(String uri);
- void startCameraWithUri();
- }
-
- interface Presenter {
- void bind(View view);
- void unbind();
- void onCreate(FragmentActivity activity, Context context);
- void onCropImageResult(@NonNull CropImageView.CropResult result);
- void onTakePictureResult(boolean success);
- }
-}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/crop_image_java/presenter/SCropImagePresenterJava.java b/sample/src/main/java/com/canhub/cropper/sample/crop_image_java/presenter/SCropImagePresenterJava.java
deleted file mode 100644
index 89ad2f55..00000000
--- a/sample/src/main/java/com/canhub/cropper/sample/crop_image_java/presenter/SCropImagePresenterJava.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.canhub.cropper.sample.crop_image_java.presenter;
-
-import android.content.Context;
-import android.net.Uri;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.FragmentActivity;
-
-import com.canhub.cropper.CropImage;
-import com.canhub.cropper.CropImageView;
-import com.canhub.cropper.sample.crop_image_java.domain.SCropImageContractJava;
-
-import java.util.Objects;
-
-public class SCropImagePresenterJava implements SCropImageContractJava.Presenter {
- private SCropImageContractJava.View view = null;
-
- @Override
- public void bind(SCropImageContractJava.View view) {
- this.view = view;
- }
-
- @Override
- public void unbind() {
- view = null;
- }
-
- @Override
- public void onCreate(FragmentActivity activity, Context context) {
- assert view != null;
- if (activity == null || context == null) {
- view.showErrorMessage("onCreate activity and/or context are null");
- }
- }
-
- @Override
- public void onCropImageResult(@NonNull CropImageView.CropResult result) {
- if (result.isSuccessful()) {
- view.handleCropImageResult(Objects.requireNonNull(result.getUriContent())
- .toString()
- .replace("file:", ""));
- } else if (result.equals(CropImage.CancelledResult.INSTANCE)) {
- view.showErrorMessage("cropping image was cancelled by the user");
- } else {
- view.showErrorMessage("cropping image failed");
- }
- }
-
- @Override
- public void onTakePictureResult(boolean success) {
- if (success) {
- view.startCameraWithUri();
- } else {
- view.showErrorMessage("taking picture failed");
- }
- }
-}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/crop_image_view/domain/SCropImageViewContract.kt b/sample/src/main/java/com/canhub/cropper/sample/crop_image_view/domain/SCropImageViewContract.kt
deleted file mode 100644
index 910db09e..00000000
--- a/sample/src/main/java/com/canhub/cropper/sample/crop_image_view/domain/SCropImageViewContract.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.canhub.cropper.sample.crop_image_view.domain
-
-import com.canhub.cropper.sample.options_dialog.domain.SOptionsDomain
-
-internal interface SCropImageViewContract {
- fun interface View {
- fun setOptions(options: SOptionsDomain)
- }
-
- interface Presenter {
- fun bind(view: View)
- fun unbind()
- fun onViewCreated()
- }
-}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/crop_image_view/presenter/SCropImageViewPresenter.kt b/sample/src/main/java/com/canhub/cropper/sample/crop_image_view/presenter/SCropImageViewPresenter.kt
deleted file mode 100644
index 58634338..00000000
--- a/sample/src/main/java/com/canhub/cropper/sample/crop_image_view/presenter/SCropImageViewPresenter.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.canhub.cropper.sample.crop_image_view.presenter
-
-import com.canhub.cropper.CropImageView
-import com.canhub.cropper.sample.crop_image_view.domain.SCropImageViewContract
-import com.canhub.cropper.sample.options_dialog.domain.SOptionsDomain
-
-internal class SCropImageViewPresenter : SCropImageViewContract.Presenter {
-
- private var view: SCropImageViewContract.View? = null
-
- override fun bind(view: SCropImageViewContract.View) {
- this.view = view
- }
-
- override fun unbind() {
- view = null
- }
-
- override fun onViewCreated() {
- view?.setOptions(getOptions())
- }
-
- private fun getOptions(): SOptionsDomain = SOptionsDomain(
- CropImageView.ScaleType.FIT_CENTER,
- CropImageView.CropShape.RECTANGLE,
- CropImageView.CropCornerShape.RECTANGLE,
- CropImageView.Guidelines.ON,
- Pair(1, 1),
- autoZoom = true,
- maxZoomLvl = 2,
- multiTouch = true,
- centerMove = true,
- showCropOverlay = true,
- showProgressBar = true,
- flipHorizontal = false,
- flipVertically = false
- )
-}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/extend_activity/domain/SExtendContract.kt b/sample/src/main/java/com/canhub/cropper/sample/extend_activity/domain/SExtendContract.kt
deleted file mode 100644
index 3079194f..00000000
--- a/sample/src/main/java/com/canhub/cropper/sample/extend_activity/domain/SExtendContract.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.canhub.cropper.sample.extend_activity.domain
-
-internal interface SExtendContract {
- interface View {
- fun updateRotationCounter(counter: String)
- fun rotate(counter: Int)
- }
-
- interface Presenter {
- fun bindView(view: View)
- fun unbindView()
- fun onRotateClick()
- }
-}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/extend_activity/presenter/SExtendPresenter.kt b/sample/src/main/java/com/canhub/cropper/sample/extend_activity/presenter/SExtendPresenter.kt
deleted file mode 100644
index 73c77acc..00000000
--- a/sample/src/main/java/com/canhub/cropper/sample/extend_activity/presenter/SExtendPresenter.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.canhub.cropper.sample.extend_activity.presenter
-
-import com.canhub.cropper.sample.extend_activity.domain.SExtendContract
-
-internal class SExtendPresenter : SExtendContract.Presenter {
-
- private var view: SExtendContract.View? = null
- private var counter = 0
-
- override fun bindView(view: SExtendContract.View) {
- this.view = view
- this.view?.updateRotationCounter(counter.toString())
- }
-
- override fun unbindView() {
- view = null
- }
-
- override fun onRotateClick() {
- counter += 90
- view?.rotate(90)
- if (counter == 360) counter = 0
- view?.updateRotationCounter(counter.toString())
- }
-}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/app/SOptionsDialogBottomSheet.kt b/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsBottomSheet.kt
similarity index 68%
rename from sample/src/main/java/com/canhub/cropper/sample/options_dialog/app/SOptionsDialogBottomSheet.kt
rename to sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsBottomSheet.kt
index 135278e3..08e1cb48 100644
--- a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/app/SOptionsDialogBottomSheet.kt
+++ b/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsBottomSheet.kt
@@ -1,6 +1,5 @@
-package com.canhub.cropper.sample.options_dialog.app
+package com.canhub.cropper.sample.options_dialog
-import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
@@ -8,26 +7,25 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import com.canhub.cropper.CropImageView
-import com.canhub.cropper.sample.options_dialog.domain.SOptionsContract
-import com.canhub.cropper.sample.options_dialog.domain.SOptionsDomain
import com.example.croppersample.databinding.FragmentOptionsBinding
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
-internal class SOptionsDialogBottomSheet : BottomSheetDialogFragment(), SOptionsContract.View {
+internal class SampleOptionsBottomSheet : BottomSheetDialogFragment() {
+
fun interface Listener {
- fun onOptionsApplySelected(options: SOptionsDomain)
+ fun onOptionsApplySelected(options: SampleOptionsEntity)
}
companion object {
fun show(
fragmentManager: FragmentManager,
- options: SOptionsDomain?,
+ options: SampleOptionsEntity?,
listener: Listener
) {
- this.listener = listener
- SOptionsDialogBottomSheet().apply {
+ Companion.listener = listener
+ SampleOptionsBottomSheet().apply {
arguments = Bundle().apply { putParcelable(OPTIONS_KEY, options) }
show(fragmentManager, null)
}
@@ -38,14 +36,8 @@ internal class SOptionsDialogBottomSheet : BottomSheetDialogFragment(), SOptions
private const val OPTIONS_KEY = "OPTIONS_KEY"
}
- private lateinit var presenter: SOptionsContract.Presenter
private lateinit var binding: FragmentOptionsBinding
-
- override fun onAttach(context: Context) {
- super.onAttach(context)
- val serviceLocator = SOptionsServiceLocator(context)
- presenter = serviceLocator.getPresenter()
- }
+ private lateinit var options: SampleOptionsEntity
override fun onCreateView(
inflater: LayoutInflater,
@@ -56,19 +48,96 @@ internal class SOptionsDialogBottomSheet : BottomSheetDialogFragment(), SOptions
return binding.root
}
- override fun onDismiss(dialog: DialogInterface) {
- presenter.onDismiss()
- super.onDismiss(dialog)
- }
-
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- presenter.bind(this)
- val options = arguments?.getParcelable(OPTIONS_KEY)
+ options = arguments?.getParcelable(OPTIONS_KEY) ?: defaultOptions
+ updateOptions(options)
- presenter.onViewCreated(options)
+ bindingActions()
+ }
+ private fun updateOptions(options: SampleOptionsEntity) {
+ when (options.scaleType) {
+ CropImageView.ScaleType.CENTER -> binding.scaleType.chipCenter.isChecked = true
+ CropImageView.ScaleType.FIT_CENTER -> binding.scaleType.chipFitCenter.isChecked = true
+ CropImageView.ScaleType.CENTER_INSIDE ->
+ binding.scaleType.chipCenterInside.isChecked = true
+ CropImageView.ScaleType.CENTER_CROP -> binding.scaleType.chipCenterCrop.isChecked = true
+ }
+ when (options.cornerShape) {
+ CropImageView.CropCornerShape.RECTANGLE ->
+ binding.cornerShape.chipRectangle.isChecked =
+ true
+ CropImageView.CropCornerShape.OVAL -> binding.cornerShape.chipOval.isChecked = true
+ }
+
+ when (options.cropShape) {
+ CropImageView.CropShape.RECTANGLE -> {
+ binding.cropShape.chipRectangle.isChecked = true
+ // Enabling the corner shape selection functionality only for Rectangle shape cropper for now
+ // To expose to other crop shape, we will need to for necessary changes in CropOverlay class
+ binding.cornerShape.root.visibility = View.VISIBLE
+ }
+ CropImageView.CropShape.OVAL -> {
+ binding.cropShape.chipOval.isChecked = true
+ }
+ CropImageView.CropShape.RECTANGLE_VERTICAL_ONLY ->
+ binding.cropShape.chipRectangleVerticalOnly.isChecked = true
+ CropImageView.CropShape.RECTANGLE_HORIZONTAL_ONLY ->
+ binding.cropShape.chipRectangleHorizontalOnly.isChecked = true
+ }
+
+ when (options.guidelines) {
+ CropImageView.Guidelines.OFF -> binding.guidelines.chipOff.isChecked = true
+ CropImageView.Guidelines.ON -> binding.guidelines.chipOn.isChecked = true
+ CropImageView.Guidelines.ON_TOUCH -> binding.guidelines.chipOnTouch.isChecked = true
+ }
+
+ when (options.ratio) {
+ Pair(1, 1) -> binding.ratio.chipOneOne.isChecked = true
+ Pair(4, 3) -> binding.ratio.chipFourThree.isChecked = true
+ Pair(16, 9) -> binding.ratio.chipSixteenNine.isChecked = true
+ else -> binding.ratio.chipFree.isChecked = true
+ }
+
+ when (options.maxZoomLvl) {
+ 4 -> binding.maxZoom.chipFour.isChecked = true
+ 8 -> binding.maxZoom.chipEight.isChecked = true
+ else -> binding.maxZoom.chipTwo.isChecked = true
+ }
+
+ binding.autoZoom.toggle.isChecked = options.autoZoom
+ binding.multiTouch.toggle.isChecked = options.multiTouch
+ binding.centerMoveEnabled.toggle.isChecked = options.centerMove
+ binding.cropOverlay.toggle.isChecked = options.showCropOverlay
+ binding.progressBar.toggle.isChecked = options.showProgressBar
+ binding.flipHorizontal.toggle.isChecked = options.flipHorizontal
+ binding.flipVertical.toggle.isChecked = options.flipVertically
+ }
+
+ override fun onDismiss(dialog: DialogInterface) {
+ listener.onOptionsApplySelected(options)
+ super.onDismiss(dialog)
+ }
+
+ private val defaultOptions = SampleOptionsEntity(
+ scaleType = CropImageView.ScaleType.FIT_CENTER,
+ cropShape = CropImageView.CropShape.RECTANGLE,
+ cornerShape = CropImageView.CropCornerShape.RECTANGLE,
+ guidelines = CropImageView.Guidelines.ON,
+ ratio = Pair(1, 1),
+ maxZoomLvl = 2,
+ autoZoom = true,
+ multiTouch = true,
+ centerMove = true,
+ showCropOverlay = true,
+ showProgressBar = true,
+ flipHorizontal = false,
+ flipVertically = false
+ )
+
+ private fun bindingActions() {
binding.optionsHeader.isSelected = false
binding.optionsItemsScroll.setOnScrollChangeListener { _, _, _, _, _ ->
binding.optionsHeader.isSelected =
@@ -76,180 +145,113 @@ internal class SOptionsDialogBottomSheet : BottomSheetDialogFragment(), SOptions
}
binding.scaleType.chipCenter.setOnClickListener {
- presenter.onScaleTypeSelect(CropImageView.ScaleType.CENTER)
+ options = options.copy(scaleType = CropImageView.ScaleType.CENTER)
}
binding.scaleType.chipCenterCrop.setOnClickListener {
- presenter.onScaleTypeSelect(CropImageView.ScaleType.CENTER_CROP)
+ options = options.copy(scaleType = CropImageView.ScaleType.CENTER_CROP)
}
binding.scaleType.chipCenterInside.setOnClickListener {
- presenter.onScaleTypeSelect(CropImageView.ScaleType.CENTER_INSIDE)
+ options = options.copy(scaleType = CropImageView.ScaleType.CENTER_INSIDE)
}
binding.scaleType.chipFitCenter.setOnClickListener {
- presenter.onScaleTypeSelect(CropImageView.ScaleType.FIT_CENTER)
+ options = options.copy(scaleType = CropImageView.ScaleType.FIT_CENTER)
}
binding.cropShape.chipRectangle.setOnClickListener {
- presenter.onCropShapeSelect(CropImageView.CropShape.RECTANGLE)
+ options = options.copy(cropShape = CropImageView.CropShape.RECTANGLE)
binding.cornerShape.root.visibility = View.VISIBLE
}
binding.cropShape.chipOval.setOnClickListener {
- presenter.onCropShapeSelect(CropImageView.CropShape.OVAL)
+ options = options.copy(cropShape = CropImageView.CropShape.OVAL)
binding.cornerShape.root.visibility = View.GONE
}
binding.cropShape.chipRectangleVerticalOnly.setOnClickListener {
- presenter.onCropShapeSelect(CropImageView.CropShape.RECTANGLE_VERTICAL_ONLY)
+ options = options.copy(cropShape = CropImageView.CropShape.RECTANGLE_VERTICAL_ONLY)
binding.cornerShape.root.visibility = View.GONE
}
binding.cropShape.chipRectangleHorizontalOnly.setOnClickListener {
- presenter.onCropShapeSelect(CropImageView.CropShape.RECTANGLE_HORIZONTAL_ONLY)
+ options = options.copy(cropShape = CropImageView.CropShape.RECTANGLE_HORIZONTAL_ONLY)
binding.cornerShape.root.visibility = View.GONE
}
binding.cornerShape.chipRectangle.setOnClickListener {
- presenter.onCropCornerShapeSelect(CropImageView.CropCornerShape.RECTANGLE)
+ options = options.copy(cornerShape = CropImageView.CropCornerShape.RECTANGLE)
}
binding.cornerShape.chipOval.setOnClickListener {
- presenter.onCropCornerShapeSelect(CropImageView.CropCornerShape.OVAL)
+ options = options.copy(cornerShape = CropImageView.CropCornerShape.OVAL)
}
binding.guidelines.chipOff.setOnClickListener {
- presenter.onGuidelinesSelect(CropImageView.Guidelines.OFF)
+ options = options.copy(guidelines = CropImageView.Guidelines.OFF)
}
binding.guidelines.chipOn.setOnClickListener {
- presenter.onGuidelinesSelect(CropImageView.Guidelines.ON)
+ options = options.copy(guidelines = CropImageView.Guidelines.ON)
}
binding.guidelines.chipOnTouch.setOnClickListener {
- presenter.onGuidelinesSelect(CropImageView.Guidelines.ON_TOUCH)
+ options = options.copy(guidelines = CropImageView.Guidelines.ON_TOUCH)
}
binding.ratio.chipFree.setOnClickListener {
- presenter.onRatioSelect(null)
+ options = options.copy(ratio = null)
}
binding.ratio.chipOneOne.setOnClickListener {
- presenter.onRatioSelect(Pair(1, 1))
+ options = options.copy(ratio = Pair(1, 1))
}
binding.ratio.chipFourThree.setOnClickListener {
- presenter.onRatioSelect(Pair(16, 9))
+ options = options.copy(ratio = Pair(16, 9))
}
binding.ratio.chipSixteenNine.setOnClickListener {
- presenter.onRatioSelect(Pair(9, 16))
+ options = options.copy(ratio = Pair(9, 16))
}
binding.maxZoom.chipTwo.setOnClickListener {
- presenter.onMaxZoomLvlSelect(2)
+ options = options.copy(maxZoomLvl = 2)
}
binding.maxZoom.chipFour.setOnClickListener {
- presenter.onMaxZoomLvlSelect(4)
+ options = options.copy(maxZoomLvl = 4)
}
binding.maxZoom.chipEight.setOnClickListener {
- presenter.onMaxZoomLvlSelect(8)
+ options = options.copy(maxZoomLvl = 8)
}
binding.autoZoom.toggle.setOnCheckedChangeListener { _, isChecked ->
- presenter.onAutoZoomSelect(isChecked)
+ options = options.copy(autoZoom = isChecked)
}
binding.cropOverlay.toggle.setOnCheckedChangeListener { _, isChecked ->
- presenter.onCropOverlaySelect(isChecked)
+ options = options.copy(showCropOverlay = isChecked)
}
binding.flipHorizontal.toggle.setOnCheckedChangeListener { _, isChecked ->
- presenter.onFlipHorizontalSelect(isChecked)
+ options = options.copy(flipHorizontal = isChecked)
}
binding.flipVertical.toggle.setOnCheckedChangeListener { _, isChecked ->
- presenter.onFlipVerticallySelect(isChecked)
+ options = options.copy(flipVertically = isChecked)
}
binding.multiTouch.toggle.setOnCheckedChangeListener { _, isChecked ->
- presenter.onMultiTouchSelect(isChecked)
+ options = options.copy(multiTouch = isChecked)
}
binding.centerMoveEnabled.toggle.setOnCheckedChangeListener { _, isChecked ->
- presenter.onCenterMoveSelect(isChecked)
+ options = options.copy(centerMove = isChecked)
}
binding.progressBar.toggle.setOnCheckedChangeListener { _, isChecked ->
- presenter.onProgressBarSelect(isChecked)
- }
- }
-
- override fun updateOptions(options: SOptionsDomain) {
-
- when (options.scaleType) {
- CropImageView.ScaleType.CENTER -> binding.scaleType.chipCenter.isChecked = true
- CropImageView.ScaleType.FIT_CENTER -> binding.scaleType.chipFitCenter.isChecked = true
- CropImageView.ScaleType.CENTER_INSIDE ->
- binding.scaleType.chipCenterInside.isChecked = true
- CropImageView.ScaleType.CENTER_CROP -> binding.scaleType.chipCenterCrop.isChecked = true
- }
- when (options.cornerShape) {
- CropImageView.CropCornerShape.RECTANGLE -> binding.cornerShape.chipRectangle.isChecked = true
- CropImageView.CropCornerShape.OVAL -> binding.cornerShape.chipOval.isChecked = true
- }
-
- when (options.cropShape) {
- CropImageView.CropShape.RECTANGLE -> {
- binding.cropShape.chipRectangle.isChecked = true
- // Enabling the corner shape selection functionality only for Rectangle shape cropper for now
- // To expose to other crop shape, we will need to for necessary changes in CropOverlay class
- binding.cornerShape.root.visibility = View.VISIBLE
- }
- CropImageView.CropShape.OVAL -> {
- binding.cropShape.chipOval.isChecked = true
- }
- CropImageView.CropShape.RECTANGLE_VERTICAL_ONLY ->
- binding.cropShape.chipRectangleVerticalOnly.isChecked = true
- CropImageView.CropShape.RECTANGLE_HORIZONTAL_ONLY ->
- binding.cropShape.chipRectangleHorizontalOnly.isChecked = true
+ options = options.copy(showProgressBar = isChecked)
}
-
- when (options.guidelines) {
- CropImageView.Guidelines.OFF -> binding.guidelines.chipOff.isChecked = true
- CropImageView.Guidelines.ON -> binding.guidelines.chipOn.isChecked = true
- CropImageView.Guidelines.ON_TOUCH -> binding.guidelines.chipOnTouch.isChecked = true
- }
-
- when (options.ratio) {
- Pair(1, 1) -> binding.ratio.chipOneOne.isChecked = true
- Pair(4, 3) -> binding.ratio.chipFourThree.isChecked = true
- Pair(16, 9) -> binding.ratio.chipSixteenNine.isChecked = true
- else -> binding.ratio.chipFree.isChecked = true
- }
-
- when (options.maxZoomLvl) {
- 4 -> binding.maxZoom.chipFour.isChecked = true
- 8 -> binding.maxZoom.chipEight.isChecked = true
- else -> binding.maxZoom.chipTwo.isChecked = true
- }
-
- binding.autoZoom.toggle.isChecked = options.autoZoom
- binding.multiTouch.toggle.isChecked = options.multiTouch
- binding.centerMoveEnabled.toggle.isChecked = options.centerMove
- binding.cropOverlay.toggle.isChecked = options.showCropOverlay
- binding.progressBar.toggle.isChecked = options.showProgressBar
- binding.flipHorizontal.toggle.isChecked = options.flipHorizontal
- binding.flipVertical.toggle.isChecked = options.flipVertically
- }
-
- override fun closeWithResult(options: SOptionsDomain) {
- listener.onOptionsApplySelected(options)
- }
-
- override fun onDestroy() {
- presenter.unbind()
- super.onDestroy()
}
}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/domain/SOptionsDomain.kt b/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsEntity.kt
similarity index 87%
rename from sample/src/main/java/com/canhub/cropper/sample/options_dialog/domain/SOptionsDomain.kt
rename to sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsEntity.kt
index 38b0ffb8..cdc538a7 100644
--- a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/domain/SOptionsDomain.kt
+++ b/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsEntity.kt
@@ -1,4 +1,4 @@
-package com.canhub.cropper.sample.options_dialog.domain
+package com.canhub.cropper.sample.options_dialog
import android.os.Parcelable
import com.canhub.cropper.CropImageView
@@ -6,7 +6,7 @@ import kotlinx.parcelize.Parcelize
import kotlinx.parcelize.RawValue
@Parcelize
-internal data class SOptionsDomain(
+internal data class SampleOptionsEntity(
val scaleType: CropImageView.ScaleType,
val cropShape: CropImageView.CropShape,
val cornerShape: CropImageView.CropCornerShape,
diff --git a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/app/SOptionsServiceLocator.kt b/sample/src/main/java/com/canhub/cropper/sample/options_dialog/app/SOptionsServiceLocator.kt
deleted file mode 100644
index 152f526e..00000000
--- a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/app/SOptionsServiceLocator.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.canhub.cropper.sample.options_dialog.app
-
-import android.content.Context
-import com.canhub.cropper.sample.options_dialog.domain.SOptionsContract
-import com.canhub.cropper.sample.options_dialog.presenter.SOptionsPresenter
-
-internal class SOptionsServiceLocator(private val context: Context) {
-
- fun getPresenter(): SOptionsContract.Presenter = SOptionsPresenter()
-}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/domain/SOptionsContract.kt b/sample/src/main/java/com/canhub/cropper/sample/options_dialog/domain/SOptionsContract.kt
deleted file mode 100644
index 2f952f07..00000000
--- a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/domain/SOptionsContract.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.canhub.cropper.sample.options_dialog.domain
-
-import com.canhub.cropper.CropImageView
-import com.canhub.cropper.CropImageView.CropShape
-import com.canhub.cropper.CropImageView.Guidelines
-import com.canhub.cropper.CropImageView.ScaleType
-
-internal interface SOptionsContract {
-
- interface View {
- fun updateOptions(options: SOptionsDomain)
- fun closeWithResult(options: SOptionsDomain)
- }
-
- interface Presenter {
- fun bind(view: View)
- fun unbind()
- fun onViewCreated(options: SOptionsDomain?)
- fun onDismiss()
- fun onScaleTypeSelect(scaleType: ScaleType)
- fun onCropShapeSelect(cropShape: CropShape)
- fun onCropCornerShapeSelect(cornerShape: CropImageView.CropCornerShape)
- fun onGuidelinesSelect(guidelines: Guidelines)
- fun onRatioSelect(ratio: Pair?)
- fun onAutoZoomSelect(enable: Boolean)
- fun onMaxZoomLvlSelect(maxZoom: Int)
- fun onMultiTouchSelect(enable: Boolean)
- fun onCenterMoveSelect(enable: Boolean)
- fun onCropOverlaySelect(show: Boolean)
- fun onProgressBarSelect(show: Boolean)
- fun onFlipHorizontalSelect(enable: Boolean)
- fun onFlipVerticallySelect(enable: Boolean)
- }
-}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/presenter/SOptionsPresenter.kt b/sample/src/main/java/com/canhub/cropper/sample/options_dialog/presenter/SOptionsPresenter.kt
deleted file mode 100644
index 94e36878..00000000
--- a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/presenter/SOptionsPresenter.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.canhub.cropper.sample.options_dialog.presenter
-
-import com.canhub.cropper.CropImageView
-import com.canhub.cropper.sample.options_dialog.domain.SOptionsContract
-import com.canhub.cropper.sample.options_dialog.domain.SOptionsDomain
-
-internal class SOptionsPresenter : SOptionsContract.Presenter {
-
- private var view: SOptionsContract.View? = null
- private var options = defaultOptions()
-
- override fun bind(view: SOptionsContract.View) {
- this.view = view
- }
-
- override fun unbind() {
- view = null
- }
-
- override fun onViewCreated(options: SOptionsDomain?) {
- options?.let { this.options = options }
- view?.updateOptions(this.options)
- }
-
- override fun onDismiss() {
- view?.closeWithResult(options)
- }
-
- override fun onScaleTypeSelect(scaleType: CropImageView.ScaleType) {
- options = options.copy(scaleType = scaleType)
- }
-
- override fun onCropShapeSelect(cropShape: CropImageView.CropShape) {
- options = options.copy(cropShape = cropShape)
- }
-
- override fun onGuidelinesSelect(guidelines: CropImageView.Guidelines) {
- options = options.copy(guidelines = guidelines)
- }
-
- override fun onRatioSelect(ratio: Pair?) {
- options = options.copy(ratio = ratio)
- }
-
- override fun onAutoZoomSelect(enable: Boolean) {
- options = options.copy(autoZoom = enable)
- }
-
- override fun onMaxZoomLvlSelect(maxZoom: Int) {
- options = options.copy(maxZoomLvl = maxZoom)
- }
-
- override fun onMultiTouchSelect(enable: Boolean) {
- options = options.copy(multiTouch = enable)
- }
-
- override fun onCenterMoveSelect(enable: Boolean) {
- options = options.copy(centerMove = enable)
- }
-
- override fun onCropOverlaySelect(show: Boolean) {
- options = options.copy(showCropOverlay = show)
- }
-
- override fun onProgressBarSelect(show: Boolean) {
- options = options.copy(showProgressBar = show)
- }
-
- override fun onFlipHorizontalSelect(enable: Boolean) {
- options = options.copy(flipHorizontal = enable)
- }
-
- override fun onFlipVerticallySelect(enable: Boolean) {
- options = options.copy(flipVertically = enable)
- }
- override fun onCropCornerShapeSelect(cornerShape: CropImageView.CropCornerShape) {
- options = options.copy(cornerShape = cornerShape)
- }
-
- private fun defaultOptions() = SOptionsDomain(
- CropImageView.ScaleType.FIT_CENTER,
- CropImageView.CropShape.RECTANGLE,
- CropImageView.CropCornerShape.RECTANGLE,
- CropImageView.Guidelines.ON,
- Pair(1, 1),
- maxZoomLvl = 2,
- autoZoom = true,
- multiTouch = true,
- centerMove = true,
- showCropOverlay = true,
- showProgressBar = true,
- flipHorizontal = false,
- flipVertically = false
- )
-}
diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml
index fa84ca47..3d2018b7 100644
--- a/sample/src/main/res/layout/activity_main.xml
+++ b/sample/src/main/res/layout/activity_main.xml
@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context="com.canhub.cropper.sample.SMainActivity">
+ tools:context="com.canhub.cropper.sample.MainActivity">
-
From 8efd2381e5002168dea822f1e751e1302c23f16e Mon Sep 17 00:00:00 2001
From: Canato
Date: Tue, 10 May 2022 11:50:51 +0100
Subject: [PATCH 4/9] Refactor documentation (#362)
* Extract java information
* Extract crop view
* Extract custom activity
* Extract FAQ
* Extract features
* Move art folder to documentation
---
.documentation/FAQ.md | 30 ++++
.../art}/activity visual customization.png | Bin
.../art}/async-crop-figure-1.png | Bin
.../art}/async-crop-figure-2.png | Bin
.../canhub_logo_horizontal_transparent.png | Bin
{art => .documentation/art}/crop.jpg | Bin
{art => .documentation/art}/demo.gif | Bin
.../art}/non-straight cropping.png | Bin
{art => .documentation/art}/pick image.gif | Bin
{art => .documentation/art}/read_package.png | Bin
.../art}/visual customization.png | Bin
.../art}/zoom sample small 2.gif | Bin
.../art}/zoom sample small 3.gif | Bin
.../art}/zoom sample small.gif | Bin
{art => .documentation/art}/zoom sample.gif | Bin
.documentation/crop_view.md | 27 ++++
.documentation/custom_activity.md | 26 ++++
.documentation/features.md | 76 +++++++++++
.documentation/java_usage.md | 5 +
README.md | 128 +++---------------
20 files changed, 184 insertions(+), 108 deletions(-)
create mode 100644 .documentation/FAQ.md
rename {art => .documentation/art}/activity visual customization.png (100%)
rename {art => .documentation/art}/async-crop-figure-1.png (100%)
rename {art => .documentation/art}/async-crop-figure-2.png (100%)
rename {art => .documentation/art}/canhub_logo_horizontal_transparent.png (100%)
rename {art => .documentation/art}/crop.jpg (100%)
rename {art => .documentation/art}/demo.gif (100%)
rename {art => .documentation/art}/non-straight cropping.png (100%)
rename {art => .documentation/art}/pick image.gif (100%)
rename {art => .documentation/art}/read_package.png (100%)
rename {art => .documentation/art}/visual customization.png (100%)
rename {art => .documentation/art}/zoom sample small 2.gif (100%)
rename {art => .documentation/art}/zoom sample small 3.gif (100%)
rename {art => .documentation/art}/zoom sample small.gif (100%)
rename {art => .documentation/art}/zoom sample.gif (100%)
create mode 100644 .documentation/crop_view.md
create mode 100644 .documentation/custom_activity.md
create mode 100644 .documentation/features.md
create mode 100644 .documentation/java_usage.md
diff --git a/.documentation/FAQ.md b/.documentation/FAQ.md
new file mode 100644
index 00000000..2b03bf08
--- /dev/null
+++ b/.documentation/FAQ.md
@@ -0,0 +1,30 @@
+# Frequently Asked Questions
+
+## Can't see the crop button. So, can't crop the image.
+Does your app theme has no action bar? If yes, you should add this to your manifest
+```kt
+
+```
+
+## Can I use this library in Java project?
+Yes! Check [Using the library in Java](
+.documentation/java_usage.md)
+
+## Bad class file error : class file has wrong version xx.0, should be yy.0
+It means your Java runtime version is different from your compiler version (javac).
+To simply solve it, just advance your JVM version to 11
+
+- Select "File" -> "Project Structure".
+- Under "Project Settings" select "Project"
+- From there you can select the "Project SDK".
+- But if you don't want to change the Java runtime version, then do the following steps:
+`JAVA_HOME= "your jdk v11 folder path", to make sure jdk is also v11 and use java -version and javac -version again to ensure it`
+
+[more information](https://stackoverflow.com/a/4692743/3117650)
+
+## Why Java 11 is needed since version 3.3.4?
+We update to Java 11 so we could update Gradle.
+And is always good to keep the most updated versions available.
+Those who do not update, keep using old versions of the library, but those who update can get the benefits of the latest versions.
+
diff --git a/art/activity visual customization.png b/.documentation/art/activity visual customization.png
similarity index 100%
rename from art/activity visual customization.png
rename to .documentation/art/activity visual customization.png
diff --git a/art/async-crop-figure-1.png b/.documentation/art/async-crop-figure-1.png
similarity index 100%
rename from art/async-crop-figure-1.png
rename to .documentation/art/async-crop-figure-1.png
diff --git a/art/async-crop-figure-2.png b/.documentation/art/async-crop-figure-2.png
similarity index 100%
rename from art/async-crop-figure-2.png
rename to .documentation/art/async-crop-figure-2.png
diff --git a/art/canhub_logo_horizontal_transparent.png b/.documentation/art/canhub_logo_horizontal_transparent.png
similarity index 100%
rename from art/canhub_logo_horizontal_transparent.png
rename to .documentation/art/canhub_logo_horizontal_transparent.png
diff --git a/art/crop.jpg b/.documentation/art/crop.jpg
similarity index 100%
rename from art/crop.jpg
rename to .documentation/art/crop.jpg
diff --git a/art/demo.gif b/.documentation/art/demo.gif
similarity index 100%
rename from art/demo.gif
rename to .documentation/art/demo.gif
diff --git a/art/non-straight cropping.png b/.documentation/art/non-straight cropping.png
similarity index 100%
rename from art/non-straight cropping.png
rename to .documentation/art/non-straight cropping.png
diff --git a/art/pick image.gif b/.documentation/art/pick image.gif
similarity index 100%
rename from art/pick image.gif
rename to .documentation/art/pick image.gif
diff --git a/art/read_package.png b/.documentation/art/read_package.png
similarity index 100%
rename from art/read_package.png
rename to .documentation/art/read_package.png
diff --git a/art/visual customization.png b/.documentation/art/visual customization.png
similarity index 100%
rename from art/visual customization.png
rename to .documentation/art/visual customization.png
diff --git a/art/zoom sample small 2.gif b/.documentation/art/zoom sample small 2.gif
similarity index 100%
rename from art/zoom sample small 2.gif
rename to .documentation/art/zoom sample small 2.gif
diff --git a/art/zoom sample small 3.gif b/.documentation/art/zoom sample small 3.gif
similarity index 100%
rename from art/zoom sample small 3.gif
rename to .documentation/art/zoom sample small 3.gif
diff --git a/art/zoom sample small.gif b/.documentation/art/zoom sample small.gif
similarity index 100%
rename from art/zoom sample small.gif
rename to .documentation/art/zoom sample small.gif
diff --git a/art/zoom sample.gif b/.documentation/art/zoom sample.gif
similarity index 100%
rename from art/zoom sample.gif
rename to .documentation/art/zoom sample.gif
diff --git a/.documentation/crop_view.md b/.documentation/crop_view.md
new file mode 100644
index 00000000..9a378c37
--- /dev/null
+++ b/.documentation/crop_view.md
@@ -0,0 +1,27 @@
+## Using CropView
+[Sample code](https://github.com/CanHub/Android-Image-Cropper/tree/main/sample/src/main/java/com/canhub/cropper/sample/SampleUsingImageView.kt)
+
+1. Add `CropImageView` into your activity
+ ```xml
+
+
+ ```
+
+2. Set image to crop
+ ```kotlin
+ cropImageView.setImageUriAsync(uri)
+ // or (prefer using uri for performance and better user experience)
+ cropImageView.setImageBitmap(bitmap)
+ ```
+
+3. Get cropped image
+ ```kotlin
+ // subscribe to async event using cropImageView.setOnCropImageCompleteListener(listener)
+ cropImageView.getCroppedImageAsync()
+ // or
+ val cropped: Bitmap = cropImageView.getCroppedImage()
+ ```
diff --git a/.documentation/custom_activity.md b/.documentation/custom_activity.md
new file mode 100644
index 00000000..47d13cfa
--- /dev/null
+++ b/.documentation/custom_activity.md
@@ -0,0 +1,26 @@
+## Extend to make a custom activity
+[Sample code](https://github.com/CanHub/Android-Image-Cropper/tree/main/sample/src/main/java/com/canhub/cropper/sample/SampleCustomActivity.kt)
+
+If you want to extend the `CropImageActivity` please be aware you will need to setup your `CropImageView`
+
+- Add `CropImageActivity` into your AndroidManifest.xml
+ ```xml
+
+ ```
+- Setup your `CropImageView` after call `super.onCreate(savedInstanceState)`
+ ```kotlin
+override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setCropImageView(binding.cropImageView)
+}
+ ```
+
+### Custom dialog for image source pick
+When calling crop directly the library will prompt a dialog for the user choose between gallery or camera (If you keep both enable).
+We use the Android default AlertDialog for this. If you wanna customised it with your app theme you need to override the method `showImageSourceDialog(..)` when extending the activity _(above)_
+```kotlin
+override fun showImageSourceDialog(openSource: (Source) -> Unit) {
+ super.showImageSourceDialog(openCamera)
+}
+```
\ No newline at end of file
diff --git a/.documentation/features.md b/.documentation/features.md
new file mode 100644
index 00000000..cf300158
--- /dev/null
+++ b/.documentation/features.md
@@ -0,0 +1,76 @@
+# Features
+
+## Optional initial URI
+Crop library can be called with or without image uri
+```kt
+cropImage.launch(
+ options(outputUri) { ... }
+)
+//OR
+cropImage.launch(
+ options { ... }
+)
+```
+
+## Image source
+```kt
+cropImage.launch(
+ options {
+ setImageSource(
+ includeGallery = true,
+ includeCamera = true,
+ )
+ }
+)
+```
+
+### List of options
+```kt
+cropImage.launch(
+ options {
+ setScaleType(CropImageView.ScaleType.FIT_CENTER)
+ setCropShape(CropImageView.CropShape.RECTANGLE)
+ setGuidelines(CropImageView.Guidelines.ON_TOUCH)
+ setAspectRatio(1, 1)
+ setMaxZoom(4)
+ setAutoZoomEnabled(true)
+ setMultiTouchEnabled(true)
+ setCenterMoveEnabled(true)
+ setShowCropOverlay(true)
+ setAllowFlipping(true)
+ setSnapRadius(3f)
+ setTouchRadius(48f)
+ setInitialCropWindowPaddingRatio(0.1f)
+ setBorderLineThickness(3f)
+ setBorderLineColor(Color.argb(170, 255, 255, 255))
+ setBorderCornerThickness(2f)
+ setBorderCornerOffset(5f)
+ setBorderCornerLength(14f)
+ setBorderCornerColor(WHITE)
+ setGuidelinesThickness(1f)
+ setGuidelinesColor(R.color.white)
+ setBackgroundColor(Color.argb(119, 0, 0, 0))
+ setMinCropWindowSize(24, 24)
+ setMinCropResultSize(20, 20)
+ setMaxCropResultSize(99999, 99999)
+ setActivityTitle("")
+ setActivityMenuIconColor(0)
+ setOutputUri(outputUri)
+ setOutputCompressFormat(Bitmap.CompressFormat.JPEG)
+ setOutputCompressQuality(90)
+ setRequestedSize(0, 0)
+ setRequestedSize(0, 0, CropImageView.RequestSizeOptions.RESIZE_INSIDE)
+ setInitialCropWindowRectangle(null)
+ setInitialRotation(0)
+ setAllowCounterRotation(false)
+ setFlipHorizontally(false)
+ setFlipVertically(false)
+ setCropMenuCropButtonTitle(null)
+ setCropMenuCropButtonIcon(0)
+ setAllowRotation(true)
+ setNoOutputImage(false)
+ setFixAspectRatio(false)
+ setIntentChooserPriorityList(listOf("com.miui.gallery", "com.google.android.apps.photos"))
+ }
+)
+```
\ No newline at end of file
diff --git a/.documentation/java_usage.md b/.documentation/java_usage.md
new file mode 100644
index 00000000..6f8fb97b
--- /dev/null
+++ b/.documentation/java_usage.md
@@ -0,0 +1,5 @@
+- [Java Sample Code](https://github.com/CanHub/Android-Image-Cropper/tree/main/sample/src/main/java/com/canhub/cropper/sample/SampleCropJava.java)
+
+Still stuck? Try This Discussion here to a **Plug and Play** Solution to get you started.
+
+- [🚨 Calling an Activity Directly To Handle this using Java](https://github.com/CanHub/Android-Image-Cropper/discussions/236)
diff --git a/README.md b/README.md
index cb2f9c40..67d033d4 100644
--- a/README.md
+++ b/README.md
@@ -1,33 +1,22 @@
-[](https://github.com/canhub)
+[](https://github.com/canhub)
[](https://jitpack.io/#CanHub/Android-Image-Cropper)
-[🚨How to migrate from ArthurHub/Android-Image-Cropper🚨](https://github.com/CanHub/Android-Image-Cropper/wiki/🚨-How-to-migrate-Android-Image-Cropper--🚨)
-
-[Java Sample Code](https://github.com/CanHub/Android-Image-Cropper/tree/main/sample/src/main/java/com/canhub/cropper/sample/crop_image_java)
-
-Still stuck? Try This Discussion here to a **Plug and Play** Solution to get you started.
-
-[🚨 Calling an Activity Directly To Handle this using Java](https://github.com/CanHub/Android-Image-Cropper/discussions/236)
-
-Wanna help the project? Amazing!
-- [Contributing Guide](https://github.com/CanHub/Android-Image-Cropper/blob/main/CONTRIBUTING.md)
+☕ [Using the library in Java](.documentation/java_usage.md)
Android Image Cropper
=======
-**Powerful** (Zoom, Rotation, Multi-Source);
-**Customizable** (Shape, Limits, Style);
-**Optimized** (Async, Sampling, Matrix);
-**Simple** image cropping library for Android.
+- **Powerful** (Zoom, Rotation, Multi-Source);
+- **Customizable** (Shape, Limits, Style);
+- **Optimized** (Async, Sampling, Matrix);
+- **Simple** image cropping library for Android.
-
+[Features List](.documentation/features.md)
-# Add to your project
-
-[See GitHub Wiki for more info.](https://github.com/CanHub/Android-Image-Cropper/wiki)
+
+# Add to your project
### Step 1. Add the JitPack repository to your root build.gradle
-
```gradle
allprojects {
repositories {
@@ -38,7 +27,6 @@ Android Image Cropper
```
### Step 2. Add the dependency
-
```gradle
dependencies {
implementation 'com.github.CanHub:Android-Image-Cropper:${version}'
@@ -46,10 +34,8 @@ Android Image Cropper
```
[Latest Release Version](https://github.com/CanHub/Android-Image-Cropper/releases)
-### Step 3. Add permissions to manifest
-
+### Step 3. Add permissions to manifest
Only need if you run on devices under OS10 (SDK 29)
-
```xml
-
- ```
-
-3. Set image to crop
- ```kotlin
- cropImageView.setImageUriAsync(uri)
- // or (prefer using uri for performance and better user experience)
- cropImageView.setImageBitmap(bitmap)
- ```
-
-4. Get cropped image
- ```kotlin
- // subscribe to async event using cropImageView.setOnCropImageCompleteListener(listener)
- cropImageView.getCroppedImageAsync()
- // or
- val cropped: Bitmap = cropImageView.getCroppedImage()
- ```
-
-## Extend to make a custom activity
-If you want to extend the `CropImageActivity` please be aware you will need to setup your `CropImageView`
-You can check a sample code in this project `com.canhub.cropper.sample.extend_activity.app.SExtendActivity`
-
-- Add `CropImageActivity` into your AndroidManifest.xml
- ```xml
-
- ```
-- Setup your `CropImageView` after call `super.onCreate(savedInstanceState)`
- ```kotlin
-override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setCropImageView(binding.cropImageView)
-}
- ```
-
-### Custom dialog for image source pick
-When calling crop directly the library will prompt a dialog for the user choose between gallery or camera (If you keep both enable).
-We use the Android default AlertDialog for this. If you wanna customised it with your app theme you need to override the method `showImageSourceDialog(..)` when extending the activity _(above)_
-```kotlin
-override fun showImageSourceDialog(openSource: (Source) -> Unit) {
- super.showImageSourceDialog(openCamera)
-}
-```
-
-## Features
-- Built-in `CropImageActivity`.
-- Set cropping image as Bitmap, Resource or Android URI (Gallery, Camera, Dropbox, etc.).
-- Image rotation/flipping during cropping.
-- Auto zoom-in/out to relevant cropping area.
-- Auto rotate bitmap by image Exif data.
-- Set result image min/max limits in pixels.
-- Set initial crop window size/location.
-- Request cropped image resize to specific size.
-- Bitmap memory optimization, OOM handling (should never occur)!
-- API Level 14.
-- More..
-
-## Customizations
-- Cropping window shape: Rectangular, Oval (square/circle by fixing aspect ratio), as well as
- rectangular modes which only allow vertical or horizontal cropping.
-- Cropping window aspect ratio: Free, 1:1, 4:3, 16:9 or Custom.
-- Guidelines appearance: Off / Always On / Show on Touch.
-- Cropping window Border line, border corner and guidelines thickness and color.
-- Cropping background color.
-
-For more information, see the [GitHub Wiki](https://github.com/CanHub/Android-Image-Cropper/wiki).
-
## Posts
- - [Android cropping image from camera or gallery](http://theartofdev.com/2015/02/15/android-cropping-image-from-camera-or-gallery/)
- - [Android Image Cropper async support and custom progress UI](http://theartofdev.com/2016/01/15/android-image-cropper-async-support-and-custom-progress-ui/)
- - [Adding auto-zoom feature to Android-Image-Cropper](https://theartofdev.com/2016/04/25/adding-auto-zoom-feature-to-android-image-cropper/)
+ - [Android cropping image from camera or gallery](https://canato.medium.com/android-cropping-image-from-camera-or-gallery-fbe732800b08)
+
+## Wanna help the project? Amazing!
+- [Contributing Guide](https://github.com/CanHub/Android-Image-Cropper/blob/main/CONTRIBUTING.md)
## License
Forked from [ArthurHub](https://github.com/ArthurHub/Android-Image-Cropper)
From aca09d7daffd3b7dc873a866801ab34d75e4ee80 Mon Sep 17 00:00:00 2001
From: LazyDevPro <49026890+lazyDevPro@users.noreply.github.com>
Date: Sat, 14 May 2022 14:00:00 +0530
Subject: [PATCH 5/9] Update java_usage.md (#367)
Added the details, on how to make it work in JAVA
---
.documentation/java_usage.md | 39 ++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/.documentation/java_usage.md b/.documentation/java_usage.md
index 6f8fb97b..3681a30e 100644
--- a/.documentation/java_usage.md
+++ b/.documentation/java_usage.md
@@ -3,3 +3,42 @@
Still stuck? Try This Discussion here to a **Plug and Play** Solution to get you started.
- [🚨 Calling an Activity Directly To Handle this using Java](https://github.com/CanHub/Android-Image-Cropper/discussions/236)
+
+So here are the steps to make the migration work for verison [3.3.6](https://github.com/CanHub/Android-Image-Cropper/releases/tag/3.3.6) or below.
+
+Follow this guide first [🚨 How to migrate Android Image Cropper 🚨](https://github.com/CanHub/Android-Image-Cropper/wiki/%F0%9F%9A%A8-How-to-migrate-Android-Image-Cropper--%F0%9F%9A%A8)
+
+Then follow the following strps to make it work.
+
+Note: You need to use a single kotlin file and also enable kotlin compiler for your project to make it work.
+
+### **Enable Compliler**
+
+goto Tools>Kotlin>Configure kotlin in this project and gradle sync the project
+
+
+
+### **Add Kotlin Code**
+
+Now create a kotlin file _GetUri.kt_
+
+add following code `fun CropImage.ActivityResult?.getUri(): Uri? { return this?.uriContent }`
+
+
+### **Get Result**
+
+then in main `onActivityResult()`
+
+```
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
+ if (resultCode == RESULT_OK) {
+ Uri resultUri = GetUriKt.getUri(CropImage.getActivityResult(data));
+ Log.e(TAG, "onActivityResult: "+resultUri.toString());
+ }
+ }
+ }
+```
+
From 0267b1871d53c93457e008a3a5cde408f8383eb0 Mon Sep 17 00:00:00 2001
From: Johannes Bester
Date: Thu, 19 May 2022 16:12:31 +0200
Subject: [PATCH 6/9] Update FAQ.md (#369)
Updated FAQ.md
---
.documentation/FAQ.md | 54 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/.documentation/FAQ.md b/.documentation/FAQ.md
index 2b03bf08..99e7f16d 100644
--- a/.documentation/FAQ.md
+++ b/.documentation/FAQ.md
@@ -28,3 +28,57 @@ We update to Java 11 so we could update Gradle.
And is always good to keep the most updated versions available.
Those who do not update, keep using old versions of the library, but those who update can get the benefits of the latest versions.
+## Downloading the Cropped image to a file
+**Ref:** [[BUG] - Uri Received lacks 'file' scheme](https://github.com/CanHub/Android-Image-Cropper/issues/368)
+
+If you need to use the cropped Image as a file e.g. send it as a file to back-end server
+You need to re-build the Uri as follow
+
+**With Android/jetpack compose**
+```kotlin
+val imageCropLauncher = rememberLauncherForActivityResult(contract = CropImageContract()) { result ->
+ if (result.isSuccessful) {
+ // use the cropped image
+ resultImageUri = result.uriContent
+ imageFilePath = result.getUriFilePath(context = context, uniqueName = true).toString()
+ if (resultImageUri?.scheme?.contains("content") == true) {
+ // replace Scheme to file
+ val builder = Uri.Builder()
+ builder.scheme("file")
+ .appendPath(imageFilePath)
+ val imageUri = builder.build()
+ // Use the imageUri then to send the file
+ }
+ } else {
+ // an error occurred cropping
+ val exception = result.error
+ Log.e(GLOBAL_TAG, "CropImageContract Exception $exception")
+ }
+}
+```
+**Convert the Uri to File**
+```kotlin
+val file: File = imageUri.toFile()
+```
+**With Retrofit/Okhttp3 you can now send it**
+```kotlin
+val response = postApi.createPost(
+ postData = MultipartBody.Part
+ .createFormData(
+ "post_data",
+ gson.toJson(request)
+ ),
+ postImage = MultipartBody.Part
+ .createFormData(
+ name = "post_image",
+ filename = file.name,
+ body = file.asRequestBody()
+ )
+)
+```
+**Note:**
+be sure to test for Errors/Exceptions along the way!
+Tested on Android Studio Chipmunk | 2021.2.1
+Android API 31 Platform
+android_image_cropper_version = "4.2.1"
+
From 7d2f271fa94d656b820273ce50fdebb10d524ebe Mon Sep 17 00:00:00 2001
From: Canato
Date: Mon, 6 Jun 2022 14:30:44 +0100
Subject: [PATCH 7/9] Add FAQ link to README (#379)
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 67d033d4..4697222e 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
[](https://jitpack.io/#CanHub/Android-Image-Cropper)
☕ [Using the library in Java](.documentation/java_usage.md)
+❓ [FAQ - frequently asked question](.documentation/FAQ.md)
Android Image Cropper
=======
From 19aad12b7ecc99c27b2ce993fb607a64e412fcf9 Mon Sep 17 00:00:00 2001
From: bhagyae5308
Date: Fri, 10 Jun 2022 17:37:02 +0530
Subject: [PATCH 8/9] Pr/cropper text label support (#382)
* Added a helper text on top of crop overlay which moves along with it
* Exposed xml attrs and setter to update the copy text styles
---
CHANGELOG.md | 6 ++
.../cropper/CropImageContractOptions.kt | 5 ++
.../com/canhub/cropper/CropImageOptions.kt | 29 ++++++++
.../java/com/canhub/cropper/CropImageView.kt | 74 ++++++++++++++++++-
.../com/canhub/cropper/CropOverlayView.kt | 71 ++++++++++++++++++
cropper/src/main/res/values/attrs.xml | 4 +
sample/src/main/AndroidManifest.xml | 2 +-
.../cropper/sample/SampleUsingImageView.kt | 4 +-
.../SampleOptionsBottomSheet.kt | 7 +-
.../options_dialog/SampleOptionsEntity.kt | 1 +
.../res/layout/fragment_crop_image_view.xml | 4 +
.../src/main/res/layout/fragment_options.xml | 3 +
.../res/layout/switch_crop_text_label.xml | 19 +++++
sample/src/main/res/values/dimens.xml | 1 +
sample/src/main/res/values/strings.xml | 2 +
15 files changed, 228 insertions(+), 4 deletions(-)
create mode 100644 sample/src/main/res/layout/switch_crop_text_label.xml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 341f0a74..0ed6834b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
### Fixed
- The translation of `Camera` and `Gallery` does not exist in some languages.
+## [unreleased 4.2.2]
+### Added
+- Added a helper text on top of crop overlay which moves along with it. [#381](https://github.com/CanHub/Android-Image-Cropper/issues/381)
+### Fixed
+- Crash on click of Sample of CustomActivity option over sample App, added the missing activity declaration on Manifest.xml
+
## [4.2.1] - 04/04/2022
### Added
- Added support for optionally displaying an intent chooser when selecting image source. [#325](https://github.com/CanHub/Android-Image-Cropper/issues/325)
diff --git a/cropper/src/main/java/com/canhub/cropper/CropImageContractOptions.kt b/cropper/src/main/java/com/canhub/cropper/CropImageContractOptions.kt
index bdddaa7e..babfa250 100644
--- a/cropper/src/main/java/com/canhub/cropper/CropImageContractOptions.kt
+++ b/cropper/src/main/java/com/canhub/cropper/CropImageContractOptions.kt
@@ -127,6 +127,11 @@ data class CropImageContractOptions @JvmOverloads constructor(
return this
}
+ fun setShowCropLabel(showCropLabel: Boolean): CropImageContractOptions {
+ cropImageOptions.showCropLabel = showCropLabel
+ return this
+ }
+
/**
* if auto-zoom functionality is enabled.
* default: true.
diff --git a/cropper/src/main/java/com/canhub/cropper/CropImageOptions.kt b/cropper/src/main/java/com/canhub/cropper/CropImageOptions.kt
index 136c9ccc..081142bc 100644
--- a/cropper/src/main/java/com/canhub/cropper/CropImageOptions.kt
+++ b/cropper/src/main/java/com/canhub/cropper/CropImageOptions.kt
@@ -83,6 +83,12 @@ open class CropImageOptions : Parcelable {
@JvmField
var showCropOverlay: Boolean
+ /**
+ * If enabled, show a text label on top of crop overlay UI, which gets moved along with the cropper
+ */
+ @JvmField
+ var showCropLabel: Boolean
+
/**
* if to show progress bar when image async loading/cropping is in progress.
* default: true, disable to provide custom progress bar UI.
@@ -311,6 +317,18 @@ open class CropImageOptions : Parcelable {
@JvmField
var intentChooserPriorityList: List?
+ /** The initial text size of cropper label **/
+ @JvmField
+ var cropperLabelTextSize: Float
+
+ /** The default cropper label text color **/
+ @JvmField
+ var cropperLabelTextColor: Int
+
+ /** The default cropper label text **/
+ @JvmField
+ var cropperLabelText: String? = ""
+
/** Init options with defaults. */
constructor() {
val dm = Resources.getSystem().displayMetrics
@@ -373,6 +391,9 @@ open class CropImageOptions : Parcelable {
showIntentChooser = false
intentChooserTitle = null
intentChooserPriorityList = listOf()
+ cropperLabelTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20f, dm)
+ cropperLabelTextColor = Color.WHITE
+ showCropLabel = false
}
/** Create object from parcel. */
@@ -435,6 +456,10 @@ open class CropImageOptions : Parcelable {
showIntentChooser = parcel.readByte().toInt() != 0
intentChooserTitle = parcel.readString()
intentChooserPriorityList = parcel.createStringArrayList()
+ cropperLabelTextSize = parcel.readFloat()
+ cropperLabelTextColor = parcel.readInt()
+ cropperLabelText = parcel.readString()!!
+ showCropLabel = parcel.readByte().toInt() != 0
}
override fun writeToParcel(dest: Parcel, flags: Int) {
@@ -496,6 +521,10 @@ open class CropImageOptions : Parcelable {
dest.writeByte((if (showIntentChooser) 1 else 0).toByte())
dest.writeString(intentChooserTitle)
dest.writeStringList(intentChooserPriorityList)
+ dest.writeFloat(cropperLabelTextSize)
+ dest.writeInt(cropperLabelTextColor)
+ dest.writeString(cropperLabelText)
+ dest.writeByte((if (showCropLabel) 1 else 0).toByte())
}
override fun describeContents(): Int {
diff --git a/cropper/src/main/java/com/canhub/cropper/CropImageView.kt b/cropper/src/main/java/com/canhub/cropper/CropImageView.kt
index 7033b52c..7cf6c707 100644
--- a/cropper/src/main/java/com/canhub/cropper/CropImageView.kt
+++ b/cropper/src/main/java/com/canhub/cropper/CropImageView.kt
@@ -5,6 +5,7 @@ import android.content.Context
import android.graphics.Bitmap
import android.graphics.Bitmap.CompressFormat
import android.graphics.BitmapFactory
+import android.graphics.Color
import android.graphics.Matrix
import android.graphics.Rect
import android.graphics.RectF
@@ -105,6 +106,29 @@ class CropImageView @JvmOverloads constructor(context: Context, attrs: Attribute
*/
private var mShowCropOverlay = true
+ /** If true, shows a helper text label over crop overlay UI
+ * default: false
+ */
+ private var mShowCropLabel = false
+
+ /**
+ * Helper text label over crop overlay UI
+ * default: empty string
+ */
+ private var mCropTextLabel = ""
+
+ /**
+ * Text size for text label over crop overlay UI
+ * default: 20sp
+ */
+ private var mCropLabelTextSize = 20f
+
+ /**
+ * Text color for text label over crop overlay UI
+ * default: White
+ */
+ private var mCropLabelTextColor = Color.WHITE
+
/**
* if to show progress bar when image async loading/cropping is in progress.
* default: true, disable to provide custom progress bar UI.
@@ -403,6 +427,35 @@ class CropImageView @JvmOverloads constructor(context: Context, attrs: Attribute
setCropOverlayVisibility()
}
}
+ /**
+ * If enabled, show a text label on top of crop overlay UI, which gets moved along with the cropper
+ */
+ var isShowCropLabel: Boolean
+ get() = mShowCropLabel
+ set(showCropLabel) {
+ if (mShowCropLabel != showCropLabel) {
+ mShowCropLabel = showCropLabel
+ mCropOverlayView?.setCropperTextLabelVisibility(mShowCropLabel)
+ }
+ }
+ var cropLabelText: String
+ get() = mCropTextLabel
+ set(cropLabelText) {
+ mCropTextLabel = cropLabelText
+ mCropOverlayView?.setCropLabelText(cropLabelText)
+ }
+ var cropLabelTextSize: Float
+ get() = mCropLabelTextSize
+ set(textSize) {
+ mCropLabelTextSize = cropLabelTextSize
+ mCropOverlayView?.setCropLabelTextSize(textSize)
+ }
+ var cropLabelTextColor: Int
+ get() = mCropLabelTextColor
+ set(cropLabelTextColor) {
+ mCropLabelTextColor = cropLabelTextColor
+ mCropOverlayView?.setCropLabelTextColor(cropLabelTextColor)
+ }
/** Returns the integer of the imageResource */
/**
* Sets a Drawable as the content of the CropImageView.
@@ -1037,7 +1090,7 @@ class CropImageView @JvmOverloads constructor(context: Context, attrs: Attribute
bundle.putInt("CROP_MAX_ZOOM", mMaxZoom)
bundle.putBoolean("CROP_FLIP_HORIZONTALLY", mFlipHorizontally)
bundle.putBoolean("CROP_FLIP_VERTICALLY", mFlipVertically)
-
+ bundle.putBoolean("SHOW_CROP_LABEL", mShowCropLabel)
return bundle
}
@@ -1088,6 +1141,8 @@ class CropImageView @JvmOverloads constructor(context: Context, attrs: Attribute
mMaxZoom = state.getInt("CROP_MAX_ZOOM")
mFlipHorizontally = state.getBoolean("CROP_FLIP_HORIZONTALLY")
mFlipVertically = state.getBoolean("CROP_FLIP_VERTICALLY")
+ mShowCropLabel = state.getBoolean("SHOW_CROP_LABEL")
+ mCropOverlayView.setCropperTextLabelVisibility(mShowCropLabel)
}
super.onRestoreInstanceState(state.getParcelable("instanceState"))
} else {
@@ -1882,6 +1937,21 @@ class CropImageView @JvmOverloads constructor(context: Context, attrs: Attribute
R.styleable.CropImageView_cropFlipHorizontally,
options.flipVertically
)
+ options.cropperLabelTextSize = ta.getDimension(
+ R.styleable.CropImageView_cropperLabelTextSize,
+ options.cropperLabelTextSize
+ )
+ options.cropperLabelTextColor = ta.getInteger(
+ R.styleable.CropImageView_cropperLabelTextColor,
+ options.cropperLabelTextColor
+ )
+ options.cropperLabelText = ta.getString(
+ R.styleable.CropImageView_cropperLabelText
+ )
+ options.showCropLabel = ta.getBoolean(
+ R.styleable.CropImageView_cropShowLabel,
+ options.showCropLabel
+ )
isSaveBitmapToInstanceState = ta.getBoolean(
R.styleable.CropImageView_cropSaveBitmapToInstanceState,
isSaveBitmapToInstanceState
@@ -1902,6 +1972,8 @@ class CropImageView @JvmOverloads constructor(context: Context, attrs: Attribute
mScaleType = options.scaleType
mAutoZoomEnabled = options.autoZoomEnabled
mMaxZoom = options.maxZoom
+ mCropLabelTextSize = options.cropperLabelTextSize
+ mShowCropLabel = options.showCropLabel
mShowCropOverlay = options.showCropOverlay
mShowProgressBar = options.showProgressBar
mFlipHorizontally = options.flipHorizontally
diff --git a/cropper/src/main/java/com/canhub/cropper/CropOverlayView.kt b/cropper/src/main/java/com/canhub/cropper/CropOverlayView.kt
index 9579ec7b..237191b8 100644
--- a/cropper/src/main/java/com/canhub/cropper/CropOverlayView.kt
+++ b/cropper/src/main/java/com/canhub/cropper/CropOverlayView.kt
@@ -34,6 +34,16 @@ class CropOverlayView
companion object {
+ /**
+ * Creates the paint object for drawing text label over crop overlay */
+ private fun getTextPaint(options: CropImageOptions): Paint =
+ Paint().apply {
+ strokeWidth = 1f
+ textSize = options.cropperLabelTextSize
+ style = Paint.Style.FILL
+ textAlign = Paint.Align.CENTER
+ this.color = options.cropperLabelTextColor
+ }
/** Creates the Paint object for drawing. */
private fun getNewPaint(color: Int): Paint =
Paint().apply {
@@ -92,6 +102,8 @@ class CropOverlayView
/** The Paint used to darken the surrounding areas outside the crop area. */
private var mBackgroundPaint: Paint? = null
+ private var textLabelPaint: Paint? = null
+
/** Used for oval crop window shape or non-straight rotation drawing. */
private val mPath = Path()
@@ -164,6 +176,14 @@ class CropOverlayView
var cornerShape: CropImageView.CropCornerShape? = null
private set
+ /** To show the text label over crop overlay **/
+ private var isCropLabelEnabled: Boolean = false
+ /** Text to show over text label over crop overlay */
+ private var cropLabelText: String = ""
+ /** Text color to apply over text label over crop overlay */
+ private var cropLabelTextSize: Float = 20f
+ /** Text color to apply over text label over crop overlay */
+ private var cropLabelTextColor = Color.WHITE
/** the initial crop window rectangle to set */
private val mInitialCropWindowRect = Rect()
@@ -253,7 +273,37 @@ class CropOverlayView
invalidate()
}
}
+ /**
+ * Sets the cropper label if it is enabled
+ */
+ fun setCropperTextLabelVisibility(isEnabled: Boolean) {
+ this.isCropLabelEnabled = isEnabled
+ invalidate()
+ }
+
+ /**
+ * Sets the copy text for cropper text
+ */
+ fun setCropLabelText(textLabel: String?) {
+ textLabel?.let {
+ this.cropLabelText = it
+ }
+ }
+ /**
+ * Sets the text size for cropper text
+ */
+ fun setCropLabelTextSize(textSize: Float) {
+ this.cropLabelTextSize = textSize
+ invalidate()
+ }
+ /**
+ * Sets the text color for cropper text
+ */
+ fun setCropLabelTextColor(textColor: Int) {
+ this.cropLabelTextColor = textColor
+ invalidate()
+ }
/**
* Sets the guidelines for the CropOverlayView to be either on, off, or to show when resizing the
* application.
@@ -410,6 +460,10 @@ class CropOverlayView
fun setInitialAttributeValues(options: CropImageOptions) {
mOptions = options
mCropWindowHandler.setInitialAttributeValues(options)
+ setCropLabelTextColor(options.cropperLabelTextColor)
+ setCropLabelTextSize(options.cropperLabelTextSize)
+ setCropLabelText(options.cropperLabelText)
+ setCropperTextLabelVisibility(options.showCropLabel)
setCropCornerRadius(options.cropCornerRadius)
setCropCornerShape(options.cornerShape)
setCropShape(options.cropShape)
@@ -430,6 +484,7 @@ class CropOverlayView
getNewPaintOrNull(options.borderCornerThickness, options.borderCornerColor)
mGuidelinePaint = getNewPaintOrNull(options.guidelinesThickness, options.guidelinesColor)
mBackgroundPaint = getNewPaint(options.backgroundColor)
+ textLabelPaint = getTextPaint(options)
}
/**
@@ -570,10 +625,26 @@ class CropOverlayView
}
// To retain the changes in Paint object when the App goes background this is required
mBorderCornerPaint = getNewPaintOrNull(mOptions?.borderCornerThickness ?: 0.0f, mOptions?.borderCornerColor ?: Color.WHITE)
+ drawCropLabelText(canvas)
drawBorders(canvas)
drawCorners(canvas)
}
+ /** Draws a text label (which can acts an helper text) on top of crop overlay **/
+ private fun drawCropLabelText(canvas: Canvas) {
+ if (isCropLabelEnabled) {
+ val rect = mCropWindowHandler.getRect()
+ var xCoordinate = (rect.left + rect.right) / 2
+ var yCoordinate = rect.top - 50
+ textLabelPaint?.apply {
+ textSize = cropLabelTextSize
+ color = cropLabelTextColor
+ }
+ canvas.drawText(cropLabelText, xCoordinate, yCoordinate, textLabelPaint!!)
+ canvas.save()
+ }
+ }
+
/** Draw shadow background over the image not including the crop area. */
private fun drawBackground(canvas: Canvas) {
val rect = mCropWindowHandler.getRect()
diff --git a/cropper/src/main/res/values/attrs.xml b/cropper/src/main/res/values/attrs.xml
index 82318aa8..0db22609 100644
--- a/cropper/src/main/res/values/attrs.xml
+++ b/cropper/src/main/res/values/attrs.xml
@@ -54,6 +54,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
index 6247b07c..55cb9a21 100644
--- a/sample/src/main/AndroidManifest.xml
+++ b/sample/src/main/AndroidManifest.xml
@@ -20,7 +20,7 @@
diff --git a/sample/src/main/java/com/canhub/cropper/sample/SampleUsingImageView.kt b/sample/src/main/java/com/canhub/cropper/sample/SampleUsingImageView.kt
index a214897a..b563aade 100644
--- a/sample/src/main/java/com/canhub/cropper/sample/SampleUsingImageView.kt
+++ b/sample/src/main/java/com/canhub/cropper/sample/SampleUsingImageView.kt
@@ -106,6 +106,7 @@ internal class SampleUsingImageView :
maxZoom = options.maxZoomLvl
isFlippedHorizontally = options.flipHorizontal
isFlippedVertically = options.flipVertically
+ isShowCropLabel = options.showCropLabel
}
if (options.scaleType == CropImageView.ScaleType.CENTER_INSIDE)
@@ -191,6 +192,7 @@ internal class SampleUsingImageView :
showCropOverlay = true,
showProgressBar = true,
flipHorizontal = false,
- flipVertically = false
+ flipVertically = false,
+ showCropLabel = false
)
}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsBottomSheet.kt b/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsBottomSheet.kt
index 08e1cb48..ce45b5e1 100644
--- a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsBottomSheet.kt
+++ b/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsBottomSheet.kt
@@ -114,6 +114,7 @@ internal class SampleOptionsBottomSheet : BottomSheetDialogFragment() {
binding.progressBar.toggle.isChecked = options.showProgressBar
binding.flipHorizontal.toggle.isChecked = options.flipHorizontal
binding.flipVertical.toggle.isChecked = options.flipVertically
+ binding.cropLabelText.toggle.isChecked = options.showCropLabel
}
override fun onDismiss(dialog: DialogInterface) {
@@ -134,7 +135,8 @@ internal class SampleOptionsBottomSheet : BottomSheetDialogFragment() {
showCropOverlay = true,
showProgressBar = true,
flipHorizontal = false,
- flipVertically = false
+ flipVertically = false,
+ showCropLabel = true
)
private fun bindingActions() {
@@ -253,5 +255,8 @@ internal class SampleOptionsBottomSheet : BottomSheetDialogFragment() {
binding.progressBar.toggle.setOnCheckedChangeListener { _, isChecked ->
options = options.copy(showProgressBar = isChecked)
}
+ binding.cropLabelText.toggle.setOnCheckedChangeListener { _, isChecked ->
+ options = options.copy(showCropLabel = isChecked)
+ }
}
}
diff --git a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsEntity.kt b/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsEntity.kt
index cdc538a7..0e7597df 100644
--- a/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsEntity.kt
+++ b/sample/src/main/java/com/canhub/cropper/sample/options_dialog/SampleOptionsEntity.kt
@@ -20,4 +20,5 @@ internal data class SampleOptionsEntity(
val showProgressBar: Boolean,
val flipHorizontal: Boolean,
val flipVertically: Boolean,
+ val showCropLabel: Boolean
) : Parcelable
diff --git a/sample/src/main/res/layout/fragment_crop_image_view.xml b/sample/src/main/res/layout/fragment_crop_image_view.xml
index a2edb728..bea13125 100644
--- a/sample/src/main/res/layout/fragment_crop_image_view.xml
+++ b/sample/src/main/res/layout/fragment_crop_image_view.xml
@@ -24,6 +24,10 @@
app:cropCornerRadius="@dimen/default_crop_corner_radius"
app:cropBorderCornerOffset="@dimen/default_crop_corner_offset"
app:cropBorderCornerThickness="@dimen/default_crop_corner_offset"
+ app:cropShowLabel="true"
+ app:cropperLabelText="@string/default_crop_label_text"
+ app:cropperLabelTextSize="@dimen/default_crop_text_size"
+ app:cropBorderCornerColor="@color/cardview_shadow_start_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/sample/src/main/res/layout/fragment_options.xml b/sample/src/main/res/layout/fragment_options.xml
index 06db3d79..0e3c2e08 100644
--- a/sample/src/main/res/layout/fragment_options.xml
+++ b/sample/src/main/res/layout/fragment_options.xml
@@ -95,6 +95,9 @@
+
\ No newline at end of file
diff --git a/sample/src/main/res/layout/switch_crop_text_label.xml b/sample/src/main/res/layout/switch_crop_text_label.xml
new file mode 100644
index 00000000..ca675818
--- /dev/null
+++ b/sample/src/main/res/layout/switch_crop_text_label.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/src/main/res/values/dimens.xml b/sample/src/main/res/values/dimens.xml
index fbc3b9c2..e63ff37a 100644
--- a/sample/src/main/res/values/dimens.xml
+++ b/sample/src/main/res/values/dimens.xml
@@ -39,4 +39,5 @@
8dp
8dp
4dp
+ 20sp
\ No newline at end of file
diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml
index 497af191..b8bba517 100644
--- a/sample/src/main/res/values/strings.xml
+++ b/sample/src/main/res/values/strings.xml
@@ -91,4 +91,6 @@
This is a sample code using the library. The sample here is for extend CropImageActivity, to be about to custom build your personal view around it. For that we need to use CropImageView.
Click to change rotation: %1$s
Corner Shape
+ Show Crop Label Text
+ Sample crop label
From e76c8020541fda2830933a41c0ba437e40476af6 Mon Sep 17 00:00:00 2001
From: Canato
Date: Fri, 10 Jun 2022 13:12:08 +0100
Subject: [PATCH 9/9] Release/4.3.0 (#383)
* Update changelong
* Update lib version
* README
---
CHANGELOG.md | 7 +++----
README.md | 5 +++--
versions.gradle | 2 +-
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0ed6834b..b39a4466 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,14 +10,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- `Security` in case of vulnerabilities.
## [x.x.x] - unreleased
-### Fixed
-- The translation of `Camera` and `Gallery` does not exist in some languages.
-## [unreleased 4.2.2]
+## [4.3.0] - 10/06/2022
### Added
- Added a helper text on top of crop overlay which moves along with it. [#381](https://github.com/CanHub/Android-Image-Cropper/issues/381)
+
### Fixed
-- Crash on click of Sample of CustomActivity option over sample App, added the missing activity declaration on Manifest.xml
+- The translation of `Camera` and `Gallery` does not exist in some languages.[#358](https://github.com/CanHub/Android-Image-Cropper/issues/358)
## [4.2.1] - 04/04/2022
### Added
diff --git a/README.md b/README.md
index 4697222e..4aadba1c 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,9 @@
[](https://jitpack.io/#CanHub/Android-Image-Cropper)
-☕ [Using the library in Java](.documentation/java_usage.md)
-❓ [FAQ - frequently asked question](.documentation/FAQ.md)
+☕[Using the library in Java](.documentation/java_usage.md)
+
+❓[FAQ - frequently asked question](.documentation/FAQ.md)
Android Image Cropper
=======
diff --git a/versions.gradle b/versions.gradle
index 475b28d7..1c0c38de 100644
--- a/versions.gradle
+++ b/versions.gradle
@@ -1,7 +1,7 @@
ext {
// Project
- libVersion = "4.2.1"
+ libVersion = "4.3.0"
compileSdkVersion = 31
targetSdkVersion = 31
minSdkVersion = 16