繁体   English   中英

页面数未知或动态的 ViewPager

[英]ViewPager with unknown or dynamic number of pages

我正在尝试为 Android 开发一个调查应用程序。 在需求中,客户要求在问题之间产生滑动效果。 我将ViewPagerFragmentPagerAdapter一起使用,一切正常。

当他们需要树决策系统时,问题就来了。 换句话说,当被调查者 select 给出答案时,我应该引导他提出一个问题,根据该答案中定义的哪个问题。

树决策系统

如图所示,在回答第一个问题之前,我无法加载第二页,因为我不知道要加载哪个问题。

我也不知道在getCount方法中应该返回多少页,只有当用户响应时,我才能知道是否还有一页,应该是它的内容。


我尝试了许多在那里发布的解决方案,但最重要的,或者至少对我来说是逻辑。 是将计数设置为已知页数,当用户 select 回答时,我尝试更改计数并调用notifyDataSetChanged方法,但我得到的只是动态更改页数,而不是内容。

场景是:

  • 在第一个问题中,我将计数设置为 1,因此用户无法滑动到下一页,因为它是未知的。

  • 当用户 select 回答时,我将计数更改为 2 并加载下一个问题。 一切还好!

  • 如果用户回到第一个问题并改变了他的答案,我试图破坏或改变第二页的内容。 但在这种情况下, notifyDataSetChanged不会替换Fragment

我知道我在问一个奇怪而困难的行为,但我想知道是否有人必须做同样的事情并且可以找到正确的解决方案。

很抱歉没有发布任何代码,但是经过这么多意图之后,我的代码变得难看,我确实在 VCS 中恢复了。

您可以尝试为您的数据项创建一个链接列表。 这是一个简单的示例,说明它的外观。

var viewPager: ViewPager? = null

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_dynamic_view_pager, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    viewPager = view.findViewById(R.id.viewPager)
    viewPager?.apply {
        adapter = MyAdapter(childFragmentManager, this).also {
            it.initialDataItem = buildDataItems()
        }
    }

}

fun buildDataItems(): DataItem {
    val item0 = DataItem(0).also {
        it.title = "What can I help you with today?"
    }
    val item1 = DataItem(1).also {
        it.title = "Technical Problem"
    }
    val item2 = DataItem(2).also {
        it.title = "Ordering Problem"
    }
    val item3 = DataItem(3).also {
        it.title = "Is your power light on?"
    }
    val item4 = DataItem(4).also {
        it.title = "Have you received your order?"
    }
    val item5 = DataItem(5).also {
        it.title = "New content node"
    }
    val item6 = DataItem(6).also {
        it.title = "New content node"
    }

    item0.yesItem = item1
    item0.noItem = item2
    item1.yesItem = item3
    item2.yesItem = item4
    item3.yesItem = item5
    item3.noItem = item6

    return item0
}

data class DataItem(
    var id: Int = 0
) {
    var title: String = ""
    var yesItem: DataItem? = null
    var noItem: DataItem? = null
    var answer: Answer = Answer.UNANSWERED
}

enum class Answer {
    UNANSWERED,
    YES,
    NO
}

class MyAdapter(fm: FragmentManager, val viewPager: ViewPager) : FragmentPagerAdapter(fm) {
    var initialDataItem: DataItem = DataItem()


    override fun getItem(position: Int): Fragment {
        var index = 0
        var dataItem: DataItem? = initialDataItem
        while (index < position) {
            when (dataItem?.answer) {
                Answer.YES -> dataItem = dataItem.yesItem
                Answer.NO -> dataItem = dataItem.noItem
                else -> {}
            }
            index ++
        }

        return DetailFragment(dataItem) {
            dataItem?.answer = if (it) Answer.YES else Answer.NO
            notifyDataSetChanged()
            viewPager.setCurrentItem(position + 1, true)
        }
    }

    override fun getCount(): Int {
        var count = 1
        var dataItem: DataItem? = initialDataItem
        while (dataItem?.answer != Answer.UNANSWERED) {
            when (dataItem?.answer) {
                Answer.YES -> dataItem = dataItem.yesItem
                Answer.NO -> dataItem = dataItem.noItem
                else -> {}
            }
            count++
        }

        return count
    }
}

class DetailFragment(val dataItem: DataItem?, val listener: ((answeredYes: Boolean) -> Unit)) : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.fragment_viewpager_detail, container, false)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        view.findViewById<TextView>(R.id.title)?.text = dataItem?.title
        view.findViewById<Button>(R.id.yesButton)?.setOnClickListener {
            listener(true)
        }
        view.findViewById<Button>(R.id.noButton)?.setOnClickListener {
            listener(false)
        }
    }
}

注意:您需要稍微改进一下以处理错误情况并到达树的末尾。 此外,您需要使用更好的方法将数据注入细节片段 - 这仅用于说明目的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM