diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bfd061ba..b0c616d8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -242,6 +242,10 @@ android:screenOrientation="portrait" android:theme="@style/Theme.AppCompat.Light.NoActionBar" /> + + Activity.goToActivity() { +inline fun Context.goToActivity() { startActivity(Intent(this, T::class.java)) } +inline fun Context.goToActivity(pre: Intent.() -> Intent) { + startActivity(pre(Intent(this, T::class.java))) +} + fun Context.toastShort(text: String) { Toast.makeText(this, text, Toast.LENGTH_SHORT).show() } @@ -52,7 +56,3 @@ fun Context.toastShort(text: String) { fun Context.toastShort(resId: Int) { Toast.makeText(this, resId, Toast.LENGTH_SHORT).show() } - -inline fun Activity.goToActivity(pre: (Intent) -> Intent) { - startActivity(pre(Intent(this, T::class.java))) -} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt index 00ebb643..9834db57 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt @@ -4,6 +4,7 @@ package com.huanchengfly.tieba.post.activities import android.animation.Animator import android.animation.AnimatorListenerAdapter +import android.content.Context import android.content.Intent import android.content.res.ColorStateList import android.graphics.Bitmap @@ -47,6 +48,7 @@ import com.huanchengfly.tieba.post.dpToPx import com.huanchengfly.tieba.post.fragments.ForumFragment import com.huanchengfly.tieba.post.fragments.ForumFragment.OnRefreshedListener import com.huanchengfly.tieba.post.fragments.ForumInfoFragment +import com.huanchengfly.tieba.post.goToActivity import com.huanchengfly.tieba.post.interfaces.Refreshable import com.huanchengfly.tieba.post.interfaces.ScrollTopable import com.huanchengfly.tieba.post.models.PhotoViewBean @@ -508,5 +510,15 @@ class ForumActivity : BaseActivity(), View.OnClickListener, OnRefreshedListener companion object { private const val TAG = "ForumActivity" const val EXTRA_FORUM_NAME = "forum_name" + + @JvmStatic + fun launch( + context: Context, + forumName: String + ) { + context.goToActivity { + putExtra(EXTRA_FORUM_NAME, forumName) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/NewSearchActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/NewSearchActivity.kt index 42dace0e..4e487159 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/activities/NewSearchActivity.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/NewSearchActivity.kt @@ -1,4 +1,348 @@ package com.huanchengfly.tieba.post.activities -class NewSearchActivity { -} \ No newline at end of file +import android.graphics.Color +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT +import android.view.inputmethod.EditorInfo +import android.widget.EditText +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.widget.TextViewCompat +import androidx.recyclerview.widget.RecyclerView +import butterknife.BindView +import cn.dreamtobe.kpswitch.util.KeyboardUtil +import com.alibaba.android.vlayout.DelegateAdapter +import com.alibaba.android.vlayout.VirtualLayoutManager +import com.alibaba.android.vlayout.layout.LinearLayoutHelper +import com.google.android.material.tabs.TabLayout +import com.google.android.material.textfield.TextInputLayout +import com.huanchengfly.tieba.post.* +import com.huanchengfly.tieba.post.adapters.FragmentTabViewPagerAdapter +import com.huanchengfly.tieba.post.adapters.HeaderDelegateAdapter +import com.huanchengfly.tieba.post.adapters.HeaderDelegateAdapter.Companion.NO_ICON +import com.huanchengfly.tieba.post.adapters.SearchHistoryAdapter +import com.huanchengfly.tieba.post.adapters.SingleLayoutDelegateAdapter +import com.huanchengfly.tieba.post.adapters.base.BaseSingleTypeDelegateAdapter +import com.huanchengfly.tieba.post.api.TiebaApi +import com.huanchengfly.tieba.post.api.models.web.HotMessageListBean +import com.huanchengfly.tieba.post.components.AutoLineFeedLayoutManager +import com.huanchengfly.tieba.post.components.MyViewHolder +import com.huanchengfly.tieba.post.components.dividers.SpacesItemDecoration +import com.huanchengfly.tieba.post.fragments.SearchForumFragment +import com.huanchengfly.tieba.post.fragments.SearchThreadFragment +import com.huanchengfly.tieba.post.fragments.SearchUserFragment +import com.huanchengfly.tieba.post.interfaces.ISearchFragment +import com.huanchengfly.tieba.post.models.database.SearchHistory +import com.huanchengfly.tieba.post.ui.theme.utils.ColorStateListUtils +import com.huanchengfly.tieba.post.utils.NavigationHelper +import com.huanchengfly.tieba.post.utils.PopupUtil +import com.huanchengfly.tieba.post.widgets.MyViewPager +import com.scwang.smart.refresh.header.MaterialHeader +import org.litepal.LitePal +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class NewSearchActivity : BaseActivity(), TabLayout.OnTabSelectedListener { + private var state: State = State.DEFAULT + + @BindView(R.id.search_bar) + lateinit var searchBar: TextInputLayout + + @BindView(R.id.tab_layout) + lateinit var tabLayout: TabLayout + + @BindView(R.id.search_edit_text) + lateinit var editText: EditText + + @BindView(R.id.view_pager) + lateinit var viewPager: MyViewPager + + @BindView(R.id.recycler_view) + lateinit var recyclerView: RecyclerView + + @BindView(R.id.bottom_app_bar) + lateinit var bottomAppBar: View + + var hotMessageListBean: HotMessageListBean? = null + + private var keyword: String? = null + set(value) { + field = value + if (value != null) { + SearchHistory(value) + .saveOrUpdate("content = ?", value) + } + state = if (value == null) { + State.INPUT + } else { + State.SEARCH + } + invalidateState() + tabLayout.post { + fragmentAdapter.fragments.forEachIndexed { index, fragment -> + if (fragment is ISearchFragment) { + fragment.setKeyword(value, tabLayout.selectedTabPosition == index) + } + } + } + } + private val fragmentAdapter: FragmentTabViewPagerAdapter = FragmentTabViewPagerAdapter(supportFragmentManager) + private val virtualLayoutManager: VirtualLayoutManager = VirtualLayoutManager(this) + private val delegateAdapter: DelegateAdapter = DelegateAdapter(virtualLayoutManager) + + override fun getLayoutId(): Int = R.layout.activity_new_search + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + fragmentAdapter.addFragment(SearchForumFragment.newInstance(), getString(R.string.title_search_forum)) + fragmentAdapter.addFragment(SearchThreadFragment.newInstance(), getString(R.string.title_search_thread)) + fragmentAdapter.addFragment(SearchUserFragment.newInstance(), getString(R.string.title_search_user)) + viewPager.adapter = fragmentAdapter + viewPager.offscreenPageLimit = 3 + tabLayout.setupWithViewPager(viewPager) + tabLayout.addOnTabSelectedListener(this) + searchBar.setStartIconOnClickListener { + onBackPressed() + } + recyclerView.layoutManager = virtualLayoutManager + recyclerView.adapter = delegateAdapter + editText.setOnEditorActionListener { v, actionId, _ -> + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + keyword = v.text.toString() + return@setOnEditorActionListener true + } + return@setOnEditorActionListener false + } + keyword = intent.getStringExtra(EXTRA_KEYWORD) + editText.post { + if (keyword == null) { + KeyboardUtil.showKeyboard(editText) + } + } + } + + private fun invalidateState() { + when (state) { + State.INPUT -> { + bottomAppBar.visibility = View.GONE + viewPager.visibility = View.GONE + recyclerView.visibility = View.VISIBLE + reloadAdapters() + } + State.SEARCH -> { + bottomAppBar.visibility = View.VISIBLE + viewPager.visibility = View.VISIBLE + recyclerView.visibility = View.GONE + } + else -> { + bottomAppBar.visibility = View.GONE + viewPager.visibility = View.GONE + recyclerView.visibility = View.GONE + } + } + } + + private fun reloadAdapters() { + delegateAdapter.clear() + LitePal.order("timestamp DESC").findAsync(SearchHistory::class.java).listen { histories -> + delegateAdapter.addAdapter(HeaderDelegateAdapter( + this, + R.string.title_search_history, + R.drawable.ic_round_keyboard, + if (histories.size > 0) R.drawable.ic_round_delete else NO_ICON + ).apply { + setBackgroundResource(R.drawable.bg_top_radius_8dp) + backgroundTintList = R.color.default_color_card + iconTintList = R.color.default_color_primary + titleTextColor = R.color.default_color_primary + topMargin = 8.dpToPx() + startPadding = 16.dpToPx() + endPadding = 16.dpToPx() + setOnEndIconClickListener { + LitePal.deleteAllAsync(SearchHistory::class.java).listen { + toastShort(R.string.toast_delete_success) + recyclerView.post { + reloadAdapters() + } + } + } + }) + delegateAdapter.addAdapter(SearchHistoryDelegateAdapter(histories)) + delegateAdapter.notifyDataSetChanged() + loadHotTopic() + } + } + + private fun loadHotTopic() { + if (hotMessageListBean != null) { + addHotTopicAdapters(hotMessageListBean!!) + } else { + TiebaApi.getInstance().hotMessageList().enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + response.body()?.let { + hotMessageListBean = it + addHotTopicAdapters(it) + } + } + + override fun onFailure(call: Call, t: Throwable) {} + }) + } + } + + private fun addHotTopicAdapters(hotMessageListBean: HotMessageListBean) { + delegateAdapter.addAdapter(HeaderDelegateAdapter( + this@NewSearchActivity, + R.string.title_hot_message, + R.drawable.ic_round_polymer, + R.drawable.ic_round_chevron_right + ).apply { + setBackgroundResource(R.drawable.bg_top_radius_8dp) + backgroundTintList = R.color.default_color_card + iconTintList = R.color.default_color_primary + titleTextColor = R.color.default_color_primary + topMargin = 8.dpToPx() + startPadding = 16.dpToPx() + endPadding = 16.dpToPx() + setOnClickListener { + goToActivity() + } + }) + delegateAdapter.addAdapter(HotTopicDelegateAdapter(hotMessageListBean.data.list.ret.subList(0, 5))) + } + + override fun onBackPressed() { + if (state == State.SEARCH) { + state = State.INPUT + invalidateState() + KeyboardUtil.showKeyboard(editText) + } else { + finish() + } + } + + enum class State { + DEFAULT, + INPUT, + SEARCH; + } + + companion object { + const val EXTRA_KEYWORD = "keyword"; + } + + inner class SearchHistoryDelegateAdapter( + val data: List? = null + ) : SingleLayoutDelegateAdapter( + this, + { + val parentLayout = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + layoutParams = RecyclerView.LayoutParams(MATCH_PARENT, WRAP_CONTENT) + setPadding(16.dpToPx(), 8.dpToPx(), 8.dpToPx(), 8.dpToPx()) + setBackgroundResource(R.drawable.bg_bottom_radius_8dp) + backgroundTintList = ColorStateListUtils.createColorStateList(context, R.color.default_color_card) + } + RecyclerView(this).apply { + id = R.id.recyclerview + addItemDecoration(SpacesItemDecoration(0, 0, 8.dpToPx(), 8.dpToPx())) + }.also { + parentLayout.addView(it) + } + View.inflate(this, R.layout.layout_no_data, null).apply { + id = R.id.no_data + }.also { + parentLayout.addView(it) + } + parentLayout + } + ) { + val adapter: SearchHistoryAdapter = SearchHistoryAdapter(context).apply { + setData(data) + setOnItemClickListener { _, item, _ -> + editText.apply { + setText(item.content) + clearFocus() + KeyboardUtil.hideKeyboard(this) + } + keyword = item.content + } + } + val layoutManager: AutoLineFeedLayoutManager = AutoLineFeedLayoutManager() + + override fun convert(viewHolder: MyViewHolder, itemView: View) { + if (data.isNullOrEmpty()) { + viewHolder.getView(R.id.recyclerview).apply { + visibility = View.GONE + } + viewHolder.getView(R.id.no_data).apply { + visibility = View.VISIBLE + } + } else { + viewHolder.getView(R.id.recyclerview).apply { + visibility = View.VISIBLE + layoutManager = this@SearchHistoryDelegateAdapter.layoutManager + adapter = this@SearchHistoryDelegateAdapter.adapter + } + viewHolder.getView(R.id.no_data).apply { + visibility = View.GONE + } + } + } + } + + inner class HotTopicDelegateAdapter( + list: List? = null + ) : BaseSingleTypeDelegateAdapter( + this, + LinearLayoutHelper(), + list + ) { + override fun convert(viewHolder: MyViewHolder, item: HotMessageListBean.HotMessageRetBean, position: Int) { + viewHolder.setText(R.id.hot_order, "${position + 1}") + viewHolder.setText(R.id.hot_title, item.mulName) + viewHolder.setText(R.id.hot_desc, item.topicInfo.topicDesc) + val textView = viewHolder.getView(R.id.hot_order) + if (position > 2) { + TextViewCompat.setTextAppearance(textView, R.style.TextAppearance_Bold) + textView.setTextColor(context.getColorCompat(R.color.tieba)) + } else { + TextViewCompat.setTextAppearance(textView, R.style.TextAppearance_Bold_Italic) + textView.setTextColor(context.getColorCompat(R.color.red_accent)) + } + viewHolder.setVisibility(R.id.hot_desc, View.GONE) + if (position + 1 >= itemCount) { + viewHolder.itemView.setBackgroundResource(R.drawable.bg_bottom_radius_8dp) + } else { + viewHolder.itemView.setBackgroundColor(Color.WHITE) + } + viewHolder.itemView.backgroundTintList = ColorStateListUtils.createColorStateList(context, R.color.default_color_card) + } + + override fun getItemLayoutId(): Int { + return R.layout.item_hot_message_list + } + + init { + val navigationHelper = NavigationHelper.newInstance(context) + setOnItemClickListener { _, item, _ -> + navigationHelper.navigationByData( + NavigationHelper.ACTION_URL, + "https://tieba.baidu.com/mo/q/hotMessage?topic_id=${item.mulId}&topic_name=${item.mulName}" + ) + } + } + } + + override fun onTabSelected(tab: TabLayout.Tab) {} + + override fun onTabUnselected(tab: TabLayout.Tab) {} + + override fun onTabReselected(tab: TabLayout.Tab) { + toastShort(tab.text.toString()) + } +} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/ThreadActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/ThreadActivity.kt index 0b642204..5b068c0f 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/activities/ThreadActivity.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/ThreadActivity.kt @@ -39,6 +39,7 @@ import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaException import com.huanchengfly.tieba.post.components.MyLinearLayoutManager import com.huanchengfly.tieba.post.components.dialogs.EditTextDialog import com.huanchengfly.tieba.post.components.dividers.ThreadDivider +import com.huanchengfly.tieba.post.goToActivity import com.huanchengfly.tieba.post.models.ReplyInfoBean import com.huanchengfly.tieba.post.models.ThreadHistoryInfoBean import com.huanchengfly.tieba.post.models.database.History @@ -862,8 +863,34 @@ class ThreadActivity : BaseActivity(), View.OnClickListener { companion object { const val ACTION_REPLY_SUCCESS = "com.huanchengfly.tieba.post.action.REPLY_SUCCESS" + + const val EXTRA_THREAD_ID = "tid" + const val EXTRA_POST_ID = "pid" + const val EXTRA_FROM = "from" + const val EXTRA_SEE_LZ = "seeLz" + const val EXTRA_MAX_PID = "max_pid" + const val FROM_COLLECT = "collect" const val FROM_HISTORY = "history" const val FROM_FORUM = "forum" + + @JvmOverloads + @JvmStatic + fun launch( + context: Context, + threadId: String, + postId: String? = null, + seeLz: Boolean = false, + from: String? = null, + maxPid: String? = null + ) { + context.goToActivity { + putExtra("tid", threadId) + putExtra("pid", postId ?: "") + putExtra("seeLz", seeLz) + putExtra("from", from ?: "") + putExtra("max_pid", maxPid ?: "") + } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/HeaderDelegateAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/HeaderDelegateAdapter.kt index dc22985c..76fb7fbf 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/HeaderDelegateAdapter.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/HeaderDelegateAdapter.kt @@ -2,6 +2,7 @@ package com.huanchengfly.tieba.post.adapters import android.content.Context import android.graphics.drawable.Drawable +import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import android.widget.RelativeLayout @@ -17,10 +18,11 @@ import com.huanchengfly.tieba.post.ui.theme.utils.ColorStateListUtils import com.huanchengfly.tieba.post.widgets.theme.TintImageView import com.huanchengfly.tieba.post.widgets.theme.TintTextView -class HeaderDelegateAdapter( +class HeaderDelegateAdapter @JvmOverloads constructor( val context: Context, val title: CharSequence = "", - val iconDrawable: Drawable? = null + val startIconDrawable: Drawable? = null, + val endIconDrawable: Drawable? = null ) : DelegateAdapter.Adapter() { var topPadding: Int = DEFAULT_PADDING_DP.dpToPx() set(value) { @@ -69,22 +71,83 @@ class HeaderDelegateAdapter( field = value notifyDataSetChanged() } - var backgroundTintList: Int = NO_TINT + var backgroundTintList: Int = R.color.default_color_card set(value) { field = value notifyDataSetChanged() } - var iconTintList: Int = NO_TINT + var iconTintList: Int = R.color.default_color_primary set(value) { field = value notifyDataSetChanged() } - var titleTextColor: Int = NO_TINT + var titleTextColor: Int = R.color.default_color_primary set(value) { field = value notifyDataSetChanged() } + var onClickListener: View.OnClickListener? = null + private set + var onStartIconClickListener: View.OnClickListener? = null + private set + var onTitleClickListener: View.OnClickListener? = null + private set + var onEndIconClickListener: View.OnClickListener? = null + private set + + fun setOnStartIconClickListener(listener: View.OnClickListener?) { + onStartIconClickListener = listener + notifyDataSetChanged() + } + + fun setOnStartIconClickListener(listener: ((View) -> Unit)?) { + setOnStartIconClickListener(View.OnClickListener { + if (listener != null) { + listener(it) + } + }) + } + + fun setOnTitleClickListener(listener: View.OnClickListener?) { + onTitleClickListener = listener + notifyDataSetChanged() + } + + fun setOnTitleClickListener(listener: ((View) -> Unit)?) { + setOnTitleClickListener(View.OnClickListener { + if (listener != null) { + listener(it) + } + }) + } + + fun setOnEndIconClickListener(listener: View.OnClickListener?) { + onEndIconClickListener = listener + notifyDataSetChanged() + } + + fun setOnEndIconClickListener(listener: ((View) -> Unit)?) { + setOnEndIconClickListener(View.OnClickListener { + if (listener != null) { + listener(it) + } + }) + } + + fun setOnClickListener(listener: View.OnClickListener?) { + onClickListener = listener + notifyDataSetChanged() + } + + fun setOnClickListener(listener: ((View) -> Unit)?) { + setOnClickListener(View.OnClickListener { + if (listener != null) { + listener(it) + } + }) + } + fun setBackgroundResource(@DrawableRes resId: Int) { background = ContextCompat.getDrawable(context, resId) } @@ -92,11 +155,13 @@ class HeaderDelegateAdapter( constructor( context: Context, titleResId: Int = NO_TITLE, - iconResId: Int = NO_ICON + startIconResId: Int = NO_ICON, + endIconResId: Int = NO_ICON ) : this( context, if (titleResId == NO_TITLE) "" else context.getString(titleResId), - if (iconResId == NO_ICON) null else ContextCompat.getDrawable(context, iconResId) + if (startIconResId == NO_ICON) null else ContextCompat.getDrawable(context, startIconResId), + if (endIconResId == NO_ICON) null else ContextCompat.getDrawable(context, endIconResId) ) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder = MyViewHolder(context, R.layout.item_header_delegate) @@ -117,9 +182,24 @@ class HeaderDelegateAdapter( rootView.background = background rootView.backgroundTintList = ColorStateListUtils.createColorStateList(context, backgroundTintList) holder.getView(R.id.icon).setTintListResId(iconTintList) + holder.getView(R.id.end_icon).setTintListResId(iconTintList) holder.getView(R.id.title).setTintResId(titleTextColor) - holder.setImageDrawable(R.id.icon, iconDrawable) + holder.setImageDrawable(R.id.icon, startIconDrawable) + holder.setVisibility(R.id.icon, if (startIconDrawable == null) View.GONE else View.VISIBLE) + holder.setImageDrawable(R.id.end_icon, endIconDrawable) + holder.setVisibility(R.id.end_icon, if (endIconDrawable == null) View.GONE else View.VISIBLE) holder.setText(R.id.title, title) + setOnClickListener(rootView, onClickListener) + setOnClickListener(holder.getView(R.id.icon), onStartIconClickListener) + setOnClickListener(holder.getView(R.id.title), onTitleClickListener) + setOnClickListener(holder.getView(R.id.end_icon), onEndIconClickListener) + } + + private fun setOnClickListener(view: View, listener: View.OnClickListener?) { + view.apply { + view.setOnClickListener(listener) + view.isClickable = listener != null + } } companion object { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/HotMessageListAdapter.java b/app/src/main/java/com/huanchengfly/tieba/post/adapters/HotMessageListAdapter.java index 0ea5d05b..87e20ccf 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/HotMessageListAdapter.java +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/HotMessageListAdapter.java @@ -18,7 +18,8 @@ public class HotMessageListAdapter extends CommonBaseAdapter navigationHelper.navigationByData(NavigationHelper.ACTION_URL, String.format("https://tieba.baidu.com/mo/q/hotMessage?topic_id=%1$s&topic_name=%2$s", hotMessageRetBean.getMulId(), hotMessageRetBean.getMulName()))); + setOnItemClickListener((viewHolder, hotMessageRetBean, position) -> + navigationHelper.navigationByData(NavigationHelper.ACTION_URL, String.format("https://tieba.baidu.com/mo/q/hotMessage?topic_id=%1$s&topic_name=%2$s", hotMessageRetBean.getMulId(), hotMessageRetBean.getMulName()))); } @Override diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchForumAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchForumAdapter.kt index c8991384..b9df67b1 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchForumAdapter.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchForumAdapter.kt @@ -1,7 +1,7 @@ package com.huanchengfly.tieba.post.adapters import android.content.Context -import android.view.View +import android.graphics.Color import com.alibaba.android.vlayout.layout.LinearLayoutHelper import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.adapters.base.BaseMultiTypeDelegateAdapter @@ -12,35 +12,29 @@ import com.huanchengfly.tieba.post.utils.ImageUtil import com.huanchengfly.tieba.post.utils.NavigationHelper import java.util.* -class SearchForumAdapter(context: Context?) : BaseMultiTypeDelegateAdapter(context!!, LinearLayoutHelper()) { - private val navigationHelper: NavigationHelper - fun setData(data: SearchForumBean.DataBean) { - val forumInfoBeans: MutableList = ArrayList() - if (data.exactMatch != null && data.exactMatch.forumNameShow != null) { - forumInfoBeans.add(data.exactMatch) - } - forumInfoBeans.addAll(data.fuzzyMatch!!) - setData(forumInfoBeans) - } - - protected override fun convert(viewHolder: MyViewHolder, forumInfoBean: SearchForumBean.ForumInfoBean, position: Int, type: Int) { - viewHolder.setText(R.id.item_search_forum_title, forumInfoBean.forumNameShow + "吧") - viewHolder.setOnClickListener(R.id.item_search_forum) { view: View? -> navigationHelper.navigationByData(NavigationHelper.ACTION_FORUM, forumInfoBean.forumName) } - ImageUtil.load(viewHolder.getView(R.id.item_search_forum_avatar), ImageUtil.LOAD_TYPE_AVATAR, forumInfoBean.avatar) - if (type == TYPE_EXACT) { - val exactForumInfoBean = forumInfoBean as ExactForumInfoBean +class SearchForumAdapter(context: Context?) : BaseMultiTypeDelegateAdapter(context!!, LinearLayoutHelper()) { + override fun convert(viewHolder: MyViewHolder, item: SearchForumBean.ForumInfoBean, position: Int, viewType: Int) { + viewHolder.setText(R.id.item_search_forum_title, context.getString(R.string.title_forum, item.forumNameShow)) + ImageUtil.load(viewHolder.getView(R.id.item_search_forum_avatar), ImageUtil.LOAD_TYPE_AVATAR, item.avatar) + if (viewType == TYPE_EXACT) { + val exactForumInfoBean = item as ExactForumInfoBean viewHolder.setText(R.id.item_search_forum_subtitle, exactForumInfoBean.slogan) } + if (position + 1 >= itemCount) { + viewHolder.itemView.setBackgroundResource(R.drawable.bg_bottom_radius_8dp_ripple) + } else { + viewHolder.itemView.setBackgroundResource(R.drawable.bg_ripple) + } } - override fun getItemLayoutId(type: Int): Int { - return if (type == TYPE_EXACT) { + override fun getItemLayoutId(itemType: Int): Int { + return if (itemType == TYPE_EXACT) { R.layout.item_search_forum_exact } else R.layout.item_search_forum } - protected override fun getViewType(i: Int, forumInfoBean: SearchForumBean.ForumInfoBean): Int { - return if (forumInfoBean is ExactForumInfoBean) { + override fun getViewType(position: Int, item: SearchForumBean.ForumInfoBean): Int { + return if (item is ExactForumInfoBean) { TYPE_EXACT } else TYPE_FUZZY } @@ -49,8 +43,4 @@ class SearchForumAdapter(context: Context?) : BaseMultiTypeDelegateAdapter(context) { - override fun getItemLayoutId(): Int { - return 0 - } +class SearchHistoryAdapter(context: Context) : BaseSingleTypeAdapter(context) { + override fun getItemLayoutId(): Int = R.layout.item_search_history_chip - protected override fun convert(viewHolder: MyViewHolder, searchHistory: SearchHistory, position: Int) {} + override fun convert(viewHolder: MyViewHolder, item: SearchHistory, position: Int) { + viewHolder.setText(R.id.text, item.content) + } } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchThreadAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchThreadAdapter.kt index 83b0db1d..0fb847fc 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchThreadAdapter.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchThreadAdapter.kt @@ -10,31 +10,34 @@ import com.huanchengfly.tieba.post.fragments.SearchThreadFragment import com.huanchengfly.tieba.post.utils.NavigationHelper import java.util.* -class SearchThreadAdapter(fragment: SearchThreadFragment) : BaseSingleTypeAdapter(fragment.requireContext()) { - private val navigationHelper: NavigationHelper - private val order = 0 - private val filter = 0 - protected override fun convert(viewHolder: MyViewHolder, threadInfoBean: SearchThreadBean.ThreadInfoBean, position: Int) { - viewHolder.setOnClickListener(R.id.item_search_thread) { view: View? -> - val map: MutableMap = HashMap() - map["tid"] = threadInfoBean.tid - map["pid"] = threadInfoBean.pid - navigationHelper.navigationByData(NavigationHelper.ACTION_THREAD, map) - } - viewHolder.setText(R.id.item_search_thread_title, threadInfoBean.title) - viewHolder.setText(R.id.item_search_thread_content, threadInfoBean.content) - viewHolder.setText(R.id.item_search_thread_user, threadInfoBean.user!!.userName) - if (threadInfoBean.forumName == null) { +class SearchThreadAdapter(fragment: SearchThreadFragment) : BaseSingleTypeAdapter(fragment.requireContext()) { + override fun convert(viewHolder: MyViewHolder, item: SearchThreadBean.ThreadInfoBean, position: Int) { + viewHolder.setText(R.id.item_search_thread_title, item.title) + viewHolder.setText(R.id.item_search_thread_content, item.content) + viewHolder.setText(R.id.item_search_thread_user, item.user!!.userName) + if (item.forumName == null) { viewHolder.setText( R.id.item_search_thread_info, - DateUtils.getRelativeTimeSpanString(threadInfoBean.time!!.toLong() * 1000L) + DateUtils.getRelativeTimeSpanString(item.time!!.toLong() * 1000L) ) } else { viewHolder.setText( R.id.item_search_thread_info, - threadInfoBean.forumName + " " + DateUtils.getRelativeTimeSpanString(threadInfoBean.time!!.toLong() * 1000L) + item.forumName + " " + DateUtils.getRelativeTimeSpanString(item.time!!.toLong() * 1000L) ) } + viewHolder.itemView.setBackgroundResource( + if (position == 0 && position + 1 == itemCount) { + R.drawable.bg_radius_8dp_ripple + } else if (position == 0) { + R.drawable.bg_top_radius_8dp_ripple + } else if (position + 1 == itemCount) { + R.drawable.bg_radius_8dp_ripple + } else { + R.drawable.bg_ripple + } + ) + } override fun getItemLayoutId(): Int { @@ -42,8 +45,6 @@ class SearchThreadAdapter(fragment: SearchThreadFragment) : BaseSingleTypeAdapte } init { - val context = fragment.requireContext() - navigationHelper = NavigationHelper.newInstance(context) /* View headerView = Util.inflate(context, R.layout.layout_search_header); if (headerView != null) { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SingleLayoutDelegateAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SingleLayoutDelegateAdapter.kt index c078408f..1917b224 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SingleLayoutDelegateAdapter.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SingleLayoutDelegateAdapter.kt @@ -1,4 +1,4 @@ -package com.huanchengfly.tieba.post.adapters.base +package com.huanchengfly.tieba.post.adapters import android.content.Context import android.view.View @@ -9,7 +9,7 @@ import com.alibaba.android.vlayout.LayoutHelper import com.alibaba.android.vlayout.layout.SingleLayoutHelper import com.huanchengfly.tieba.post.components.MyViewHolder -abstract class BaseSingleLayoutAdapter( +open class SingleLayoutDelegateAdapter( val context: Context, val itemView: View ) : DelegateAdapter.Adapter() { @@ -32,13 +32,13 @@ abstract class BaseSingleLayoutAdapter( final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder = MyViewHolder(itemView) - final override fun onBindViewHolder(holder: MyViewHolder, position: Int) { - convert(holder, itemView) + final override fun onBindViewHolder(viewHolder: MyViewHolder, position: Int) { + convert(viewHolder, itemView) } final override fun getItemCount(): Int = 1 override fun onCreateLayoutHelper(): LayoutHelper = SingleLayoutHelper() - abstract fun convert(holder: MyViewHolder, itemView: View) + open fun convert(viewHolder: MyViewHolder, itemView: View) {} } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseAdapter.kt index 691dbd24..a3e27b87 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseAdapter.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseAdapter.kt @@ -1,15 +1,15 @@ package com.huanchengfly.tieba.post.adapters.base import android.content.Context +import androidx.recyclerview.widget.RecyclerView import com.alibaba.android.vlayout.DelegateAdapter import com.alibaba.android.vlayout.LayoutHelper import com.huanchengfly.tieba.post.components.MyViewHolder -abstract class BaseDelegateAdapter( +abstract class BaseAdapter( val context: Context, - val layoutHelper: LayoutHelper, items: List? = null -) : DelegateAdapter.Adapter() { +) : RecyclerView.Adapter() { private var itemList: MutableList = (items ?: emptyList()).toMutableList() var onItemClickListener: OnItemClickListener? = null @@ -49,8 +49,6 @@ abstract class BaseDelegateAdapter( override fun getItemCount(): Int = getCount() - override fun onCreateLayoutHelper(): LayoutHelper = layoutHelper - fun getItem(position: Int): Item = itemList[position] fun getItemList(): MutableList = itemList @@ -101,12 +99,4 @@ abstract class BaseDelegateAdapter( itemList.clear() notifyDataSetChanged() } - - interface OnItemClickListener { - fun onClick(viewHolder: MyViewHolder, item: Item, position: Int) - } - - interface OnItemLongClickListener { - fun onLongClick(viewHolder: MyViewHolder, item: Item, position: Int): Boolean - } } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseDelegateAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseDelegateAdapter.kt index 691dbd24..b4d30445 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseDelegateAdapter.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseDelegateAdapter.kt @@ -101,12 +101,4 @@ abstract class BaseDelegateAdapter( itemList.clear() notifyDataSetChanged() } - - interface OnItemClickListener { - fun onClick(viewHolder: MyViewHolder, item: Item, position: Int) - } - - interface OnItemLongClickListener { - fun onLongClick(viewHolder: MyViewHolder, item: Item, position: Int): Boolean - } } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseMultiTypeAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseMultiTypeAdapter.kt index 9f21e974..9a67c700 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseMultiTypeAdapter.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseMultiTypeAdapter.kt @@ -6,11 +6,10 @@ import android.view.ViewGroup import com.alibaba.android.vlayout.LayoutHelper import com.huanchengfly.tieba.post.components.MyViewHolder -abstract class BaseMultiTypeDelegateAdapter( - context: Context, - layoutHelper: LayoutHelper -) : BaseDelegateAdapter( - context, layoutHelper +abstract class BaseMultiTypeAdapter( + context: Context +) : BaseAdapter( + context ) { protected abstract fun getItemLayoutId( itemType: Int @@ -28,12 +27,12 @@ abstract class BaseMultiTypeDelegateAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder = MyViewHolder(context, getItemLayoutId(viewType)) override fun onBindViewHolder(holder: MyViewHolder, position: Int) { - holder.setItemOnClickListener(View.OnClickListener { + holder.setItemOnClickListener { onItemClickListener?.onClick(holder, getItem(position), position) - }) - holder.setItemOnLongClickListener(View.OnLongClickListener { + } + holder.setItemOnLongClickListener { onItemLongClickListener?.onLongClick(holder, getItem(position), position) ?: false - }) + } convert(holder, getItem(position), position, getItemViewType(position)) } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseSingleTypeAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseSingleTypeAdapter.kt index 427052cc..cf710cbd 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseSingleTypeAdapter.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseSingleTypeAdapter.kt @@ -6,23 +6,22 @@ import android.view.ViewGroup import com.alibaba.android.vlayout.LayoutHelper import com.huanchengfly.tieba.post.components.MyViewHolder -abstract class BaseSingleTypeDelegateAdapter( - context: Context, - layoutHelper: LayoutHelper -) : BaseDelegateAdapter( - context, layoutHelper +abstract class BaseSingleTypeAdapter( + context: Context +) : BaseAdapter( + context ) { protected abstract fun getItemLayoutId(): Int override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder = MyViewHolder(context, getItemLayoutId()) override fun onBindViewHolder(holder: MyViewHolder, position: Int) { - holder.setItemOnClickListener(View.OnClickListener { + holder.setItemOnClickListener { onItemClickListener?.onClick(holder, getItem(position), position) - }) - holder.setItemOnLongClickListener(View.OnLongClickListener { + } + holder.setItemOnLongClickListener { onItemLongClickListener?.onLongClick(holder, getItem(position), position) ?: false - }) + } convert(holder, getItem(position), position) } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseSingleTypeDelegateAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseSingleTypeDelegateAdapter.kt index 427052cc..fbeb7198 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseSingleTypeDelegateAdapter.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseSingleTypeDelegateAdapter.kt @@ -6,11 +6,12 @@ import android.view.ViewGroup import com.alibaba.android.vlayout.LayoutHelper import com.huanchengfly.tieba.post.components.MyViewHolder -abstract class BaseSingleTypeDelegateAdapter( +abstract class BaseSingleTypeDelegateAdapter @JvmOverloads constructor( context: Context, - layoutHelper: LayoutHelper + layoutHelper: LayoutHelper, + items: List? = null ) : BaseDelegateAdapter( - context, layoutHelper + context, layoutHelper, items ) { protected abstract fun getItemLayoutId(): Int diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/interfaces.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/interfaces.kt index 9e464113..35b879ca 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/interfaces.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/interfaces.kt @@ -1,2 +1,11 @@ package com.huanchengfly.tieba.post.adapters.base +import com.huanchengfly.tieba.post.components.MyViewHolder + +interface OnItemClickListener { + fun onClick(viewHolder: MyViewHolder, item: Item, position: Int) +} + +interface OnItemLongClickListener { + fun onLongClick(viewHolder: MyViewHolder, item: Item, position: Int): Boolean +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/components/AutoLineFeedLayoutManager.java b/app/src/main/java/com/huanchengfly/tieba/post/components/AutoLineFeedLayoutManager.java index f14c9f87..2c8de548 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/components/AutoLineFeedLayoutManager.java +++ b/app/src/main/java/com/huanchengfly/tieba/post/components/AutoLineFeedLayoutManager.java @@ -1,4 +1,54 @@ package com.huanchengfly.tieba.post.components; -public class AutoLineFeedLayoutManager { +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + +public class AutoLineFeedLayoutManager extends RecyclerView.LayoutManager { + @Override + public RecyclerView.LayoutParams generateDefaultLayoutParams() { + return new RecyclerView.LayoutParams( + RecyclerView.LayoutParams.WRAP_CONTENT, + RecyclerView.LayoutParams.WRAP_CONTENT); + } + + @Override + public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + detachAndScrapAttachedViews(recycler); + + int sumWidth = getWidth(); + + int curLineWidth = 0, curLineTop = 0; + int lastLineMaxHeight = 0; + for (int i = 0; i < getItemCount(); i++) { + View view = recycler.getViewForPosition(i); + + addView(view); + measureChildWithMargins(view, 0, 0); + int width = getDecoratedMeasuredWidth(view); + int height = getDecoratedMeasuredHeight(view); + + curLineWidth += width; + if (curLineWidth <= sumWidth) {//不需要换行 + layoutDecorated(view, curLineWidth - width, curLineTop, curLineWidth, curLineTop + height); + //比较当前行多有item的最大高度 + lastLineMaxHeight = Math.max(lastLineMaxHeight, height); + } else {//换行 + curLineWidth = width; + if (lastLineMaxHeight == 0) { + lastLineMaxHeight = height; + } + //记录当前行top + curLineTop += lastLineMaxHeight; + + layoutDecorated(view, 0, curLineTop, width, curLineTop + height); + lastLineMaxHeight = height; + } + } + } + + @Override + public boolean isAutoMeasureEnabled() { + return true; + } } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/components/dividers/SearchDivider.java b/app/src/main/java/com/huanchengfly/tieba/post/components/dividers/SearchDivider.java index ae8dc24d..a7586e63 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/components/dividers/SearchDivider.java +++ b/app/src/main/java/com/huanchengfly/tieba/post/components/dividers/SearchDivider.java @@ -2,6 +2,7 @@ package com.huanchengfly.tieba.post.components.dividers; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.view.View; @@ -24,14 +25,12 @@ public class SearchDivider extends RecyclerView.ItemDecoration implements Tintab private int mOrientation; private int mDividerHeight; private int mCommonDividerHeight; - private Context mContext; public SearchDivider(Context context) { - mContext = context; mOrientation = LinearLayoutManager.VERTICAL; mDivider = ContextCompat.getDrawable(context, R.drawable.drawable_divider); mDividerHeight = DisplayUtil.dp2px(context, 8); - mCommonDividerHeight = DisplayUtil.dp2px(context, 1); + mCommonDividerHeight = DisplayUtil.dp2px(context, 0); tint(); } @@ -95,6 +94,6 @@ public class SearchDivider extends RecyclerView.ItemDecoration implements Tintab @Override public void tint() { - mDivider = ThemeUtils.tintDrawable(mDivider, ThemeUtils.getColorByAttr(mContext, R.attr.colorDivider)); + mDivider = ThemeUtils.tintDrawable(mDivider, Color.TRANSPARENT); } } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/components/dividers/SpacesItemDecoration.java b/app/src/main/java/com/huanchengfly/tieba/post/components/dividers/SpacesItemDecoration.java index 00e2ca50..a4bfda44 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/components/dividers/SpacesItemDecoration.java +++ b/app/src/main/java/com/huanchengfly/tieba/post/components/dividers/SpacesItemDecoration.java @@ -7,18 +7,31 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; public class SpacesItemDecoration extends RecyclerView.ItemDecoration { - private int space; + private int leftSpace; + private int topSpace; + private int rightSpace; + private int bottomSpace; public SpacesItemDecoration(int space) { - this.space = space; + this.leftSpace = + this.topSpace = + this.rightSpace = + this.bottomSpace = space; + } + + public SpacesItemDecoration(int left, int top, int right, int bottom) { + this.topSpace = top; + this.rightSpace = right; + this.bottomSpace = bottom; + this.leftSpace = left; } @Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { - outRect.left = space; - outRect.right = space; - outRect.bottom = space; - outRect.top = space; + outRect.left = leftSpace; + outRect.top = topSpace; + outRect.right = rightSpace; + outRect.bottom = bottomSpace; } } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/fragments/MainForumListFragment.kt b/app/src/main/java/com/huanchengfly/tieba/post/fragments/MainForumListFragment.kt index 335517f4..ee519318 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/fragments/MainForumListFragment.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/fragments/MainForumListFragment.kt @@ -15,12 +15,15 @@ import com.alibaba.android.vlayout.DelegateAdapter import com.alibaba.android.vlayout.VirtualLayoutManager import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout.OnOffsetChangedListener -import com.huanchengfly.tieba.post.BaseApplication -import com.huanchengfly.tieba.post.R +import com.google.android.material.textfield.TextInputLayout +import com.huanchengfly.tieba.post.* import com.huanchengfly.tieba.post.activities.ForumActivity +import com.huanchengfly.tieba.post.activities.NewSearchActivity import com.huanchengfly.tieba.post.adapters.HeaderDelegateAdapter import com.huanchengfly.tieba.post.adapters.MainForumListAdapter import com.huanchengfly.tieba.post.adapters.base.BaseDelegateAdapter +import com.huanchengfly.tieba.post.adapters.base.OnItemClickListener +import com.huanchengfly.tieba.post.adapters.base.OnItemLongClickListener import com.huanchengfly.tieba.post.api.Error import com.huanchengfly.tieba.post.api.ForumSortType import com.huanchengfly.tieba.post.api.TiebaApi @@ -29,10 +32,8 @@ import com.huanchengfly.tieba.post.api.models.ForumRecommend import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaException import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaLocalException import com.huanchengfly.tieba.post.components.MyViewHolder -import com.huanchengfly.tieba.post.dpToPx import com.huanchengfly.tieba.post.interfaces.Refreshable import com.huanchengfly.tieba.post.models.database.TopForum -import com.huanchengfly.tieba.post.toastShort import com.huanchengfly.tieba.post.utils.* import com.huanchengfly.tieba.post.utils.preload.PreloadUtil import com.huanchengfly.tieba.post.utils.preload.loaders.ForumLoader @@ -45,8 +46,8 @@ import retrofit2.Response import kotlin.math.abs class MainForumListFragment : BaseFragment(), Refreshable, Toolbar.OnMenuItemClickListener, - BaseDelegateAdapter.OnItemClickListener, - BaseDelegateAdapter.OnItemLongClickListener { + OnItemClickListener, + OnItemLongClickListener { companion object { val MOTION_START_OFFSET = 83f.dpToPx() } @@ -57,6 +58,9 @@ class MainForumListFragment : BaseFragment(), Refreshable, Toolbar.OnMenuItemCli @BindView(R.id.search_bar_motion) lateinit var searchBarMotionLayout: MotionLayout + @BindView(R.id.search_bar) + lateinit var searchBar: TextInputLayout + @BindView(R.id.refresh_header) lateinit var refreshLayoutHeader: MaterialHeader @@ -163,6 +167,12 @@ class MainForumListFragment : BaseFragment(), Refreshable, Toolbar.OnMenuItemCli } reloadAdapters() toolbar.setOnMenuItemClickListener(this) + searchBar.editText?.setOnFocusChangeListener { v, hasFocus -> + if (hasFocus) { + v.clearFocus() + attachContext.goToActivity() + } + } btnOkSign.setOnClickListener { TiebaUtil.startSign(attachContext) } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchForumFragment.kt b/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchForumFragment.kt index 70694dc0..98492dff 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchForumFragment.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchForumFragment.kt @@ -2,55 +2,73 @@ package com.huanchengfly.tieba.post.fragments import android.os.Bundle import android.view.View -import android.widget.Toast import androidx.recyclerview.widget.RecyclerView -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import butterknife.BindView +import com.alibaba.android.vlayout.DelegateAdapter import com.alibaba.android.vlayout.VirtualLayoutManager import com.huanchengfly.tieba.post.R +import com.huanchengfly.tieba.post.activities.ForumActivity +import com.huanchengfly.tieba.post.adapters.HeaderDelegateAdapter import com.huanchengfly.tieba.post.adapters.SearchForumAdapter +import com.huanchengfly.tieba.post.adapters.base.OnItemClickListener import com.huanchengfly.tieba.post.api.TiebaApi.getInstance import com.huanchengfly.tieba.post.api.models.SearchForumBean +import com.huanchengfly.tieba.post.components.MyViewHolder +import com.huanchengfly.tieba.post.dpToPx import com.huanchengfly.tieba.post.interfaces.ISearchFragment +import com.huanchengfly.tieba.post.toastShort import com.huanchengfly.tieba.post.utils.ThemeUtil +import com.scwang.smart.refresh.layout.SmartRefreshLayout import retrofit2.Call import retrofit2.Callback import retrofit2.Response -class SearchForumFragment : BaseFragment(), ISearchFragment { - @BindView(R.id.fragment_search_refresh_layout) - var refreshLayout: SwipeRefreshLayout? = null +class SearchForumFragment : BaseFragment(), ISearchFragment, OnItemClickListener { + @JvmField + @BindView(R.id.fragment_search_refresh) + var refreshLayout: SmartRefreshLayout? = null @BindView(R.id.fragment_search_recycler_view) - var recyclerView: RecyclerView? = null + lateinit var recyclerView: RecyclerView + private var keyword: String? = null - private var mAdapter: SearchForumAdapter? = null + private lateinit var layoutManager: VirtualLayoutManager + private lateinit var delegateAdapter: DelegateAdapter + private lateinit var exactMatchAdapter: SearchForumAdapter + private lateinit var fuzzyMatchAdapter: SearchForumAdapter private var mData: SearchForumBean.DataBean? = null + override fun setKeyword( keyword: String?, needRefresh: Boolean ) { this.keyword = keyword - if (mAdapter != null) { - if (needRefresh) { - refresh() - } else { - mData = null - mAdapter!!.reset() - } + if (needRefresh) { + refreshLayout?.autoRefresh() + } else { + mData = null + delegateAdapter.clear() } } override fun onFragmentVisibleChange(isVisible: Boolean) { if (mData == null && isVisible) { - refresh() + refreshLayout?.autoRefresh() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (arguments != null) { - keyword = arguments!!.getString(ARG_KEYWORD) + keyword = requireArguments().getString(ARG_KEYWORD) + } + layoutManager = VirtualLayoutManager(attachContext) + delegateAdapter = DelegateAdapter(layoutManager) + exactMatchAdapter = SearchForumAdapter(attachContext).apply { + setOnItemClickListener(this@SearchForumFragment) + } + fuzzyMatchAdapter = SearchForumAdapter(attachContext).apply { + setOnItemClickListener(this@SearchForumFragment) } } @@ -60,44 +78,73 @@ class SearchForumFragment : BaseFragment(), ISearchFragment { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - recyclerView!!.layoutManager = VirtualLayoutManager(attachContext) - mAdapter = SearchForumAdapter(attachContext) - recyclerView!!.adapter = mAdapter + recyclerView.layoutManager = layoutManager + recyclerView.adapter = delegateAdapter refreshLayout!!.setOnRefreshListener { refresh() } - ThemeUtil.setThemeForSwipeRefreshLayout(refreshLayout) - } - - private fun setRefreshing(refreshing: Boolean) { - if (refreshLayout != null) refreshLayout!!.isRefreshing = refreshing + ThemeUtil.setThemeForSmartRefreshLayout(refreshLayout) } private fun refresh() { if (keyword == null) { return } - setRefreshing(true) getInstance().searchForum(keyword!!).enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { mData = response.body()!!.data + refreshLayout?.finishRefreshWithNoMoreData() reloadAdapters() - setRefreshing(false) } override fun onFailure(call: Call, t: Throwable) { - setRefreshing(false) - Toast.makeText(attachContext, t.message, Toast.LENGTH_SHORT).show() + t.message?.let { attachContext.toastShort(it) } + refreshLayout?.finishRefresh(false) } }) } - private fun reloadAdapters() {} + private fun reloadAdapters() { + delegateAdapter.clear() + if (mData != null) { + if (mData!!.exactMatch != null) { + exactMatchAdapter.setData(listOf(mData!!.exactMatch!!)) + delegateAdapter.addAdapter(HeaderDelegateAdapter( + attachContext, + R.string.title_exact_match, + R.drawable.ic_round_graphic_eq + ).apply { + setBackgroundResource(R.drawable.bg_top_radius_8dp) + topMargin = 8.dpToPx() + startPadding = 16.dpToPx() + endPadding = 16.dpToPx() + }) + delegateAdapter.addAdapter(exactMatchAdapter) + } + if (!mData!!.fuzzyMatch.isNullOrEmpty()) { + fuzzyMatchAdapter.setData(mData!!.fuzzyMatch!!) + delegateAdapter.addAdapter(HeaderDelegateAdapter( + attachContext, + R.string.title_fuzzy_match, + R.drawable.ic_infinite + ).apply { + setBackgroundResource(R.drawable.bg_top_radius_8dp) + topMargin = 8.dpToPx() + startPadding = 16.dpToPx() + endPadding = 16.dpToPx() + }) + delegateAdapter.addAdapter(fuzzyMatchAdapter) + } + } + } + override fun onFragmentFirstVisible() { - refresh() + refreshLayout!!.autoRefresh() } companion object { const val TAG = "SearchForumFragment" const val ARG_KEYWORD = "keyword" + + @JvmStatic @JvmOverloads fun newInstance(keyword: String? = null): SearchForumFragment { val forumFragment = SearchForumFragment() @@ -107,4 +154,8 @@ class SearchForumFragment : BaseFragment(), ISearchFragment { return forumFragment } } + + override fun onClick(viewHolder: MyViewHolder, item: SearchForumBean.ForumInfoBean, position: Int) { + item.forumName?.let { ForumActivity.launch(attachContext, it) } + } } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchThreadFragment.kt b/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchThreadFragment.kt index a921d2e1..d75be04f 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchThreadFragment.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchThreadFragment.kt @@ -5,26 +5,29 @@ import android.view.View import android.widget.Toast import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import butterknife.BindView import com.huanchengfly.tieba.post.api.SearchThreadFilter import com.huanchengfly.tieba.post.api.SearchThreadOrder import com.huanchengfly.tieba.post.api.TiebaApi import com.huanchengfly.tieba.post.api.models.SearchThreadBean import com.huanchengfly.tieba.post.R +import com.huanchengfly.tieba.post.activities.ThreadActivity import com.huanchengfly.tieba.post.adapters.SearchThreadAdapter import com.huanchengfly.tieba.post.components.MyLinearLayoutManager import com.huanchengfly.tieba.post.components.dividers.CommonDivider +import com.huanchengfly.tieba.post.interfaces.ISearchFragment import com.huanchengfly.tieba.post.interfaces.OnOrderSwitchListener import com.huanchengfly.tieba.post.utils.ThemeUtil +import com.scwang.smart.refresh.layout.SmartRefreshLayout import retrofit2.Call import retrofit2.Callback import retrofit2.Response -class SearchThreadFragment : BaseFragment(), OnOrderSwitchListener { +class SearchThreadFragment : BaseFragment(), OnOrderSwitchListener, ISearchFragment { private var keyword: String? = null - @BindView(R.id.fragment_search_refresh_layout) - lateinit var refreshLayout: SwipeRefreshLayout + @JvmField + @BindView(R.id.fragment_search_refresh) + var refreshLayout: SmartRefreshLayout? = null @BindView(R.id.fragment_search_recycler_view) lateinit var recyclerView: RecyclerView private var mAdapter: SearchThreadAdapter? = null @@ -32,19 +35,25 @@ class SearchThreadFragment : BaseFragment(), OnOrderSwitchListener { private var filter: SearchThreadFilter = SearchThreadFilter.ONLY_THREAD private var mData: SearchThreadBean.DataBean? = null private var page = 0 - fun setKeyword(keyword: String?, refresh: Boolean) { + + override fun setKeyword( + keyword: String?, + needRefresh: Boolean + ) { this.keyword = keyword - if (refresh) { - refresh() - } else { - mData = null - mAdapter!!.reset() + if (mAdapter != null) { + if (needRefresh) { + refreshLayout?.autoRefresh() + } else { + mData = null + mAdapter!!.reset() + } } } override fun onFragmentVisibleChange(isVisible: Boolean) { if (mData == null && isVisible) { - refresh() + refreshLayout?.autoRefresh() } } @@ -53,7 +62,7 @@ class SearchThreadFragment : BaseFragment(), OnOrderSwitchListener { order = SearchThreadOrder.NEW filter = SearchThreadFilter.ONLY_THREAD if (arguments != null) { - keyword = arguments!!.getString(ARG_KEYWORD) + keyword = requireArguments().getString(ARG_KEYWORD) } } @@ -64,19 +73,18 @@ class SearchThreadFragment : BaseFragment(), OnOrderSwitchListener { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) mAdapter = SearchThreadAdapter(this).apply { - setLoadingView(R.layout.layout_footer_loading) - setLoadEndView(R.layout.layout_footer_loadend) - setLoadFailedView(R.layout.layout_footer_load_failed) - setOnLoadMoreListener { isReload: Boolean -> loadMore(isReload) } + setOnItemClickListener { _, item, _ -> + ThreadActivity.launch(attachContext, item.tid!!, item.pid) + } } recyclerView.apply { layoutManager = MyLinearLayoutManager(attachContext) adapter = mAdapter - addItemDecoration(CommonDivider(attachContext, LinearLayoutManager.VERTICAL, R.drawable.drawable_divider_1dp)) } - refreshLayout.apply { + refreshLayout!!.apply { setOnRefreshListener { refresh() } - ThemeUtil.setThemeForSwipeRefreshLayout(this) + setOnLoadMoreListener { loadMore() } + ThemeUtil.setThemeForSmartRefreshLayout(this) } } @@ -85,52 +93,52 @@ class SearchThreadFragment : BaseFragment(), OnOrderSwitchListener { return false } if (mData!!.hasMore == 0) { - mAdapter!!.loadEnd() + refreshLayout?.setNoMoreData(true) } return mData!!.hasMore != 0 } private fun refresh() { - refreshLayout.isRefreshing = true + if (keyword == null) { + return + } page = 1 TiebaApi.getInstance().searchThread(keyword!!, page, order, filter).enqueue(object : Callback { override fun onFailure(call: Call, t: Throwable) { - refreshLayout.isRefreshing = false Toast.makeText(attachContext, t.message, Toast.LENGTH_SHORT).show() + refreshLayout?.finishRefresh(false) } override fun onResponse(call: Call, response: Response) { val searchThreadBean = response.body()!! mData = searchThreadBean.data - mAdapter!!.setNewData(mData!!.postList) - refreshLayout.isRefreshing = false + mAdapter!!.setData(mData!!.postList) + refreshLayout?.finishRefresh(true) } }) } - private fun loadMore(isReload: Boolean) { + private fun loadMore() { if (hasMore()) { - if (!isReload) { - page += 1 - } - TiebaApi.getInstance().searchThread(keyword!!, page, order, filter).enqueue(object : Callback { + TiebaApi.getInstance().searchThread(keyword!!, page + 1, order, filter).enqueue(object : Callback { override fun onFailure(call: Call, t: Throwable) { - refreshLayout.isRefreshing = false Toast.makeText(attachContext, t.message, Toast.LENGTH_SHORT).show() + refreshLayout?.finishLoadMore(false) } override fun onResponse(call: Call, response: Response) { val searchThreadBean = response.body()!! mData = searchThreadBean.data - mAdapter!!.setLoadMoreData(mData!!.postList) - refreshLayout.isRefreshing = false + mData!!.postList?.let { mAdapter!!.insert(it) } + page += 1 + refreshLayout?.finishLoadMore(true) } }) } } override fun onFragmentFirstVisible() { - refresh() + refreshLayout!!.autoRefresh() } override fun onSwitch(type: Int, value: Int) { @@ -144,8 +152,10 @@ class SearchThreadFragment : BaseFragment(), OnOrderSwitchListener { companion object { const val TAG = "SearchThreadFragment" const val ARG_KEYWORD = "keyword" + @JvmStatic - fun newInstance(keyword: String?): SearchThreadFragment { + @JvmOverloads + fun newInstance(keyword: String? = null): SearchThreadFragment { val fragment = SearchThreadFragment() val bundle = Bundle() bundle.putString(ARG_KEYWORD, keyword) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchUserFragment.kt b/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchUserFragment.kt index 2a7c01ae..c620ef59 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchUserFragment.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchUserFragment.kt @@ -13,39 +13,49 @@ import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.adapters.SearchUserAdapter import com.huanchengfly.tieba.post.components.MyLinearLayoutManager import com.huanchengfly.tieba.post.components.dividers.SearchDivider +import com.huanchengfly.tieba.post.interfaces.ISearchFragment +import com.huanchengfly.tieba.post.toastShort import com.huanchengfly.tieba.post.utils.ThemeUtil +import com.scwang.smart.refresh.layout.SmartRefreshLayout import retrofit2.Call import retrofit2.Callback import retrofit2.Response -class SearchUserFragment : BaseFragment() { +class SearchUserFragment : BaseFragment(), ISearchFragment { private var keyword: String? = null - @BindView(R.id.fragment_search_refresh_layout) - lateinit var mRefreshLayout: SwipeRefreshLayout + @JvmField + @BindView(R.id.fragment_search_refresh) + var mRefreshLayout: SmartRefreshLayout? = null @BindView(R.id.fragment_search_recycler_view) lateinit var mRecyclerView: RecyclerView private var mAdapter: SearchUserAdapter? = null private var mData: SearchUserDataBean? = null - fun setKeyword(keyword: String?, refresh: Boolean) { + + override fun setKeyword( + keyword: String?, + needRefresh: Boolean + ) { this.keyword = keyword - if (refresh) { - refresh() - } else { - mData = null - mAdapter!!.reset() + this.mData = null + if (mAdapter != null) { + if (needRefresh) { + mRefreshLayout?.autoRefresh() + } else { + mAdapter!!.reset() + } } } override fun onFragmentVisibleChange(isVisible: Boolean) { if (mData == null && isVisible) { - refresh() + mRefreshLayout?.autoRefresh() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (arguments != null) { - keyword = arguments!!.getString(ARG_KEYWORD) + keyword = requireArguments().getString(ARG_KEYWORD) } } @@ -55,53 +65,52 @@ class SearchUserFragment : BaseFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - mAdapter = SearchUserAdapter(attachContext).apply { - setLoadEndView(R.layout.layout_footer_loadend) - setLoadFailedView(R.layout.layout_footer_load_failed) - } + mAdapter = SearchUserAdapter(attachContext) mRecyclerView.apply { layoutManager = MyLinearLayoutManager(attachContext) addItemDecoration(SearchDivider(attachContext)) adapter = mAdapter } - mRefreshLayout.apply { + mRefreshLayout!!.apply { + setEnableLoadMore(false) setOnRefreshListener { refresh() } - ThemeUtil.setThemeForSwipeRefreshLayout(this) + ThemeUtil.setThemeForSmartRefreshLayout(this) } } private fun refresh() { - mRefreshLayout.isRefreshing = true + if (keyword == null) { + return + } TiebaApi.getInstance().searchUser(keyword!!).enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { val searchUserDataBean = response.body()!!.data mData = searchUserDataBean mAdapter!!.setData(searchUserDataBean) - mRefreshLayout.isRefreshing = false + mRefreshLayout?.finishRefreshWithNoMoreData() if (searchUserDataBean?.hasMore == 0) mAdapter!!.loadEnd() } override fun onFailure(call: Call, t: Throwable) { - mRefreshLayout.isRefreshing = false - Toast.makeText(attachContext, t.message, Toast.LENGTH_SHORT).show() + t.message?.let { attachContext.toastShort(it) } + mRefreshLayout?.finishRefresh(false) } }) } override fun onFragmentFirstVisible() { - refresh() + mRefreshLayout!!.autoRefresh() } companion object { const val TAG = "SearchUserFragment" const val ARG_KEYWORD = "keyword" @JvmStatic - fun newInstance(keyword: String?): SearchUserFragment { - val forumFragment = SearchUserFragment() - val bundle = Bundle() - bundle.putString(ARG_KEYWORD, keyword) - forumFragment.arguments = bundle - return forumFragment + @JvmOverloads + fun newInstance(keyword: String? = null): SearchUserFragment = SearchUserFragment().apply { + arguments = Bundle().apply { + putString(ARG_KEYWORD, keyword) + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/interfaces/ISearchFragment.kt b/app/src/main/java/com/huanchengfly/tieba/post/interfaces/ISearchFragment.kt index ff03040a..32a619ec 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/interfaces/ISearchFragment.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/interfaces/ISearchFragment.kt @@ -1,4 +1,8 @@ package com.huanchengfly.tieba.post.interfaces interface ISearchFragment { + fun setKeyword( + keyword: String?, + needRefresh: Boolean = true + ) } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/AnimUtil.kt b/app/src/main/java/com/huanchengfly/tieba/post/utils/AnimUtil.kt index d52b99a1..9b4116d0 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/AnimUtil.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/AnimUtil.kt @@ -34,10 +34,9 @@ object AnimUtil { @JvmStatic fun bindTextSizeAnim(appBar: AppBarLayout, textView: TextView, startSize: Int, endSize: Int, endOffset: Int = 0) { - appBar.addOnOffsetChangedListener(OnOffsetChangedListener { appBarLayout: AppBarLayout, verticalOffset: Int -> + appBar.addOnOffsetChangedListener(OnOffsetChangedListener { _, verticalOffset -> val offset = abs(verticalOffset * 1f) if (offset <= endOffset) { - val totalScrollRange = appBarLayout.totalScrollRange val percent = offset / endOffset val changeSize = endSize - startSize val size = startSize + percent * changeSize diff --git a/app/src/main/java/com/huanchengfly/tieba/post/widgets/theme/TintMaterialHeader.kt b/app/src/main/java/com/huanchengfly/tieba/post/widgets/theme/TintMaterialHeader.kt index 50297f72..e778392f 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/widgets/theme/TintMaterialHeader.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/widgets/theme/TintMaterialHeader.kt @@ -10,8 +10,11 @@ import com.scwang.smart.refresh.header.MaterialHeader class TintMaterialHeader @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : MaterialHeader(context, attrs), Tintable { + init { + tint() + } + override fun tint() { setColorSchemeColors(ThemeUtils.getColorById(context, R.color.default_color_primary)) } - } \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/widgets/theme/TintTextInputEditText.kt b/app/src/main/java/com/huanchengfly/tieba/post/widgets/theme/TintTextInputEditText.kt index c6c6aafd..3a043d38 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/widgets/theme/TintTextInputEditText.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/widgets/theme/TintTextInputEditText.kt @@ -7,7 +7,7 @@ import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.ui.theme.interfaces.Tintable import com.huanchengfly.tieba.post.ui.theme.utils.ColorStateListUtils -class TintEditText @JvmOverloads constructor( +class TintTextInputEditText @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.attr.editTextStyle ) : AppCompatEditText(context, attrs, defStyleAttr), Tintable { private var textColorResId: Int @@ -18,9 +18,9 @@ class TintEditText @JvmOverloads constructor( textColorResId = 0 textColorHintResId = 0 } else { - val array = getContext().obtainStyledAttributes(attrs, R.styleable.TintEditText, defStyleAttr, 0) - textColorResId = array.getResourceId(R.styleable.TintEditText_textColor, 0) - textColorHintResId = array.getResourceId(R.styleable.TintEditText_android_textColorHint, 0) + val array = getContext().obtainStyledAttributes(attrs, R.styleable.TintTextInputEditText, defStyleAttr, 0) + textColorResId = array.getResourceId(R.styleable.TintTextInputEditText_textColor, 0) + textColorHintResId = array.getResourceId(R.styleable.TintTextInputEditText_android_textColorHint, 0) array.recycle() } tint() diff --git a/app/src/main/res/drawable/bg_bottom_radius_8dp_ripple.xml b/app/src/main/res/drawable/bg_bottom_radius_8dp_ripple.xml index 48968d92..445ff043 100644 --- a/app/src/main/res/drawable/bg_bottom_radius_8dp_ripple.xml +++ b/app/src/main/res/drawable/bg_bottom_radius_8dp_ripple.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_radius_8dp_ripple.xml b/app/src/main/res/drawable/bg_radius_8dp_ripple.xml index 710bea4c..2e34cdd6 100644 --- a/app/src/main/res/drawable/bg_radius_8dp_ripple.xml +++ b/app/src/main/res/drawable/bg_radius_8dp_ripple.xml @@ -1,6 +1,4 @@ - - - - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_ripple.xml b/app/src/main/res/drawable/bg_ripple.xml index 9287b65e..62f08880 100644 --- a/app/src/main/res/drawable/bg_ripple.xml +++ b/app/src/main/res/drawable/bg_ripple.xml @@ -1,4 +1,9 @@ - - + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_top_radius_8dp_ripple.xml b/app/src/main/res/drawable/bg_top_radius_8dp_ripple.xml index 3a5f7fee..48968d92 100644 --- a/app/src/main/res/drawable/bg_top_radius_8dp_ripple.xml +++ b/app/src/main/res/drawable/bg_top_radius_8dp_ripple.xml @@ -1,7 +1,4 @@ - - - - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_forum.xml b/app/src/main/res/layout/activity_forum.xml index 29e217db..146867fb 100644 --- a/app/src/main/res/layout/activity_forum.xml +++ b/app/src/main/res/layout/activity_forum.xml @@ -1,11 +1,12 @@ - + android:stateListAnimator="@animator/appbar_elevation" + app:backgroundTint="@color/default_color_toolbar"> + 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="match_parent" + app:backgroundTint="@color/default_color_window_background"> + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/footer_no_more.xml b/app/src/main/res/layout/footer_no_more.xml index 61a4490a..1391c7cc 100644 --- a/app/src/main/res/layout/footer_no_more.xml +++ b/app/src/main/res/layout/footer_no_more.xml @@ -1,6 +1,24 @@ - - \ No newline at end of file + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_main_forum_list.xml b/app/src/main/res/layout/fragment_main_forum_list.xml index 1adfd13e..73caf9b7 100644 --- a/app/src/main/res/layout/fragment_main_forum_list.xml +++ b/app/src/main/res/layout/fragment_main_forum_list.xml @@ -39,12 +39,11 @@ app:layoutDescription="@xml/fragment_main_forum_list_scene"> - + android:cursorVisible="false" + android:textColorHint="@color/default_color_text_secondary" + android:hint="@string/hint_search" /> - - - - + layout="@layout/footer_no_more" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_message.xml b/app/src/main/res/layout/fragment_message.xml index e2a59fbd..09c621c7 100644 --- a/app/src/main/res/layout/fragment_message.xml +++ b/app/src/main/res/layout/fragment_message.xml @@ -40,12 +40,12 @@ @@ -66,5 +66,5 @@ app:layout_behavior="@string/appbar_scrolling_view_behavior" android:id="@+id/fragment_message_vp" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_message_list.xml b/app/src/main/res/layout/fragment_message_list.xml index 172807eb..c6f158ba 100644 --- a/app/src/main/res/layout/fragment_message_list.xml +++ b/app/src/main/res/layout/fragment_message_list.xml @@ -16,6 +16,7 @@ - - - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_header_delegate.xml b/app/src/main/res/layout/item_header_delegate.xml index 46f2139e..b81b6b0d 100644 --- a/app/src/main/res/layout/item_header_delegate.xml +++ b/app/src/main/res/layout/item_header_delegate.xml @@ -1,7 +1,8 @@ + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools"> + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_search_forum.xml b/app/src/main/res/layout/item_search_forum.xml index 435a61bb..3b4c0f2c 100644 --- a/app/src/main/res/layout/item_search_forum.xml +++ b/app/src/main/res/layout/item_search_forum.xml @@ -1,32 +1,27 @@ - + android:padding="16dp"> - + + - - - - - - \ No newline at end of file + app:tint="@color/default_color_text" + android:textSize="16sp" + android:layout_centerVertical="true" + tools:text="Title" /> + \ No newline at end of file diff --git a/app/src/main/res/layout/item_search_forum_exact.xml b/app/src/main/res/layout/item_search_forum_exact.xml index fd089d56..2e762a88 100644 --- a/app/src/main/res/layout/item_search_forum_exact.xml +++ b/app/src/main/res/layout/item_search_forum_exact.xml @@ -1,44 +1,39 @@ - + android:padding="16dp"> - + + + app:tint="@color/default_color_text" + android:textSize="18sp" + tools:text="Title" /> - - - - - - - \ No newline at end of file + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_search_history_chip.xml b/app/src/main/res/layout/item_search_history_chip.xml index d7451568..ccc33aff 100644 --- a/app/src/main/res/layout/item_search_history_chip.xml +++ b/app/src/main/res/layout/item_search_history_chip.xml @@ -1,7 +1,6 @@ diff --git a/app/src/main/res/layout/item_search_thread.xml b/app/src/main/res/layout/item_search_thread.xml index 3053809c..d9968965 100644 --- a/app/src/main/res/layout/item_search_thread.xml +++ b/app/src/main/res/layout/item_search_thread.xml @@ -1,58 +1,52 @@ - + android:padding="16dp" + android:id="@+id/item_search_thread" + app:backgroundTint="@color/default_color_card"> - + app:tint="@color/default_color_text" + android:textSize="16sp" + android:layout_marginBottom="4dp" + android:textStyle="bold" + tools:text="Title" /> - + - + - - - - - - \ No newline at end of file + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_no_data.xml b/app/src/main/res/layout/layout_no_data.xml index 8469a444..343c6e9b 100644 --- a/app/src/main/res/layout/layout_no_data.xml +++ b/app/src/main/res/layout/layout_no_data.xml @@ -1,5 +1,17 @@ - + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="8dp" + xmlns:app="http://schemas.android.com/apk/res-auto"> + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_search_thread.xml b/app/src/main/res/menu/menu_search_thread.xml index fe187c0c..29b3ea01 100644 --- a/app/src/main/res/menu/menu_search_thread.xml +++ b/app/src/main/res/menu/menu_search_thread.xml @@ -1,4 +1,14 @@ - - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index a2dba73d..8ad2695f 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -147,6 +147,11 @@ + + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 5f50e2b2..7dd9e421 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -23,6 +23,8 @@ #000 #4477E0 + #EDF2F6 + #FF31343C #FF545967 #6131343C @@ -166,5 +168,4 @@ #FF3373EE #FF8E6DCA #50000000 - #EDF2F6 \ No newline at end of file diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml index 75fd0cbe..ec6b8481 100644 --- a/app/src/main/res/values/ids.xml +++ b/app/src/main/res/values/ids.xml @@ -2,4 +2,5 @@ + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9e8f20dc..cadd01c3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,7 +6,7 @@ 动态 搜索 - 进吧、搜贴 + 发现更多 在 %1$s 吧内搜索 浏览历史 退出 @@ -367,4 +367,15 @@ 上拉加载更多 释放开始加载 %1$s·%2$s + 搜吧 + 搜贴 + 搜人 + 搜索历史 + 这里什么都没有 + 推荐结果 + 查询结果 + 仅看主题贴 + 新贴在前 + 旧贴在前 + 相关度 diff --git a/app/src/main/res/xml/fragment_main_forum_list_scene.xml b/app/src/main/res/xml/fragment_main_forum_list_scene.xml index d2bb1b27..32f20b34 100644 --- a/app/src/main/res/xml/fragment_main_forum_list_scene.xml +++ b/app/src/main/res/xml/fragment_main_forum_list_scene.xml @@ -13,10 +13,11 @@ app:layout_constraintStart_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" />