Last active
March 29, 2023 09:14
-
-
Save smartherd/2ec415563f8369af10cfc4a3ea24e1aa to your computer and use it in GitHub Desktop.
Android Draggable MaterialCardView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<com.sriyank.mdccomponents.DraggableCoordinatorLayout | |
xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
android:id="@+id/parentCoordinatorLayout" | |
android:layout_width="match_parent" | |
android:background="#eee" | |
android:layout_height="match_parent"> | |
<com.google.android.material.card.MaterialCardView | |
android:id="@+id/draggableCard1" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_gravity="center" | |
android:clickable="true" | |
android:focusable="true"> | |
<ImageView | |
android:layout_width="150dp" | |
android:layout_height="150dp" | |
app:srcCompat="@drawable/house_part_1" /> | |
</com.google.android.material.card.MaterialCardView> | |
<com.google.android.material.card.MaterialCardView | |
android:id="@+id/draggableCard2" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_gravity="bottom|start" | |
android:clickable="true" | |
android:focusable="true"> | |
<ImageView | |
android:layout_width="150dp" | |
android:layout_height="150dp" | |
app:srcCompat="@drawable/house_part_2" /> | |
</com.google.android.material.card.MaterialCardView> | |
<com.google.android.material.card.MaterialCardView | |
android:id="@+id/draggableCard3" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_gravity="bottom|end" | |
android:clickable="true" | |
android:focusable="true"> | |
<ImageView | |
android:layout_width="150dp" | |
android:layout_height="150dp" | |
app:srcCompat="@drawable/house_part_3" /> | |
</com.google.android.material.card.MaterialCardView> | |
<com.google.android.material.card.MaterialCardView | |
android:id="@+id/draggableCard4" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_gravity="top|center" | |
android:clickable="true" | |
android:focusable="true"> | |
<ImageView | |
android:layout_width="150dp" | |
android:layout_height="150dp" | |
app:srcCompat="@drawable/house_part_4" /> | |
</com.google.android.material.card.MaterialCardView> | |
</com.sriyank.mdccomponents.DraggableCoordinatorLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.sriyank.mdccomponents | |
import android.content.Context | |
import android.util.AttributeSet | |
import android.view.MotionEvent | |
import android.view.View | |
import androidx.coordinatorlayout.widget.CoordinatorLayout | |
import androidx.customview.widget.ViewDragHelper | |
import java.util.* | |
class DraggableCoordinatorLayout @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) | |
: CoordinatorLayout(context!!, attrs) { | |
/** A listener to use when a child view is being dragged */ | |
interface ViewDragListener { | |
fun onViewCaptured(view: View, i: Int) | |
fun onViewReleased(view: View, v: Float, v1: Float) | |
} | |
private val viewDragHelper: ViewDragHelper | |
private val draggableChildren: MutableList<View> = ArrayList() | |
private var viewDragListener: ViewDragListener? = null | |
fun addDraggableChild(child: View) { | |
require(!(child.parent !== this)) | |
draggableChildren.add(child) | |
} | |
fun removeDraggableChild(child: View) { | |
require(!(child.parent !== this)) | |
draggableChildren.remove(child) | |
} | |
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { | |
return viewDragHelper.shouldInterceptTouchEvent(ev) || super.onInterceptTouchEvent(ev) | |
} | |
override fun onTouchEvent(ev: MotionEvent): Boolean { | |
viewDragHelper.processTouchEvent(ev) | |
return super.onTouchEvent(ev) | |
} | |
private val dragCallback: ViewDragHelper.Callback = object : ViewDragHelper.Callback() { | |
override fun tryCaptureView(view: View, i: Int): Boolean { | |
return view.visibility == VISIBLE && viewIsDraggableChild(view) | |
} | |
override fun onViewCaptured(view: View, i: Int) { | |
if (viewDragListener != null) { | |
viewDragListener!!.onViewCaptured(view, i) | |
} | |
} | |
override fun onViewReleased(view: View, v: Float, v1: Float) { | |
if (viewDragListener != null) { | |
viewDragListener!!.onViewReleased(view, v, v1) | |
} | |
} | |
override fun getViewHorizontalDragRange(view: View): Int { | |
return view.width | |
} | |
override fun getViewVerticalDragRange(view: View): Int { | |
return view.height | |
} | |
override fun clampViewPositionHorizontal(view: View, left: Int, dx: Int): Int { | |
return left | |
} | |
override fun clampViewPositionVertical(view: View, top: Int, dy: Int): Int { | |
return top | |
} | |
} | |
private fun viewIsDraggableChild(view: View): Boolean { | |
return draggableChildren.isEmpty() || draggableChildren.contains(view) | |
} | |
fun setViewDragListener(viewDragListener: ViewDragListener?) { | |
this.viewDragListener = viewDragListener | |
} | |
init { | |
viewDragHelper = ViewDragHelper.create(this, dragCallback) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.sriyank.mdccomponents | |
import android.os.Bundle | |
import android.view.View | |
import android.widget.Toast | |
import androidx.appcompat.app.AppCompatActivity | |
import androidx.customview.widget.ViewDragHelper | |
import com.google.android.material.card.MaterialCardView | |
import com.google.android.material.snackbar.Snackbar | |
import kotlinx.android.synthetic.main.activity_main.* | |
class MainActivity : AppCompatActivity() { | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_main) | |
parentContainer.addDraggableChild(draggableCard1) | |
parentContainer.addDraggableChild(draggableCard2) | |
parentContainer.addDraggableChild(draggableCard3) | |
parentContainer.addDraggableChild(draggableCard4) | |
parentContainer.setViewDragListener(object : DraggableCoordinatorLayout.ViewDragListener { | |
override fun onViewCaptured(view: View, i: Int) { | |
when (view.id) { | |
R.id.draggableCard1 -> draggableCard1.isDragged = true | |
R.id.draggableCard2 -> draggableCard2.isDragged = true | |
R.id.draggableCard3 -> draggableCard3.isDragged = true | |
R.id.draggableCard4 -> draggableCard4.isDragged = true | |
} | |
} | |
override fun onViewReleased(view: View, v: Float, v1: Float) { | |
when (view.id) { | |
R.id.draggableCard1 -> draggableCard1.isDragged = false | |
R.id.draggableCard2 -> draggableCard2.isDragged = false | |
R.id.draggableCard3 -> draggableCard3.isDragged = false | |
R.id.draggableCard4 -> draggableCard4.isDragged = false | |
} | |
} | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment