feat: 吧内搜索筛选、排序、历史记录

This commit is contained in:
HuanCheng65 2022-06-26 20:51:54 +08:00
parent b94d638928
commit 867d47fa59
No known key found for this signature in database
GPG Key ID: E9031EF91A805148
15 changed files with 591 additions and 41 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="tblite" />
<version value="23" />
<version value="24" />
<list>
<mapping class="com.huanchengfly.tieba.post.models.database.Account" />
<mapping class="com.huanchengfly.tieba.post.models.database.Draft" />
@ -9,5 +9,6 @@
<mapping class="com.huanchengfly.tieba.post.models.database.Block" />
<mapping class="com.huanchengfly.tieba.post.models.database.TopForum" />
<mapping class="com.huanchengfly.tieba.post.models.database.SearchHistory" />
<mapping class="com.huanchengfly.tieba.post.models.database.SearchPostHistory" />
</list>
</litepal>

View File

@ -17,7 +17,6 @@ import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
@ -280,7 +279,6 @@ class ForumActivity : BaseActivity(), View.OnClickListener, OnRefreshedListener,
} else {
1f
}
Log.i("OffsetChange", "changed")
if (titleVisible != isTitleVisible) {
title = if (isTitleVisible) getString(R.string.title_forum, forumName) else null
titleVisible = isTitleVisible

View File

@ -2,28 +2,52 @@ package com.huanchengfly.tieba.post.activities
import android.graphics.Color
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.widget.ListPopupWindow
import androidx.core.widget.TextViewCompat
import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import cn.dreamtobe.kpswitch.util.KeyboardUtil
import com.google.android.material.textfield.TextInputLayout
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.adapters.SearchPostAdapter
import com.huanchengfly.tieba.post.adapters.SearchPostHistoryAdapter
import com.huanchengfly.tieba.post.adapters.SingleChooseAdapter
import com.huanchengfly.tieba.post.adapters.SingleLayoutAdapter
import com.huanchengfly.tieba.post.api.TiebaApi.getInstance
import com.huanchengfly.tieba.post.api.models.SearchPostBean
import com.huanchengfly.tieba.post.api.retrofit.doIfFailure
import com.huanchengfly.tieba.post.api.retrofit.doIfSuccess
import com.huanchengfly.tieba.post.components.AutoLineFeedLayoutManager
import com.huanchengfly.tieba.post.components.MyLinearLayoutManager
import com.huanchengfly.tieba.post.components.MyViewHolder
import com.huanchengfly.tieba.post.components.dividers.SpacesItemDecoration
import com.huanchengfly.tieba.post.dpToPx
import com.huanchengfly.tieba.post.models.database.SearchPostHistory
import com.huanchengfly.tieba.post.toastShort
import com.huanchengfly.tieba.post.utils.PopupUtil
import com.huanchengfly.tieba.post.utils.ThemeUtil
import com.huanchengfly.tieba.post.utils.Util
import com.huanchengfly.tieba.post.utils.anim.animSet
import com.scwang.smart.refresh.layout.SmartRefreshLayout
import org.litepal.LitePal
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class SearchPostActivity : BaseActivity() {
private var state: State = State.INPUT
set(value) {
field = value
invalidateState()
}
@BindView(R.id.search_post_refresh_layout)
lateinit var refreshLayout: SmartRefreshLayout
@ -36,14 +60,47 @@ class SearchPostActivity : BaseActivity() {
@BindView(R.id.search_edit_text)
lateinit var editText: EditText
lateinit var searchPostAdapter: SearchPostAdapter
private var headerView: View? = null
private val searchPostAdapter: SearchPostAdapter by lazy { SearchPostAdapter(this) }
private var forumName: String? = null
private var keyword: String? = null
set(value) {
field = value
if (value != null) refreshLayout.autoRefresh()
state = if (value == null) {
State.INPUT
} else {
State.SEARCH
}
if (value != null) {
refreshLayout.autoRefresh()
SearchPostHistory(value, forumName)
.saveOrUpdate("content = ?", value)
}
}
private var page = 1
private var sortMode = 1
set(value) {
val changed = field != value
field = value
if (changed) {
refreshHeader()
if (keyword != null) {
refreshLayout.autoRefresh()
}
}
}
private var onlyThread = false
set(value) {
val changed = field != value
field = value
if (changed) {
refreshHeader()
if (keyword != null) {
refreshLayout.autoRefresh()
}
}
}
override fun getLayoutId(): Int = R.layout.activity_search_post
@ -69,13 +126,120 @@ class SearchPostActivity : BaseActivity() {
}
}
private fun invalidateState() {
when (state) {
State.INPUT -> {
refreshLayout.setEnableRefresh(false)
refreshLayout.setEnableLoadMore(false)
recyclerView.adapter = null
loadHistory()
}
State.SEARCH -> {
refreshLayout.setEnableRefresh(true)
refreshLayout.setEnableLoadMore(true)
recyclerView.adapter = searchPostAdapter
}
}
}
private fun refreshHeader() {
headerView?.apply {
val allBtn: TextView = findViewById(R.id.search_post_header_btn_all)
val onlyThreadBtn: TextView = findViewById(R.id.search_post_header_btn_only_thread)
val sortModeText: TextView = findViewById(R.id.search_post_header_sort_mode_title)
if (onlyThread) {
TextViewCompat.setTextAppearance(allBtn, R.style.TextAppearance_Normal)
TextViewCompat.setTextAppearance(onlyThreadBtn, R.style.TextAppearance_Bold)
} else {
TextViewCompat.setTextAppearance(allBtn, R.style.TextAppearance_Bold)
TextViewCompat.setTextAppearance(onlyThreadBtn, R.style.TextAppearance_Normal)
}
sortModeText.text = when (sortMode) {
1 -> getString(R.string.title_search_post_sort_by_time)
2 -> getString(R.string.title_search_post_sort_by_relevant)
else -> null
}
}
}
override fun onBackPressed() {
if (state == State.SEARCH) {
state = State.INPUT
KeyboardUtil.showKeyboard(editText)
} else {
finish()
}
}
private fun showSortModeMenu(view: View) {
val arrow: ImageView = view.findViewById(R.id.search_post_header_sort_mode_arrow)
val animSet = animSet {
anim {
values = floatArrayOf(180f, 0f)
action = { value -> arrow.rotation = value as Float }
duration = 150
interpolator = LinearInterpolator()
}
start()
}
val adapter = SingleChooseAdapter(
this,
listOf(
getString(R.string.title_search_post_sort_by_time),
getString(R.string.title_search_post_sort_by_relevant)
),
sortMode - 1
)
ListPopupWindow(this).apply {
PopupUtil.replaceBackground(this)
anchorView = view
width = ViewGroup.LayoutParams.WRAP_CONTENT
height = ViewGroup.LayoutParams.WRAP_CONTENT
isModal = true
setAdapter(adapter)
setOnItemClickListener { _, _, position: Int, _ ->
dismiss()
sortMode = position + 1
}
setOnDismissListener {
animSet.reverse()
}
show()
}
}
private fun loadHistory() {
LitePal.order("timestamp DESC").findAsync(SearchPostHistory::class.java)
.listen { histories ->
if (state == State.INPUT) {
recyclerView.post {
recyclerView.adapter = SearchHistoryDelegateAdapter(histories)
}
}
}
}
private fun initView() {
refreshLayout.apply {
ThemeUtil.setThemeForSmartRefreshLayout(this)
setOnLoadMoreListener { loadMore() }
setOnRefreshListener { refresh() }
}
searchPostAdapter = SearchPostAdapter(this)
searchPostAdapter.addHeaderView(R.layout.layout_search_post_header) {
headerView = this
findViewById<View>(R.id.search_post_header_sort_mode).setOnClickListener {
showSortModeMenu(
it
)
}
findViewById<View>(R.id.search_post_header_btn_all).setOnClickListener {
onlyThread = false
}
findViewById<View>(R.id.search_post_header_btn_only_thread).setOnClickListener {
onlyThread = true
}
refreshHeader()
}
searchPostAdapter.setOnItemClickListener { _, item, _ ->
ThreadActivity.launch(this, item.tid!!, item.pid)
}
@ -101,22 +265,22 @@ class SearchPostActivity : BaseActivity() {
return
}
page = 1
getInstance().searchPost(keyword!!, forumName!!, false, page, 30)
.enqueue(object : Callback<SearchPostBean> {
override fun onResponse(
call: Call<SearchPostBean>,
response: Response<SearchPostBean>
) {
val data = response.body()
searchPostAdapter.setData(data!!.postList)
launchIO {
getInstance().searchPostAsync(
keyword!!,
forumName!!,
onlyThread = onlyThread,
sortMode = sortMode,
page = page,
pageSize = 30
)
.doIfSuccess {
searchPostAdapter.setData(it.postList)
refreshLayout.finishRefresh()
refreshLayout.setNoMoreData("1" != data.page!!.hasMore)
refreshLayout.setNoMoreData("1" != it.page!!.hasMore)
}
override fun onFailure(call: Call<SearchPostBean?>, t: Throwable) {
refreshLayout.finishRefresh(false)
}
})
.doIfFailure { refreshLayout.finishRefresh(false) }
}
}
private fun loadMore() {
@ -124,7 +288,14 @@ class SearchPostActivity : BaseActivity() {
refreshLayout.finishLoadMore(false)
return
}
getInstance().searchPost(keyword!!, forumName!!, false, page + 1, 30)
getInstance().searchPost(
keyword!!,
forumName!!,
onlyThread = onlyThread,
sortMode = sortMode,
page = page + 1,
pageSize = 30
)
.enqueue(object : Callback<SearchPostBean> {
override fun onResponse(
call: Call<SearchPostBean>,
@ -143,6 +314,64 @@ class SearchPostActivity : BaseActivity() {
})
}
enum class State {
INPUT,
SEARCH;
}
inner class SearchHistoryDelegateAdapter(
val data: List<SearchPostHistory>? = null
) : SingleLayoutAdapter(
this,
R.layout.layout_search_post_history
) {
val adapter: SearchPostHistoryAdapter = SearchPostHistoryAdapter(context).apply {
setData(data)
setOnItemClickListener { _, item, _ ->
editText.apply {
setText(item.content)
clearFocus()
KeyboardUtil.hideKeyboard(this)
}
keyword = item.content
}
}
val layoutManager: AutoLineFeedLayoutManager = AutoLineFeedLayoutManager()
override fun initView(view: View) {
view.findViewById<RecyclerView>(R.id.recyclerview)
.addItemDecoration(SpacesItemDecoration(0, 0, 8.dpToPx(), 8.dpToPx()))
view.findViewById<View>(R.id.end_icon).setOnClickListener {
LitePal.deleteAllAsync(SearchPostHistory::class.java).listen {
toastShort(R.string.toast_delete_success)
recyclerView.post {
loadHistory()
}
}
}
}
override fun convert(viewHolder: MyViewHolder, itemView: View) {
if (data.isNullOrEmpty()) {
viewHolder.getView<RecyclerView>(R.id.recyclerview).apply {
visibility = View.GONE
}
viewHolder.getView<View>(R.id.no_data).apply {
visibility = View.VISIBLE
}
} else {
viewHolder.getView<RecyclerView>(R.id.recyclerview).apply {
visibility = View.VISIBLE
layoutManager = this@SearchHistoryDelegateAdapter.layoutManager
adapter = this@SearchHistoryDelegateAdapter.adapter
}
viewHolder.getView<View>(R.id.no_data).apply {
visibility = View.GONE
}
}
}
}
companion object {
val TAG = SearchPostActivity::class.java.simpleName
const val PARAM_FORUM = "forum_name"

View File

@ -0,0 +1,16 @@
package com.huanchengfly.tieba.post.adapters
import android.content.Context
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.adapters.base.BaseSingleTypeAdapter
import com.huanchengfly.tieba.post.components.MyViewHolder
import com.huanchengfly.tieba.post.models.database.SearchPostHistory
class SearchPostHistoryAdapter(context: Context) :
BaseSingleTypeAdapter<SearchPostHistory>(context) {
override fun getItemLayoutId(): Int = R.layout.item_search_history_chip
override fun convert(viewHolder: MyViewHolder, item: SearchPostHistory, position: Int) {
viewHolder.setText(R.id.text, item.content)
}
}

View File

@ -0,0 +1,43 @@
package com.huanchengfly.tieba.post.adapters
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.recyclerview.widget.RecyclerView
import com.huanchengfly.tieba.post.components.MyViewHolder
open class SingleLayoutAdapter(
val context: Context,
val itemView: View
) : RecyclerView.Adapter<MyViewHolder>() {
constructor(
context: Context,
@LayoutRes
layoutResId: Int
) : this(
context,
View.inflate(context, layoutResId, null)
)
constructor(
context: Context,
createViewFunction: () -> View
) : this(
context,
createViewFunction()
)
final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder =
MyViewHolder(itemView.apply { initView(itemView) })
final override fun onBindViewHolder(viewHolder: MyViewHolder, position: Int) {
convert(viewHolder, itemView)
}
final override fun getItemCount(): Int = 1
open fun initView(view: View) {}
open fun convert(viewHolder: MyViewHolder, itemView: View) {}
}

View File

@ -654,13 +654,6 @@ class ThreadReplyAdapter(context: Context) :
context.getString(R.string.btn_agree_post_default)
}
)
viewHolder.setText(
R.id.thread_list_item_reply_btn, if (item.subPostNumber != "0") {
context.getString(R.string.btn_reply_post, item.subPostNumber)
} else {
context.getString(R.string.btn_reply_post_default)
}
)
viewHolder.itemView.background = getItemBackgroundDrawable(
context,
position,

View File

@ -20,7 +20,7 @@ abstract class BaseAdapter<Item>(
val onItemChildClickListeners: MutableMap<Int, OnItemChildClickListener<Item>?> = mutableMapOf()
val headers: MutableList<View> = mutableListOf()
val headers: MutableList<Layout> = mutableListOf()
val footers: MutableList<View> = mutableListOf()
@ -71,15 +71,19 @@ abstract class BaseAdapter<Item>(
}
fun addHeaderView(view: View) {
headers.add(view)
headers.add(Layout(view = view))
notifyItemInserted(headers.size - 1)
}
fun removeHeaderView(view: View) {
val index = headers.indexOf(view)
if (index >= 0) {
headers.removeAt(index)
notifyItemRemoved(index)
fun addHeaderView(layoutRes: Int, viewInitializer: (View.() -> Unit)?) {
headers.add(Layout(layoutRes = layoutRes, viewInitializer = viewInitializer))
notifyItemInserted(headers.size - 1)
}
fun removeHeaderViewAt(position: Int) {
if (position >= 0) {
headers.removeAt(position)
notifyItemRemoved(position)
}
}
@ -140,7 +144,16 @@ abstract class BaseAdapter<Item>(
final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return if (viewType <= ITEM_TYPE_HEADER) {
MyViewHolder(headers[ITEM_TYPE_HEADER - viewType])
val headerLayout = headers[ITEM_TYPE_HEADER - viewType]
if (headerLayout.layoutRes != -1) {
MyViewHolder(context, headerLayout.layoutRes, parent).apply {
headerLayout.viewInitializer?.invoke(itemView)
}
} else if (headerLayout.view != null) {
MyViewHolder(headerLayout.view)
} else {
throw IllegalArgumentException("Layout is empty!")
}
} else if (viewType >= ITEM_TYPE_FOOTER) {
MyViewHolder(footers[viewType - ITEM_TYPE_FOOTER])
} else {
@ -205,4 +218,10 @@ abstract class BaseAdapter<Item>(
itemList.clear()
notifyDataSetChanged()
}
class Layout(
val layoutRes: Int = -1,
val view: View? = null,
val viewInitializer: (View.() -> Unit)? = null
)
}

View File

@ -282,6 +282,7 @@ interface ITiebaApi {
* @param keyword 搜索关键词
* @param forumName 搜索吧名
* @param onlyThread 是否仅搜索主题贴
* @param sortMode 排序模式1 = 时间倒序2 = 相关性排序
* @param page 分页页码 1 开始
* @param pageSize 每页贴数默认 30
*/
@ -289,10 +290,30 @@ interface ITiebaApi {
keyword: String,
forumName: String,
onlyThread: Boolean = false,
sortMode: Int = 1,
page: Int = 1,
pageSize: Int = 30
): Call<SearchPostBean>
/**
* 吧内搜索异步
*
* @param keyword 搜索关键词
* @param forumName 搜索吧名
* @param onlyThread 是否仅搜索主题贴
* @param sortMode 排序模式1 = 时间倒序2 = 相关性排序
* @param page 分页页码 1 开始
* @param pageSize 每页贴数默认 30
*/
fun searchPostAsync(
keyword: String,
forumName: String,
onlyThread: Boolean = false,
sortMode: Int = 1,
page: Int = 1,
pageSize: Int = 30
): Deferred<ApiResult<SearchPostBean>>
/**
* 搜索用户
*

View File

@ -172,13 +172,35 @@ object MixedTiebaApiImpl : ITiebaApi {
)
override fun searchPost(
keyword: String, forumName: String, onlyThread: Boolean, page: Int, pageSize: Int
keyword: String,
forumName: String,
onlyThread: Boolean,
sortMode: Int,
page: Int,
pageSize: Int
): Call<SearchPostBean> = RetrofitTiebaApi.MINI_TIEBA_API.searchPost(
keyword,
forumName,
page,
pageSize,
only_thread = if (onlyThread) 1 else 0
only_thread = if (onlyThread) 1 else 0,
sortMode = sortMode
)
override fun searchPostAsync(
keyword: String,
forumName: String,
onlyThread: Boolean,
sortMode: Int,
page: Int,
pageSize: Int
): Deferred<ApiResult<SearchPostBean>> = RetrofitTiebaApi.MINI_TIEBA_API.searchPostAsync(
keyword,
forumName,
page,
pageSize,
only_thread = if (onlyThread) 1 else 0,
sortMode = sortMode
)
override fun searchUser(keyword: String): Call<SearchUserBean> =

View File

@ -277,9 +277,21 @@ interface MiniTiebaApi {
@Field("kw") forumName: String,
@Field("pn") page: Int = 1,
@Field("rn") pageSize: Int = 30,
@Field("only_thread") only_thread: Int = 0
@Field("only_thread") only_thread: Int = 0,
@Field("sm") sortMode: Int = 1
): Call<SearchPostBean>
@POST("/c/s/searchpost")
@FormUrlEncoded
fun searchPostAsync(
@Field("word") keyword: String,
@Field("kw") forumName: String,
@Field("pn") page: Int = 1,
@Field("rn") pageSize: Int = 30,
@Field("only_thread") only_thread: Int = 0,
@Field("sm") sortMode: Int = 1
): Deferred<ApiResult<SearchPostBean>>
@GET("/mo/q/search/user")
fun searchUser(
@Query("word") keyword: String,

View File

@ -0,0 +1,44 @@
package com.huanchengfly.tieba.post.models.database;
import org.litepal.crud.LitePalSupport;
public class SearchPostHistory extends LitePalSupport {
private int id;
private long timestamp;
private String content;
private String forumName;
public SearchPostHistory(String content, String forumName) {
this.timestamp = System.currentTimeMillis();
this.content = content;
this.forumName = forumName;
}
public int getId() {
return id;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getForumName() {
return forumName;
}
public void setForumName(String forumName) {
this.forumName = forumName;
}
}

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical">
<com.huanchengfly.tieba.post.widgets.theme.TintLinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_radius_16dp"
android:orientation="horizontal"
android:padding="16dp"
app:backgroundTint="@color/default_color_card">
<LinearLayout
android:id="@+id/search_post_header_sort_mode"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:orientation="horizontal">
<com.huanchengfly.tieba.post.widgets.theme.TintTextView
android:id="@+id/search_post_header_sort_mode_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textStyle="bold"
app:tint="@color/default_color_text"
tools:text="时间倒序" />
<ImageView
android:id="@+id/search_post_header_sort_mode_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:rotation="180"
app:srcCompat="@drawable/ic_round_arrow_drop_up" />
</LinearLayout>
<com.huanchengfly.tieba.post.widgets.theme.TintTextView
android:id="@+id/search_post_header_btn_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/title_all_reply"
app:tint="@color/default_color_text"
tools:textStyle="bold" />
<com.huanchengfly.tieba.post.widgets.theme.TintView
android:layout_width="0.75dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
app:backgroundTint="@color/default_color_text_disabled" />
<com.huanchengfly.tieba.post.widgets.theme.TintTextView
android:id="@+id/search_post_header_btn_only_thread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/title_search_filter_only_thread"
app:tint="@color/default_color_text" />
</com.huanchengfly.tieba.post.widgets.theme.TintLinearLayout>
</LinearLayout>

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<com.huanchengfly.tieba.post.widgets.theme.TintLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_radius_8dp"
android:orientation="vertical"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:paddingBottom="12dp"
app:backgroundTint="@color/default_color_card">
<RelativeLayout
android:id="@+id/header_root_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="8dp"
android:paddingStart="8dp"
android:paddingEnd="8dp">
<com.huanchengfly.tieba.post.widgets.theme.TintImageView
android:id="@+id/icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
app:srcCompat="@drawable/ic_round_watch_later_blue"
app:tint="@color/default_color_primary" />
<com.huanchengfly.tieba.post.widgets.theme.TintTextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginStart="8dp"
android:layout_toStartOf="@id/end_icon"
android:layout_toEndOf="@id/icon"
android:text="@string/title_search_history"
android:textStyle="bold"
app:tint="@color/default_color_primary" />
<com.huanchengfly.tieba.post.widgets.theme.TintImageView
android:id="@+id/end_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
app:srcCompat="@drawable/ic_round_delete"
app:tint="@color/default_color_primary" />
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<include
android:id="@id/no_data"
layout="@layout/layout_no_data" />
</com.huanchengfly.tieba.post.widgets.theme.TintLinearLayout>

View File

@ -378,7 +378,7 @@
<string name="text_no_data">这里什么都没有</string>
<string name="title_exact_match">推荐结果</string>
<string name="title_fuzzy_match">查询结果</string>
<string name="title_search_filter_only_thread">看主题贴</string>
<string name="title_search_filter_only_thread">看主题贴</string>
<string name="title_search_order_new">新贴在前</string>
<string name="title_search_order_old">旧贴在前</string>
<string name="title_search_order_relevant">相关度</string>
@ -523,4 +523,6 @@
<string name="title_hide_forum_intro_and_stat">精简吧页面</string>
<string name="summary_hide_forum_intro_and_stat">开启后将隐藏吧页面的吧简介和数据(仍然可以通过“关于本吧”查看这些内容)</string>
<string name="relative_date_today">今天 %1$s</string>
<string name="title_search_post_sort_by_time">时间倒序</string>
<string name="title_search_post_sort_by_relevant">相关性排序</string>
</resources>

View File

@ -1,4 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
<cloud-backup></cloud-backup>
<cloud-backup>
<exclude
domain="sharedpref"
path="crash.xml" />
<exclude
domain="sharedpref"
path="AppCenter.xml" />
<exclude
domain="database"
path="com.microsoft.appcenter.persistence" />
<exclude
domain="database"
path="com.microsoft.appcenter.persistence-journal" />
<exclude
domain="file"
path="error" />
<exclude
domain="file"
path="appcenter" />
</cloud-backup>
</data-extraction-rules>