将ImageView拖放到容器中以进行验证

Ski*_*ᴉʞS 5 java android drag-and-drop android-layout kotlin

为了更好地理解它,请阅读以下内容:

First game :

Skate QuestionMark
Archery QuestionMark
Swim QuestionMark

---------------------------
Water Bow Wheel

If user drags Water to Skate or Archery QuestionMark it will animate to the list (because it is not correct)

If user drags twice incorrect (it will mark the one that is correct from the answer list)

If user still fail in the third try it will drag to the incorrect one and then it will highlight or just change the color doesn't matter to red.

If user drags to the correct one it will highlight green and replace QuestionMark with the correct one (I do not want to be draggable anymore that image)

------

Game 2 (is more or less the same...)

There's no QuestionMark column, there's only :

Skate
Swim
Archery
--------------
(Lot of answers)

Now the way to play is the same (about the fails and etc) the thing is now when I drag any answer to the correct one it won't replace the correct one, it will just disappear and if it fails instead of highlighting all the corrects one it will highlight the correct answer (for instance; if I drag wheel to Swim once, it doesn't happen anything just animate to the place where it was, if I do it twice it will highlight the Skate one, and if it fails at third one it just drag wherever he did and highlight with red)
Run Code Online (Sandbox Code Playgroud)

我打算构建一个进行简单检查的应用程序,调用一个端点,然后获取一些参数,然后知道ImageView屏幕上将显示多少个参数。这就像一个难题,看起来像这样:

在此处输入图片说明

因此,我有不同的选择,其中仅包含一个正确的答案,我正在计划实现此目的的方法,可以将“弓形”拖动到“滑板”的问号前面,然后说这是不正确的,然后将其拖动到“射箭”之一,并ImageView从底部替换包含“箭头”一词的问号。

布局应在问题一栏(应该是体育项目)中包含一栏,然后在问题一之前包含另一栏,并应是答案一栏,然后在其下方应包含选项一。

清楚了吗?否则,请告诉我,我将尝试用更多细节进行解释。

编辑

我以为就像一个包含一个Answers列表的类,或者只是创建像:

RightList:(id:1,id:2,id:3)

LeftList:(id:1,id:2,id:3)

DownList:(弓= ID:2),(滑板= ID:1),(球= ID:3)

然后做拖放的事情时,DragEvent.ACTION_DROP还是 DragEvent.ACTION_DRAG_ENDED我不知道是哪一个,检查(以下伪代码)

if(imageDragged.id==location.id) then replace the question mark image for imageDragged
else animate the image to the place where it comes
Run Code Online (Sandbox Code Playgroud)

我不知道是否要创建一个实现onDragListener()或类似的类,我想让它通用,这样我就可以在不同的游戏中使用它,例如:

滑冰(id:1)射箭(id:2)足球(id:3)

答案:TABLE(CA id:1)BOW(CA id:2)GRASS(CA id:3)GOAL(CA id:3)BALL(CA id:3)ARROW(CA id:2)轴(CA id:1) )车轮(CA id:1)

因此,如果我将BOW拖放到FOOTBALL,那么它应该显示不好,否则就说好。

Gen*_*mes 6

实施例1/3

仅供参考并总结所有内容。这是一个100行代码,在单个代码Activity和导入代码中,即使使用简单的动画也代表了所有此行为。

在此处输入图片说明

class MainActivity : AppCompatActivity() {

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

    private fun bind() {
        addQuestions()
        addAnswers()
    }

    @SuppressLint("InflateParams")
    private fun addQuestions() {
        val inflater = getSystemService(
            Context.LAYOUT_INFLATER_SERVICE
        ) as LayoutInflater
        for (i in 1..8) {
            val view = inflater.inflate(R.layout.item_question, null)
            view.setOnDragListener(DragListener())
            questionContainer.addView(view)
        }
    }


    @SuppressLint("InflateParams")
    private fun addAnswers() {
        val inflater = getSystemService(
            Context.LAYOUT_INFLATER_SERVICE
        ) as LayoutInflater
        for (i in 1..8) {
            val view = inflater.inflate(R.layout.item_answer, null)
            view.setOnTouchListener(DragItemTouchListener())
            answerContainer.addView(view)
        }
    }

    private inner class DragItemTouchListener : OnTouchListener {

        override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
            return if (motionEvent.action == MotionEvent.ACTION_DOWN) {
                dragMultiple(view)
                true
            } else {
                false
            }
        }

