Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pr/cropper text label support #382

Merged
merged 5 commits into from
Jun 10, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br></br>
* default: true.
Expand Down
29 changes: 29 additions & 0 deletions cropper/src/main/java/com/canhub/cropper/CropImageOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br></br>
* default: true, disable to provide custom progress bar UI.
Expand Down Expand Up @@ -311,6 +317,18 @@ open class CropImageOptions : Parcelable {
@JvmField
var intentChooserPriorityList: List<String>?

/** 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
Expand Down Expand Up @@ -373,6 +391,9 @@ open class CropImageOptions : Parcelable {
showIntentChooser = false
intentChooserTitle = null
intentChooserPriorityList = listOf()
cropperLabelTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20f, dm)

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers.

This expression contains a magic number. Consider defining it to a well named constant.
cropperLabelTextColor = Color.WHITE
showCropLabel = false
}

/** Create object from parcel. */
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 {
Expand Down
74 changes: 73 additions & 1 deletion cropper/src/main/java/com/canhub/cropper/CropImageView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers.

This expression contains a magic number. Consider defining it to a well named constant.

/**
* 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.<br></br>
* default: true, disable to provide custom progress bar UI.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
73 changes: 73 additions & 0 deletions cropper/src/main/java/com/canhub/cropper/CropOverlayView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ class CropOverlayView

companion object {

/**
* Creates the paint object for drawing text label over crop overlay
*/
private fun getTextPaint(options: CropImageOptions): Paint {
return Paint().apply {
strokeWidth = 1f
textSize = options.cropperLabelTextSize
style = Paint.Style.FILL
textAlign = Paint.Align.CENTER
this.color = options.cropperLabelTextColor
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change to:
/** Creates the paint object for drawing text label over crop overlay */

private fun getTextPaint(options: CropImageOptions): Paint = , removing return

/** Creates the Paint object for drawing. */
private fun getNewPaint(color: Int): Paint =
Paint().apply {
Expand Down Expand Up @@ -92,6 +104,8 @@ class CropOverlayView
/** The Paint used to darken the surrounding areas outside the crop area. */
private var mBackgroundPaint: Paint? = null

private var mTextLabelPaint: Paint? = null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this m is the old java way. And we didn't remove every where, please use textLabelPaint


/** Used for oval crop window shape or non-straight rotation drawing. */
private val mPath = Path()

Expand Down Expand Up @@ -164,6 +178,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

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers.

This expression contains a magic number. Consider defining it to a well named constant.
/** 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()

Expand Down Expand Up @@ -253,7 +275,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.
Expand Down Expand Up @@ -410,6 +462,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)
Expand All @@ -430,6 +486,7 @@ class CropOverlayView
getNewPaintOrNull(options.borderCornerThickness, options.borderCornerColor)
mGuidelinePaint = getNewPaintOrNull(options.guidelinesThickness, options.guidelinesColor)
mBackgroundPaint = getNewPaint(options.backgroundColor)
mTextLabelPaint = getTextPaint(options)
}

/**
Expand Down Expand Up @@ -570,10 +627,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
Fixed Show fixed Hide fixed

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers.

This expression contains a magic number. Consider defining it to a well named constant.
mTextLabelPaint?.apply {
textSize = cropLabelTextSize
color = cropLabelTextColor
}
canvas.drawText(cropLabelText, xCoordinate, yCoordinate, mTextLabelPaint!!)
canvas.save()
}
}

/** Draw shadow background over the image not including the crop area. */
private fun drawBackground(canvas: Canvas) {
val rect = mCropWindowHandler.getRect()
Expand Down
4 changes: 4 additions & 0 deletions cropper/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
<attr name="cropFlipVertically" format="boolean"/>
<attr name="cropCornerCircleFillColor" format="color"/>
<attr name="cropCornerRadius" format="dimension"/>
<attr name="cropperLabelTextSize" format="float"/>
<attr name="cropperLabelTextColor" format="color"/>
<attr name="cropperLabelText" format="string"/>
<attr name="cropShowLabel" format="boolean"/>
</declare-styleable>

</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -191,6 +192,7 @@ internal class SampleUsingImageView :
showCropOverlay = true,
showProgressBar = true,
flipHorizontal = false,
flipVertically = false
flipVertically = false,
showCropLabel = false
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -134,7 +135,8 @@ internal class SampleOptionsBottomSheet : BottomSheetDialogFragment() {
showCropOverlay = true,
showProgressBar = true,
flipHorizontal = false,
flipVertically = false
flipVertically = false,
showCropLabel = true
)

private fun bindingActions() {
Expand Down Expand Up @@ -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)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ internal data class SampleOptionsEntity(
val showProgressBar: Boolean,
val flipHorizontal: Boolean,
val flipVertically: Boolean,
val showCropLabel: Boolean
) : Parcelable
4 changes: 4 additions & 0 deletions sample/src/main/res/layout/fragment_crop_image_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading