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

5

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

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)

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

enter image description here

所以我有不同的选项,其中只包含一个正确答案,我正在计划实现这个方式,可以把“Bow”拖到“skateboarding”前面的问号处,然后说那不是正确答案,然后把它拖到“archery”上并用底部包含单词“Arrow”的ImageView替换问号。
布局应该包含一列问题(这应该是体育运动),然后在问题之前还应该有另一列,即答案,然后在它们下面应该包含选项
清楚吗?否则请告诉我,我会尝试用更多的细节来解释一下。
编辑
我想的是有一个包含答案列表的类,或者只是创建像:
RightList:(id:1,id:2,id:3)
LeftList:(id:1,id:2,id:3)
DownList:(Bow = id:2),(Skate = id:1),(Ball = 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

我不知道是否需要创建一个实现onDragListener()的类,我希望它是通用的,这样我就可以在不同的游戏中使用,比如:

SKATE(id:1) ARCHERY(id:2) FOOTBALL(id:3)

答案:TABLE(C.A. id:1) BOW(C.A. id:2) GRASS(C.A. id:3) GOAL(C.A. id:3) BALL(C.A. id:3) ARROW(C.A. id:2) AXES(C.A. id:1) WHEELS(C.A. id:1)

所以,如果我将BOW拖放到FOOTBALL上,那么它应该显示为错误,否则就是正确的。


1
你的问题是想知道你想做的事情对于不熟悉的用户是否有意义,还是希望我们建议如何实现你上述描述的内容? - Nikos Hidalgo
一个建议,游戏是这样的。请。 - Skizo-ozᴉʞS ツ
作为一种完全不同的方法,我建议使用bubbles-for-android。(它们基于Facebook Chatheads)请参见我的回答 - Jon Goodwin
2个回答

6

示例 1/3

这里提供一个参考,总结所有内容。以下是一个包含100行代码的单个Activity和导入文件,即使带有简单的动画也能表示所有这些行为。

enter image description here

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
        }
    }
}

使用所有的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>

例子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
        }
    }
}

示例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()
        }
    }
}

更新

这是来自评论区的最新更新,我认为已经足够了,当然你需要根据你的要求和动画来修改两个“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.LayoutParams)
                .apply {
                    gravity = Gravity.END
                }
            view.layoutParams = params
            checkIsCorrect(parent)
        }

        private fun checkIsCorrect(parent : ViewGroup) {
            val correct = false
            if (correct) {
                animateColorChange(parent, true)
                return
            }
            if (++failsCount > Companion.MAX_FAIL_COUNT) {
                animateColorChange(parent, false)
                return
            }
            animateWrongAttempt(parent)
        }

        private fun animateWrongAttempt(parent: ViewGroup) {
            val questionMark = parent.findViewById<View>(R.id.questionView)
            questionMark.setBackgroundColor(Color.RED)

            val va = ValueAnimator.ofFloat(1f, 1.1f)
            va.interpolator = BounceInterpolator()

            va.duration = ANIM_DURATION_SHORT
            va.addUpdateListener { animation ->
                questionMark.scaleX = animation.animatedValue as Float
                questionMark.scaleY = animation.animatedValue as Float
            }
            va.start()

        }

        private fun animateColorChange(parent : ViewGroup, right : Boolean) {
            val colorFrom = Color.WHITE
            ObjectAnimator
                .ofObject(parent, ANIM_COLOR,
                    ArgbEvaluator(), colorFrom,
                    if (right) GREEN_ALPHA else RED_ALPHA)
                .setDuration(ANIM_DURATION_LONG)
                .start()
        }
    }

    companion object {
        const val MAX_FAIL_COUNT = 2
    }
}

以及新的 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:paddingTop="10dp">

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="start"
        android:layout_margin="5dp"
        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:layout_margin="5dp"
        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>

@Skizo-ozᴉʞS 你说的"缺少xml"是什么意思?所有的项都是在运行时构建的。我不明白你的意思。并且拖动几个项你也可以用同样的方法。 - GensaGames
什么是questionContainer和answerContainer?只需分享XML文件,让我检查一下它是否符合我的要求。 - Skizo-ozᴉʞS ツ
@Skizo-ozᴉʞS,根据您的问题,我已经创建了您所需的内容。您有“问题”、“标记”和“答案”行。您可以将“答案”瓷砖拖到“问题”标记上,并使用拖动监听器来实现错误/正确的行为(在开始拖动时传递相关数据的回调函数)。 - GensaGames
关于您提出的第一个问题,不清楚是否能在“ACTION_DROP”回调中,使用传递的拖动对象数据,实现正确/错误答案的动画和检查。上述代码中只需要添加一个简单的“if”语句即可… - GensaGames
你有检查聊天吗?:( - Skizo-ozᴉʞS ツ
显示剩余9条评论

0

我认为,有各种方法可以实现。对我来说,将屏幕分成两个主要部分似乎不错。a) 可以使用单个垂直列表,其中包含项目和指向“问号”的连接,如下图所示。

enter image description here 垂直列表中的单行

因此,通过动态添加和删除简单的View,可以轻松更改从服务器检索的项目列表的大小。一旦正确的瓷砖放置在“问号”顶部,您将在此View的顶部更改新视图。b) 创建底部列表以显示可能的“答案”,将使用水平列表,并显示这些项目。正如您在问题中提到的那样。

enter image description here

底部水平列表


描述

a) 我真的不喜欢使用 Android 小部件(如 RecyclerView)来实现这种任务。对于少量项目,我们可以进行大量自定义。对于第一个列表,我将使用带有 LinearLayoutView(具有任何您的布局)的 VerticalScrollView

注意。您的最后一个布局可以是 ConstraintLayout。例如 1。在这种情况下,您拖动的项目将粘在您所在的确切位置。如果它粘在具有超过一半大小的特定行上,则可以为其更改视图(变为绿色或红色)。例如 2。也许更好的方法是使用“属性动画”从瓷砖所在的位置移动到最近的“问号”。

b) 要创建底部列表,我将使用与“HorizontalListView”相同的结构。这将有助于使用“属性动画”,不仅可以动画拖动,还可以沿着您的分级轨迹移动对象。在具有简单视图的容器中动态添加项目将反映底部或顶部列表中的更改。


实现

1)为每个“答案”瓦片初始化监听器。

// Assign the touch listener to your view which you want to move
findViewById(R.id.myimage1).setOnTouchListener(new MyTouchListener());

// This defines your touch listener
private final class MyTouchListener implements OnTouchListener {
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
            ClipData data = ClipData.newPlainText("", "");
            DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(
                view);
            view.startDrag(data, shadowBuilder, view, 0);
            view.setVisibility(View.INVISIBLE);
            return true;
        } else {
        return false;
        }
    }
}

2) 在顶部列表中定义每个目标视图

findViewById(R.id.bottomright).setOnDragListener(new MyDragListener());

class MyDragListener implements OnDragListener {
    Drawable enterShape = getResources().getDrawable(
            R.drawable.shape_droptarget);
    Drawable normalShape = getResources().getDrawable(R.drawable.shape);

    @Override
    public boolean onDrag(View v, DragEvent event) {
        int action = event.getAction();
        switch (event.getAction()) {
        case DragEvent.ACTION_DRAG_STARTED:
        // do nothing
            break;
        case DragEvent.ACTION_DRAG_ENTERED:
            v.setBackgroundDrawable(enterShape);
            break;
        case DragEvent.ACTION_DRAG_EXITED:
            v.setBackgroundDrawable(normalShape);
            break;
        case DragEvent.ACTION_DROP:
            // Dropped, reassign View to ViewGroup
            View view = (View) event.getLocalState();
            ViewGroup owner = (ViewGroup) view.getParent();
            owner.removeView(view);
            LinearLayout container = (LinearLayout) v;
            container.addView(view);
            view.setVisibility(View.VISIBLE);
            break;
        case DragEvent.ACTION_DRAG_ENDED:
            v.setBackgroundDrawable(normalShape);
            default:
            break;
        }
        return true;
    }
}

3) 这就是你需要创建拖动的全部内容。只需在ActivityView中进行另一种设置更改即可。

但是,您可以检查其他几个拖放实现示例。但由于您正在使用简单的ViewsScrollable容器,因此您可以将每个示例与您的列表配合使用。


我发现和你所发布的其他答案描述的问题相同。我应该有一种方式来确定哪一个是正确的ID,然后给图像分配一个ID和正确的ID或类似的东西。但是我也在寻找不同的方法,但按照你所说的我无法想象如何在一个图像中说出多个图像是正确的。 - Skizo-ozᴉʞS ツ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接