        private fun dragMultiple(view : View) {
            val data = ClipData.newPlainText("", "")
            val shadowBuilder = DragShadowBuilder(
                view
            )
            val parent = view.parent as ViewGroup

            view.startDragAndDrop(data, shadowBuilder, view, 0)
            parent.removeView(view)
        }
    }


    private inner class DragListener : OnDragListener {

        override fun onDrag(v: View, event: DragEvent): Boolean {
            when (event.action) {
                DragEvent.ACTION_DRAG_STARTED -> {

                }
                DragEvent.ACTION_DRAG_ENTERED -> {

                }
                DragEvent.ACTION_DRAG_EXITED -> {

                }
                DragEvent.ACTION_DROP -> {
                    animateDropEffect(v as ViewGroup, event.localState as View)
                }
                DragEvent.ACTION_DRAG_ENDED -> {

                }
                else -> {
                }
            }
            return true
        }

        private fun animateDropEffect(into: ViewGroup, view: View) {
            into.addView(view)
            val params = (view.layoutParams as FrameLayout.LayoutParams)
                .apply {
                    gravity = Gravity.END
                }
            view.layoutParams = params
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用所有Xml。在xml下面的所有示例。

/* activity_main.xml */
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    android:id="@+id/mainContainer"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">


        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="500dp"
            android:animateLayoutChanges="true">

            <LinearLayout
                android:id="@+id/questionContainer"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:animateLayoutChanges="true"
                android:orientation="vertical">

            </LinearLayout>
        </ScrollView>

        <HorizontalScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:animateLayoutChanges="true">

            <LinearLayout
                android:id="@+id/answerContainer"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:animateLayoutChanges="true"
                android:orientation="horizontal">

            </LinearLayout>
        </HorizontalScrollView>

    </LinearLayout>
</FrameLayout>


/* item_question.xml */
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:animateLayoutChanges="true"
    android:padding="5dp">

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="start"
        android:background="@android:color/holo_blue_bright">

    </View>

    <View
        android:id="@+id/questionView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="end"
        android:background="@android:color/holo_orange_light">

    </View>

</FrameLayout>


/* item_answer.xml */
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="5dp"
    android:tag="Test">


    <LinearLayout
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"
        android:background="@android:color/darker_gray">

    </LinearLayout>

</FrameLayout>
Run Code Online (Sandbox Code Playgroud)

示例2/3

使用相同的方法来拖动几个元素不是问题。这是一个小例子,但简单的例子。

在此处输入图片说明

第二个示例的修改代码。Xml保持不变。

class MainActivity : AppCompatActivity() {

    var activeOneDrag : Boolean = false

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

    private fun bind() {
        addQuestions()
        addAnswers()
    }

    fun getRandomColor(): Int {
        return Color.argb(255, Random.nextInt(255),
            Random.nextInt(255), Random.nextInt(255))
    }

    @SuppressLint("InflateParams")
    private fun addQuestions() {
        val inflater = getSystemService(
            Context.LAYOUT_INFLATER_SERVICE
        ) as LayoutInflater
        for (i in 1..8) {
            val view = inflater.inflate(R.layout.item_question, null)
            view.setOnDragListener(DragListener())
            questionContainer.addView(view)
        }
    }


    @SuppressLint("InflateParams")
    private fun addAnswers() {
        val inflater = getSystemService(
            Context.LAYOUT_INFLATER_SERVICE
        ) as LayoutInflater
        for (i in 1..8) {
            val view = inflater.inflate(R.layout.item_answer, null)
            (view as ViewGroup).getChildAt(0).setBackgroundColor(getRandomColor())
            view.setOnTouchListener(DragItemTouchListener())
            answerContainer.addView(view)
        }
    }


    private inner class DragItemTouchListener : OnTouchListener {

        override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
            return if (motionEvent.action == MotionEvent.ACTION_DOWN) {
                dragMultiple(view)
                true
            } else {
                false
            }
        }

        private fun dragMultiple(view : View) {
            val parent = view.parent as ViewGroup
            parent.removeView(view)
            /**
             * Some other logic with selective multiple View.
             * Just getting neighbor in our case
             */

            var anotherView : View? = null
            if (!activeOneDrag) {
                anotherView = parent.getChildAt(
                    parent.indexOfChild(view) + 1)
                parent.removeView(anotherView)
            }
            activeOneDrag = !activeOneDrag

            /**
             * As you can see, there is postDelay here.
             * But only for our case with animateLayoutChanges,
             * with delays removing View! In your samples, you could remove it
             * with listener on your own animation, if any!
             */
            parent.postDelayed({

                val layout = LinearLayout(this@MainActivity)
                val params = FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.WRAP_CONTENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT)
                params.gravity = Gravity.BOTTOM
                layout.layoutParams = params
                layout.orientation = LinearLayout.HORIZONTAL


                layout.addView(view)
                if (anotherView != null) {
                    layout.addView(anotherView)
                }
                layout.visibility = INVISIBLE
                mainContainer.addView(layout)

                parent.post {
                    layout.startDragAndDrop(
                        ClipData.newPlainText("", ""),
                        DragShadowBuilder(layout), layout, 0)
                }

            }, 400)

        }
    }


    private inner class DragListener : OnDragListener {

        override fun onDrag(v: View, event: DragEvent): Boolean {
            when (event.action) {
                DragEvent.ACTION_DRAG_STARTED -> {

                }
                DragEvent.ACTION_DRAG_ENTERED -> {

                }
                DragEvent.ACTION_DRAG_EXITED -> {

                }
                DragEvent.ACTION_DROP -> {
                    val view = event.localState as View
                    (view.parent as ViewGroup).removeView(view)
                    view.visibility = VISIBLE
                    animateDropEffect(v as ViewGroup, event.localState as View)
                }
                DragEvent.ACTION_DRAG_ENDED -> {

                }
                else -> {
                }
            }
            return true
        }

        private fun animateDropEffect(into: ViewGroup, view: View) {
            into.addView(view)
            val params = (view.layoutParams as FrameLayout.LayoutParams)
                .apply {
                    gravity = Gravity.END
                }
            view.layoutParams = params
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

示例3/3

如我所见,还不清楚如何使用动画或拖动侦听区域更改简单的动作。这是执行所有操作的另一个简单示例

在此处输入图片说明

class MainActivity : AppCompatActivity() {

    @Volatile
    var state : State = State.INACTIVE

    enum class State {
        ACTIVE, INACTIVE, HANDLED
    }

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

    private fun bind() {
        addQuestions()
        addAnswers()
    }

    private fun getRandomColor(): Int {
        return Color.argb(255, Random.nextInt(255),
            Random.nextInt(255), Random.nextInt(255))
    }

    @SuppressLint("InflateParams")
    private fun addQuestions() {
        val inflater = getSystemService(
            Context.LAYOUT_INFLATER_SERVICE
        ) as LayoutInflater
        for (i in 1..8) {
            val view = inflater.inflate(R.layout.item_question, null)
            view.findViewById<View>(R.id.questionView)
                .setOnDragListener(DragListener())
            questionContainer.addView(view)
        }
    }


    @SuppressLint("InflateParams")
    private fun addAnswers() {
        val inflater = getSystemService(
            Context.LAYOUT_INFLATER_SERVICE
        ) as LayoutInflater
        for (i in 1..8) {
            val view = inflater.inflate(R.layout.item_answer, null)
            (view as ViewGroup).getChildAt(0).setBackgroundColor(getRandomColor())
            view.setOnTouchListener(DragItemTouchListener())
            answerContainer.addView(view)
        }
    }

    private inner class DragItemTouchListener : OnTouchListener {
        val ITEM_INDEX_D = "Index-From"

        override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
            return if (motionEvent.action == MotionEvent.ACTION_DOWN) {
                createDrag(view)
                true
            } else {
                false
            }
        }

        private fun createDrag(view : View) {
            val parent = view.parent as ViewGroup
            view.tag = Pair(ITEM_INDEX_D,
                parent.indexOfChild(view))

            view.startDragAndDrop(ClipData.newPlainText("", ""),
                DragShadowBuilder(view), view, 0)
            parent.removeView(view)
            parent.setBackgroundColor(Color.WHITE)
        }
    }

    private inner class DragListener : OnDragListener {

        override fun onDrag(parent: View, event: DragEvent): Boolean {
            val view = event.localState as View

            when (event.action) {
                DragEvent.ACTION_DRAG_STARTED -> {
                    state = State.ACTIVE
                }
                DragEvent.ACTION_DRAG_ENTERED -> {
                }
                DragEvent.ACTION_DRAG_EXITED -> {

                }
                DragEvent.ACTION_DROP -> {
                    state = State.HANDLED
                    animateDropEffect(parent, view)
                    return true
                }
                DragEvent.ACTION_DRAG_ENDED -> {
                    if (state == State.ACTIVE) {
                        state = State.INACTIVE
                        animateMoveBack(view,
                            (view.tag as Pair<*, *>).second as Int)
                    }
                    return true
                }
                else -> {
                }
            }
            return true
        }

        private fun animateMoveBack(view: View, index : Int) {
            answerContainer.addView(view, index)
        }

        private fun animateDropEffect(into: View, view: View) {
            val parent = (into.parent as ViewGroup)
            parent.addView(view)

            val params = (view.layoutParams as FrameLayout.LayoutParams)
                .apply {
                    gravity = Gravity.END
                }
            view.layoutParams = params
            checkIsCorrect(parent)
        }

        private fun checkIsCorrect(parent : ViewGroup) {
            val correct = Random.nextBoolean()

            val colorFrom = Color.WHITE
            val colorTo : Int = if (correct) 0x8000ff00.toInt() else 0x80ff0000.toInt()
            ObjectAnimator.ofObject(
                parent,
                "backgroundColor",
                ArgbEvaluator(),
                colorFrom,
                colorTo
            )
                .setDuration(1000)
                .start()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

更新

评论部分的最新更新。我认为就足够了,当然您需要进行更改。因此,只需更改两个“ if”语句以符合您的要求和动画。

在此处输入图片说明

在此处输入图片说明

class MainActivity : AppCompatActivity() {

    enum class State {
        ACTIVE, INACTIVE, HANDLED
    }

    var state : State = State.INACTIVE

    var failsCount = 0

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

    private fun bind() {
        addQuestions()
        addAnswers()
    }

    private fun getRandomColor(): Int {
        return Color.argb(255, Random.nextInt(255),
            Random.nextInt(255), Random.nextInt(255))
    }

    @SuppressLint("InflateParams")
    private fun addQuestions() {
        val inflater = getSystemService(
            Context.LAYOUT_INFLATER_SERVICE
        ) as LayoutInflater
        for (i in 1..3) {
            val view = inflater.inflate(R.layout.item_question, null)
            view.findViewById<View>(R.id.questionView)
                .setOnDragListener(DragListener())
            questionContainer.addView(view)
        }
    }


    @SuppressLint("InflateParams")
    private fun addAnswers() {
        val inflater = getSystemService(
            Context.LAYOUT_INFLATER_SERVICE
        ) as LayoutInflater
        for (i in 1..3) {
            val view = inflater.inflate(R.layout.item_answer, null)
            (view as ViewGroup).getChildAt(0).setBackgroundColor(getRandomColor())
            view.setOnTouchListener(DragItemTouchListener())
            answerContainer.addView(view)
        }
    }

    private inner class DragItemTouchListener : OnTouchListener {
        val ITEM_INDEX_D = "Index-From"

        override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
            return if (motionEvent.action == MotionEvent.ACTION_DOWN) {
                createDrag(view)
                true
            } else {
                false
            }
        }

        private fun createDrag(view : View) {
            val parent = view.parent as ViewGroup
            view.tag = Pair(ITEM_INDEX_D,
                parent.indexOfChild(view))

            view.startDragAndDrop(ClipData.newPlainText("", ""),
                DragShadowBuilder(view), view, 0)
            parent.removeView(view)
            parent.setBackgroundColor(Color.WHITE)
        }
    }

    private inner class DragListener : OnDragListener {

        val ANIM_DURATION_LONG = TimeUnit.SECONDS.toMillis(1)
        val ANIM_DURATION_SHORT = TimeUnit.MILLISECONDS.toMillis(500)

        val GREEN_ALPHA = 0x8000ff00.toInt()
        val RED_ALPHA = 0x80ff0000.toInt()
        val ANIM_COLOR = "backgroundColor"

            override fun onDrag(parent: View, event: DragEvent): Boolean {
            val view = event.localState as View

            when (event.action) {
                DragEvent.ACTION_DRAG_STARTED -> {
                    state = State.ACTIVE
                }
                DragEvent.ACTION_DRAG_ENTERED -> {
                }
                DragEvent.ACTION_DRAG_EXITED -> {

                }
                DragEvent.ACTION_DROP -> {
                    state = State.HANDLED
                    animateDropEffect(parent, view)
                    return true
                }
                DragEvent.ACTION_DRAG_ENDED -> {
                    if (state == State.ACTIVE) {
                        state = State.INACTIVE
                        animateMoveBack(view,
                            (view.tag as Pair<*, *>).second as Int)
                    }
                    return true
                }
                else -> {
                }
            }
            return true
        }

        private fun animateMoveBack(view: View, index : Int) {
            answerContainer.addView(view, index)
        }

        private fun animateDropEffect(into: View, view: View) {
            val parent = (into.parent as ViewGroup)
            parent.addView(view)

            val params = (view.layoutParams as FrameLayout.