From 566e776825ca90615d5bc1ea9e02090802a10ef9 Mon Sep 17 00:00:00 2001 From: HuanChengFly <609486518@qq.com> Date: Sat, 22 Aug 2020 11:22:51 +0800 Subject: [PATCH 1/4] =?UTF-8?q?chore:=20=E6=8F=90=E5=8D=87=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application.properties b/application.properties index 3541d848..7fb27f5b 100644 --- a/application.properties +++ b/application.properties @@ -1,4 +1,4 @@ -versionCode=38201 +versionCode=38202 versionName=3.8.3 isPerRelease=true preReleaseName=beta From 6d864de25327514b224cae157175bcdb62e4dd13 Mon Sep 17 00:00:00 2001 From: HuanChengFly <609486518@qq.com> Date: Fri, 28 Aug 2020 18:52:29 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=A5=BC=E4=B8=AD?= =?UTF-8?q?=E6=A5=BC=E6=97=A0=E6=B3=95=E6=98=BE=E7=A4=BA=E6=9B=B4=E5=A4=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/adapters/RecyclerThreadAdapter.java | 23 +++++++++++-------- .../tieba/post/fragments/FloorFragment.kt | 4 ++-- application.properties | 4 ++-- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/RecyclerThreadAdapter.java b/app/src/main/java/com/huanchengfly/tieba/post/adapters/RecyclerThreadAdapter.java index f634de78..83c099cb 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/RecyclerThreadAdapter.java +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/RecyclerThreadAdapter.java @@ -79,6 +79,7 @@ public class RecyclerThreadAdapter extends MultiBaseAdapter userInfoBeanMap; private NavigationHelper navigationHelper; private LinearLayout.LayoutParams defaultLayoutParams; @@ -344,14 +345,15 @@ public class RecyclerThreadAdapter extends MultiBaseAdapter 0) { + if (bean.getSubPostNumber() != null && bean.getSubPostList() != null && bean.getSubPostList().getSubPostList() != null && bean.getSubPostList().getSubPostList().size() > 0) { holder.setVisibility(R.id.thread_list_item_content_floor_card, View.VISIBLE); - int count = Integer.valueOf(bean.getSubPostNumber()); - List postListItemBeans = bean.getSubPostList().getSubPostList(); - List subPostList = postListItemBeans; + int count = Integer.parseInt(bean.getSubPostNumber()); + List subPostList = bean.getSubPostList().getSubPostList(); List views = new ArrayList<>(); - if (postListItemBeans.size() > 3) { - subPostList = subPostList.subList(0, 3); + if (subPostList.size() > MAX_SUB_POST_SHOW) { + subPostList = subPostList.subList(0, MAX_SUB_POST_SHOW); + holder.setVisibility(R.id.thread_list_item_content_floor_more, View.VISIBLE); + } else if (subPostList.size() < count) { holder.setVisibility(R.id.thread_list_item_content_floor_more, View.VISIBLE); } else { holder.setVisibility(R.id.thread_list_item_content_floor_more, View.GONE); @@ -360,14 +362,16 @@ public class RecyclerThreadAdapter extends MultiBaseAdapter { try { - if (postListItemBeans.size() < Integer.parseInt(bean.getSubPostNumber())) { - FloorFragment.newInstance(threadBean.getId(), bean.getSubPostList().getPid(), "", true).show(((BaseActivity) mContext).getSupportFragmentManager(), threadBean.getId() + "_Floor"); + if (bean.getSubPostList().getSubPostList().size() < count) { + FloorFragment.newInstance(threadBean.getId(), bean.getSubPostList().getPid(), null, true) + .show(((BaseActivity) mContext).getSupportFragmentManager(), threadBean.getId() + "_Floor"); } else { myLinearLayout.removeAllViews(); List newViews = new ArrayList<>(); - for (ThreadContentBean.PostListItemBean postListItemBean : postListItemBeans) { + for (ThreadContentBean.PostListItemBean postListItemBean : bean.getSubPostList().getSubPostList()) { newViews.add(getContentView(postListItemBean, bean)); } myLinearLayout.addViews(newViews); @@ -377,7 +381,6 @@ public class RecyclerThreadAdapter extends MultiBaseAdapter Date: Mon, 31 Aug 2020 23:21:31 +0800 Subject: [PATCH 3/4] =?UTF-8?q?pref:=20=E4=BF=AE=E6=94=B9=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E3=80=81=E6=90=9C=E5=90=A7=E7=95=8C=E9=9D=A2=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/activities/NewSearchActivity.kt | 4 + .../post/adapters/SearchForumAdapter.java | 70 ---------- .../tieba/post/adapters/SearchForumAdapter.kt | 56 ++++++++ .../post/adapters/SearchHistoryAdapter.kt | 14 ++ ...eadAdapter.java => SearchThreadAdapter.kt} | 97 +++++++------- .../adapters/SingleLayoutDelegateAdapter.kt | 44 +++++++ .../tieba/post/adapters/base/BaseAdapter.kt | 112 ++++++++++++++++ .../adapters/base/BaseMultiTypeAdapter.kt | 41 ++++++ .../adapters/base/BaseSingleTypeAdapter.kt | 30 +++++ .../tieba/post/adapters/base/interfaces.kt | 2 + .../components/AutoLineFeedLayoutManager.java | 4 + .../post/fragments/SearchForumFragment.java | 122 ------------------ .../post/fragments/SearchForumFragment.kt | 110 ++++++++++++++++ .../tieba/post/interfaces/ISearchFragment.kt | 4 + .../widgets/theme/TintTextInputEditText.kt | 37 ++++++ .../drawable/bg_bottom_radius_8dp_ripple.xml | 4 + .../res/drawable/bg_radius_8dp_ripple.xml | 6 + app/src/main/res/drawable/bg_ripple.xml | 4 + .../res/drawable/bg_top_radius_8dp_ripple.xml | 7 + .../res/drawable/ic_round_chevron_right.xml | 9 ++ .../main/res/drawable/ic_round_graphic_eq.xml | 9 ++ .../main/res/drawable/ic_round_keyboard.xml | 9 ++ .../main/res/drawable/ic_round_polymer.xml | 9 ++ .../main/res/layout/activity_new_search.xml | 6 + app/src/main/res/layout/footer_no_more.xml | 6 + .../res/layout/item_search_history_chip.xml | 20 +++ app/src/main/res/layout/layout_no_data.xml | 5 + app/src/main/res/menu/menu_search_thread.xml | 4 + 28 files changed, 601 insertions(+), 244 deletions(-) create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/activities/NewSearchActivity.kt delete mode 100644 app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchForumAdapter.java create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchForumAdapter.kt create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchHistoryAdapter.kt rename app/src/main/java/com/huanchengfly/tieba/post/adapters/{SearchThreadAdapter.java => SearchThreadAdapter.kt} (57%) create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/adapters/SingleLayoutDelegateAdapter.kt create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseAdapter.kt create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseMultiTypeAdapter.kt create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseSingleTypeAdapter.kt create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/adapters/base/interfaces.kt create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/components/AutoLineFeedLayoutManager.java delete mode 100644 app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchForumFragment.java create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchForumFragment.kt create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/interfaces/ISearchFragment.kt create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/widgets/theme/TintTextInputEditText.kt create mode 100644 app/src/main/res/drawable/bg_bottom_radius_8dp_ripple.xml create mode 100644 app/src/main/res/drawable/bg_radius_8dp_ripple.xml create mode 100644 app/src/main/res/drawable/bg_ripple.xml create mode 100644 app/src/main/res/drawable/bg_top_radius_8dp_ripple.xml create mode 100644 app/src/main/res/drawable/ic_round_chevron_right.xml create mode 100644 app/src/main/res/drawable/ic_round_graphic_eq.xml create mode 100644 app/src/main/res/drawable/ic_round_keyboard.xml create mode 100644 app/src/main/res/drawable/ic_round_polymer.xml create mode 100644 app/src/main/res/layout/activity_new_search.xml create mode 100644 app/src/main/res/layout/footer_no_more.xml create mode 100644 app/src/main/res/layout/item_search_history_chip.xml create mode 100644 app/src/main/res/layout/layout_no_data.xml create mode 100644 app/src/main/res/menu/menu_search_thread.xml 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 new file mode 100644 index 00000000..42dace0e --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/NewSearchActivity.kt @@ -0,0 +1,4 @@ +package com.huanchengfly.tieba.post.activities + +class NewSearchActivity { +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchForumAdapter.java b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchForumAdapter.java deleted file mode 100644 index 38bff620..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchForumAdapter.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.huanchengfly.tieba.post.adapters; - -import android.app.Activity; -import android.content.Context; - -import com.huanchengfly.tieba.post.api.models.SearchForumBean; -import com.huanchengfly.tieba.post.R; -import com.huanchengfly.tieba.post.utils.ImageUtil; -import com.huanchengfly.tieba.post.utils.NavigationHelper; -import com.othershe.baseadapter.ViewHolder; -import com.othershe.baseadapter.base.MultiBaseAdapter; - -import java.util.ArrayList; -import java.util.List; - -public class SearchForumAdapter extends MultiBaseAdapter { - public static final int TYPE_EXACT = 0; - public static final int TYPE_FUZZY = 1; - private NavigationHelper navigationHelper; - - public SearchForumAdapter(Context context) { - super(context, null, true); - navigationHelper = NavigationHelper.newInstance(context); - } - - public void setData(SearchForumBean.DataBean data) { - List forumInfoBeans = new ArrayList<>(); - if (data.getExactMatch() != null && data.getExactMatch().getForumNameShow() != null) { - forumInfoBeans.add(data.getExactMatch()); - } - forumInfoBeans.addAll(data.getFuzzyMatch()); - setNewData(forumInfoBeans); - } - - private boolean canLoadGlide() { - if (mContext instanceof Activity) { - return !((Activity) mContext).isDestroyed(); - } - return false; - } - - @Override - protected void convert(ViewHolder viewHolder, SearchForumBean.ForumInfoBean forumInfoBean, int position, int type) { - viewHolder.setText(R.id.item_search_forum_title, forumInfoBean.getForumNameShow() + "吧"); - viewHolder.setOnClickListener(R.id.item_search_forum, (view) -> { - navigationHelper.navigationByData(NavigationHelper.ACTION_FORUM, forumInfoBean.getForumName()); - }); - ImageUtil.load(viewHolder.getView(R.id.item_search_forum_avatar), ImageUtil.LOAD_TYPE_AVATAR, forumInfoBean.getAvatar()); - if (type == TYPE_EXACT) { - SearchForumBean.ExactForumInfoBean exactForumInfoBean = (SearchForumBean.ExactForumInfoBean) forumInfoBean; - viewHolder.setText(R.id.item_search_forum_subtitle, exactForumInfoBean.getSlogan()); - } - } - - @Override - protected int getItemLayoutId(int type) { - if (type == TYPE_EXACT) { - return R.layout.item_search_forum_exact; - } - return R.layout.item_search_forum; - } - - @Override - protected int getViewType(int i, SearchForumBean.ForumInfoBean forumInfoBean) { - if (forumInfoBean instanceof SearchForumBean.ExactForumInfoBean) { - return TYPE_EXACT; - } - return TYPE_FUZZY; - } -} 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 new file mode 100644 index 00000000..c8991384 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchForumAdapter.kt @@ -0,0 +1,56 @@ +package com.huanchengfly.tieba.post.adapters + +import android.content.Context +import android.view.View +import com.alibaba.android.vlayout.layout.LinearLayoutHelper +import com.huanchengfly.tieba.post.R +import com.huanchengfly.tieba.post.adapters.base.BaseMultiTypeDelegateAdapter +import com.huanchengfly.tieba.post.api.models.SearchForumBean +import com.huanchengfly.tieba.post.api.models.SearchForumBean.ExactForumInfoBean +import com.huanchengfly.tieba.post.components.MyViewHolder +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 + viewHolder.setText(R.id.item_search_forum_subtitle, exactForumInfoBean.slogan) + } + } + + override fun getItemLayoutId(type: Int): Int { + return if (type == 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) { + TYPE_EXACT + } else TYPE_FUZZY + } + + companion object { + const val TYPE_EXACT = 0 + const val TYPE_FUZZY = 1 + } + + init { + navigationHelper = NavigationHelper.newInstance(context) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchHistoryAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchHistoryAdapter.kt new file mode 100644 index 00000000..dce20fb3 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchHistoryAdapter.kt @@ -0,0 +1,14 @@ +package com.huanchengfly.tieba.post.adapters + +import android.content.Context +import com.huanchengfly.tieba.post.adapters.base.BaseSingleTypeAdapter +import com.huanchengfly.tieba.post.components.MyViewHolder +import com.huanchengfly.tieba.post.models.database.SearchHistory + +class SearchHistoryAdapter(context: Context) : BaseSingleTypeAdapter(context) { + override fun getItemLayoutId(): Int { + return 0 + } + + protected override fun convert(viewHolder: MyViewHolder, searchHistory: SearchHistory, position: Int) {} +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchThreadAdapter.java b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchThreadAdapter.kt similarity index 57% rename from app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchThreadAdapter.java rename to app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchThreadAdapter.kt index 3c020308..83b0db1d 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchThreadAdapter.java +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchThreadAdapter.kt @@ -1,35 +1,50 @@ -package com.huanchengfly.tieba.post.adapters; +package com.huanchengfly.tieba.post.adapters -import android.content.Context; -import android.text.format.DateUtils; -import android.view.View; +import android.text.format.DateUtils +import android.view.View +import com.huanchengfly.tieba.post.R +import com.huanchengfly.tieba.post.adapters.base.BaseSingleTypeAdapter +import com.huanchengfly.tieba.post.api.models.SearchThreadBean +import com.huanchengfly.tieba.post.components.MyViewHolder +import com.huanchengfly.tieba.post.fragments.SearchThreadFragment +import com.huanchengfly.tieba.post.utils.NavigationHelper +import java.util.* -import com.allen.library.SuperTextView; -import com.huanchengfly.tieba.post.api.SearchThreadFilter; -import com.huanchengfly.tieba.post.api.SearchThreadOrder; -import com.huanchengfly.tieba.post.api.models.SearchThreadBean; -import com.huanchengfly.tieba.post.R; -import com.huanchengfly.tieba.post.components.dialogs.SingleChooseDialog; -import com.huanchengfly.tieba.post.fragments.SearchThreadFragment; -import com.huanchengfly.tieba.post.utils.NavigationHelper; -import com.huanchengfly.tieba.post.utils.Util; -import com.othershe.baseadapter.ViewHolder; -import com.othershe.baseadapter.base.CommonBaseAdapter; +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) { + viewHolder.setText( + R.id.item_search_thread_info, + DateUtils.getRelativeTimeSpanString(threadInfoBean.time!!.toLong() * 1000L) + ) + } else { + viewHolder.setText( + R.id.item_search_thread_info, + threadInfoBean.forumName + " " + DateUtils.getRelativeTimeSpanString(threadInfoBean.time!!.toLong() * 1000L) + ) + } + } -import java.util.HashMap; -import java.util.Map; + override fun getItemLayoutId(): Int { + return R.layout.item_search_thread + } -public class SearchThreadAdapter extends CommonBaseAdapter { - private NavigationHelper navigationHelper; - private int order; - private int filter; - - public SearchThreadAdapter(SearchThreadFragment fragment) { - super(fragment.getContext(), null, true); - order = 0; - filter = 0; - Context context = fragment.getContext(); - navigationHelper = NavigationHelper.newInstance(context); + init { + val context = fragment.requireContext() + navigationHelper = NavigationHelper.newInstance(context) + /* View headerView = Util.inflate(context, R.layout.layout_search_header); if (headerView != null) { SuperTextView orderTextView = headerView.findViewById(R.id.search_order); @@ -73,28 +88,6 @@ public class SearchThreadAdapter extends CommonBaseAdapter { - Map map = new HashMap<>(); - map.put("tid", threadInfoBean.getTid()); - map.put("pid", threadInfoBean.getPid()); - navigationHelper.navigationByData(NavigationHelper.ACTION_THREAD, map); - }); - viewHolder.setText(R.id.item_search_thread_title, threadInfoBean.getTitle()); - viewHolder.setText(R.id.item_search_thread_content, threadInfoBean.getContent()); - viewHolder.setText(R.id.item_search_thread_user, threadInfoBean.getUser().getUserName()); - if (threadInfoBean.getForumName() == null) { - viewHolder.setText(R.id.item_search_thread_info, String.valueOf(DateUtils.getRelativeTimeSpanString(Long.valueOf(threadInfoBean.getTime()) * 1000L))); - } else { - viewHolder.setText(R.id.item_search_thread_info, threadInfoBean.getForumName() + " " + DateUtils.getRelativeTimeSpanString(Long.valueOf(threadInfoBean.getTime()) * 1000L)); - } - } - - @Override - protected int getItemLayoutId() { - return R.layout.item_search_thread; - } -} +} \ No newline at end of file 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 new file mode 100644 index 00000000..c078408f --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SingleLayoutDelegateAdapter.kt @@ -0,0 +1,44 @@ +package com.huanchengfly.tieba.post.adapters.base + +import android.content.Context +import android.view.View +import android.view.ViewGroup +import androidx.annotation.LayoutRes +import com.alibaba.android.vlayout.DelegateAdapter +import com.alibaba.android.vlayout.LayoutHelper +import com.alibaba.android.vlayout.layout.SingleLayoutHelper +import com.huanchengfly.tieba.post.components.MyViewHolder + +abstract class BaseSingleLayoutAdapter( + val context: Context, + val itemView: View +) : DelegateAdapter.Adapter() { + 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) + + final override fun onBindViewHolder(holder: MyViewHolder, position: Int) { + convert(holder, itemView) + } + + final override fun getItemCount(): Int = 1 + + override fun onCreateLayoutHelper(): LayoutHelper = SingleLayoutHelper() + + abstract fun convert(holder: 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 new file mode 100644 index 00000000..691dbd24 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseAdapter.kt @@ -0,0 +1,112 @@ +package com.huanchengfly.tieba.post.adapters.base + +import android.content.Context +import com.alibaba.android.vlayout.DelegateAdapter +import com.alibaba.android.vlayout.LayoutHelper +import com.huanchengfly.tieba.post.components.MyViewHolder + +abstract class BaseDelegateAdapter( + val context: Context, + val layoutHelper: LayoutHelper, + items: List? = null +) : DelegateAdapter.Adapter() { + private var itemList: MutableList = (items ?: emptyList()).toMutableList() + + var onItemClickListener: OnItemClickListener? = null + private set + + var onItemLongClickListener: OnItemLongClickListener? = null + private set + + fun setOnItemClickListener(listener: OnItemClickListener?) { + onItemClickListener = listener + } + + fun setOnItemClickListener(listener: ((viewHolder: MyViewHolder, item: Item, position: Int) -> Unit)?) { + onItemClickListener = object : OnItemClickListener { + override fun onClick(viewHolder: MyViewHolder, item: Item, position: Int) { + if (listener != null) { + listener(viewHolder, item, position) + } + } + } + } + + fun setOnItemLongClickListener(listener: OnItemLongClickListener?) { + onItemLongClickListener = listener + } + + fun setOnItemLongClickListener(listener: ((viewHolder: MyViewHolder, item: Item, position: Int) -> Boolean)?) { + onItemLongClickListener = object : OnItemLongClickListener { + override fun onLongClick(viewHolder: MyViewHolder, item: Item, position: Int): Boolean { + if (listener != null) { + return listener(viewHolder, item, position) + } + return false + } + } + } + + override fun getItemCount(): Int = getCount() + + override fun onCreateLayoutHelper(): LayoutHelper = layoutHelper + + fun getItem(position: Int): Item = itemList[position] + + fun getItemList(): MutableList = itemList + + fun getCount() = itemList.size + + fun setData(items: List?) { + itemList.clear() + itemList.addAll(items ?: emptyList()) + notifyDataSetChanged() + } + + open fun remove(position: Int) { + if (position < itemList.size && position >= 0) { + itemList.removeAt(position) + notifyItemRemoved(position) + if (position != itemList.size) { + this.notifyItemRangeChanged(position, itemList.size - position) + } + } + } + + open fun insert(items: List, position: Int) { + if (position <= itemList.size && position >= 0) { + itemList.addAll(position, items) + notifyItemRangeInserted(position, items.size) + this.notifyItemRangeChanged(position, itemList.size - position) + } + } + + open fun insert(items: List) { + insert(items, itemList.size) + } + + open fun insert(data: Item, position: Int) { + if (position <= itemList.size && position >= 0) { + itemList.add(position, data) + notifyItemInserted(position) + this.notifyItemRangeChanged(position, itemList.size - position) + } + } + + open fun insert(data: Item) { + this.insert(data, itemList.size) + } + + open fun reset() { + 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 new file mode 100644 index 00000000..9f21e974 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseMultiTypeAdapter.kt @@ -0,0 +1,41 @@ +package com.huanchengfly.tieba.post.adapters.base + +import android.content.Context +import android.view.View +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 +) { + protected abstract fun getItemLayoutId( + itemType: Int + ): Int + + protected abstract fun getViewType( + position: Int, + item: Item + ): Int + + final override fun getItemViewType(position: Int): Int { + return getViewType(position, getItem(position)) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder = MyViewHolder(context, getItemLayoutId(viewType)) + + override fun onBindViewHolder(holder: MyViewHolder, position: Int) { + holder.setItemOnClickListener(View.OnClickListener { + onItemClickListener?.onClick(holder, getItem(position), position) + }) + holder.setItemOnLongClickListener(View.OnLongClickListener { + onItemLongClickListener?.onLongClick(holder, getItem(position), position) ?: false + }) + convert(holder, getItem(position), position, getItemViewType(position)) + } + + protected abstract fun convert(viewHolder: MyViewHolder, item: Item, position: Int, viewType: Int) +} \ No newline at end of file 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 new file mode 100644 index 00000000..427052cc --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseSingleTypeAdapter.kt @@ -0,0 +1,30 @@ +package com.huanchengfly.tieba.post.adapters.base + +import android.content.Context +import android.view.View +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 +) { + 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 { + onItemClickListener?.onClick(holder, getItem(position), position) + }) + holder.setItemOnLongClickListener(View.OnLongClickListener { + onItemLongClickListener?.onLongClick(holder, getItem(position), position) ?: false + }) + convert(holder, getItem(position), position) + } + + protected abstract fun convert(viewHolder: MyViewHolder, item: Item, position: Int) +} \ No newline at end of file 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 new file mode 100644 index 00000000..9e464113 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/interfaces.kt @@ -0,0 +1,2 @@ +package com.huanchengfly.tieba.post.adapters.base + 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 new file mode 100644 index 00000000..f14c9f87 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/components/AutoLineFeedLayoutManager.java @@ -0,0 +1,4 @@ +package com.huanchengfly.tieba.post.components; + +public class AutoLineFeedLayoutManager { +} diff --git a/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchForumFragment.java b/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchForumFragment.java deleted file mode 100644 index ef810e1a..00000000 --- a/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchForumFragment.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.huanchengfly.tieba.post.fragments; - - -import android.os.Bundle; -import android.view.View; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.RecyclerView; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - -import com.huanchengfly.tieba.post.api.TiebaApi; -import com.huanchengfly.tieba.post.api.models.SearchForumBean; -import com.huanchengfly.tieba.post.R; -import com.huanchengfly.tieba.post.adapters.SearchForumAdapter; -import com.huanchengfly.tieba.post.components.MyLinearLayoutManager; -import com.huanchengfly.tieba.post.components.dividers.SearchDivider; -import com.huanchengfly.tieba.post.utils.ThemeUtil; - -import org.jetbrains.annotations.NotNull; - -import butterknife.BindView; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; - -public class SearchForumFragment extends BaseFragment { - public static final String TAG = "SearchForumFragment"; - - public static final String ARG_KEYWORD = "keyword"; - @BindView(R.id.fragment_search_refresh_layout) - SwipeRefreshLayout refreshLayout; - @BindView(R.id.fragment_search_recycler_view) - RecyclerView recyclerView; - private String keyword; - private SearchForumAdapter mAdapter; - - private SearchForumBean.DataBean mData; - - public SearchForumFragment() { - } - - public static SearchForumFragment newInstance(String keyword) { - SearchForumFragment forumFragment = new SearchForumFragment(); - Bundle bundle = new Bundle(); - bundle.putString(ARG_KEYWORD, keyword); - forumFragment.setArguments(bundle); - return forumFragment; - } - - public void setKeyword(String keyword, boolean refresh) { - this.keyword = keyword; - if (refresh) { - refresh(); - } else { - this.mData = null; - mAdapter.reset(); - } - } - - @Override - protected void onFragmentVisibleChange(boolean isVisible) { - if (mData == null && isVisible) { - refresh(); - } - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (getArguments() != null) { - keyword = getArguments().getString(ARG_KEYWORD); - } - } - - @Override - int getLayoutId() { - return R.layout.fragment_search; - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - recyclerView.setLayoutManager(new MyLinearLayoutManager(getAttachContext())); - recyclerView.addItemDecoration(new SearchDivider(getAttachContext())); - mAdapter = new SearchForumAdapter(getAttachContext()); - mAdapter.setLoadEndView(R.layout.layout_footer_loadend); - mAdapter.setLoadFailedView(R.layout.layout_footer_load_failed); - recyclerView.setAdapter(mAdapter); - refreshLayout.setOnRefreshListener(this::refresh); - ThemeUtil.setThemeForSwipeRefreshLayout(refreshLayout); - } - - private void setRefreshing(boolean refreshing) { - if (refreshLayout != null) refreshLayout.setRefreshing(refreshing); - } - - private void refresh() { - setRefreshing(true); - TiebaApi.getInstance().searchForum(keyword).enqueue(new Callback() { - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) { - mData = response.body().getData(); - mAdapter.setData(mData); - setRefreshing(false); - mAdapter.loadEnd(); - } - - @Override - public void onFailure(@NotNull Call call, @NotNull Throwable t) { - setRefreshing(false); - Toast.makeText(getAttachContext(), t.getMessage(), Toast.LENGTH_SHORT).show(); - } - }); - } - - @Override - protected void onFragmentFirstVisible() { - refresh(); - } -} \ No newline at end of file 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 new file mode 100644 index 00000000..70694dc0 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/fragments/SearchForumFragment.kt @@ -0,0 +1,110 @@ +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.VirtualLayoutManager +import com.huanchengfly.tieba.post.R +import com.huanchengfly.tieba.post.adapters.SearchForumAdapter +import com.huanchengfly.tieba.post.api.TiebaApi.getInstance +import com.huanchengfly.tieba.post.api.models.SearchForumBean +import com.huanchengfly.tieba.post.interfaces.ISearchFragment +import com.huanchengfly.tieba.post.utils.ThemeUtil +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class SearchForumFragment : BaseFragment(), ISearchFragment { + @BindView(R.id.fragment_search_refresh_layout) + var refreshLayout: SwipeRefreshLayout? = null + + @BindView(R.id.fragment_search_recycler_view) + var recyclerView: RecyclerView? = null + private var keyword: String? = null + private var mAdapter: SearchForumAdapter? = null + 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() + } + } + } + + override fun onFragmentVisibleChange(isVisible: Boolean) { + if (mData == null && isVisible) { + refresh() + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + if (arguments != null) { + keyword = arguments!!.getString(ARG_KEYWORD) + } + } + + public override fun getLayoutId(): Int { + return R.layout.fragment_search + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + recyclerView!!.layoutManager = VirtualLayoutManager(attachContext) + mAdapter = SearchForumAdapter(attachContext) + recyclerView!!.adapter = mAdapter + refreshLayout!!.setOnRefreshListener { refresh() } + ThemeUtil.setThemeForSwipeRefreshLayout(refreshLayout) + } + + private fun setRefreshing(refreshing: Boolean) { + if (refreshLayout != null) refreshLayout!!.isRefreshing = refreshing + } + + 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 + reloadAdapters() + setRefreshing(false) + } + + override fun onFailure(call: Call, t: Throwable) { + setRefreshing(false) + Toast.makeText(attachContext, t.message, Toast.LENGTH_SHORT).show() + } + }) + } + + private fun reloadAdapters() {} + override fun onFragmentFirstVisible() { + refresh() + } + + companion object { + const val TAG = "SearchForumFragment" + const val ARG_KEYWORD = "keyword" + @JvmOverloads + fun newInstance(keyword: String? = null): SearchForumFragment { + val forumFragment = SearchForumFragment() + val bundle = Bundle() + bundle.putString(ARG_KEYWORD, keyword) + forumFragment.arguments = bundle + return forumFragment + } + } +} \ 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 new file mode 100644 index 00000000..ff03040a --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/interfaces/ISearchFragment.kt @@ -0,0 +1,4 @@ +package com.huanchengfly.tieba.post.interfaces + +interface ISearchFragment { +} \ 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 new file mode 100644 index 00000000..c6c6aafd --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/widgets/theme/TintTextInputEditText.kt @@ -0,0 +1,37 @@ +package com.huanchengfly.tieba.post.widgets.theme + +import android.content.Context +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatEditText +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( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.attr.editTextStyle +) : AppCompatEditText(context, attrs, defStyleAttr), Tintable { + private var textColorResId: Int + private var textColorHintResId: Int + + init { + if (isInEditMode || attrs == null) { + 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) + array.recycle() + } + tint() + } + + override fun tint() { + if (textColorResId != 0) { + setTextColor(ColorStateListUtils.createColorStateList(context, textColorResId)) + } + if (textColorHintResId != 0) { + setHintTextColor(ColorStateListUtils.createColorStateList(context, textColorHintResId)) + } + } +} \ No newline at end of file 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 new file mode 100644 index 00000000..48968d92 --- /dev/null +++ b/app/src/main/res/drawable/bg_bottom_radius_8dp_ripple.xml @@ -0,0 +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 new file mode 100644 index 00000000..710bea4c --- /dev/null +++ b/app/src/main/res/drawable/bg_radius_8dp_ripple.xml @@ -0,0 +1,6 @@ + + + + + \ 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 new file mode 100644 index 00000000..9287b65e --- /dev/null +++ b/app/src/main/res/drawable/bg_ripple.xml @@ -0,0 +1,4 @@ + + + + \ 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 new file mode 100644 index 00000000..3a5f7fee --- /dev/null +++ b/app/src/main/res/drawable/bg_top_radius_8dp_ripple.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_round_chevron_right.xml b/app/src/main/res/drawable/ic_round_chevron_right.xml new file mode 100644 index 00000000..29772976 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_chevron_right.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_graphic_eq.xml b/app/src/main/res/drawable/ic_round_graphic_eq.xml new file mode 100644 index 00000000..3932127d --- /dev/null +++ b/app/src/main/res/drawable/ic_round_graphic_eq.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_keyboard.xml b/app/src/main/res/drawable/ic_round_keyboard.xml new file mode 100644 index 00000000..71116165 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_keyboard.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_polymer.xml b/app/src/main/res/drawable/ic_round_polymer.xml new file mode 100644 index 00000000..2a9b5f95 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_polymer.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_new_search.xml b/app/src/main/res/layout/activity_new_search.xml new file mode 100644 index 00000000..1766253b --- /dev/null +++ b/app/src/main/res/layout/activity_new_search.xml @@ -0,0 +1,6 @@ + + + + \ 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 new file mode 100644 index 00000000..61a4490a --- /dev/null +++ b/app/src/main/res/layout/footer_no_more.xml @@ -0,0 +1,6 @@ + + + + \ 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 new file mode 100644 index 00000000..d7451568 --- /dev/null +++ b/app/src/main/res/layout/item_search_history_chip.xml @@ -0,0 +1,20 @@ + + + + \ 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 new file mode 100644 index 00000000..8469a444 --- /dev/null +++ b/app/src/main/res/layout/layout_no_data.xml @@ -0,0 +1,5 @@ + + + + \ 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 new file mode 100644 index 00000000..fe187c0c --- /dev/null +++ b/app/src/main/res/menu/menu_search_thread.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 6cd9cba48b7869d8f36cd26eef078a8e49909c96 Mon Sep 17 00:00:00 2001 From: HuanChengFly <609486518@qq.com> Date: Mon, 31 Aug 2020 23:22:07 +0800 Subject: [PATCH 4/4] =?UTF-8?q?pref:=20=E4=BF=AE=E6=94=B9=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E7=95=8C=E9=9D=A2=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 4 + .../tieba/post/BaseApplication.kt | 2 + .../com/huanchengfly/tieba/post/Extensions.kt | 10 +- .../tieba/post/activities/ForumActivity.kt | 12 + .../post/activities/NewSearchActivity.kt | 348 +++++++++++++++++- .../tieba/post/activities/ThreadActivity.kt | 27 ++ .../post/adapters/HeaderDelegateAdapter.kt | 96 ++++- .../post/adapters/HotMessageListAdapter.java | 3 +- .../tieba/post/adapters/SearchForumAdapter.kt | 42 +-- .../post/adapters/SearchHistoryAdapter.kt | 11 +- .../post/adapters/SearchThreadAdapter.kt | 39 +- .../adapters/SingleLayoutDelegateAdapter.kt | 10 +- .../tieba/post/adapters/base/BaseAdapter.kt | 16 +- .../post/adapters/base/BaseDelegateAdapter.kt | 8 - .../adapters/base/BaseMultiTypeAdapter.kt | 17 +- .../adapters/base/BaseSingleTypeAdapter.kt | 17 +- .../base/BaseSingleTypeDelegateAdapter.kt | 7 +- .../tieba/post/adapters/base/interfaces.kt | 9 + .../components/AutoLineFeedLayoutManager.java | 52 ++- .../components/dividers/SearchDivider.java | 7 +- .../dividers/SpacesItemDecoration.java | 25 +- .../post/fragments/MainForumListFragment.kt | 22 +- .../post/fragments/SearchForumFragment.kt | 111 ++++-- .../post/fragments/SearchThreadFragment.kt | 78 ++-- .../post/fragments/SearchUserFragment.kt | 65 ++-- .../tieba/post/interfaces/ISearchFragment.kt | 4 + .../huanchengfly/tieba/post/utils/AnimUtil.kt | 3 +- .../post/widgets/theme/TintMaterialHeader.kt | 5 +- .../widgets/theme/TintTextInputEditText.kt | 8 +- .../drawable/bg_bottom_radius_8dp_ripple.xml | 2 +- .../res/drawable/bg_radius_8dp_ripple.xml | 8 +- app/src/main/res/drawable/bg_ripple.xml | 9 +- .../res/drawable/bg_top_radius_8dp_ripple.xml | 9 +- app/src/main/res/layout/activity_forum.xml | 7 +- .../main/res/layout/activity_new_search.xml | 91 ++++- app/src/main/res/layout/footer_no_more.xml | 24 +- .../res/layout/fragment_main_forum_list.xml | 37 +- app/src/main/res/layout/fragment_message.xml | 8 +- .../main/res/layout/fragment_message_list.xml | 1 + app/src/main/res/layout/fragment_search.xml | 30 +- .../main/res/layout/item_header_delegate.xml | 11 +- app/src/main/res/layout/item_search_forum.xml | 45 +-- .../res/layout/item_search_forum_exact.xml | 67 ++-- .../res/layout/item_search_history_chip.xml | 3 +- .../main/res/layout/item_search_thread.xml | 90 +++-- app/src/main/res/layout/layout_no_data.xml | 16 +- app/src/main/res/menu/menu_search_thread.xml | 14 +- app/src/main/res/values/attrs.xml | 5 + app/src/main/res/values/colors.xml | 3 +- app/src/main/res/values/ids.xml | 1 + app/src/main/res/values/strings.xml | 13 +- .../xml/fragment_main_forum_list_scene.xml | 10 +- 52 files changed, 1150 insertions(+), 412 deletions(-) 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" />