Android拖放startDragAndDrop拖拽Glide加载堆叠圆角图,Kotlin(5)-CSDN博客文章浏览阅读1.3k次。Android DynamicGrid:拖曳交换位置Android DynamicGrid是一个第三方开源项目,DynamicGrid在github上的项目主页是:https://github.com/askerov/DynamicGrid它实现在一个网格布局内,拖曳任意子view实现动态的交换位置,这很类似手机的桌面,手机桌面的图标,均可自由拖曳实现摆放位置的交换,如动图所示:_android 拖拽交换位置。Android View拖拽startDragAndDrop,Kotlin-CSDN博客。https://blog.csdn.net/zhangphil/article/details/134269432上面文章(5)虽然可以做到拖拽实现Glide动态加载1张或若干张堆叠的旋转图片,但需要在xml布局和上层Kotlin代码中小心谨慎的写好(计算好)尺寸,否则会显示布局和View异常,不够灵活。这次,现在改造文章(5)中的实现,实现低代码、灵活加载旋转的堆叠图。
- 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 //图片旋转的角度。
- const val RADIUS = 30 //图片的圆角半径。
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
-
- val shadowBuilder = createDragShadowBuilder()
- setData(shadowBuilder.getShadowView())
-
- val triggerView = findViewById
(R.id.image) - triggerView.setOnLongClickListener(object : OnLongClickListener {
- //长按事件触发拖拽.
- override fun onLongClick(v: View?): Boolean {
- val data = ClipData.newPlainText("name", "phil") //测试数据。
- 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 -> {
- //拖放开始
- Log.d(TAG, "ACTION_DRAG_STARTED")
- }
-
- DragEvent.ACTION_DRAG_ENTERED -> {
- //进入imageView
- Log.d(TAG, "ACTION_DRAG_ENTERED")
- }
-
- DragEvent.ACTION_DRAG_ENDED -> {
- //拖放结束
- Log.d(TAG, "ACTION_DRAG_ENDED")
- }
-
- DragEvent.ACTION_DRAG_EXITED -> {
- //离开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) {
- //从1和4两个数字中随机选一个。
- var cnt = intArrayOf(1, 4).random()
- Log.d(TAG, "cnt=$cnt")
-
- val number = viewGroup.findViewById
(R.id.number) - when (cnt) {
- 1 -> {
- //只显示一张。
- 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 -> {
- //显示重叠在一起的4张。
- 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)) //先中心缩放,再切圆角。
- .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
(R.id.folder) - //封面
- GlideApp.with(this)
- .load(R.mipmap.pic4)
- .transform(CenterCrop(), RoundedCorners(RADIUS)) //先中心缩放,再切圆角。
- .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() {
- //放大参数 1.5 , 2.0
- //适当的放大拖拽区域的面积,否则因为图片旋转,左右两侧和顶部因为旋转半径,图会被切边。
- //简单的说,绘制略微大一些的区域,容纳图片旋转,半径扫过的区域。
- 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?) {
- //拖动图像的宽和高
- outShadowSize?.set(width, height)
-
- //手指在拖动图像的位置 中点
- 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:
- "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>
注意,根布局layout如果不使用FrameLayout,而是其他layout布局如RelativeLayout或ConstraintLayout,xml里面定义的居中放置子View失效。
dimens.xml:
- "1.0" encoding="utf-8"?>
- <resources>
- <dimen name="image_size_w">180dpdimen>
- <dimen name="image_size_h">120dpdimen>
- resources>
strings.xml:
- <resources>
- <string name="normal_image_view_tag">normal_image_view_tagstring>
- resources>
拖拽1张图片:

拖拽4张图片,背景3张旋转,封面不旋转:
