StickerView swap layer of the sticker?

37 views Asked by At

https://github.com/outsbook/CanvasEditor

I have used this repo as i want to implement stickerview functionality with customization

needs to implement the swap the sticker layer functionality

for example i have 10 stickers on a canvas and want to swap sticker from lets say index 5 to 10

needs to swap the sticker with proper validating ui

i have stickerview class with customization as follow

internal class CanvasEditorView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
) : RelativeLayout(context, attrs, defStyleAttr) {

    private val mUndoList = mutableListOf<DrawObject>()
    private val mRedoList = mutableListOf<DrawObject>()

    private val stickerViewListener = object : StickerViewListener {
        override fun onRemove() {
            mListener?.onStickerRemove()
            mListener?.onEnableUndo(mUndoList.isNotEmpty())
        }

        override fun onClone() {

        }

        override fun onDone(obj: DrawObject) {
            addStickerToPaint(obj)
            mListener?.onStickerDone()
        }

        override fun onZoomAndRotate() {
            mListener?.onStickerZoomAndRotate()
        }

        override fun onFlip() {
            mListener?.onStickerFlip()
        }

        override fun onReplace(sticker: Sticker) {

        }

        override fun onClickStickerOutside(x: Float, y: Float) {
            val pos = findTapedSticker(x, y)
            if (pos > -1) {
                enableEditModeSticker(pos)
            }
        }

        override fun onTouchEvent(event: MotionEvent) {
            mListener?.onTouchEvent(event)
        }
    }


    private val paintViewListener = object : PaintViewListener {

        override fun onTouchUp(obj: DrawObject) {
//            mUndoList.add(obj)
            mRedoList.clear()
            mListener?.onEnableUndo(true)
            mListener?.onEnableRedo(false)

        }

        override fun onClick(x: Float, y: Float) {
            val pos = findTapedSticker(x, y)
            if (pos > -1) enableEditModeSticker(pos)

        }

        override fun onTouchEvent(event: MotionEvent) {
            mListener?.onTouchEvent(event)
            mStickerView.onTouchEvent(MotionEvent.obtain(event))
        }
    }


    private val mStickerView: StickerView = StickerView(context, stickerViewListener)
    private val mPaintView: PaintView = PaintView(context, paintViewListener)
    private var mListener: CanvasEditorListener? = null

    init {
        val params = LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
        )
        mPaintView.layoutParams = params
        mPaintView.setBackgroundColor(ContextCompat.getColor(context, android.R.color.white))
        addView(mPaintView)

        mStickerView.layoutParams = params
        mStickerView.setBackgroundColor(
            ContextCompat.getColor(
                context, android.R.color.transparent
            )
        )
        addView(mStickerView)
        mStickerView.visibility = View.GONE
    }

    fun setListener(listener: CanvasEditorListener) {
        mListener = listener
    }

    fun setPaintColor(color: Int) {
        doneStickerEdit()
        mPaintView.paint.color = color
    }

    fun setStrokeWidth(strokeWidth: Float) {
        doneStickerEdit()
        mPaintView.paint.strokeWidth = strokeWidth
    }

    fun setStrokeCap(strokeCap: Paint.Cap) {
        doneStickerEdit()
        mPaintView.paint.strokeCap = strokeCap
    }

    //region add sticker
    fun addDrawableSticker(drawable: Drawable) {
        doneStickerEdit()
        mStickerView.visibility = View.VISIBLE
        val sticker = DrawableSticker(drawable)
        mStickerView.addSticker(sticker)
        mListener?.onEnableUndo(true)
        mListener?.onEnableRedo(false)
        mListener?.onStickerActive()
    }

    fun addBitmapSticker(bitmap: Bitmap) {
        doneStickerEdit()
        mStickerView.visibility = View.VISIBLE
        val sticker = BitmapSticker(context, bitmap)
        mStickerView.addSticker(sticker)
        mListener?.onEnableUndo(true)
        mListener?.onEnableRedo(false)
        mListener?.onStickerActive()
    }

    fun addTextSticker(text: String, textColor: Int, typeface: Typeface?) {
        doneStickerEdit()
        mStickerView.visibility = View.VISIBLE
        val sticker = TextSticker(context, null)
        sticker.setText(text)
        sticker.setTextColor(textColor)
        typeface?.let {
            sticker.setTypeface(it)
        }
        sticker.setAlpha(255)
        sticker.resizeText()
        mStickerView.addSticker(sticker)
        mListener?.onEnableUndo(true)
        mListener?.onEnableRedo(false)
        mListener?.onStickerActive()
    }

    fun addDrawableTextSticker(
        drawable: Drawable,
        text: String,
        textColor: Int,
        typeface: Typeface?,
    ) {
        doneStickerEdit()
        mStickerView.visibility = View.VISIBLE
        val sticker = TextSticker(context, drawable)
        sticker.setText(text)
        sticker.setTextColor(textColor)
        typeface?.let {
            sticker.setTypeface(it)
        }
        sticker.resizeText()
        mStickerView.addSticker(sticker)
        mListener?.onEnableUndo(true)
        mListener?.onEnableRedo(false)
        mListener?.onStickerActive()
    }

    fun doneActiveSticker() {
        if (mStickerView.visibility == View.VISIBLE) {
            mStickerView.done()
        }
    }

    fun removeActiveSticker() {
        if (mStickerView.visibility == View.VISIBLE) {
            mStickerView.remove()
        }
    }

    fun zoomAndRotateActiveSticker(motionEvent: MotionEvent) {
        if (mStickerView.visibility == View.VISIBLE) {
            mStickerView.zoomAndRotate(motionEvent)
        }
    }

    fun flipActiveSticker() {

        if (mStickerView.visibility == View.VISIBLE) {
            mStickerView.flip()
        }
    }


    fun swapLayer(position: Int, newPosition: Int) {
        mStickerView.sendToLayer(position, newPosition)
    }

    fun setLocked(locked: Boolean) {
        mStickerView.setLocked(locked)
        mListener?.onStickerActive()
    }

    fun getStickers(): List<Sticker> {
        return mStickerView.getStickers()
    }

    fun isLocked(): Boolean {
        return mStickerView.isLocked()
    }
    //endregion

    fun undo() {
        if (mStickerView.visibility == View.VISIBLE) {
            mStickerView.remove()
            return
        }
        if (mUndoList.isNotEmpty()) {
            mRedoList.add(mUndoList.last())
            mUndoList.removeAt(mUndoList.lastIndex)
            mPaintView.initCanvas()
            mUndoList.forEach {
                drawObject(it)
            }
            mListener?.onEnableUndo(mUndoList.isNotEmpty())
            mListener?.onEnableRedo(mRedoList.isNotEmpty())
        }
    }


    fun redo() {
        if (mRedoList.isNotEmpty()) {
            val obj = mRedoList.last()
            mUndoList.add(obj)
            mRedoList.removeAt(mRedoList.lastIndex)
            drawObject(obj)
            mListener?.onEnableUndo(mUndoList.isNotEmpty())
            mListener?.onEnableRedo(mRedoList.isNotEmpty())
        }
    }

    fun removeAll() {
        mUndoList.clear()
        mRedoList.clear()
        mStickerView.remove()
        mPaintView.initCanvas()
        mListener?.onEnableUndo(false)
        mListener?.onEnableRedo(false)
    }

    fun downloadBitmap(): Bitmap {
        doneStickerEdit()
        return mPaintView.extraBitmap
    }

    suspend fun saveStickerViewToFile(fileName: String, viewGroup: ViewGroup): String {
        return withContext(IO) {
            val bitmap = Bitmap.createBitmap(
                viewGroup.width, viewGroup.height, Bitmap.Config.ARGB_8888
            )
            val canvas = Canvas(bitmap)
            viewGroup.draw(canvas)


//        val dir = File(context.cacheDir, "sticker")
//        if (dir.exists().not()) dir.mkdirs()
//        val file = File(dir, fileName)

            val publicDirectory =
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
            val funnyEmojiDir = File(publicDirectory, "FunnyEmoji")
            if (funnyEmojiDir.exists().not()) funnyEmojiDir.mkdirs()

            val file = File(funnyEmojiDir, fileName)
            val outStream = FileOutputStream(file)
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream)
            outStream.flush()
            outStream.close()
            file.path
        }
    }

    private fun drawObject(obj: DrawObject) {
        when (obj.drawType) {
            DrawType.PATH -> {
//                mPaintView.drawPath(obj.pathAndPaint!!)
            }

            DrawType.STICKER -> {
                mPaintView.drawSticker(obj.sticker!!)
            }
        }
    }

    //region find double tap inside sticker
    private fun findTapedSticker(x: Float, y: Float): Int {
        for (i in mUndoList.size - 1 downTo 0) {
            val obj = mUndoList[i]
            if (obj.drawType == DrawType.STICKER) {
                val sticker = obj.sticker!!
                if (sticker.contains(x, y)) {
                    return i
                }
            }
        }
        return -1
    }

    private fun enableEditModeSticker(pos: Int) {
        val obj = mUndoList[pos]
        val sticker = obj.sticker!!
        mStickerView.visibility = View.VISIBLE
        mStickerView.currentSticker = sticker
        mUndoList.removeAt(pos)
        mPaintView.initCanvas()
        mUndoList.forEach {
            drawObject(it)
        }
        mRedoList.clear()
        mListener?.onEnableUndo(true)
        mListener?.onEnableRedo(mRedoList.isNotEmpty())
        mListener?.onStickerActive()
        mStickerView.setIsTouchInsideSticker()
    }


    private fun addStickerToPaint(obj: DrawObject) {
        mPaintView.drawSticker(obj.sticker!!)
        mUndoList.add(obj)
//        mRedoList.clear()
        mListener?.onEnableUndo(true)
        mListener?.onEnableRedo(false)
    }

    private fun doneStickerEdit() {
        if (mStickerView.visibility == View.VISIBLE) {
            mStickerView.done()
        }
    }

}

needs to tweak the swap layer function code in given class not work

needs to implementing swap layer of the sticker so that selected sticker came to top of the stack of the sticker.

0

There are 0 answers