Android drag and drop startDragAndDrop drag and drop Glide to flexibly load stacked rounded corners, Kotlin (6)

Android drag and drop startDragAndDrop drag and drop Glide to flexibly load stacked rounded corners, Kotlin (6)

Android drag and drop startDragAndDrop drag and drop Glide to load stacked rounded corners, Kotlin (5) – CSDN blog article has been read 1.3k times. Android DynamicGrid: Drag to swap positions. Android DynamicGrid is a third-party open source project. DynamicGrid’s project homepage on github is: https://github.com/askerov/DynamicGrid. It is implemented in a grid layout and drags any subview. Achieve dynamic exchange of positions, which is very similar to the mobile phone’s desktop. The icons on the mobile phone’s desktop can be freely dragged to realize the exchange of positions, as shown in the animation: _android drag and drop to exchange positions. Android View drag startDragAndDrop, Kotlin-CSDN blog. https:/ /blog.csdn.net/zhangphil/article/details/134269432 Although the above article (5) can be dragged and dropped to implement Glide to dynamically load one or several stacked rotating pictures, you need to be careful in the xml layout and upper-layer Kotlin code. Write (calculate) the size carefully, otherwise the layout and View will be abnormal and not flexible enough. This time, we will transform the implementation in article (5) to achieve low-code and flexible loading of rotated stacked graphs.

import android.content.ClipData
import android.content.Context
import android.graphics.Canvas
import android.graphics.Point
import android.os.Bundle
import android.util.Log
import android.view.DragEvent
import android.view.LayoutInflater
import android.view.View
import android.view.View.OnDragListener
import android.view.View.OnLongClickListener
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.children
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners

class MainActivity : AppCompatActivity() {
    companion object {
        const val TAG = "fly"
        const val DEGREE = -10 //Angle of image rotation.
        const val RADIUS = 30 //Corner radius of the picture.
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val shadowBuilder = createDragShadowBuilder()
        setData(shadowBuilder.getShadowView())

        val triggerView = findViewById<ImageView>(R.id.image)
        triggerView.setOnLongClickListener(object : OnLongClickListener {
            //Long press event triggers dragging.
            override fun onLongClick(v: View?): Boolean {
                val data = ClipData.newPlainText("name", "phil") //Test data.
                triggerView.startDragAndDrop(
                    data,
                    shadowBuilder,
                    null,
                    0 or View.DRAG_FLAG_GLOBAL or View.DRAG_FLAG_OPAQUE
                )

                return true
            }
        })

        triggerView.setOnDragListener(object : OnDragListener {
            override fun onDrag(v: View?, event: DragEvent?): Boolean {
                when (event?.action) {
                    DragEvent.ACTION_DRAG_STARTED -> {
                        //Drag and drop starts
                        Log.d(TAG, "ACTION_DRAG_STARTED")
                    }

                    DragEvent.ACTION_DRAG_ENTERED -> {
                        //Enter imageView
                        Log.d(TAG, "ACTION_DRAG_ENTERED")
                    }

                    DragEvent.ACTION_DRAG_ENDED -> {
                        //End of drag and drop
                        Log.d(TAG, "ACTION_DRAG_ENDED")
                    }

                    DragEvent.ACTION_DRAG_EXITED -> {
                        //leave imageView
                        Log.d(TAG, "ACTION_DRAG_EXITED")
                    }
                }

                return true
            }
        })
    }

    private fun createDragShadowBuilder(): MyDragShadowBuilder {
        val shadowView = LayoutInflater.from(this).inflate(R.layout.dnd, null)
        return MyDragShadowBuilder(this, shadowView)
    }

