Day16 - 进入和退出文章

是的,总算要切换到下一页了...

PreviewFragment

目前先使用预设建立的画面,一个FrameLayout跟TextView,将目前的画面印出来而已。

class PreviewFragment : Fragment() {

    private val mTag = "PreviewFragment"

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_preview, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // ...
        tmp.text = PttClient.getInstance().getScreen()
    }
}

nav_main.xml

目前流程的预览如下
https://ithelp.ithome.com.tw/upload/images/20210930/20124602YUPgkvgMQC.png

进入文章

接着先回到搜寻页面,为文章列表加上点击事件。

SearchArticleResultAdapter

class SearchArticleResultAdapter : RecyclerView.Adapter<SearchArticleResultAdapter.ViewHolder>() {
    private val articleList = mutableListOf<Article>()
    var onArticleClickListener: ((article: Article) -> Unit)? = null
    // ...

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        init {
            itemView.setOnClickListener {
                onArticleClickListener?.invoke(articleList[adapterPosition])
            }
        }
        // ...
    }
}

宣告一个onArticleClickListener callback,并在ViewHolder创建时为itemView加上click事件的呼叫。

onArticleClickListener

articleAdapter.onArticleClickListener = { article ->
    (requireActivity() as MainActivity).showLoading("")
    viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
        val ret = withContext(Dispatchers.IO) {
            PttClient.getInstance().send("${article.number}\r\nr")
            delay(200L)
            PttClient.getInstance()
                .expect(arrayOf("浏览[\\s\\S]*第[\\s\\S]*页[\\s\\S]*目前显示[\\s\\S]*第[\\s\\S]*行[\\s\\S]*离开"))
        }

        if (ret == 0) {
            NavHostFragment.findNavController(this@SearchArticleFragment)
                .navigate(R.id.action_searchArticleFragment_to_previewFragment)
        }
        (requireActivity() as MainActivity).dismissLoading()
    }
}

Ptt进入文章的除了一般操作的上下左右外,也可以直接输入文章编号+(enter or r),也就是我此处send的内容。接着就是判断是否有成功进入文章内了,使用的Pattern也就是我们在阅读文章时最下面会显示的内容:
https://ithelp.ithome.com.tw/upload/images/20210930/20124602KrOt3lS0Od.png
确认进入文章後就使用Navigation导到下一页并显示内容来做确认了,接下来几天会再来做解析推文的部分。

离开文章

因为我PreviewFragment的画面还没设定,因此目前是先处理点击back键的退出流程。

onBackPressedDispatcher

在Fragment内取得Activity的onBackPressedDispatcher并addCallback。

requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner,
    object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            (requireActivity() as MainActivity).showLoading("")
            viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
                val ret = withContext(Dispatchers.IO) {
                    PttClient.getInstance().send("q")
                    delay(200L)
                    PttClient.getInstance().expect(arrayOf("文章选读"))
                }
                (requireActivity() as MainActivity).dismissLoading()
                if (ret == 0) {
                    PttClient.getInstance().printScreen()
                    NavHostFragment.findNavController(this@PreviewFragment).popBackStack()
                } else {
                    AlertDialog.Builder(requireContext())
                        .setTitle("Error")
                        .setMessage("Something wrong.")
                        .setPositiveButton(android.R.string.ok) { _, _ ->
                            requireActivity().finish()
                        }
                        .setCancelable(false)
                        .show()
                }
            }
        }
    })

离开文章基本上就是用"q",并判断是否有正确回到文章列表,有的话就可以呼叫NavController的popBackStack回到上一页了。

消失的Chip

做完退出功能後开心的测试,突然发现有点不对劲...我刚刚的搜寻条件Chip消失了。
https://ithelp.ithome.com.tw/upload/images/20210930/20124602Q6i1OA0czz.png

应该是因为我的Chip是动态加入的关系,使用Navigation切换到下一页&回来会经历DestroyView和CreateView的过程,动态加入的元件不在layout中自然也就消失了。解决的方法也很简单,因为Fragment本身没被销毁,全域变数的值还保留着,在onViewCreated中判断searchTitleSetsearchAuthorSet是否有内容,有的话就重新加回来:

//...
if ((searchAuthorSet.isNotEmpty() || searchTitleSet.isNotEmpty())) {
    searchAuthorSet.forEach { addAuthorChip(it) }
    searchTitleSet.forEach { addTitleChip(it) }
}
//...

addAuthorChipaddTitleChip都是Day13的内容,就不重复贴了。

目前画面

https://i.imgur.com/juvYxbB.gif


<<:  [第16天]理财达人Mx. Ada-已实现损益

>>:  Day 27 - 工作满一年了,该离职吗?

Java 语言和你 SAY HELLO!!

第十二天 各位点进来的朋友,你们好阿 小的不才只能做这个系列的文章,但还是希望分享给点进来的朋友,知...

Day 13-假物件 (Fake) - 模拟物件 (Mock)-2 (核心技术-5)

假物件兄弟战:虚设常式 V.S 模拟物件 相信许多人刚接触完虚设常式与模拟物件,会说不出两者之间确切...

[第15天]理财达人Mx. Ada-持仓部位(库存)(positions)

前言 本文说明持仓部位(库存)(positions)资讯。 程序实作 程序 positions =a...

[Day 9] SRE - 自动化

自动化 什麽东西可以自动化?对我而言只要可以列出SOP的事情,都可以实现自动化。 价值 一致性 当不...

Day 06 CSS <复合选择器>

CSS的选择器分为基础选择器以及复合选择器 本日将将继续说明复合选择器 复合选择器可以更准确更高效的...