今天来做搜寻看板的部分,首先Layout我先简单的放一个EditText以及Button,点击Button後将输入的内容送出做搜寻:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SearchArticleFragment">
<EditText
android:id="@+id/searchBoardInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/one_and_half_grid_unit"
android:layout_marginTop="@dimen/one_and_half_grid_unit"
android:layout_marginEnd="@dimen/half_grid_unit"
android:background="@color/text_normal"
android:padding="@dimen/one_grid_unit"
android:textColor="@color/background"
app:layout_constraintEnd_toStartOf="@id/searchBoard"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Gossip" />
<ImageView
android:id="@+id/searchBoard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/text_normal"
android:padding="@dimen/half_grid_unit"
android:layout_marginEnd="@dimen/one_and_half_grid_unit"
android:src="@drawable/ic_baseline_location_searching"
app:layout_constraintBottom_toBottomOf="@id/searchBoardInput"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
searchBoard.setOnClickListener {
val board = searchBoardInput.text.toString().trim()
searchBoardInput.setText(board)
if (board.isEmpty()) return@setOnClickListener
PttClient.getInstance().send("s$board ")
//...
}
搜寻的起始是小写的英文字母s,接着就是输入板名+空白键。以输入"a"为例,在Ptt按上述操作输入後的画面如下:
接着要做的事便是将回传画面下方的看板列表给解析出来。
首先可以看到上图的最後一行显示"按空白键可列出更多项目",这代表以"a"搜寻还有更多的结果无法在一个画面内呈现。若持续点击空白键把结果走到最後的话,画面的呈现如下:
唯一的差别就只有最後一行消失了。
於是为了确保解析出所有搜寻结果页面,我先设定了以下Pattern:
private val searchBoardPattern = arrayOf(
"按空白键可列出更多项目",
"相关资讯一览表"
)
如果先匹配到"按空白键可列出更多项目",代表还有内容需要解析,反之代表最後一页。
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
val boardList = mutableListOf<String>()
do {
val ret = PttClient.getInstance().expect(searchBoardPattern)
Log.d(mTag, "expect: ret=$ret")
if (ret == 0 || ret == 1) {
// ... -> 解析看板名称
}
if (ret == 0) {
PttClient.getInstance().send(" ")
delay(100L)
}
} while (ret == 0)
// ... -> 回归主页面
}
接下来要做的是上面程序码注解中的解析看板名称部分,解析出来的内容我会放到上方已宣告的boardList中。一样我们先看画面内容:
基本上要做的事情就如上图的标记,拿到页面的字串後分割出第3~22行的内容,并且将每行内容以长度22做分割。
val searchResult = PttClient.getInstance().getScreen().split("\n")
for (i in 3..22) {
val splitResult = arrayOf(
searchResult[i].substring(0, 22).trim(),
searchResult[i].substring(22, 44).trim(),
searchResult[i].substring(44).trim()
)
splitResult.forEach {
if (it.isNotEmpty()) {
boardList.add(it)
}
}
}
trim完之後不为空的内容就加入到boardList之中,以前面的"a"来搜寻的话,下中断点能看到以下的结果:
在搜寻完成後我预计要做的事是将结果呈现并让使用者做选择,在此之前我想要先确保我的Ptt页面是在主列表中,这样在後续的操作会比较方便。而要离开搜寻的话需要送出Enter,但有时候当我搜寻的内容本来就有能匹配到的看板的话,按下Enter可能会直接进入该看板中,如下:
此时点击Enter会直接进入该看板:
并且有些看板会有进版画面:
因此在送出Enter後我会有以下Pattern需要判断:
private val cancelSearchBoardPattern = arrayOf(
"【主功能表】",
"请按任意键继续", // 进板画面
"文章选读", // 看板内
)
最後就简单了。
PttClient.getInstance().send("\r\n")
var ret = PttClient.getInstance().expect(cancelSearchBoardPattern)
while (ret != 0 && ret != -1) {
PttClient.getInstance().send("qq")
delay(50L)
ret = PttClient.getInstance().expect(cancelSearchBoardPattern)
}
// PttClient.getInstance().printScreen()
一次送两个q是为了能更快速的回到主列表。
因为不想每次送出内容都还要另外加toByteArray(Charset)来转换成big5编码的byte array,所以我有复写了PttClient的send方法,之後直接送字串就好了。
override fun send(text: String?) {
text?.run {
send(toByteArray(BIG5))
}
}
今天的内容就到这边了,明天是想把搜寻的结果呈现给User做点选,应该内容会比较少一点。
>>: [Day18] - 在 React 中引用现成的 Web Component
今天是30天程序语言研究的第二天,研究的语言一样是python,今天主要学习的部分是string 和...
Document Object 我们知道 DOM 是 Document Object Model(文...
(我想到的这个标题真的很误导人。因为「不是只有爱用iPhone的设计师会有这些毛病。」) 下面这是在...
这是一个在疫情期间无法去学校上课且刚放暑假的我, 为了自己的目标和理想所以努力的学习, 在完成了前一...
Object detection - Recognize individual types of o...