Configure Stickers
PhotoEditor SDK supports several configuration options for the StickerToolPanel
allowing flexible adaptation to different needs and use cases.
Personal stickers#
The default configuration does not allow users to add custom stickers. In this example, we enable users to add stickers from the device's gallery.
Weather smart stickers#
By default, the editor provides a variety of different stickers when the assets:sticker-shapes
and assets:sticker-emoticons
modules are included in your project. Including backend:sticker-smart
module also adds some smart stickers.
Here, we also want to include weather smart stickers. For this, we provide our implementation of WeatherProvider
.
Custom stickers#
Here, we add a CustomStickerCategoryItem
that shows your own Fragment
when the category is selected. This allows you to fully customize the UI according to your needs. For this example, we have created an ExampleStickersFragment
that adds a sticker to the canvas when a button is clicked.
Dynamic smart stickers#
Here, we add a MetadataImageStickerItem
that shows your own DialogFragment
when the sticker is selected. This allows you to construct the metadata
that is needed for your dynamic smart sticker while fully customizing the UI according to your needs.
For this example, we have created an ExampleMetadataFragment
that takes text input from the user and passes it as part of the metadata
. The ExampleSmartLinkTextSticker
takes this metadata
to render its content.
Set available tools#
By default, all available sticker tools are enabled. In our example, we only allow replacing stickers and changing the color.
Set available colors#
By default, the editor provides a variety of different colors to customize the color of the sticker. For this example, only a small selection of colors is shown by default.
class PhotoStickerConfiguration(private val activity: AppCompatActivity) : Example(activity) {override fun invoke() {// In this example, we do not need access to the Uri(s) after the editor is closed// so we pass false in the constructorval settingsList = PhotoEditorSettingsList(false)// Set the source as the Uri of the image to be loaded.configure<LoadSettings> {it.source = activity.resourceUri(R.drawable.la)}settingsList.configure<UiConfigSticker> {it.setStickerLists(PersonalStickerAddItem(),StickerPackShapes.getStickerCategory(),// Sticker category with emoticons and all smart stickers// Alternatively, you can use SmartStickerPack.getStickerCategory(settingsList, TestWeatherProvider::class.java)// to get only the smart stickers categoryStickerPackEmoticons.getStickerCategory(settingsList, TestWeatherProvider::class.java),CustomStickerCategoryItem("custom_sticker_category",ExampleStickersFragment::class.java,"Custom Stickers",ImageSource.create(ly.img.android.pesdk.assets.sticker.emoticons.R.drawable.imgly_sticker_emoticons_hitman)),StickerCategoryItem("custom_smart_sticker_category","Custom",ImageSource.create(SmartLinkTextSticker0::class.java),MetadataImageStickerItem("imgly_smart_sticker_custom_text",ExampleMetadataFragment::class.java,"Custom Link Text",ImageSource.create(SmartLinkTextSticker0::class.java))))// Add the asset for our custom smart sticker to the AssetConfigsettingsList.config.addAsset(MultiImageStickerAsset(id = "imgly_smart_sticker_custom_text", stickerAssets = arrayListOf(ImageStickerAsset("imgly_smart_sticker_custom_text_0", ImageSource.create(SmartLinkTextSticker0::class.java)),ImageStickerAsset("imgly_smart_sticker_custom_text_1", ImageSource.create(SmartLinkTextSticker1::class.java)))))// By default all available sticker tools are enabled// For this example only a couple are enabledit.optionList.set(it.optionList.filter { item ->item.id == StickerOptionToolPanel.OPTION_REPLACE|| item.id == StickerOptionToolPanel.OPTION_COLOR_COLORIZED})// By default the editor provides a variety of different colors to customize the color of the sticker// For this example only a small selection of colors is shownit.setStickerColorList(ColorItem(ly.img.android.pesdk.ui.R.string.pesdk_common_title_whiteColor, ColorAsset(-0x1)),ColorItem(ly.img.android.pesdk.ui.R.string.pesdk_common_title_blackColor, ColorAsset(-0x1000000)))}// Start the photo editor using PhotoEditorBuilder// The result will be obtained in onActivityResult() corresponding to EDITOR_REQUEST_CODEPhotoEditorBuilder(activity).setSettingsList(settingsList).startActivityForResult(activity, EDITOR_REQUEST_CODE)// Release the SettingsList once donesettingsList.release()}override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {intent ?: returnif (requestCode == EDITOR_REQUEST_CODE) {// Wrap the intent into an EditorSDKResultval result = EditorSDKResult(intent)when (result.resultStatus) {EditorSDKResult.Status.CANCELED -> showMessage("Editor cancelled")EditorSDKResult.Status.EXPORT_DONE -> showMessage("Result saved at ${result.resultUri}")else -> {}}}}}class TestWeatherProvider : WeatherProvider() {private lateinit var job: Jobprivate var temperature: Temperature? = null// Unit in which temperature should be shown in the UIoverride fun getShownUnit() = Unit.Celsius// Called when the editor startsoverride fun onStart() {// Launch coroutine to fetch weatherjob = GlobalScope.launch(Dispatchers.IO) {// Delay to mock fetching weatherdelay(10000)temperature = Temperature(27.3f, Unit.Celsius)// Updates the temperature for the stickers on the canvasupdate()}}// Called when the editor is closedoverride fun onStop() {// cancel coroutinejob.cancel()}// Called by the SDK to fetch the temperature// If the method returns null, the default text (R.string.imgly_smart_sticker_temperature_default_text) is shownoverride fun provideTemperature() = temperature}class ExampleStickersFragment : CustomStickersFragment() {override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {return Button(context).apply {text = "Add Sticker\n(pew-pew)"setOnClickListener {// Call onStickerSelected() on stickerSelectedListener and pass the ImageSource for the sticker to be addedstickerSelectedListener.onStickerSelected(ImageSource.create(ly.img.android.pesdk.assets.sticker.emoticons.R.drawable.imgly_sticker_emoticons_hitman))}}}}/*** Implementation of [DialogFragment] that provides the metadata for [ExampleSmartLinkTextSticker]*/class ExampleMetadataFragment : DialogFragment(), MetadataProvider {// this is auto-initialised by the SDKoverride lateinit var stickerMetadataListener: StickerMetadataListeneroverride fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {return inflater.inflate(R.layout.fragment_example_metadata, container)}override fun onStart() {super.onStart()dialog?.window?.setLayout(WindowManager.LayoutParams.MATCH_PARENT,WindowManager.LayoutParams.WRAP_CONTENT)}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)view.findViewById<EditText>(R.id.et_custom_text).setOnEditorActionListener { et, i, _ ->return@setOnEditorActionListener if (i == EditorInfo.IME_ACTION_DONE) {/* The setMetadata() function takes a `Map<String, String>`.* This metadata is passed to `CustomSmartLinkTextSticker` in our example.*/stickerMetadataListener.setMetadata(mapOf(Pair("text", et.text.toString())))true} else false}}}/*** A [SmartSticker] that displays a link.* The link text is passed to the sticker through its constructor as part of the metadata via [ExampleMetadataFragment].*/open class ExampleSmartLinkTextSticker(context: Context,metadata: Map<String, String>?,private val textColor: ColorValue,font: Font = Font.OpenSans,boxColor: ColorValue = Color.TRANSPARENT) : SmartSticker(context) {private val fontSize = 17.0fprivate val verticalMargin = 4.0fprivate val leftMargin = 8.0fprivate val rightMargin = 16.0fprivate val cornerRadius = 10.0fprivate val drawableSize = 24.0fprivate val drawablePadding = 4.0fprivate val drawableFont = getDrawableFont(font)private val boxPaint by lazy {if (boxColor != Color.TRANSPARENT) {Paint().also {it.isAntiAlias = trueit.color = boxColorit.style = Paint.Style.FILL}} else {null}}private val textPaint by lazy {TextPaint().also {it.isAntiAlias = trueit.textAlign = Paint.Align.LEFTit.textSize = fontSizeit.style = Paint.Style.FILLit.typeface = drawableFont.fontif (textColor == Color.TRANSPARENT) {it.color = Color.WHITEif (boxPaint != null) {it.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)}} else {it.color = textColor}}}private val text = metadata?.get("text")?.takeWhile { it != '/' } ?: "Custom"private val textBounds by lazy {drawableFont.boundsOf(text, fontSize = fontSize)}override fun calculateSize(): ImageSize {return ImageSize(width = (textBounds.width() + leftMargin + rightMargin + drawableSize + drawablePadding).roundToInt(),height = (drawableSize + verticalMargin * 2).roundToInt())}@SuppressLint("Range")private fun drawBackground(canvas: Canvas) {val boxPaint = this.boxPaintif (boxPaint != null) {MultiRect.obtain(0, 0, size.width, size.height).recycleAfter {canvas.drawRoundRect(it, cornerRadius, cornerRadius, boxPaint)}}}@SuppressLint("Range")override fun draw(canvas: Canvas) {canvas.save()if (textColor == Color.TRANSPARENT) {@Suppress("DEPRECATION") canvas.saveLayer(0f, 0f, size.width.toFloat(), size.height.toFloat(), Paint(), Canvas.ALL_SAVE_FLAG)}drawBackground(canvas)val drawable = AppCompatResources.getDrawable(context!!, R.drawable.ic_link)!!drawable.setTint(textColor)drawable.setBounds((leftMargin).toInt(),(verticalMargin).toInt(),(leftMargin + drawableSize).toInt(),(verticalMargin + drawableSize).toInt())drawable.draw(canvas)canvas.translate(-textBounds.left, -textBounds.top)canvas.drawText(text, drawable.bounds.right + drawablePadding, (drawable.bounds.centerY() - textBounds.height / 2), textPaint)if (textColor == Color.TRANSPARENT) {canvas.restore()}canvas.restore()}}// We have two different variants of the smart sticker here. Similarly, more variants can be created.class SmartLinkTextSticker0(context: Context, metadata: Map<String, String>?) : ExampleSmartLinkTextSticker(context, metadata, textColor = Color.parseColor("#333337"), boxColor = Color.parseColor("#8CF6F6F6"))class SmartLinkTextSticker1(context: Context, metadata: Map<String, String>?) : ExampleSmartLinkTextSticker(context, metadata, textColor = Color.parseColor("#F6F6F6"), boxColor = Color.parseColor("#8C333337"))