    private fun setData(viewGroup: View) {
        // Randomly select one of the two numbers 1 and 4.
        var cnt = intArrayOf(1, 4).random()
        Log.d(TAG, "cnt=$cnt")

        val number = viewGroup.findViewById<TextView>(R.id.number)
        when (cnt) {
            1 -> {
                //Only one page is displayed.
                number.text = "1"

                val fl: FrameLayout? = viewGroup as? FrameLayout
                fl?.children?.filter {
                    (it as? ImageView)?.tag == resources.getString(R.string.normal_image_view_tag)
                }?.forEach { view ->
                    view.apply {
                        View.GONE
                    }
                }
            }

            4 -> {
                //Display 4 pictures overlapped together.
                number.text = "4"

                val resIds = arrayOf(
                    R.mipmap.pic1,
                    R.mipmap.pic2,
                    R.mipmap.pic3
                )

                val fl: FrameLayout? = viewGroup as? FrameLayout
                fl?.children?.filter {
                    (it as? ImageView)?.tag == resources.getString(R.string.normal_image_view_tag)
                }?.forEachIndexed { index, view ->
                    view.apply {
                        View.VISIBLE
                    }

                    val degree = (resIds.size - index) * DEGREE
                    Log.d(TAG, "index=$index degree=$degree")

                    view.rotation = degree.toFloat()

                    GlideApp.with(this)
                        .load(resIds[index])
                        .transform(CenterCrop(), RoundedCorners(RADIUS)) //First scale the center and then cut the rounded corners.
                        .override(
                            resources.getDimensionPixelSize(R.dimen.image_size_w),
                            resources.getDimensionPixelSize(R.dimen.image_size_h)
                        ).placeholder(R.drawable.ic_launcher_foreground)
                        .error(android.R.drawable.stat_notify_error)
                        .into(view as ImageView)
                }
            }
        }

        val folder = viewGroup.findViewById<ImageView>(R.id.folder)
        //Cover
        GlideApp.with(this)
            .load(R.mipmap.pic4)
            .transform(CenterCrop(), RoundedCorners(RADIUS)) //First scale the center and then cut the rounded corners.
            .override(
                resources.getDimensionPixelSize(R.dimen.image_size_w),
                resources.getDimensionPixelSize(R.dimen.image_size_h)
            ).placeholder(R.drawable.ic_launcher_foreground)
            .error(android.R.drawable.stat_notify_error)
            .into(folder)
    }

    class MyDragShadowBuilder(ctx: Context, private var mShadow: View):
        View.DragShadowBuilder() {
        //Enlarge parameters 1.5, 2.0
        //Appropriately enlarge the area of the dragging area, otherwise because the image is rotated, the left and right sides and the top will be cut off due to the rotation radius.
        //Simply put, draw a slightly larger area to accommodate the image rotation and the area swept by the radius.
        private val width: Int =
            (ctx.resources.getDimensionPixelSize(R.dimen.image_size_w) * 1.5).toInt()
        private val height: Int =
            (ctx.resources.getDimensionPixelSize(R.dimen.image_size_h) * 2.0).toInt()

        fun getShadowView(): View {
            return mShadow
        }

        override fun onProvideShadowMetrics(outShadowSize: Point?, outShadowTouchPoint: Point?) {
            //Drag the width and height of the image
            outShadowSize?.set(width, height)

            //The middle point of where the finger is dragging the image
            outShadowTouchPoint?.set(width / 2, height / 2)
        }

        override fun onDrawShadow(canvas: Canvas) {
            mShadow.measure(width, height)
            mShadow.layout(0, 0, width, height)
            mShadow.draw(canvas)

            Log.d(TAG, "onDrawShadow width=${mShadow.width} height=${mShadow.height}")
        }
    }
}

dnd.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/holo_orange_light">

    <ImageView
        android:id="@ + id/iv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:tag="@string/normal_image_view_tag" />

    <ImageView
        android:id="@ + id/iv2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:tag="@string/normal_image_view_tag" />

    <ImageView
        android:id="@ + id/iv3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:tag="@string/normal_image_view_tag" />

    <ImageView
        android:id="@ + id/folder"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />


    <androidx.cardview.widget.CardView
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_gravity="top|right"
        app:cardBackgroundColor="@android:color/holo_red_light"
        app:cardCornerRadius="15dp">

        <TextView
            android:id="@ + id/number"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="--"
            android:textColor="@android:color/white"
            android:textSize="15dp" />
    </androidx.cardview.widget.CardView>
</FrameLayout>

Note that if the root layout does not use FrameLayout, but other layouts such as RelativeLayout or ConstraintLayout, the centered sub-View defined in xml will be invalid.

dimens.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="image_size_w">180dp</dimen>
    <dimen name="image_size_h">120dp</dimen>
</resources>

strings.xml:

<resources>
    <string name="normal_image_view_tag">normal_image_view_tag</string>
</resources>

Drag and drop an image:

Drag 4 pictures, rotate 3 backgrounds, but the cover will not rotate:

Android transforms CardView into a circular view, Kotlin_android circular view-CSDN blog article has been read 1k times. You can use the cardCornerRadius feature of androidx.cardview.widget.CardView to transform the CardView into a circular View. The key to technical implementation is to first set the CardView to a View (square) with equal width and height, and then set the radius to the width ( Or height, the same, because the width and height of a square are equal) 1/2, at this time the CardView will naturally become a circle. Android RoundedBitmapDrawable: Android official rounded graphics image implementation solution_android official rounded corners-CSDN blog. _android circular viewhttps://blog.csdn.net/zhangphil/article/details/133346170