feat: 专题合集新增自定义设置—客户端 https://jira.shanqu.cc/browse/GHZSCY-7496
This commit is contained in:
@ -2,12 +2,10 @@ package com.gh.common.util
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.therouter.TheRouter
|
||||
import com.gh.common.iinterface.ISuperiorChain
|
||||
import com.gh.gamecenter.amway.AmwayFragment
|
||||
import com.gh.gamecenter.category2.CategoryV2Fragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.provider.IHelpAndFeedbackProvider
|
||||
import com.gh.gamecenter.discovery.DiscoveryFragment
|
||||
@ -38,6 +36,7 @@ import com.gh.gamecenter.toolbox.ToolboxFragment
|
||||
import com.gh.gamecenter.video.detail.HomeVideoFragment
|
||||
import com.gh.gamecenter.wrapper.ToolbarWrapperFragment
|
||||
import com.halo.assistant.fragment.WebFragment
|
||||
import com.therouter.TheRouter
|
||||
|
||||
/**
|
||||
* 通用跳转Fragment方法
|
||||
@ -148,6 +147,15 @@ object ViewPagerFragmentHelper {
|
||||
bundle.putString(EntranceConsts.KEY_QUESTIONS_ID, linkEntity.link)
|
||||
NewQuestionDetailFragment().with(bundle)
|
||||
}
|
||||
// 专题合集详情页
|
||||
TYPE_COLUMN_COLLECTION -> {
|
||||
bundle.putString(EntranceConsts.KEY_COLLECTION_ID, linkEntity.link)
|
||||
bundle.putInt(EntranceConsts.KEY_POSITION, 0)
|
||||
bundle.putString(EntranceConsts.KEY_COLUMNNAME, linkEntity.text)
|
||||
bundle.putBoolean(EntranceConsts.KEY_IS_COLUMN_COLLECTION, true)
|
||||
bundle.putString(EntranceConsts.KEY_SUBJECT_TYPE, "tab")
|
||||
ColumnCollectionDetailFragment().with(bundle)
|
||||
}
|
||||
// 其他原来带Toolbar的Fragment
|
||||
else -> createToolbarWrapperFragment(bundle, linkEntity, isTabWrapper)
|
||||
}
|
||||
@ -177,15 +185,6 @@ object ViewPagerFragmentHelper {
|
||||
bundle.putString(EntranceConsts.KEY_SUBJECT_TYPE, "detail")
|
||||
bundle.putBoolean(EntranceConsts.KEY_SHOW_DOWNLOAD_MENU, !isTabWrapper)
|
||||
}
|
||||
// 专题合集详情页
|
||||
TYPE_COLUMN_COLLECTION -> {
|
||||
className = ColumnCollectionDetailFragment::class.java.name
|
||||
bundle.putString(EntranceConsts.KEY_COLLECTION_ID, entity.link)
|
||||
bundle.putInt(EntranceConsts.KEY_POSITION, 0)
|
||||
bundle.putString(EntranceConsts.KEY_COLUMNNAME, entity.text)
|
||||
bundle.putBoolean(EntranceConsts.KEY_IS_COLUMN_COLLECTION, true)
|
||||
bundle.putString(EntranceConsts.KEY_SUBJECT_TYPE, "tab")
|
||||
}
|
||||
// 开服表
|
||||
TYPE_SERVER -> {
|
||||
className = GameServersPublishFragment::class.java.name
|
||||
|
||||
@ -1,18 +1,23 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.CheckedTextView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.forEach
|
||||
import androidx.core.view.setPadding
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.setDrawableEnd
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.toDrawable
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.google.android.flexbox.FlexboxLayout
|
||||
|
||||
@ -30,11 +35,15 @@ class ConfigFilterView @JvmOverloads constructor(
|
||||
var recommendedTv: TextView
|
||||
var updateTv: TextView //更新
|
||||
var container: View
|
||||
private var dot1: View
|
||||
private var dot2: View
|
||||
private var dot3: View
|
||||
|
||||
var sizeFilterArray: ArrayList<SubjectSettingEntity.Size>? = null
|
||||
private var sizeFilterArray: ArrayList<SubjectSettingEntity.Size>? = null
|
||||
|
||||
private var mOnConfigFilterSetupListener: OnConfigFilterSetupListener? = null
|
||||
private var mSelectionTvList: ArrayList<TextView>
|
||||
private var highlightedSortedType: SortType? = null
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.layout_config_filter, this)
|
||||
@ -45,6 +54,9 @@ class ConfigFilterView @JvmOverloads constructor(
|
||||
updateTv = findViewById(R.id.updateTv)
|
||||
recommendedTv = findViewById(R.id.recommended_tv)
|
||||
container = findViewById(R.id.config_controller)
|
||||
dot1 = findViewById(R.id.dot1)
|
||||
dot2 = findViewById(R.id.dot2)
|
||||
dot3 = findViewById(R.id.dot3)
|
||||
|
||||
mSelectionTvList = arrayListOf(newestTv, ratingTv, updateTv, recommendedTv)
|
||||
|
||||
@ -54,24 +66,30 @@ class ConfigFilterView @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
ratingTv.setOnClickListener {
|
||||
highlightedSortedType = SortType.RATING
|
||||
mOnConfigFilterSetupListener?.onSetupSortType(SortType.RATING)
|
||||
updateHighlightedTextView(ratingTv)
|
||||
}
|
||||
|
||||
updateTv.setOnClickListener {
|
||||
highlightedSortedType = SortType.UPDATE
|
||||
mOnConfigFilterSetupListener?.onSetupSortType(SortType.UPDATE)
|
||||
updateHighlightedTextView(updateTv)
|
||||
}
|
||||
|
||||
newestTv.setOnClickListener {
|
||||
highlightedSortedType = SortType.NEWEST
|
||||
mOnConfigFilterSetupListener?.onSetupSortType(SortType.NEWEST)
|
||||
updateHighlightedTextView(newestTv)
|
||||
}
|
||||
|
||||
recommendedTv.setOnClickListener {
|
||||
highlightedSortedType = SortType.RECOMMENDED
|
||||
mOnConfigFilterSetupListener?.onSetupSortType(SortType.RECOMMENDED)
|
||||
updateHighlightedTextView(recommendedTv)
|
||||
}
|
||||
|
||||
updateAllTextView(SortType.UPDATE)
|
||||
}
|
||||
|
||||
private fun updateHighlightedTextView(highlightedTv: TextView) {
|
||||
@ -80,14 +98,17 @@ class ConfigFilterView @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun updateAllTextView(sortType: SortType) {
|
||||
when (sortType) {
|
||||
SortType.RECOMMENDED -> updateHighlightedTextView(recommendedTv)
|
||||
SortType.NEWEST -> updateHighlightedTextView(newestTv)
|
||||
SortType.RATING -> updateHighlightedTextView(ratingTv)
|
||||
SortType.UPDATE -> updateHighlightedTextView(updateTv)
|
||||
fun updateAllTextView(sortType: SortType? = highlightedSortedType) {
|
||||
highlightedSortedType = sortType
|
||||
sortType?.let {
|
||||
when (it) {
|
||||
SortType.RECOMMENDED -> updateHighlightedTextView(recommendedTv)
|
||||
SortType.NEWEST -> updateHighlightedTextView(newestTv)
|
||||
SortType.RATING -> updateHighlightedTextView(ratingTv)
|
||||
SortType.UPDATE -> updateHighlightedTextView(updateTv)
|
||||
}
|
||||
mSizeTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
}
|
||||
mSizeTv.setTextColor(com.gh.gamecenter.common.R.color.text_757575.toColor(context))
|
||||
}
|
||||
|
||||
fun setOnConfigSetupListener(onConfigFilterSetupListener: OnConfigFilterSetupListener) {
|
||||
@ -96,11 +117,11 @@ class ConfigFilterView @JvmOverloads constructor(
|
||||
|
||||
private fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
|
||||
if (highlightIt) {
|
||||
targetTextView.background = R.drawable.bg_tag_text.toDrawable()
|
||||
targetTextView.setTextColor(com.gh.gamecenter.common.R.color.text_white.toColor(context))
|
||||
targetTextView.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
|
||||
targetTextView.setTypeface(Typeface.DEFAULT, Typeface.BOLD)
|
||||
} else {
|
||||
targetTextView.background = null
|
||||
targetTextView.setTextColor(com.gh.gamecenter.common.R.color.text_757575.toColor(context))
|
||||
targetTextView.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
targetTextView.setTypeface(Typeface.DEFAULT, Typeface.NORMAL)
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,8 +133,8 @@ class ConfigFilterView @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
private fun showSelectionPopupWindow(containerView: View, sizeTv: TextView, sizeText: String) {
|
||||
sizeTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(sizeTv.context))
|
||||
sizeTv.setDrawableEnd(R.drawable.ic_filter_arrow_up)
|
||||
sizeTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(sizeTv.context))
|
||||
sizeTv.setDrawableEnd(R.drawable.ic_auxiliary_arrow_up_primary_8)
|
||||
|
||||
val inflater = LayoutInflater.from(sizeTv.context)
|
||||
val layout = inflater.inflate(R.layout.layout_filter_size, null)
|
||||
@ -136,43 +157,39 @@ class ConfigFilterView @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
flexboxLayout.setOnClickListener { }
|
||||
backgroundView.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
|
||||
for (size in sizeFilterArray!!) {
|
||||
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
|
||||
val item = inflater.inflate(R.layout.item_config_filter_size, flexboxLayout, false)
|
||||
|
||||
// 单列 4 个,强行设置宽度为屏幕的 1/4
|
||||
val width = sizeTv.context.resources.displayMetrics.widthPixels / 4
|
||||
val width = (sizeTv.context.resources.displayMetrics.widthPixels - 56F.dip2px()) / 4
|
||||
val height = item.layoutParams.height
|
||||
|
||||
item.layoutParams = ViewGroup.LayoutParams(width, height)
|
||||
flexboxLayout.addView(item)
|
||||
|
||||
val tv = item.findViewById<TextView>(R.id.size_tv)
|
||||
val tv = item.findViewById<CheckedTextView>(R.id.size_tv)
|
||||
tv.text = size.text
|
||||
|
||||
if (sizeText == size.text) {
|
||||
toggleHighlightedTextView(tv, true)
|
||||
} else {
|
||||
toggleHighlightedTextView(tv, false)
|
||||
}
|
||||
|
||||
tv.isChecked = sizeText == size.text
|
||||
tv.tag = size.text
|
||||
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(tv, true)
|
||||
tv.setOnClickListener {
|
||||
flexboxLayout.forEach { checkedTv ->
|
||||
(checkedTv as CheckedTextView).isChecked = checkedTv == tv
|
||||
}
|
||||
popupWindow.dismiss()
|
||||
sizeTv.text = size.text
|
||||
|
||||
mOnConfigFilterSetupListener?.onSetupSortSize(size)
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
sizeTv.setTextColor(com.gh.gamecenter.common.R.color.text_757575.toColor(sizeTv.context))
|
||||
sizeTv.setDrawableEnd(R.drawable.ic_filter_arrow_down)
|
||||
sizeTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(sizeTv.context))
|
||||
sizeTv.setDrawableEnd(R.drawable.ic_auxiliary_arrow_down_8)
|
||||
mPopupWindow = null
|
||||
}
|
||||
|
||||
@ -193,6 +210,49 @@ class ConfigFilterView @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun initSubjectFilterView(subjectSetting: SubjectSettingEntity) {
|
||||
ratingTv.visibility = View.VISIBLE
|
||||
|
||||
if (subjectSetting.filterOptions.size > 1) {
|
||||
// 重排序
|
||||
subjectSetting.filterOptions.forEachIndexed { index, s ->
|
||||
when (index) {
|
||||
0 -> updateTv.text = s
|
||||
1 -> recommendedTv.text = s
|
||||
2 -> newestTv.text = s
|
||||
3 -> ratingTv.text = s
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updateTv.setPadding(0)
|
||||
updateTv.setTypeface(Typeface.DEFAULT, Typeface.NORMAL)
|
||||
updateTv.isClickable = false
|
||||
updateTv.text = when (subjectSetting.filterOptions.first()) {
|
||||
"推荐" -> "根据光环推荐排序"
|
||||
"最新" -> "根据游戏上新排序"
|
||||
"评分" -> "根据游戏评分排序"
|
||||
"更新" -> "根据更新时间排序"
|
||||
else -> subjectSetting.filterOptions.first()
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏相关选项
|
||||
updateTv.goneIf(subjectSetting.filterOptions.isEmpty())
|
||||
recommendedTv.goneIf(subjectSetting.filterOptions.size <= 1)
|
||||
dot1.goneIf(subjectSetting.filterOptions.size <= 1)
|
||||
newestTv.goneIf(subjectSetting.filterOptions.size <= 2)
|
||||
dot2.goneIf(subjectSetting.filterOptions.size <= 2)
|
||||
ratingTv.goneIf(subjectSetting.filterOptions.size <= 3)
|
||||
dot3.goneIf(subjectSetting.filterOptions.size <= 3)
|
||||
sizeFilterArray = subjectSetting.filterSizes
|
||||
|
||||
if (subjectSetting.filterOptions.size == 1) {
|
||||
updateTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
|
||||
updateTv.setTypeface(Typeface.DEFAULT, Typeface.NORMAL)
|
||||
highlightedSortedType = null
|
||||
}
|
||||
}
|
||||
|
||||
interface OnConfigFilterSetupListener {
|
||||
fun onShowSortSize()
|
||||
fun onSetupSortSize(sortSize: SubjectSettingEntity.Size)
|
||||
|
||||
@ -7,5 +7,8 @@ class GameColumnCollection(
|
||||
val id: String = "",
|
||||
val name: String = "",
|
||||
// 取值为 "1-1" 或 "1-2" 或 "top" 相应地代表 1行1个 或 1行2个 或 排行榜
|
||||
val style: String = ""
|
||||
val style: String = "",
|
||||
val custom: Boolean = false, // 自定义设置
|
||||
@SerializedName("custom_size")
|
||||
val customSize: Int = 0 // 默认显示前X个专题
|
||||
)
|
||||
@ -7,7 +7,7 @@ import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
class SubjectData(
|
||||
data class SubjectData(
|
||||
// 入口必填
|
||||
var subjectId: String?,
|
||||
var subjectName: String?,
|
||||
@ -21,13 +21,28 @@ class SubjectData(
|
||||
var subjectStyle: String = "",
|
||||
var showDetailSubtitle: Boolean = false,
|
||||
var showDetailIconSubscript: Boolean = false,
|
||||
var customLimit: String = "", // unlimited(无限制)、forbidden(禁止移出)
|
||||
|
||||
var requireUpdateSetting: Boolean = false, // 多专题页面需要专题页面自行获取专题配置
|
||||
var isAdData: Boolean = false,
|
||||
var adId: String = "", // 广告ID(本地字段),不为空时为广告专题
|
||||
var codeId: String = "" // 广告CODE_ID(本地字段),不为空时为广告专题
|
||||
var codeId: String = "", // 广告CODE_ID(本地字段),不为空时为广告专题
|
||||
var tag: String = "" // 分类标签,埋点用
|
||||
) : Parcelable, Cloneable {
|
||||
|
||||
@IgnoredOnParcel
|
||||
val isForbidden
|
||||
get() = customLimit == "forbidden"
|
||||
|
||||
@IgnoredOnParcel
|
||||
val sortChinese
|
||||
get() = when {
|
||||
sort.contains("publish") -> "最新"
|
||||
sort.contains("star") -> "评分"
|
||||
sort.contains("update") -> "更新"
|
||||
else -> "推荐"
|
||||
}
|
||||
|
||||
@IgnoredOnParcel
|
||||
val subjectStyleChinese: String
|
||||
get() = CustomPageItem.subjectTypeToComponentStyle[subjectStyle] ?: ""
|
||||
|
||||
@ -13,7 +13,7 @@ class SubjectSettingEntity(
|
||||
@SerializedName("type")
|
||||
var typeEntity: TypeEntity = TypeEntity(),
|
||||
var tag: String = "",
|
||||
var filter: String = "", // rows: off/on
|
||||
var filter: String = "", // off/on
|
||||
var order: Boolean = false, // 是否显示序号
|
||||
|
||||
@SerializedName("brief_style")
|
||||
@ -34,6 +34,9 @@ class SubjectSettingEntity(
|
||||
private val _showDetailIconSubscript: Boolean? = null
|
||||
) : Parcelable {
|
||||
|
||||
val isFilterEnabled: Boolean
|
||||
get() = filter == "on"
|
||||
|
||||
val showDetailSubtitle: Boolean
|
||||
get() = _showDetailSubtitle ?: false
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ package com.gh.gamecenter.game.columncollection.detail
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.core.view.isVisible
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.baselist.LazyListFragment
|
||||
@ -14,6 +14,8 @@ import com.gh.gamecenter.common.json.json
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.common.utils.observeNonNull
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.FragmentColumnCollectionDetailBinding
|
||||
import com.gh.gamecenter.entity.GameColumnCollection
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
@ -23,6 +25,7 @@ class ColumnCollectionDetailFragment : LazyListFragment<LinkEntity, ColumnCollec
|
||||
|
||||
private var mAdapter: ColumnCollectionDetailAdapter? = null
|
||||
private var mBinding: FragmentColumnCollectionDetailBinding? = null
|
||||
private var mFragment: SubjectTabFragment? = null
|
||||
|
||||
private var mTabIndex = -1
|
||||
private var mBasicExposureSourceList: ArrayList<ExposureSource>? = null
|
||||
@ -56,6 +59,11 @@ class ColumnCollectionDetailFragment : LazyListFragment<LinkEntity, ColumnCollec
|
||||
override fun onFragmentFirstVisible() {
|
||||
super.onFragmentFirstVisible()
|
||||
|
||||
if (mIsFromMainWrapper) {
|
||||
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn)
|
||||
mBinding?.statusBar?.isVisible = true
|
||||
}
|
||||
|
||||
mListViewModel.getGameColumnCollection()
|
||||
mListViewModel.columnCollection.observeNonNull(this) {
|
||||
setNavigationTitle(it.name)
|
||||
@ -91,7 +99,7 @@ class ColumnCollectionDetailFragment : LazyListFragment<LinkEntity, ColumnCollec
|
||||
}
|
||||
|
||||
override fun onChanged(list: MutableList<LinkEntity>?) {
|
||||
if (list != null && list.isNotEmpty()) {
|
||||
if (!list.isNullOrEmpty()) {
|
||||
showSubjectTab(list)
|
||||
}
|
||||
}
|
||||
@ -115,25 +123,28 @@ class ColumnCollectionDetailFragment : LazyListFragment<LinkEntity, ColumnCollec
|
||||
isOrder = false,
|
||||
requireUpdateSetting = true,
|
||||
filter = "type:全部", // 默认显示大图
|
||||
subjectType = subjectType
|
||||
subjectType = subjectType,
|
||||
customLimit = link.customLimit
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val fragment = childFragmentManager.findFragmentByTag(SubjectTabFragment::class.java.name)
|
||||
mFragment = childFragmentManager.findFragmentByTag(SubjectTabFragment::class.java.name) as? SubjectTabFragment
|
||||
?: SubjectTabFragment()
|
||||
val bundle = arguments
|
||||
mListViewModel.columnCollection.value?.let {
|
||||
bundle?.putString(EntranceConsts.KEY_COLUMN_COLLECTION_ID, it.id)
|
||||
bundle?.putString(EntranceConsts.KEY_COLUMN_COLLECTION_NAME, it.name)
|
||||
bundle?.putString(EntranceConsts.KEY_COLUMN_COLLECTION_STYLE, it.style)
|
||||
bundle?.putBoolean(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM, it.custom)
|
||||
bundle?.putInt(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM_SIZE, it.customSize)
|
||||
}
|
||||
bundle?.putParcelableArrayList(EntranceConsts.KEY_DATA, subjectDataList)
|
||||
bundle?.putBoolean(EntranceConsts.KEY_IS_COLUMN_COLLECTION, true)
|
||||
|
||||
fragment.arguments = bundle
|
||||
mFragment!!.arguments = bundle
|
||||
mBinding?.placeholder?.visibility = View.VISIBLE
|
||||
childFragmentManager.beginTransaction().replace(R.id.placeholder, fragment, SubjectTabFragment::class.java.name)
|
||||
childFragmentManager.beginTransaction().replace(R.id.placeholder, mFragment!!, SubjectTabFragment::class.java.name)
|
||||
.commitAllowingStateLoss()
|
||||
}
|
||||
|
||||
@ -167,9 +178,18 @@ class ColumnCollectionDetailFragment : LazyListFragment<LinkEntity, ColumnCollec
|
||||
arguments?.getString(EntranceConsts.KEY_COLLECTION_ID)
|
||||
?: ""
|
||||
)
|
||||
return ViewModelProviders.of(this, factory).get(ColumnCollectionDetailViewModel::class.java)
|
||||
return viewModelProviderFromParent(factory, arguments?.getString(EntranceConsts.KEY_COLLECTION_ID) ?: "")
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
if (mIsFromMainWrapper) {
|
||||
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean = mFragment?.onBackPressed() ?: false
|
||||
|
||||
companion object {
|
||||
const val TYPE_QQ_MINI_GAME_COLUMN = "qq_mini_game_column"
|
||||
const val TYPE_WECHAT_MINI_GAME_COLUMN = "wechat_mini_game_column"
|
||||
|
||||
@ -42,6 +42,7 @@ class SubjectAdapter(
|
||||
private val mSubjectViewModel: SubjectViewModel?,
|
||||
private val mEntrance: String?,
|
||||
private val mIsColumnCollection: Boolean,
|
||||
private val mColumnCollectionCustomPosition: Int = -1,
|
||||
private val mCollectionId: String,
|
||||
private val mCollectionName: String,
|
||||
private val mCollectionStyle: String
|
||||
@ -217,9 +218,10 @@ class SubjectAdapter(
|
||||
|
||||
mSubjectViewModel?.subjectSettingLD?.value?.let { subjectSetting ->
|
||||
subjectStyle = subjectSetting.typeEntity.layout
|
||||
isFilterOn = subjectSetting.filter == "on"
|
||||
isFilterOn = subjectSetting.isFilterEnabled
|
||||
}
|
||||
|
||||
gameEntity.sequence = position
|
||||
val exposureEvent = generateExposureEvent(gameEntity, subjectStyle, isFilterOn)
|
||||
val humanReadablePosition = position + 1
|
||||
mExposureEventSparseArray.put(position, exposureEvent)
|
||||
@ -266,7 +268,10 @@ class SubjectAdapter(
|
||||
gameColumnName = subjectData.subjectName ?: "",
|
||||
gameId = gameEntity.id,
|
||||
gameName = gameEntity.name ?: "",
|
||||
text = "游戏"
|
||||
text = "游戏",
|
||||
gameTag = mViewModel.selectedLabelList.ifEmpty { listOf(mViewModel.subjectData.tag) },
|
||||
sort = mViewModel.subjectData.sortChinese,
|
||||
inclusionSize = mViewModel.selectedFilterSize.text ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -326,7 +331,10 @@ class SubjectAdapter(
|
||||
gameColumnName = subjectData.subjectName ?: "",
|
||||
gameId = gameEntity.id,
|
||||
gameName = gameEntity.name ?: "",
|
||||
text = "按钮"
|
||||
text = "按钮",
|
||||
gameTag = mViewModel.selectedLabelList.ifEmpty { listOf(mViewModel.subjectData.tag) },
|
||||
sort = mViewModel.subjectData.sortChinese,
|
||||
inclusionSize = mViewModel.selectedFilterSize.text ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
@ -446,7 +454,10 @@ class SubjectAdapter(
|
||||
linkId = linkEntity.link ?: "",
|
||||
linkText = linkEntity.text ?: "",
|
||||
linkType = linkEntity.type ?: "",
|
||||
text = "头图"
|
||||
text = "头图",
|
||||
gameTag = mViewModel.selectedLabelList.ifEmpty { listOf(mViewModel.subjectData.tag) },
|
||||
sort = mViewModel.subjectData.sortChinese,
|
||||
inclusionSize = mViewModel.selectedFilterSize.text ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -471,13 +482,12 @@ class SubjectAdapter(
|
||||
"$mCollectionName+${CustomPageItem.collectionTypeToComponentName[mCollectionStyle] ?: mCollectionStyle}+$mCollectionId"
|
||||
)
|
||||
)
|
||||
exposureSourceList.add(ExposureSource("合集详情"))
|
||||
exposureSourceList.add(
|
||||
ExposureSource(
|
||||
"专题",
|
||||
"${subjectData.subjectName}+${subjectData.subjectStyleChinese}+${subjectData.subjectId}"
|
||||
)
|
||||
)
|
||||
exposureSourceList.add(ExposureSource(if (mColumnCollectionCustomPosition == -1) "合集详情" else "自定义合集详情"))
|
||||
var value = "${subjectData.subjectName}+${subjectData.subjectStyleChinese}+${subjectData.subjectId}"
|
||||
if (mColumnCollectionCustomPosition != -1) {
|
||||
value += "+${mColumnCollectionCustomPosition}"
|
||||
}
|
||||
exposureSourceList.add(ExposureSource("专题", value))
|
||||
} else {
|
||||
var sourceString = ""
|
||||
exposureSourceList.add(
|
||||
@ -493,12 +503,7 @@ class SubjectAdapter(
|
||||
sourceString = filter
|
||||
|
||||
if (isFilterOn) {
|
||||
val sort = when {
|
||||
subjectData.sort.contains("publish") -> "最新"
|
||||
subjectData.sort.contains("star") -> "评分"
|
||||
else -> "最热"
|
||||
}
|
||||
|
||||
val sort = subjectData.sortChinese
|
||||
val filterSize = mViewModel.selectedFilterSize.text
|
||||
|
||||
sourceString =
|
||||
@ -516,12 +521,7 @@ class SubjectAdapter(
|
||||
}
|
||||
|
||||
if (isFilterOn) {
|
||||
val sort = when {
|
||||
subjectData.sort.contains("publish") -> "最新"
|
||||
subjectData.sort.contains("star") -> "评分"
|
||||
else -> "推荐"
|
||||
}
|
||||
|
||||
val sort = subjectData.sortChinese
|
||||
val filterSize = mViewModel.selectedFilterSize.text
|
||||
|
||||
sourceString =
|
||||
@ -532,12 +532,7 @@ class SubjectAdapter(
|
||||
}
|
||||
|
||||
else -> {
|
||||
val sort = when {
|
||||
subjectData.sort.contains("publish") -> "最新"
|
||||
subjectData.sort.contains("star") -> "评分"
|
||||
else -> "推荐"
|
||||
}
|
||||
|
||||
val sort = subjectData.sortChinese
|
||||
val filterSize = mViewModel.selectedFilterSize.text
|
||||
|
||||
if (isFilterOn) {
|
||||
|
||||
@ -125,7 +125,7 @@ open class SubjectFragment : LazyFragment() {
|
||||
}
|
||||
val bundle = arguments
|
||||
bundle?.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, mViewModel?.subjectData)
|
||||
bundle?.putParcelable(SubjectSettingEntity::class.java.simpleName, entity)
|
||||
bundle?.putParcelable(EntranceConsts.KEY_SUBJECT_SETTING_DATA, entity)
|
||||
fragment.arguments = bundle
|
||||
transaction.replace(R.id.subject_content, fragment, tag)
|
||||
transaction.commitAllowingStateLoss()
|
||||
|
||||
@ -6,6 +6,8 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.view.ConfigFilterView
|
||||
import com.gh.common.view.ConfigFilterView.SortType
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
import com.gh.download.DownloadManager
|
||||
@ -14,11 +16,12 @@ import com.gh.gamecenter.common.baselist.LazyListFragment
|
||||
import com.gh.gamecenter.common.baselist.LoadType
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
|
||||
import com.gh.gamecenter.common.view.SpacingItemDecoration
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
@ -44,6 +47,8 @@ open class SubjectListFragment : LazyListFragment<GameEntity, SubjectListViewMod
|
||||
private var mCollectionName = ""
|
||||
private var mCollectionStyle = ""
|
||||
private var mScrollTop = false
|
||||
private var mMaxSize = ""
|
||||
private var mMinSize = ""
|
||||
|
||||
var selectedLabelList = arrayListOf<String>()
|
||||
|
||||
@ -79,6 +84,7 @@ open class SubjectListFragment : LazyListFragment<GameEntity, SubjectListViewMod
|
||||
mSubjectViewModel,
|
||||
arguments?.getString(EntranceConsts.KEY_ENTRANCE),
|
||||
mIsColumnCollection,
|
||||
arguments?.getInt(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM_POSITION, -1) ?: -1,
|
||||
mCollectionId,
|
||||
mCollectionName,
|
||||
mCollectionStyle
|
||||
@ -120,10 +126,14 @@ open class SubjectListFragment : LazyListFragment<GameEntity, SubjectListViewMod
|
||||
mCollectionName = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_NAME, "") ?: ""
|
||||
mCollectionStyle = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_STYLE, "") ?: ""
|
||||
super.onFragmentFirstVisible()
|
||||
(mListViewModel as SubjectListViewModel).lastPageDataMap =
|
||||
arguments?.get(SubjectFragment.LAST_PAGE_DATA) as? HashMap<String, String>
|
||||
(mListViewModel as SubjectListViewModel).run {
|
||||
lastPageDataMap =
|
||||
arguments?.get(SubjectFragment.LAST_PAGE_DATA) as? HashMap<String, String>
|
||||
arguments?.getString(EntranceConsts.KEY_SUBJECT_SORT_SIZE)?.let { selectedFilterSize = SubjectSettingEntity.Size(text = it) }
|
||||
}
|
||||
|
||||
mCachedView?.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
|
||||
initFilterView()
|
||||
val skeletonLayoutId = when (arguments?.getString(EntranceConsts.KEY_SUBJECT_TYPE) ?: "") {
|
||||
"detail" -> R.layout.fragment_subject_detail_skeleton
|
||||
"tab" -> R.layout.fragment_subject_tab_skeleton
|
||||
@ -141,7 +151,62 @@ open class SubjectListFragment : LazyListFragment<GameEntity, SubjectListViewMod
|
||||
mListViewModel.load(LoadType.REFRESH)
|
||||
}
|
||||
|
||||
override fun getRealLayoutId() = R.layout.fragment_list_base_skeleton
|
||||
private fun initFilterView() {
|
||||
val subjectSetting= arguments?.getParcelable<SubjectSettingEntity>(EntranceConsts.KEY_SUBJECT_SETTING_DATA) ?: return
|
||||
val originalFilter = mListViewModel.subjectData.filter
|
||||
mCachedView?.findViewById<ConfigFilterView>(R.id.filterView)?.run {
|
||||
goneIf(!subjectSetting.isFilterEnabled) {
|
||||
initSubjectFilterView(subjectSetting)
|
||||
when (updateTv.text) {
|
||||
"更新" -> mListViewModel.subjectData.sort = UrlFilterUtils.getFilterQuery("update_time", "-1")
|
||||
"最新" -> mListViewModel.subjectData.sort = UrlFilterUtils.getFilterQuery("publish", "-1")
|
||||
"评分" -> mListViewModel.subjectData.sort = UrlFilterUtils.getFilterQuery("star", "-1")
|
||||
else -> mListViewModel.subjectData.sort = UrlFilterUtils.getFilterQuery("position", "1")
|
||||
}
|
||||
setOnConfigSetupListener(object :
|
||||
ConfigFilterView.OnConfigFilterSetupListener {
|
||||
override fun onShowSortSize() {}
|
||||
|
||||
override fun onSetupSortSize(sortSize: SubjectSettingEntity.Size) {
|
||||
mMinSize = sortSize.min.toString()
|
||||
mMaxSize = sortSize.max.toString()
|
||||
|
||||
var filter = originalFilter.ifEmpty { "type:全部" }
|
||||
if (mMinSize.isNotEmpty() && mMinSize != "-1") {
|
||||
filter += ",${UrlFilterUtils.getFilterQuery("min_size", mMinSize)}"
|
||||
}
|
||||
if (mMaxSize.isNotEmpty() && mMaxSize != "-1") {
|
||||
filter += ",${UrlFilterUtils.getFilterQuery("max_size", mMaxSize)}"
|
||||
}
|
||||
|
||||
refreshPage(filter = filter, size = sortSize)
|
||||
}
|
||||
|
||||
override fun onSetupSortType(sortType: SortType) {
|
||||
val clickTv = when (sortType) {
|
||||
SortType.RATING -> ratingTv
|
||||
SortType.NEWEST -> newestTv
|
||||
SortType.UPDATE -> updateTv
|
||||
else -> recommendedTv
|
||||
}
|
||||
|
||||
val sort = when (clickTv.text) {
|
||||
"更新" -> UrlFilterUtils.getFilterQuery("update_time", "-1")
|
||||
"最新" -> UrlFilterUtils.getFilterQuery("publish", "-1")
|
||||
"评分" -> UrlFilterUtils.getFilterQuery("star", "-1")
|
||||
else -> UrlFilterUtils.getFilterQuery("position", "1")
|
||||
}
|
||||
|
||||
if (mListViewModel.subjectData.sort != sort) {
|
||||
refreshPage(sort = sort)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRealLayoutId() = R.layout.fragment_subject_list
|
||||
|
||||
override fun initRealView() {
|
||||
super.initRealView()
|
||||
@ -161,7 +226,11 @@ open class SubjectListFragment : LazyListFragment<GameEntity, SubjectListViewMod
|
||||
mListRv?.addOnScrollListener(mExposureListener)
|
||||
}
|
||||
|
||||
fun refreshPage(filter: String, sort: String, size: SubjectSettingEntity.Size) {
|
||||
fun refreshPage(
|
||||
filter: String = mListViewModel.subjectData.filter,
|
||||
sort: String = mListViewModel.subjectData.sort,
|
||||
size: SubjectSettingEntity.Size = mListViewModel.selectedFilterSize
|
||||
) {
|
||||
mListViewModel.selectedFilterSize = size
|
||||
mListViewModel.selectedLabelList = selectedLabelList
|
||||
mListViewModel.subjectData.filter = filter
|
||||
@ -182,10 +251,6 @@ open class SubjectListFragment : LazyListFragment<GameEntity, SubjectListViewMod
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
override fun onFragmentResume() {
|
||||
super.onFragmentResume()
|
||||
DownloadManager.getInstance().addObserver(dataWatcher)
|
||||
@ -230,5 +295,10 @@ open class SubjectListFragment : LazyListFragment<GameEntity, SubjectListViewMod
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
mAdapter?.let { it.notifyItemRangeChanged(0, it.itemCount) }
|
||||
mCachedView?.findViewById<ConfigFilterView>(R.id.filterView)?.run {
|
||||
if (isVisible) {
|
||||
updateAllTextView()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,6 @@ import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.PageLocation
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
@ -29,7 +28,7 @@ open class SubjectListViewModel(
|
||||
var exposureSourceList: List<ExposureSource>?
|
||||
) : ListViewModel<GameEntity, GameEntity>(application) {
|
||||
|
||||
// 供专题类型为 rows 时统计用
|
||||
// 供统计用
|
||||
var selectedLabelList = arrayListOf<String>()
|
||||
var selectedFilterSize = SubjectSettingEntity.Size(text = "全部大小")
|
||||
|
||||
|
||||
@ -1,19 +1,24 @@
|
||||
package com.gh.gamecenter.subject.rows
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.widget.CheckedTextView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.gh.common.view.ConfigFilterView
|
||||
import com.gh.common.view.ConfigFilterView.SortType
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.common.view.ConfigFilterView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.subject.SubjectListFragment
|
||||
@ -32,13 +37,15 @@ class SubjectRowsFragment : BaseFragment<Any>() {
|
||||
// 统计用的大小筛选选中文案
|
||||
private var mSelectedFilterSize = SubjectSettingEntity.Size(text = "全部大小")
|
||||
|
||||
private lateinit var filterView: ConfigFilterView
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.fragment_subject_rows
|
||||
}
|
||||
|
||||
override fun initView(view: View) {
|
||||
super.initView(view)
|
||||
mSettingEntity = arguments?.getParcelable(SubjectSettingEntity::class.java.simpleName)
|
||||
mSettingEntity = arguments?.getParcelable(EntranceConsts.KEY_SUBJECT_SETTING_DATA)
|
||||
?: return
|
||||
mSubjectData = arguments?.getParcelable(EntranceConsts.KEY_SUBJECT_DATA) ?: return
|
||||
|
||||
@ -55,7 +62,7 @@ class SubjectRowsFragment : BaseFragment<Any>() {
|
||||
mListFragment =
|
||||
childFragmentManager.findFragmentByTag(SubjectListFragment::class.java.name) as? SubjectListFragment
|
||||
?: SubjectListFragment()
|
||||
mListFragment.arguments = arguments
|
||||
mListFragment.arguments = (arguments?.clone() as? Bundle)?.apply { remove(EntranceConsts.KEY_SUBJECT_SETTING_DATA) }
|
||||
childFragmentManager.beginTransaction()
|
||||
.replace(R.id.rows_list_container, mListFragment, SubjectListFragment::class.java.name)
|
||||
.commitAllowingStateLoss()
|
||||
@ -64,18 +71,29 @@ class SubjectRowsFragment : BaseFragment<Any>() {
|
||||
@SuppressLint("InflateParams")
|
||||
private fun createLabelsLayout() {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
for (labels in mSettingEntity.typeEntity.labels) {
|
||||
mSettingEntity.typeEntity.labels.forEachIndexed { index, labels ->
|
||||
val labelsItem = inflater.inflate(R.layout.subject_rows_label, mLabelsContainer, false)
|
||||
val labelContainer = labelsItem.findViewById<LinearLayout>(R.id.label_container)
|
||||
for (index in 0 until labels.label.size) {
|
||||
val labelName = labels.label[index]
|
||||
labelsItem.updateLayoutParams<MarginLayoutParams> {
|
||||
topMargin = if (index == 0) 0 else 12F.dip2px()
|
||||
}
|
||||
for (labelIndex in 0 until labels.label.size) {
|
||||
val labelName = labels.label[labelIndex]
|
||||
val labelItem =
|
||||
inflater.inflate(R.layout.subject_rows_label_item, labelContainer, false)
|
||||
val label = labelItem.findViewById<CheckedTextView>(R.id.label)
|
||||
if (index == 0) label.isChecked = true
|
||||
label.updateLayoutParams<MarginLayoutParams> {
|
||||
leftMargin = if (labelIndex == 0) 0 else 8F.dip2px()
|
||||
}
|
||||
if (labelIndex == 0) {
|
||||
label.isChecked = true
|
||||
label.setTypeface(Typeface.DEFAULT, Typeface.BOLD)
|
||||
} else {
|
||||
label.setTypeface(Typeface.DEFAULT, Typeface.NORMAL)
|
||||
}
|
||||
label.text = labelName
|
||||
label.setOnClickListener {
|
||||
mFilterMap[labels.name] = if (index == 0) {
|
||||
mFilterMap[labels.name] = if (labelIndex == 0) {
|
||||
""
|
||||
} else {
|
||||
labelName
|
||||
@ -92,26 +110,18 @@ class SubjectRowsFragment : BaseFragment<Any>() {
|
||||
private fun selectLabel(labelContainer: LinearLayout, label: CheckedTextView) {
|
||||
for (i in 0 until labelContainer.childCount) {
|
||||
val view = labelContainer.getChildAt(i)
|
||||
if (view is CheckedTextView && view.isChecked) view.isChecked = false
|
||||
if (view is CheckedTextView && view.isChecked) {
|
||||
view.isChecked = false
|
||||
view.setTypeface(Typeface.DEFAULT, Typeface.NORMAL)
|
||||
}
|
||||
}
|
||||
label.isChecked = true
|
||||
label.setTypeface(Typeface.DEFAULT, Typeface.BOLD)
|
||||
}
|
||||
|
||||
private fun createFilterLayout() {
|
||||
if (mSettingEntity.filter == "on") {
|
||||
val filterView = ConfigFilterView(requireContext())
|
||||
filterView.ratingTv.visibility = View.VISIBLE
|
||||
|
||||
// 重排序
|
||||
mSettingEntity.filterOptions.forEachIndexed { index, s ->
|
||||
when (index) {
|
||||
0 -> filterView.updateTv.text = s
|
||||
1 -> filterView.recommendedTv.text = s
|
||||
2 -> filterView.newestTv.text = s
|
||||
3 -> filterView.ratingTv.text = s
|
||||
}
|
||||
}
|
||||
|
||||
if (mSettingEntity.isFilterEnabled) {
|
||||
filterView = ConfigFilterView(requireContext()).apply { initSubjectFilterView(mSettingEntity) }
|
||||
// 设置默认页面链接
|
||||
when (filterView.updateTv.text) {
|
||||
"更新" -> mSubjectData.sort = UrlFilterUtils.getFilterQuery("update_time", "-1")
|
||||
@ -119,15 +129,14 @@ class SubjectRowsFragment : BaseFragment<Any>() {
|
||||
"评分" -> mSubjectData.sort = UrlFilterUtils.getFilterQuery("star", "-1")
|
||||
else -> mSubjectData.sort = UrlFilterUtils.getFilterQuery("position", "1")
|
||||
}
|
||||
|
||||
// 隐藏相关选项
|
||||
filterView.updateTv.goneIf(mSettingEntity.filterOptions.isEmpty())
|
||||
filterView.recommendedTv.goneIf(mSettingEntity.filterOptions.size <= 1)
|
||||
filterView.newestTv.goneIf(mSettingEntity.filterOptions.size <= 2)
|
||||
filterView.ratingTv.goneIf(mSettingEntity.filterOptions.size <= 3)
|
||||
filterView.sizeFilterArray = mSettingEntity.filterSizes
|
||||
|
||||
mLabelsContainer.addView(filterView)
|
||||
mLabelsContainer.addView(
|
||||
filterView,
|
||||
LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply {
|
||||
topMargin = 8F.dip2px()
|
||||
})
|
||||
|
||||
filterView.setOnConfigSetupListener(object :
|
||||
ConfigFilterView.OnConfigFilterSetupListener {
|
||||
@ -150,11 +159,11 @@ class SubjectRowsFragment : BaseFragment<Any>() {
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSetupSortType(sortType: ConfigFilterView.SortType) {
|
||||
override fun onSetupSortType(sortType: SortType) {
|
||||
val clickTv = when (sortType) {
|
||||
ConfigFilterView.SortType.RATING -> filterView.ratingTv
|
||||
ConfigFilterView.SortType.NEWEST -> filterView.newestTv
|
||||
ConfigFilterView.SortType.UPDATE -> filterView.updateTv
|
||||
SortType.RATING -> filterView.ratingTv
|
||||
SortType.NEWEST -> filterView.newestTv
|
||||
SortType.UPDATE -> filterView.updateTv
|
||||
else -> filterView.recommendedTv
|
||||
}
|
||||
|
||||
@ -171,6 +180,8 @@ class SubjectRowsFragment : BaseFragment<Any>() {
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
mLabelsContainer.setPadding(0, 8F.dip2px(), 0, 8F.dip2px())
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,4 +253,11 @@ class SubjectRowsFragment : BaseFragment<Any>() {
|
||||
mListFragment.selectedLabelList = findAllSelectedLabel(mLabelsContainer)
|
||||
mListFragment.refreshPage(mSubjectData.filter, mSubjectData.sort, mSelectedFilterSize)
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
if (::filterView.isInitialized) {
|
||||
filterView.updateAllTextView()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
package com.gh.gamecenter.subject.tab
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.toJson
|
||||
import com.gh.gamecenter.core.utils.GsonUtils
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.livedata.Event
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
class ColumnCollectionTabViewModel(
|
||||
application: Application,
|
||||
private val columnCollectionId: String,
|
||||
private val customSize: Int,
|
||||
private val subjectDataList: List<SubjectData>
|
||||
) : AndroidViewModel(application) {
|
||||
private val columnCollectionSp by lazy {
|
||||
HaloApp.getInstance().getSharedPreferences(Constants.SP_COLUMN_COLLECTION_CUSTOM_TAB, Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
val tabListLiveData = MutableLiveData<List<SubjectData>>()
|
||||
val followListLiveData = MutableLiveData<List<SubjectData>>()
|
||||
val moreListLiveData = MutableLiveData<List<SubjectData>>()
|
||||
|
||||
val addFollowLiveData = MutableLiveData<Event<SubjectData>>()
|
||||
val addMoreLiveData = MutableLiveData<Event<SubjectData>>()
|
||||
|
||||
init {
|
||||
initData()
|
||||
}
|
||||
|
||||
private fun initData() {
|
||||
val customTabIdList = GsonUtils.fromJsonList<String>(SPUtils.getString(columnCollectionSp, columnCollectionId))
|
||||
if (customTabIdList.isEmpty()) {
|
||||
val followTabList = subjectDataList.take(customSize)
|
||||
tabListLiveData.postValue(followTabList)
|
||||
followListLiveData.postValue(followTabList)
|
||||
moreListLiveData.postValue(subjectDataList - followTabList.toSet())
|
||||
} else {
|
||||
val newAddedForbiddenList = subjectDataList.filter { it.isForbidden && it.subjectId !in customTabIdList }
|
||||
val tabList = arrayListOf<SubjectData>().apply { addAll(newAddedForbiddenList) }
|
||||
|
||||
customTabIdList.forEach { subjectId->
|
||||
subjectDataList.find { subjectId == it.subjectId }?.let {
|
||||
tabList.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
val followTabList = tabList.take(CUSTOM_MAX_TAB).ifEmpty { subjectDataList.take(customSize) }
|
||||
tabListLiveData.postValue(followTabList)
|
||||
followListLiveData.postValue(followTabList)
|
||||
moreListLiveData.postValue(subjectDataList - followTabList.toSet())
|
||||
}
|
||||
}
|
||||
|
||||
fun addFollow(subjectData: SubjectData) {
|
||||
addFollowLiveData.postValue(Event(subjectData))
|
||||
}
|
||||
|
||||
fun addMore(subjectData: SubjectData) {
|
||||
addMoreLiveData.postValue(Event(subjectData))
|
||||
}
|
||||
|
||||
fun saveCustomTab(followTabList: List<SubjectData>) {
|
||||
tabListLiveData.postValue(followTabList)
|
||||
followListLiveData.postValue(followTabList)
|
||||
moreListLiveData.postValue(subjectDataList - followTabList.toSet())
|
||||
|
||||
val followSubjectIdList = followTabList.map { it.subjectId ?: "" }.distinct()
|
||||
SPUtils.setString(columnCollectionSp, columnCollectionId, followSubjectIdList.toJson())
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CUSTOM_MAX_TAB = 15
|
||||
}
|
||||
|
||||
class Factory(
|
||||
private val columnCollectionId: String,
|
||||
private val customSize: Int,
|
||||
private val subjectDataList: List<SubjectData>
|
||||
) : ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return ColumnCollectionTabViewModel(
|
||||
HaloApp.getInstance().application,
|
||||
columnCollectionId,
|
||||
customSize,
|
||||
subjectDataList
|
||||
) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package com.gh.gamecenter.subject.tab
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.DiffUtil.ItemCallback
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.view.Chips
|
||||
import com.gh.gamecenter.databinding.ItemColumnCollectionCustomTabBinding
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
|
||||
class CustomTabFollowAdapter(private val viewModel: ColumnCollectionTabViewModel?) :
|
||||
ListAdapter<SubjectData, CustomTabFollowAdapter.CustomTabFollowItemViewHolder>(createDiffItemCallBack()) {
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
): CustomTabFollowItemViewHolder {
|
||||
return CustomTabFollowItemViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: CustomTabFollowItemViewHolder, position: Int) {
|
||||
val subjectData = currentList.getOrNull(position) ?: return
|
||||
val isForbidden = subjectData.isForbidden
|
||||
holder.binding.chips.run {
|
||||
setState(if (isForbidden) Chips.STATE_FILL else Chips.STATE_DEFAULT)
|
||||
setText(subjectData.subjectName ?: "")
|
||||
endIcon.isVisible = !isForbidden
|
||||
endIcon.setImageResource(R.drawable.ic_basic_x_8_secondary)
|
||||
endIcon.imageTintList = null
|
||||
setOnClickListener {
|
||||
if (!isForbidden) {
|
||||
viewModel?.addMore(subjectData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CustomTabFollowItemViewHolder(val binding: ItemColumnCollectionCustomTabBinding) :
|
||||
ViewHolder(binding.root)
|
||||
|
||||
companion object {
|
||||
|
||||
fun createDiffItemCallBack() = object : ItemCallback<SubjectData>() {
|
||||
override fun areItemsTheSame(oldItem: SubjectData, newItem: SubjectData): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: SubjectData, newItem: SubjectData): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.gh.gamecenter.subject.tab
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.DiffUtil.ItemCallback
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.common.view.Chips
|
||||
import com.gh.gamecenter.databinding.ItemColumnCollectionCustomTabBinding
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
|
||||
class CustomTabMoreAdapter(private val viewModel: ColumnCollectionTabViewModel?) :
|
||||
ListAdapter<SubjectData, CustomTabMoreAdapter.CustomTabMoreItemViewHolder>(createDiffItemCallBack()) {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomTabMoreItemViewHolder {
|
||||
return CustomTabMoreItemViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: CustomTabMoreItemViewHolder, position: Int) {
|
||||
val subjectData = currentList.getOrNull(position) ?: return
|
||||
holder.binding.chips.run {
|
||||
setState(Chips.STATE_DEFAULT)
|
||||
setText(subjectData.subjectName ?: "")
|
||||
startIcon.isVisible = true
|
||||
startIcon.setImageResource(R.drawable.ic_auxiliary_plus_secondary_8)
|
||||
startIcon.imageTintList = null
|
||||
setOnClickListener {
|
||||
viewModel?.addFollow(subjectData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CustomTabMoreItemViewHolder(val binding: ItemColumnCollectionCustomTabBinding) : ViewHolder(binding.root)
|
||||
|
||||
companion object {
|
||||
|
||||
fun createDiffItemCallBack() = object : ItemCallback<SubjectData>() {
|
||||
override fun areItemsTheSame(oldItem: SubjectData, newItem: SubjectData): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: SubjectData, newItem: SubjectData): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,56 +1,154 @@
|
||||
package com.gh.gamecenter.subject.tab
|
||||
|
||||
import android.animation.AnimatorSet
|
||||
import android.animation.ValueAnimator
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.widget.CheckedTextView
|
||||
import android.widget.TextView
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.gh.common.util.NewLogUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.toDrawable
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.DialogHelper.Config
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentSubjectTabBinding
|
||||
import com.gh.gamecenter.databinding.LayoutColumnCollectionSettingBinding
|
||||
import com.gh.gamecenter.databinding.TabItemMainBinding
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem
|
||||
import com.gh.gamecenter.livedata.EventObserver
|
||||
import com.gh.gamecenter.subject.SubjectFragment
|
||||
import com.gh.gamecenter.subject.SubjectListFragment
|
||||
import com.google.android.flexbox.FlexboxLayoutManager
|
||||
import com.google.android.flexbox.JustifyContent
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class SubjectTabFragment : BaseFragment<Any>() {
|
||||
class SubjectTabFragment : ToolbarFragment() {
|
||||
|
||||
private val mBinding by lazy { FragmentSubjectTabBinding.inflate(layoutInflater) }
|
||||
private val binding by lazy { FragmentSubjectTabBinding.inflate(layoutInflater) }
|
||||
private var settingBinding: LayoutColumnCollectionSettingBinding? = null
|
||||
private var isSubject = false
|
||||
private var isCustomEnabled = false
|
||||
private var tabStyle = TabStyle.SUBJECT_NORMAL
|
||||
private var tabBindingList = arrayListOf<TabItemMainBinding>()
|
||||
private var isSettingAnimating = false
|
||||
private var columnCollectionTabViewModel: ColumnCollectionTabViewModel? = null
|
||||
private val fragmentTag by lazy { "android:switcher:${binding.subjectViewpager.id}:" }
|
||||
private var collectionId = ""
|
||||
private var collectionName = ""
|
||||
private var collectionStyle = ""
|
||||
private val followAdapter by lazy { CustomTabFollowAdapter(columnCollectionTabViewModel) }
|
||||
private val moreAdapter by lazy { CustomTabMoreAdapter(columnCollectionTabViewModel) }
|
||||
private val showOrHideMore: (Boolean) -> Unit = { isShow ->
|
||||
settingBinding?.run {
|
||||
if (isShow == moreContainer.isVisible) return@run
|
||||
|
||||
val startHeight = if (isShow) 0 else moreContainer.height
|
||||
val endHeight = if (isShow) {
|
||||
moreContainer.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
|
||||
moreContainer.measuredHeight
|
||||
} else 0
|
||||
ValueAnimator.ofInt(startHeight, endHeight).apply {
|
||||
duration = ANIMATOR_DURATION
|
||||
interpolator = AccelerateDecelerateInterpolator()
|
||||
doOnStart {
|
||||
if (isShow) {
|
||||
moreContainer.updateLayoutParams<MarginLayoutParams> { height = 0 }
|
||||
moreContainer.isVisible = true
|
||||
} else {
|
||||
moreContainer.isInvisible = true
|
||||
}
|
||||
}
|
||||
doOnEnd {
|
||||
if (isShow) {
|
||||
moreContainer.updateLayoutParams<MarginLayoutParams> { height = MarginLayoutParams.WRAP_CONTENT }
|
||||
} else {
|
||||
moreContainer.isVisible = false
|
||||
}
|
||||
}
|
||||
addUpdateListener { animation ->
|
||||
moreContainer.updateLayoutParams<MarginLayoutParams> { height = animation.animatedValue as Int }
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
private val itemTouchHelper by lazy {
|
||||
ItemTouchHelper(object : ItemTouchHelper.Callback() {
|
||||
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
|
||||
return makeMovementFlags(ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.START or ItemTouchHelper.END, 0)
|
||||
}
|
||||
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
val from = viewHolder.bindingAdapterPosition
|
||||
val to = target.bindingAdapterPosition
|
||||
val newList = followAdapter.currentList.toMutableList()
|
||||
Collections.swap(newList, from, to)
|
||||
followAdapter.submitList(newList)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun isLongPressDragEnabled(): Boolean = true
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) = Unit
|
||||
})
|
||||
}
|
||||
|
||||
override fun getLayoutId() = 0
|
||||
override fun getInflatedLayout() = mBinding.root
|
||||
override fun getInflatedLayout() = binding.root
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val subjectList = arguments?.getParcelableArrayList<SubjectData>(EntranceConsts.KEY_DATA)
|
||||
val subjectList = arguments?.getParcelableArrayList<SubjectData>(EntranceConsts.KEY_DATA) ?: arrayListOf()
|
||||
isSubject = subjectList.isEmpty()
|
||||
tabStyle = when {
|
||||
mIsFromMainWrapper && !isSubject -> TabStyle.COLUMN_COLLECTION_MAIN_WRAPPER
|
||||
isSubject -> TabStyle.SUBJECT_NORMAL
|
||||
else -> TabStyle.COLUMN_COLLECTION_NORMAL
|
||||
}
|
||||
val fragments = ArrayList<Fragment>()
|
||||
var tagList = arrayListOf<String>()
|
||||
val fragmentTag = "android:switcher:${mBinding.subjectViewpager.id}:"
|
||||
if (subjectList.isNullOrEmpty()) {
|
||||
val tagList: ArrayList<String>
|
||||
if (isSubject) {
|
||||
// 专题详情
|
||||
val subjectData = arguments?.getParcelable<SubjectData>(EntranceConsts.KEY_SUBJECT_DATA)
|
||||
?: return
|
||||
val settingsEntity =
|
||||
arguments?.getParcelable<SubjectSettingEntity>(SubjectSettingEntity::class.java.simpleName)
|
||||
arguments?.getParcelable<SubjectSettingEntity>(EntranceConsts.KEY_SUBJECT_SETTING_DATA)
|
||||
?: return
|
||||
tagList = settingsEntity.typeEntity.content as ArrayList<String>
|
||||
if (tagList.size > 1) {
|
||||
mBinding.subjectTabContainer.visibility = View.VISIBLE
|
||||
binding.subjectTabContainer.visibility = View.VISIBLE
|
||||
}
|
||||
tagList.forEachIndexed { index, tag ->
|
||||
val element = childFragmentManager.findFragmentByTag("${fragmentTag}$index")
|
||||
@ -60,69 +158,192 @@ class SubjectTabFragment : BaseFragment<Any>() {
|
||||
copyData.filter = if (tag == "全部") {
|
||||
UrlFilterUtils.getFilterQuery("tags", tag, "type", "全部")
|
||||
} else {
|
||||
copyData.tag = tag
|
||||
UrlFilterUtils.getFilterQuery("tags", tag)
|
||||
}
|
||||
bundle?.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, copyData)
|
||||
bundle?.putParcelable(EntranceConsts.KEY_SUBJECT_SETTING_DATA, settingsEntity)
|
||||
element.arguments = bundle
|
||||
fragments.add(element)
|
||||
}
|
||||
if (binding.subjectTabContainer.isVisible) {
|
||||
binding.subjectTabIndicator.setupWithTabLayout(binding.subjectTab)
|
||||
binding.subjectTabIndicator.setupWithViewPager(binding.subjectViewpager)
|
||||
}
|
||||
|
||||
val adapter = object : FragmentStatePagerAdapter(childFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
||||
override fun getItem(position: Int): Fragment {
|
||||
return fragments[position]
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return fragments.size
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence {
|
||||
return tagList[position]
|
||||
}
|
||||
|
||||
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
|
||||
// super.destroyItem(container, position, `object`)
|
||||
}
|
||||
}
|
||||
binding.subjectViewpager.adapter = adapter
|
||||
binding.subjectTab.setupWithViewPager(binding.subjectViewpager)
|
||||
initTabLayout()
|
||||
} else {
|
||||
// 专题合集详情
|
||||
mBinding.subjectTabContainer.visibility = View.VISIBLE
|
||||
isCustomEnabled = arguments?.getBoolean(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM) ?: false
|
||||
val customSize = (arguments?.getInt(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM_SIZE)
|
||||
?: ColumnCollectionTabViewModel.CUSTOM_MAX_TAB).coerceAtMost(ColumnCollectionTabViewModel.CUSTOM_MAX_TAB)
|
||||
collectionId = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_ID, "") ?: ""
|
||||
collectionName = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_NAME, "") ?: ""
|
||||
collectionStyle = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_STYLE, "") ?: ""
|
||||
binding.optionIv.isVisible = isCustomEnabled
|
||||
binding.maskView.isVisible = isCustomEnabled
|
||||
binding.optionIv.setOnClickListener {
|
||||
showSettingView()
|
||||
SensorsBridge.trackColumnCollectionClick(
|
||||
location = "合集详情",
|
||||
columnCollectionName = collectionName,
|
||||
columnCollectionId = collectionId,
|
||||
text = "自定义设置",
|
||||
columnCollectionPattern = CustomPageItem.collectionTypeToComponentName[collectionStyle]
|
||||
?: collectionStyle
|
||||
)
|
||||
}
|
||||
binding.subjectTabContainer.visibility = View.VISIBLE
|
||||
if (isCustomEnabled) {
|
||||
val columnCollectionId = arguments?.getString(EntranceConsts.KEY_COLUMN_COLLECTION_ID) ?: ""
|
||||
columnCollectionTabViewModel = viewModelProvider(ColumnCollectionTabViewModel.Factory(columnCollectionId, customSize, subjectList))
|
||||
observerData()
|
||||
if (SPUtils.getBoolean(Constants.SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_SETTING, true)) {
|
||||
mBaseHandler.post {
|
||||
showSettingView()
|
||||
}
|
||||
SPUtils.setBoolean(Constants.SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_SETTING, false)
|
||||
}
|
||||
} else {
|
||||
initColumnCollectionViewPager(subjectList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subjectList.filterIndexed { index, subject ->
|
||||
val element = childFragmentManager.findFragmentByTag("${fragmentTag}$index")
|
||||
?: SubjectFragment()
|
||||
val bundle = arguments?.clone() as Bundle?
|
||||
bundle?.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, subject)
|
||||
bundle?.putParcelableArrayList(EntranceConsts.KEY_DATA, null)
|
||||
element.arguments = bundle
|
||||
fragments.add(element)
|
||||
|
||||
tagList.add(subject.subjectName ?: "")
|
||||
private fun observerData() {
|
||||
columnCollectionTabViewModel?.tabListLiveData?.observe(viewLifecycleOwner) {
|
||||
binding.subjectTab.clearOnTabSelectedListeners()
|
||||
initColumnCollectionViewPager(it)
|
||||
}
|
||||
columnCollectionTabViewModel?.followListLiveData?.observe(viewLifecycleOwner) {
|
||||
followAdapter.submitList(it)
|
||||
}
|
||||
columnCollectionTabViewModel?.moreListLiveData?.observe(viewLifecycleOwner) {
|
||||
moreAdapter.submitList(it) {
|
||||
showOrHideMore.invoke(it.isNotEmpty())
|
||||
}
|
||||
}
|
||||
columnCollectionTabViewModel?.addFollowLiveData?.observe(viewLifecycleOwner, EventObserver {
|
||||
val newFollowList = followAdapter.currentList.toMutableList()
|
||||
if (newFollowList.size < ColumnCollectionTabViewModel.CUSTOM_MAX_TAB) {
|
||||
val newMoreList = moreAdapter.currentList.toMutableList().apply { remove(it) }
|
||||
followAdapter.submitList(newFollowList.apply { add(it) })
|
||||
moreAdapter.submitList(newMoreList) {
|
||||
showOrHideMore.invoke(newMoreList.isNotEmpty())
|
||||
}
|
||||
} else {
|
||||
toast("最多可以添加15个关注内容哦~")
|
||||
}
|
||||
})
|
||||
columnCollectionTabViewModel?.addMoreLiveData?.observe(viewLifecycleOwner, EventObserver {
|
||||
if (followAdapter.currentList.size == 1) {
|
||||
toast("至少添加1个内容哦~")
|
||||
return@EventObserver
|
||||
}
|
||||
|
||||
mBinding.subjectViewpager.post {
|
||||
mBinding.subjectViewpager.offscreenPageLimit = fragments.size
|
||||
var position = arguments?.getInt(EntranceConsts.KEY_POSITION, 0) ?: 0
|
||||
val columnName = arguments?.getString(EntranceConsts.KEY_COLUMNNAME) ?: ""
|
||||
if (columnName.isNotEmpty()) {
|
||||
position = subjectList.indexOfFirst { it.subjectName == columnName }
|
||||
}
|
||||
if (position < subjectList.size) {
|
||||
mBinding.subjectViewpager.setCurrentItem(position, false)
|
||||
}
|
||||
followAdapter.submitList(followAdapter.currentList.toMutableList().apply { remove(it) })
|
||||
val newMoreList = moreAdapter.currentList.toMutableList().apply { add(it) }
|
||||
moreAdapter.submitList(newMoreList) {
|
||||
showOrHideMore.invoke(newMoreList.isNotEmpty())
|
||||
}
|
||||
val categoryId = requireArguments().getString(EntranceConsts.KEY_COLUMN_COLLECTION_ID, "")
|
||||
val categoryName = requireArguments().getString(EntranceConsts.KEY_COLUMN_COLLECTION_NAME, "")
|
||||
})
|
||||
}
|
||||
|
||||
mBinding.subjectViewpager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
subjectList[position]?.let {
|
||||
MtaHelper.onEvent("游戏专题合集", "详情Tab", it.subjectName)
|
||||
NewLogUtils.logColumnCategoryDetailContentClick(
|
||||
it.subjectName ?: "", it.subjectId ?: "", categoryName, categoryId
|
||||
)
|
||||
private fun initColumnCollectionViewPager(subjectList: List<SubjectData>) {
|
||||
val fragments = arrayListOf<Fragment>()
|
||||
val tagList = arrayListOf<String>()
|
||||
subjectList.filterIndexed { index, subject ->
|
||||
val element = childFragmentManager.findFragmentByTag("${fragmentTag}$index")
|
||||
?: SubjectFragment()
|
||||
val bundle = arguments?.clone() as Bundle?
|
||||
bundle?.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, subject)
|
||||
bundle?.putParcelableArrayList(EntranceConsts.KEY_DATA, null)
|
||||
bundle?.putBoolean(EntranceConsts.KEY_IS_FROM_MAIN_WRAPPER, false)
|
||||
bundle?.putBoolean(EntranceConsts.KEY_IS_FROM_TAB_WRAPPER, false)
|
||||
bundle?.putBoolean(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM, false)
|
||||
if (isCustomEnabled) {
|
||||
bundle?.putInt(EntranceConsts.KEY_COLUMN_COLLECTION_CUSTOM_POSITION, index)
|
||||
}
|
||||
element.arguments = bundle
|
||||
fragments.add(element)
|
||||
|
||||
if (categoryName?.contains("排行榜") == true) {
|
||||
val trackEvent = JSONObject()
|
||||
try {
|
||||
trackEvent.put("list_name", it.subjectName)
|
||||
trackEvent.put("position", position)
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
SensorsBridge.trackEvent("GameListPageSelected", trackEvent)
|
||||
tagList.add(subject.subjectName ?: "")
|
||||
}
|
||||
|
||||
binding.subjectViewpager.post {
|
||||
binding.subjectViewpager.offscreenPageLimit = fragments.size
|
||||
var position = arguments?.getInt(EntranceConsts.KEY_POSITION, 0) ?: 0
|
||||
val columnName = arguments?.getString(EntranceConsts.KEY_COLUMNNAME) ?: ""
|
||||
if (columnName.isNotEmpty()) {
|
||||
position = subjectList.indexOfFirst { it.subjectName == columnName }
|
||||
}
|
||||
if (position < subjectList.size) {
|
||||
binding.subjectViewpager.setCurrentItem(position, false)
|
||||
}
|
||||
}
|
||||
val categoryId = requireArguments().getString(EntranceConsts.KEY_COLUMN_COLLECTION_ID, "")
|
||||
val categoryName = requireArguments().getString(EntranceConsts.KEY_COLUMN_COLLECTION_NAME, "")
|
||||
|
||||
binding.subjectViewpager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
subjectList.getOrNull(position)?.let {
|
||||
MtaHelper.onEvent("游戏专题合集", "详情Tab", it.subjectName)
|
||||
NewLogUtils.logColumnCategoryDetailContentClick(
|
||||
it.subjectName ?: "", it.subjectId ?: "", categoryName, categoryId
|
||||
)
|
||||
|
||||
if (categoryName?.contains("排行榜") == true) {
|
||||
val trackEvent = JSONObject()
|
||||
try {
|
||||
trackEvent.put("list_name", it.subjectName)
|
||||
trackEvent.put("position", position)
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
SensorsBridge.trackEvent("GameListPageSelected", trackEvent)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (mBinding.subjectTabContainer.visibility == View.VISIBLE) {
|
||||
mBinding.subjectTabIndicator.setupWithTabLayout(mBinding.subjectTab)
|
||||
mBinding.subjectTabIndicator.setupWithViewPager(mBinding.subjectViewpager)
|
||||
}
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
|
||||
if (mIsFromMainWrapper) {
|
||||
// 这里的 selectedPosition 指的是应该被高亮显示的 position
|
||||
val selectedPosition = try {
|
||||
(position + positionOffset).roundToInt()
|
||||
} catch (e: IllegalArgumentException) {
|
||||
// roundToInt() 方法有时候会报 Cannot round NaN value. 错误 positionOffset 的值为 NAN
|
||||
// https://sentry.shanqu.cc/organizations/lightgame/issues/301377/?project=22
|
||||
position
|
||||
}
|
||||
val positionOffsetOnRealSelectedPosition = if (positionOffset >= 0.5) {
|
||||
positionOffset - 1
|
||||
} else {
|
||||
positionOffset
|
||||
}
|
||||
updateTabStyle(selectedPosition, positionOffsetOnRealSelectedPosition)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
val adapter = object : FragmentStatePagerAdapter(childFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
||||
override fun getItem(position: Int): Fragment {
|
||||
@ -133,7 +354,7 @@ class SubjectTabFragment : BaseFragment<Any>() {
|
||||
return fragments.size
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence? {
|
||||
override fun getPageTitle(position: Int): CharSequence {
|
||||
return tagList[position]
|
||||
}
|
||||
|
||||
@ -141,76 +362,478 @@ class SubjectTabFragment : BaseFragment<Any>() {
|
||||
// super.destroyItem(container, position, `object`)
|
||||
}
|
||||
}
|
||||
mBinding.subjectViewpager.adapter = adapter
|
||||
mBinding.subjectTab.setupWithViewPager(mBinding.subjectViewpager)
|
||||
// 首页样式的 tabLayout
|
||||
if (arguments?.getBoolean(EntranceConsts.KEY_IS_HOME) == true) {
|
||||
mBinding.subjectTabIndicator.visibility = View.GONE
|
||||
for (i in 0 until mBinding.subjectTab.tabCount) {
|
||||
val tab = mBinding.subjectTab.getTabAt(i) ?: continue
|
||||
binding.subjectViewpager.adapter = adapter
|
||||
binding.subjectTab.setupWithViewPager(binding.subjectViewpager)
|
||||
binding.subjectTabIndicator.setupWithTabLayout(binding.subjectTab)
|
||||
binding.subjectTabIndicator.setupWithViewPager(binding.subjectViewpager)
|
||||
initTabLayout()
|
||||
}
|
||||
|
||||
private fun initTabLayout() {
|
||||
if (tabStyle == TabStyle.COLUMN_COLLECTION_NORMAL) {
|
||||
if (SPUtils.getBoolean(Constants.SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_GUIDE, true)) {
|
||||
binding.subjectTab.addOnTabSelectedListener(object : OnTabSelectedListener {
|
||||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||
showSettingGuideIfNeeded(this)
|
||||
}
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) {}
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) {
|
||||
showSettingGuideIfNeeded(this)
|
||||
}
|
||||
})
|
||||
}
|
||||
binding.subjectTabIndicator.run {
|
||||
setIndicatorWidth(12)
|
||||
updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
bottomMargin = 10F.dip2px()
|
||||
}
|
||||
}
|
||||
for (i in 0 until binding.subjectTab.tabCount) {
|
||||
binding.subjectTab.getTabAt(i)?.view?.run {
|
||||
background = null
|
||||
if (i == 0) {
|
||||
updateLayoutParams<MarginLayoutParams> { leftMargin = 4F.dip2px() }
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tabBindingList.clear()
|
||||
|
||||
val tabCount = binding.subjectTab.tabCount
|
||||
for (i in 0 until tabCount) {
|
||||
val tab = binding.subjectTab.getTabAt(i) ?: continue
|
||||
val tabTitle = if (tab.text != null) tab.text.toString() else ""
|
||||
|
||||
tab.view.background = null
|
||||
tab.customView = provideTabView(tabTitle)
|
||||
if (i == 0) {
|
||||
tab.customView?.background = R.drawable.border_round_theme_14.toDrawable(requireContext())
|
||||
tab.customView?.findViewById<TextView>(R.id.tab_title)
|
||||
?.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(requireContext()))
|
||||
if (tabStyle == TabStyle.COLUMN_COLLECTION_MAIN_WRAPPER) {
|
||||
tab.view.setPadding(0, 0, 0, 0)
|
||||
if (i == 0) {
|
||||
tab.view.updateLayoutParams {
|
||||
this as LinearLayout.LayoutParams
|
||||
setMargins(10F.dip2px(), 0, 0, 0)
|
||||
}
|
||||
} else if (i == tabCount - 1) {
|
||||
tab.view.updateLayoutParams {
|
||||
this as LinearLayout.LayoutParams
|
||||
setMargins(0, 0, 10F.dip2px(), 0)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tab.customView?.background = R.drawable.border_round_eee_14.toDrawable(requireContext())
|
||||
tab.customView?.findViewById<TextView>(R.id.tab_title)
|
||||
?.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext()))
|
||||
}
|
||||
|
||||
when (i) {
|
||||
0 -> tab.view.setPadding(12F.dip2px(), 0, 0, 0)
|
||||
|
||||
mBinding.subjectTab.tabCount - 1 -> tab.view.setPadding(8F.dip2px(), 0, 12F.dip2px(), 0)
|
||||
|
||||
else -> tab.view.setPadding(8F.dip2px(), 0, 0, 0)
|
||||
when (i) {
|
||||
0 -> tab.view.setPadding(16F.dip2px(), 0, 0, 0)
|
||||
binding.subjectTab.tabCount - 1 -> tab.view.setPadding(8F.dip2px(), 0, 16F.dip2px(), 0)
|
||||
else -> tab.view.setPadding(8F.dip2px(), 0, 0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mBinding.subjectTab.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) {}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) {
|
||||
tab?.customView?.background = R.drawable.border_round_eee_14.toDrawable(requireContext())
|
||||
tab?.customView?.findViewById<TextView>(R.id.tab_title)
|
||||
?.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext()))
|
||||
binding.subjectTabIndicator.isVisible = mIsFromMainWrapper
|
||||
if (tabStyle == TabStyle.COLUMN_COLLECTION_MAIN_WRAPPER) {
|
||||
binding.subjectTabIndicator.run {
|
||||
setIndicatorWidth(18)
|
||||
updateIndicatorDrawable(R.drawable.ic_commodity_selected.toDrawable(requireContext()))
|
||||
updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
height = 8F.dip2px()
|
||||
bottomMargin = 8F.dip2px()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||
tab?.customView?.background = R.drawable.border_round_theme_14.toDrawable(requireContext())
|
||||
tab?.customView?.findViewById<TextView>(R.id.tab_title)
|
||||
?.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(requireContext()))
|
||||
binding.settingGuideIv.updateLayoutParams<ConstraintLayout.LayoutParams> { topMargin = 40F.dip2px() }
|
||||
binding.subjectTabContainer.updateLayoutParams<ConstraintLayout.LayoutParams> { height = 56F.dip2px() }
|
||||
binding.subjectTab.updateLayoutParams<ConstraintLayout.LayoutParams> {
|
||||
setMargins(0, 8F.dip2px(), 8F.dip2px(), 8F.dip2px())
|
||||
}
|
||||
})
|
||||
} else {
|
||||
binding.subjectTab.addOnTabSelectedListener(object : OnTabSelectedListener {
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) {}
|
||||
|
||||
override fun onTabUnselected(tab: TabLayout.Tab?) {
|
||||
tab?.customView?.findViewById<CheckedTextView>(R.id.tab_title)?.isChecked = false
|
||||
}
|
||||
|
||||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||
tab?.customView?.findViewById<CheckedTextView>(R.id.tab_title)?.isChecked = true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun provideTabView(title: String): View {
|
||||
val view = LayoutInflater.from(requireContext()).inflate(R.layout.tab_item_ranking_home, null)
|
||||
val tabTitle = view.findViewById<View>(R.id.tab_title)
|
||||
if (tabTitle is CheckedTextView) {
|
||||
tabTitle.text = title
|
||||
if (tabStyle == TabStyle.COLUMN_COLLECTION_MAIN_WRAPPER) {
|
||||
val tabBinding = TabItemMainBinding.inflate(LayoutInflater.from(requireContext()))
|
||||
tabBinding.titleTv.run {
|
||||
visibility = View.VISIBLE
|
||||
text = title
|
||||
textSize = 16F
|
||||
setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
|
||||
}
|
||||
tabBinding.invisibleTitleTv.run {
|
||||
visibility = View.INVISIBLE
|
||||
text = title
|
||||
textSize = 16F
|
||||
}
|
||||
tabBindingList.add(tabBinding)
|
||||
return tabBinding.root
|
||||
} else {
|
||||
val view = LayoutInflater.from(requireContext()).inflate(R.layout.tab_item_subject_tab, null)
|
||||
val tabTitle = view.findViewById<View>(R.id.tab_title)
|
||||
if (tabTitle is CheckedTextView) {
|
||||
tabTitle.text = title
|
||||
}
|
||||
return view
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
for (i in 0 until mBinding.subjectTab.tabCount) {
|
||||
val tab = mBinding.subjectTab.getTabAt(i) ?: continue
|
||||
tab.customView?.background =
|
||||
if (tab.isSelected) R.drawable.border_round_theme_14.toDrawable(requireContext()) else R.drawable.border_round_eee_14.toDrawable(
|
||||
requireContext()
|
||||
)
|
||||
tab.customView?.findViewById<TextView>(R.id.tab_title)
|
||||
?.setTextColor(
|
||||
if (tab.isSelected) com.gh.gamecenter.common.R.color.text_theme.toColor(requireContext()) else com.gh.gamecenter.common.R.color.text_primary.toColor(
|
||||
requireContext()
|
||||
)
|
||||
)
|
||||
when (tabStyle) {
|
||||
TabStyle.COLUMN_COLLECTION_NORMAL -> {
|
||||
binding.subjectTabIndicator.updateIndicatorColor(com.gh.gamecenter.common.R.color.primary_theme)
|
||||
binding.subjectTab.setTabTextColors(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()), com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext()))
|
||||
}
|
||||
TabStyle.COLUMN_COLLECTION_MAIN_WRAPPER -> updateTabStyle(binding.subjectViewpager.currentItem, 0F)
|
||||
TabStyle.SUBJECT_NORMAL -> {
|
||||
for (i in 0 until binding.subjectTab.tabCount) {
|
||||
val tab = binding.subjectTab.getTabAt(i) ?: continue
|
||||
tab.customView?.findViewById<CheckedTextView>(R.id.tab_title)?.run {
|
||||
background = R.drawable.subject_tab_background_selector.toDrawable(context)
|
||||
setTextColor(ContextCompat.getColorStateList(context, com.gh.gamecenter.common.R.color.text_tabbar_style))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settingBinding?.run {
|
||||
saveTv.background = com.gh.gamecenter.common.R.drawable.button_blue_oval.toDrawable(requireContext())
|
||||
cancelTv.background = com.gh.gamecenter.feature.R.drawable.button_round_gray_light.toDrawable(requireContext())
|
||||
cancelTv.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
|
||||
followAdapter.notifyItemRangeChanged(0, followAdapter.itemCount)
|
||||
moreAdapter.notifyItemRangeChanged(0, moreAdapter.itemCount)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTabStyle(selectedPosition: Int, positionOffset: Float) {
|
||||
if (tabBindingList.isEmpty()) return
|
||||
|
||||
val currentTabDefaultColor = com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext())
|
||||
val currentTabSelectedColor = com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext())
|
||||
|
||||
val prePosition = selectedPosition - 1
|
||||
val nextPosition = selectedPosition + 1
|
||||
|
||||
// positionOffset 小于零,表示 indicator 当前位置处于选中的 tab 的左边
|
||||
val indicatorOnLeft = positionOffset < 0F
|
||||
|
||||
val selectedTabBinding = tabBindingList.safelyGetInRelease(selectedPosition) ?: return
|
||||
|
||||
// 前一个 tab、当前选中的 tab、后一个 tab 的显示比例
|
||||
val preScaleRatio = 1 + abs(positionOffset) / 4
|
||||
val selectedScaleRatio = 1 + (1 - abs(positionOffset)) / 4
|
||||
val nextScaleRatio = 1 + positionOffset / 4
|
||||
|
||||
// 处理前一个 tab
|
||||
if (prePosition != -1) {
|
||||
tabBindingList[prePosition].run {
|
||||
if (indicatorOnLeft) {
|
||||
titleTv.scaleX = preScaleRatio
|
||||
titleTv.scaleY = preScaleRatio
|
||||
titleTv.setTextColor(
|
||||
ColorUtils.blendARGB(
|
||||
currentTabDefaultColor,
|
||||
currentTabSelectedColor,
|
||||
abs(positionOffset)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
titleTv.setTextColor(currentTabDefaultColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新当前选中的 tab
|
||||
selectedTabBinding.run {
|
||||
titleTv.scaleX = selectedScaleRatio
|
||||
titleTv.scaleY = selectedScaleRatio
|
||||
titleTv.setTextColor(
|
||||
ColorUtils.blendARGB(
|
||||
currentTabDefaultColor,
|
||||
currentTabSelectedColor,
|
||||
1 - abs(positionOffset)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 处理后一个 tab
|
||||
if (nextPosition < tabBindingList.size) {
|
||||
tabBindingList[nextPosition].run {
|
||||
if (!indicatorOnLeft) {
|
||||
titleTv.scaleX = nextScaleRatio
|
||||
titleTv.scaleY = nextScaleRatio
|
||||
titleTv.setTextColor(
|
||||
ColorUtils.blendARGB(
|
||||
currentTabDefaultColor,
|
||||
currentTabSelectedColor,
|
||||
positionOffset
|
||||
)
|
||||
)
|
||||
} else {
|
||||
titleTv.setTextColor(currentTabDefaultColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 多 tab 切换的时候可能会出现某些 tab 的文字没有回归到原始大小的问题的问题 (positionOffset 不保证连续)
|
||||
for ((index, tabBinding) in tabBindingList.withIndex()) {
|
||||
if (index != prePosition && index != selectedPosition && index != nextPosition) {
|
||||
if (tabBinding.titleTv.scaleX != 1F) {
|
||||
tabBinding.titleTv.scaleX = 1F
|
||||
tabBinding.titleTv.scaleY = 1F
|
||||
}
|
||||
tabBinding.titleTv.setTextColor(currentTabDefaultColor)
|
||||
if (tabBinding.titleIv.scaleX != 1F) {
|
||||
tabBinding.titleIv.scaleX = 1F
|
||||
tabBinding.titleIv.scaleY = 1F
|
||||
}
|
||||
}
|
||||
|
||||
if (index == selectedPosition) {
|
||||
if (positionOffset == 0F) {
|
||||
tabBinding.titleTv.setTextColor(currentTabSelectedColor)
|
||||
}
|
||||
|
||||
tabBinding.titleTv.setTypeface(tabBinding.titleTv.typeface, Typeface.BOLD)
|
||||
} else {
|
||||
if (positionOffset == 0F) {
|
||||
tabBinding.titleTv.setTextColor(currentTabDefaultColor)
|
||||
}
|
||||
|
||||
tabBinding.titleTv.setTypeface(null, Typeface.NORMAL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSettingGuideIfNeeded(listener: OnTabSelectedListener) {
|
||||
if (SPUtils.getBoolean(Constants.SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_GUIDE, true)) {
|
||||
binding.skipView.setOnClickListener {
|
||||
dismissSettingGuide()
|
||||
SensorsBridge.trackColumnCollectionClick(
|
||||
location = "合集详情",
|
||||
columnCollectionName = collectionName,
|
||||
columnCollectionId = collectionId,
|
||||
text = "新手引导-取消",
|
||||
columnCollectionPattern = CustomPageItem.collectionTypeToComponentName[collectionStyle]
|
||||
?: collectionStyle
|
||||
)
|
||||
}
|
||||
binding.settingClickView.setOnClickListener {
|
||||
dismissSettingGuide()
|
||||
showSettingView()
|
||||
SensorsBridge.trackColumnCollectionClick(
|
||||
location = "合集详情",
|
||||
columnCollectionName = collectionName,
|
||||
columnCollectionId = collectionId,
|
||||
text = "新手引导-立即设置",
|
||||
columnCollectionPattern = CustomPageItem.collectionTypeToComponentName[collectionStyle]
|
||||
?: collectionStyle
|
||||
)
|
||||
}
|
||||
binding.settingGuideContainer.setOnClickListener {
|
||||
dismissSettingGuide()
|
||||
SensorsBridge.trackColumnCollectionClick(
|
||||
location = "合集详情",
|
||||
columnCollectionName = collectionName,
|
||||
columnCollectionId = collectionId,
|
||||
text = "新手引导-关闭引导",
|
||||
columnCollectionPattern = CustomPageItem.collectionTypeToComponentName[collectionStyle]
|
||||
?: collectionStyle
|
||||
)
|
||||
}
|
||||
mBaseHandler.post {
|
||||
binding.settingGuideContainer.isVisible = true
|
||||
}
|
||||
SPUtils.setBoolean(Constants.SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_GUIDE, false)
|
||||
binding.subjectTab.removeOnTabSelectedListener(listener)
|
||||
}
|
||||
}
|
||||
|
||||
private fun dismissSettingGuide() {
|
||||
binding.settingGuideIv.animate()?.alpha(0F)?.setDuration(200L)?.doOnEnd {
|
||||
binding.settingGuideContainer.isVisible = false
|
||||
}?.start()
|
||||
}
|
||||
|
||||
private fun showSettingView() {
|
||||
if (isSettingAnimating) return
|
||||
|
||||
binding.background.setOnClickListener {
|
||||
showDismissSettingDialogIfNeeded()
|
||||
}
|
||||
|
||||
settingBinding = LayoutColumnCollectionSettingBinding.inflate(layoutInflater, null, false).apply {
|
||||
followRv.isNestedScrollingEnabled = false
|
||||
moreRv.isNestedScrollingEnabled = false
|
||||
columnCollectionTabViewModel?.followListLiveData?.value?.let {
|
||||
followAdapter.submitList(it) {
|
||||
followRv.adapter = followAdapter
|
||||
}
|
||||
} ?: run {
|
||||
followRv.adapter = followAdapter
|
||||
}
|
||||
columnCollectionTabViewModel?.moreListLiveData?.value?.let {
|
||||
moreAdapter.submitList(it) {
|
||||
moreRv.adapter = moreAdapter
|
||||
}
|
||||
} ?: run {
|
||||
moreRv.adapter = moreAdapter
|
||||
}
|
||||
followRv.layoutManager = FlexboxLayoutManager(requireContext()).apply { justifyContent = JustifyContent.FLEX_START }
|
||||
moreRv.layoutManager = FlexboxLayoutManager(requireContext()).apply { justifyContent = JustifyContent.FLEX_START }
|
||||
itemTouchHelper.attachToRecyclerView(followRv)
|
||||
moreContainer.isVisible = !columnCollectionTabViewModel?.moreListLiveData?.value.isNullOrEmpty()
|
||||
saveTv.setOnClickListener {
|
||||
dismissSettingView {
|
||||
saveCustomTab()
|
||||
}
|
||||
}
|
||||
cancelTv.setOnClickListener {
|
||||
dismissSettingView()
|
||||
}
|
||||
root.setOnClickListener {}
|
||||
}
|
||||
|
||||
binding.settingContainer.addView(
|
||||
settingBinding!!.root,
|
||||
FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)
|
||||
)
|
||||
binding.settingContainer.post {
|
||||
val height = binding.settingContainer.height
|
||||
binding.background.visibility = View.VISIBLE
|
||||
AnimatorSet().apply {
|
||||
val translateAnimator = ValueAnimator.ofFloat(0F, height.toFloat()).apply {
|
||||
addUpdateListener { va -> binding.settingContainer.translationY = (va.animatedValue as Float) }
|
||||
}
|
||||
val alphaAnimator = ValueAnimator.ofFloat(0F, 0.2F).apply {
|
||||
addUpdateListener { va -> binding.background.alpha = (va.animatedValue as Float) }
|
||||
}
|
||||
playTogether(translateAnimator, alphaAnimator)
|
||||
duration = ANIMATOR_DURATION
|
||||
doOnStart {
|
||||
isSettingAnimating = true
|
||||
}
|
||||
doOnEnd {
|
||||
ConstraintSet().apply {
|
||||
clone(binding.root)
|
||||
clear(binding.settingContainer.id, ConstraintSet.BOTTOM)
|
||||
connect(binding.settingContainer.id, ConstraintSet.TOP, binding.subjectTabContainer.id, ConstraintSet.TOP)
|
||||
}.applyTo(binding.root)
|
||||
binding.settingContainer.translationY = 0F
|
||||
isSettingAnimating = false
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveCustomTab() {
|
||||
if (followAdapter.currentList.isEmpty()) {
|
||||
toast("至少添加1个内容哦~")
|
||||
return
|
||||
}
|
||||
|
||||
SensorsBridge.trackEvent("ColumnCollectionCustomSetting",
|
||||
"column_collection_name", collectionName,
|
||||
"column_collection_id", collectionId,
|
||||
"original_text", columnCollectionTabViewModel?.followListLiveData?.value?.joinToString("、") { it.subjectName ?: "" } ?: "",
|
||||
"save_text", followAdapter.currentList.joinToString("、") { it.subjectName ?: "" },
|
||||
)
|
||||
columnCollectionTabViewModel?.saveCustomTab(followAdapter.currentList)
|
||||
}
|
||||
|
||||
private fun showDismissSettingDialogIfNeeded() {
|
||||
if (followAdapter.currentList == columnCollectionTabViewModel?.followListLiveData?.value) {
|
||||
dismissSettingView()
|
||||
} else {
|
||||
DialogHelper.showDialog(
|
||||
requireContext(),
|
||||
title = "提示",
|
||||
content = "是否保存当前自定义设置",
|
||||
confirmText = "保存设置",
|
||||
cancelText = "退出",
|
||||
confirmClickCallback = {
|
||||
dismissSettingView {
|
||||
saveCustomTab()
|
||||
}
|
||||
},
|
||||
cancelClickCallback = {
|
||||
dismissSettingView()
|
||||
},
|
||||
extraConfig = Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun dismissSettingView(doOnEnd: (() -> Unit)? = null) {
|
||||
if (settingBinding == null || isSettingAnimating) return
|
||||
|
||||
val height = binding.settingContainer.height
|
||||
AnimatorSet().apply {
|
||||
val translateAnimator = ValueAnimator.ofFloat(0F, -height.toFloat()).apply {
|
||||
addUpdateListener { va -> binding.settingContainer.translationY = (va.animatedValue as Float) }
|
||||
}
|
||||
val alphaAnimator = ValueAnimator.ofFloat(0.2F, 0F).apply {
|
||||
addUpdateListener { va -> binding.background.alpha = (va.animatedValue as Float) }
|
||||
}
|
||||
playTogether(translateAnimator, alphaAnimator)
|
||||
duration = ANIMATOR_DURATION
|
||||
doOnStart {
|
||||
isSettingAnimating = true
|
||||
}
|
||||
doOnEnd {
|
||||
binding.background.visibility = View.GONE
|
||||
binding.settingContainer.removeAllViews()
|
||||
binding.settingContainer.translationY = 0F
|
||||
ConstraintSet().apply {
|
||||
clone(binding.root)
|
||||
clear(binding.settingContainer.id, ConstraintSet.TOP)
|
||||
connect(binding.settingContainer.id, ConstraintSet.BOTTOM, binding.subjectTabContainer.id, ConstraintSet.TOP)
|
||||
}.applyTo(binding.root)
|
||||
settingBinding = null
|
||||
isSettingAnimating = false
|
||||
doOnEnd?.invoke()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
if (binding.settingGuideContainer.isVisible) {
|
||||
binding.settingGuideContainer.performClick()
|
||||
return true
|
||||
}
|
||||
if (settingBinding != null) {
|
||||
showDismissSettingDialogIfNeeded()
|
||||
return true
|
||||
}
|
||||
return super.onBackPressed()
|
||||
}
|
||||
|
||||
enum class TabStyle {
|
||||
/**
|
||||
* 专题详情样式
|
||||
*/
|
||||
SUBJECT_NORMAL,
|
||||
|
||||
/**
|
||||
* 专题合集-关联首页底部Tab样式
|
||||
*/
|
||||
COLUMN_COLLECTION_MAIN_WRAPPER,
|
||||
|
||||
/**
|
||||
* 专题合集-常规样式
|
||||
*/
|
||||
COLUMN_COLLECTION_NORMAL,
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ANIMATOR_DURATION = 200L
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,19 +4,24 @@ import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.gh.common.view.ConfigFilterView
|
||||
import com.gh.common.view.ConfigFilterView.SortType
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarController
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.view.GridSpacingItemDecoration
|
||||
import com.gh.gamecenter.core.utils.StringUtils
|
||||
import com.gh.gamecenter.core.utils.UrlFilterUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.FragmentSubjectTiledBinding
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarController
|
||||
import com.gh.gamecenter.subject.SubjectListFragment
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import kotlin.math.abs
|
||||
@ -32,6 +37,28 @@ class SubjectTileFragment : BaseFragment<Any>() {
|
||||
|
||||
private var mIsTouchScreen: Boolean = false
|
||||
|
||||
private var mMaxSize = ""
|
||||
private var mMinSize = ""
|
||||
private var mSelectedFilterSize = SubjectSettingEntity.Size(text = "全部大小")
|
||||
|
||||
private val finalFilter: String
|
||||
get() {
|
||||
var filter = if (mSelectedTypeName == "全部") {
|
||||
// 全部的时候添加头图
|
||||
UrlFilterUtils.getFilterQuery("tags", mSelectedTypeName, "type", mSelectedTypeName)
|
||||
} else {
|
||||
UrlFilterUtils.getFilterQuery("tags", mSelectedTypeName)
|
||||
}
|
||||
if (mMinSize.isNotEmpty() && mMinSize != "-1") {
|
||||
filter += ",${UrlFilterUtils.getFilterQuery("min_size", mMinSize)}"
|
||||
}
|
||||
if (mMaxSize.isNotEmpty() && mMaxSize != "-1") {
|
||||
filter += ",${UrlFilterUtils.getFilterQuery("max_size", mMaxSize)}"
|
||||
}
|
||||
|
||||
return filter
|
||||
}
|
||||
|
||||
override fun getLayoutId() = 0
|
||||
override fun getInflatedLayout() = mBinding.root
|
||||
|
||||
@ -40,45 +67,75 @@ class SubjectTileFragment : BaseFragment<Any>() {
|
||||
// 初始化数据
|
||||
mSubjectData = arguments?.getParcelable(EntranceConsts.KEY_SUBJECT_DATA) ?: return
|
||||
mSettingsEntity =
|
||||
arguments?.getParcelable(SubjectSettingEntity::class.java.simpleName) ?: return
|
||||
arguments?.getParcelable(EntranceConsts.KEY_SUBJECT_SETTING_DATA) ?: return
|
||||
|
||||
mSelectedTypeName = "全部"
|
||||
mSubjectData.filter = UrlFilterUtils.getFilterQuery("type", "全部")
|
||||
mSubjectData.sort = UrlFilterUtils.getFilterQuery("position", "1")
|
||||
|
||||
mBinding.subjectFilterContainer.visibility =
|
||||
if (mSettingsEntity.filter == "on") View.VISIBLE else View.GONE
|
||||
|
||||
// 初始化顶部类型列表
|
||||
val layoutManager = object : GridLayoutManager(context, 4) {
|
||||
override fun canScrollVertically(): Boolean {
|
||||
return false
|
||||
mBinding.subjectTypeList.goneIf(mSettingsEntity.typeEntity.content.size <= 1) {
|
||||
// 初始化顶部类型列表
|
||||
val layoutManager = object : GridLayoutManager(context, 4) {
|
||||
override fun canScrollVertically(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
mBinding.subjectTypeList.isNestedScrollingEnabled = false
|
||||
mBinding.subjectTypeList.layoutManager = layoutManager
|
||||
mBinding.subjectTabbarHottest.setOnClickListener(this)
|
||||
mBinding.subjectTabbarNewest.setOnClickListener(this)
|
||||
|
||||
if (mSettingsEntity.typeEntity.content.size > 1) {
|
||||
mBinding.subjectTypeList.isNestedScrollingEnabled = false
|
||||
mBinding.subjectTypeList.layoutManager = layoutManager
|
||||
mBinding.subjectTypeList.addItemDecoration(GridSpacingItemDecoration(4, 8F.dip2px(), false))
|
||||
val adapter = SubjectTypeListAdapter(requireContext(), mItemClickListener = {
|
||||
mSelectedTypeName = it
|
||||
if (it == "全部") {
|
||||
// 全部的时候添加头图
|
||||
mSubjectData.filter = UrlFilterUtils.getFilterQuery("tags", it, "type", it)
|
||||
} else {
|
||||
mSubjectData.filter = UrlFilterUtils.getFilterQuery("tags", it)
|
||||
}
|
||||
mSubjectData.filter = finalFilter
|
||||
mSubjectData.tag = it
|
||||
loadData()
|
||||
}, mGameType = mSettingsEntity.typeEntity.content)
|
||||
mBinding.subjectTypeList.adapter = adapter
|
||||
}
|
||||
|
||||
mBinding.filterView.goneIf(!mSettingsEntity.isFilterEnabled) {
|
||||
mBinding.filterView.run {
|
||||
initSubjectFilterView(mSettingsEntity)
|
||||
setOnConfigSetupListener(object :
|
||||
ConfigFilterView.OnConfigFilterSetupListener {
|
||||
override fun onShowSortSize() {}
|
||||
|
||||
override fun onSetupSortSize(sortSize: SubjectSettingEntity.Size) {
|
||||
mMinSize = sortSize.min.toString()
|
||||
mMaxSize = sortSize.max.toString()
|
||||
mSelectedFilterSize = sortSize
|
||||
mSubjectData.filter = finalFilter
|
||||
loadData()
|
||||
}
|
||||
|
||||
override fun onSetupSortType(sortType: SortType) {
|
||||
val clickTv = when (sortType) {
|
||||
SortType.RATING -> ratingTv
|
||||
SortType.NEWEST -> newestTv
|
||||
SortType.UPDATE -> updateTv
|
||||
else -> recommendedTv
|
||||
}
|
||||
|
||||
val sort = when (clickTv.text) {
|
||||
"更新" -> UrlFilterUtils.getFilterQuery("update_time", "-1")
|
||||
"最新" -> UrlFilterUtils.getFilterQuery("publish", "-1")
|
||||
"评分" -> UrlFilterUtils.getFilterQuery("star", "-1")
|
||||
else -> UrlFilterUtils.getFilterQuery("position", "1")
|
||||
}
|
||||
|
||||
if (mSubjectData.sort != sort) {
|
||||
mSubjectData.sort = sort
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 是否为专题合集详情子页面
|
||||
val isColumnCollection = arguments?.getBoolean(EntranceConsts.KEY_IS_COLUMN_COLLECTION) ?: false
|
||||
if (!isColumnCollection) {
|
||||
// Appbar 交互
|
||||
mBinding.subjectAppbar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset ->
|
||||
mBinding.subjectAppbar.addOnOffsetChangedListener { appBarLayout, verticalOffset ->
|
||||
if (!TextUtils.isEmpty(mSubjectData.subjectName) && activity is ToolbarController) {
|
||||
val totalScrollRange = appBarLayout.totalScrollRange
|
||||
if (abs(verticalOffset) < totalScrollRange / 2) {
|
||||
@ -94,7 +151,7 @@ class SubjectTileFragment : BaseFragment<Any>() {
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
loadData()
|
||||
@ -116,23 +173,6 @@ class SubjectTileFragment : BaseFragment<Any>() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.subject_tabbar_hottest -> {
|
||||
mBinding.subjectTabbarHottest.isChecked = true
|
||||
mBinding.subjectTabbarNewest.isChecked = false
|
||||
mSubjectData.sort = UrlFilterUtils.getFilterQuery("position", "1")
|
||||
loadData()
|
||||
}
|
||||
R.id.subject_tabbar_newest -> {
|
||||
mBinding.subjectTabbarHottest.isChecked = false
|
||||
mBinding.subjectTabbarNewest.isChecked = true
|
||||
mSubjectData.sort = UrlFilterUtils.getFilterQuery("publish", "-1")
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun loadData() {
|
||||
val transaction = childFragmentManager.beginTransaction()
|
||||
hideFragments(transaction)
|
||||
@ -151,8 +191,10 @@ class SubjectTileFragment : BaseFragment<Any>() {
|
||||
transaction.show(fragmentByTag)
|
||||
} else {
|
||||
fragmentByTag = SubjectListFragment()
|
||||
val bundle = arguments ?: Bundle()
|
||||
val bundle = arguments?.clone() as? Bundle ?: Bundle()
|
||||
bundle.remove(EntranceConsts.KEY_SUBJECT_SETTING_DATA)
|
||||
bundle.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, mSubjectData)
|
||||
bundle.putString(EntranceConsts.KEY_SUBJECT_SORT_SIZE, mSelectedFilterSize.text)
|
||||
fragmentByTag.arguments = bundle
|
||||
transaction.add(R.id.subject_content_rl, fragmentByTag, fmTag)
|
||||
}
|
||||
@ -161,6 +203,13 @@ class SubjectTileFragment : BaseFragment<Any>() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged() {
|
||||
super.onDarkModeChanged()
|
||||
if (mBinding.filterView.isVisible) {
|
||||
mBinding.filterView.updateAllTextView()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val OPEN_APPBAR = "openAppBar"
|
||||
}
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
package com.gh.gamecenter.subject.tile
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.CheckedTextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.toDrawable
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class SubjectTypeListAdapter(
|
||||
@ -20,28 +22,26 @@ class SubjectTypeListAdapter(
|
||||
private var mCurType = "全部"
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SubjectTypeViewHolder {
|
||||
return SubjectTypeViewHolder(mLayoutInflater.inflate(R.layout.item_filter_size, parent, false))
|
||||
return SubjectTypeViewHolder(mLayoutInflater.inflate(R.layout.subject_rows_label_item, parent, false))
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: SubjectTypeViewHolder, position: Int) {
|
||||
holder.itemView.layoutParams = holder.itemView.layoutParams.apply {
|
||||
holder.type.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
}
|
||||
holder.type.background = R.drawable.subject_label_background_style.toDrawable(mContext)
|
||||
holder.type.setTextColor(ContextCompat.getColorStateList(mContext, R.color.subject_label_text_style))
|
||||
holder.type.text = mGameType[position]
|
||||
|
||||
if (!TextUtils.isEmpty(mCurType) && mCurType == mGameType[position]) {
|
||||
holder.type.background = ContextCompat.getDrawable(mContext, R.drawable.bg_tag_text)
|
||||
holder.type.setTextColor(Color.WHITE)
|
||||
} else {
|
||||
holder.type.background = null
|
||||
holder.type.setTextColor(ContextCompat.getColor(mContext, com.gh.gamecenter.common.R.color.text_757575))
|
||||
}
|
||||
val isChecked = !TextUtils.isEmpty(mCurType) && mCurType == mGameType[position]
|
||||
holder.type.isChecked = isChecked
|
||||
holder.type.setTypeface(Typeface.DEFAULT, if (isChecked) Typeface.BOLD else Typeface.NORMAL)
|
||||
|
||||
holder.type.setOnClickListener {
|
||||
if (holder.adapterPosition == -1) return@setOnClickListener
|
||||
if (holder.bindingAdapterPosition == -1) return@setOnClickListener
|
||||
|
||||
mCurType = mGameType[holder.adapterPosition]
|
||||
mItemClickListener.invoke(mGameType[holder.adapterPosition])
|
||||
mCurType = mGameType[holder.bindingAdapterPosition]
|
||||
mItemClickListener.invoke(mGameType[holder.bindingAdapterPosition])
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
@ -51,6 +51,6 @@ class SubjectTypeListAdapter(
|
||||
}
|
||||
|
||||
inner class SubjectTypeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
val type by lazy { itemView.findViewById<TextView>(R.id.size_tv) }
|
||||
val type: CheckedTextView by lazy { itemView.findViewById(R.id.label) }
|
||||
}
|
||||
}
|
||||
5
app/src/main/res/color/subject_label_text_style.xml
Normal file
5
app/src/main/res/color/subject_label_text_style.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/text_tertiary" android:state_checked="false" />
|
||||
<item android:color="@color/text_theme" android:state_checked="true" />
|
||||
</selector>
|
||||
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/text_757575" android:state_checked="false" />
|
||||
<item android:color="@color/white" android:state_checked="true" />
|
||||
</selector>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
@ -1,9 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@color/title" />
|
||||
|
||||
<corners android:radius="4dp" />
|
||||
|
||||
<corners android:radius="6dp" />
|
||||
<solid android:color="@color/primary_theme_10" />
|
||||
</shape>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/bg_shape_primary_theme_alpha_10_radius_6" android:state_checked="true" />
|
||||
<item android:drawable="@drawable/bg_shape_primary_theme_alpha_10_radius_6" android:state_focused="true" />
|
||||
<item android:drawable="@drawable/bg_shape_f8_radius_6" />
|
||||
</selector>
|
||||
@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="8dp"
|
||||
android:height="6dp"
|
||||
android:viewportWidth="8"
|
||||
android:viewportHeight="6">
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M7,4.5L4,1.5L1,4.5"
|
||||
android:strokeLineJoin="round"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="@color/text_primary"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
14
app/src/main/res/drawable/ic_auxiliary_plus_secondary_8.xml
Normal file
14
app/src/main/res/drawable/ic_auxiliary_plus_secondary_8.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="8dp"
|
||||
android:height="8dp"
|
||||
android:viewportWidth="8"
|
||||
android:viewportHeight="8">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,0h8v8h-8z"/>
|
||||
<path
|
||||
android:pathData="M4,0C4.2761,0 4.5,0.2239 4.5,0.5V3.5H7.5C7.7761,3.5 8,3.7239 8,4C8,4.2761 7.7761,4.5 7.5,4.5H4.5V7.5C4.5,7.7761 4.2761,8 4,8C3.7239,8 3.5,7.7761 3.5,7.5V4.5H0.5C0.2239,4.5 0,4.2761 0,4C0,3.7239 0.2239,3.5 0.5,3.5H3.5V0.5C3.5,0.2239 3.7239,0 4,0Z"
|
||||
android:fillColor="@color/text_secondary"
|
||||
android:fillType="evenOdd"/>
|
||||
</group>
|
||||
</vector>
|
||||
14
app/src/main/res/drawable/ic_basic_x_8_secondary.xml
Normal file
14
app/src/main/res/drawable/ic_basic_x_8_secondary.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="8dp"
|
||||
android:height="8dp"
|
||||
android:viewportWidth="8"
|
||||
android:viewportHeight="8">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,0h8v8h-8z"/>
|
||||
<path
|
||||
android:pathData="M0.6464,0.6464C0.8417,0.4512 1.1583,0.4512 1.3535,0.6464L4,3.2929L6.6465,0.6464C6.8417,0.4512 7.1583,0.4512 7.3535,0.6464C7.5488,0.8417 7.5488,1.1583 7.3535,1.3535L4.7071,4L7.3535,6.6465C7.5488,6.8417 7.5488,7.1583 7.3535,7.3535C7.1583,7.5488 6.8417,7.5488 6.6465,7.3535L4,4.7071L1.3535,7.3535C1.1583,7.5488 0.8417,7.5488 0.6464,7.3535C0.4512,7.1583 0.4512,6.8417 0.6464,6.6465L3.2929,4L0.6464,1.3535C0.4512,1.1583 0.4512,0.8417 0.6464,0.6464Z"
|
||||
android:fillColor="@color/text_secondary"
|
||||
android:fillType="evenOdd"/>
|
||||
</group>
|
||||
</vector>
|
||||
5
app/src/main/res/drawable/ic_filter_dot.xml
Normal file
5
app/src/main/res/drawable/ic_filter_dot.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="@color/ui_divider" />
|
||||
</shape>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/bg_shape_primary_theme_alpha_10_radius_6" android:state_checked="true" />
|
||||
<item android:drawable="@drawable/bg_shape_primary_theme_alpha_10_radius_6" android:state_focused="true" />
|
||||
</selector>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/button_round_theme_alpha_10" android:state_pressed="true" />
|
||||
<item android:drawable="@drawable/button_round_theme_alpha_10" android:state_focused="true" />
|
||||
<item android:drawable="@drawable/button_round_theme_alpha_10" android:state_selected="true" />
|
||||
<item android:drawable="@drawable/button_round_theme_alpha_10" android:state_checked="true" />
|
||||
<item android:drawable="@drawable/bg_shape_ui_container_1_radius_999" />
|
||||
</selector>
|
||||
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:drawable="@drawable/subject_tab_down" android:state_selected="true" />
|
||||
<item android:drawable="@color/white" android:state_focused="false" />
|
||||
|
||||
</selector>
|
||||
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:drawable="@drawable/bg_tag_text" android:state_checked="true" />
|
||||
<item android:drawable="@drawable/bg_tag_text" android:state_focused="true" />
|
||||
|
||||
</selector>
|
||||
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
@ -7,9 +8,18 @@
|
||||
android:id="@+id/contentContainer"
|
||||
layout="@layout/fragment_list_base_skeleton" />
|
||||
|
||||
<com.gh.gamecenter.common.view.StatusBarView
|
||||
android:id="@+id/statusBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/ui_surface"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/placeholder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/statusBar" />
|
||||
|
||||
</RelativeLayout>
|
||||
45
app/src/main/res/layout/fragment_subject_list.xml
Normal file
45
app/src/main/res/layout/fragment_subject_list.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/ui_surface">
|
||||
|
||||
<com.gh.common.view.ConfigFilterView
|
||||
android:id="@+id/filterView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/list_skeleton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/filterView"/>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/list_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/filterView">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list_rv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<include
|
||||
layout="@layout/reuse_loading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true" />
|
||||
|
||||
<include layout="@layout/reuse_no_connection" />
|
||||
|
||||
<include layout="@layout/reuse_none_data" />
|
||||
|
||||
<include layout="@layout/reuse_data_exception" />
|
||||
|
||||
</RelativeLayout>
|
||||
@ -1,48 +1,146 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/subject_tab_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/tab_layout_height"
|
||||
android:background="@color/ui_surface"
|
||||
android:visibility="gone">
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/subject_viewpager"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/subject_tab_container" />
|
||||
|
||||
<!-- <View-->
|
||||
<!-- android:id="@+id/subject_tab_line"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="1dp"-->
|
||||
<!-- android:layout_alignParentBottom="true"-->
|
||||
<!-- android:background="@color/background"-->
|
||||
<!-- android:visibility="gone" />-->
|
||||
<View
|
||||
android:id="@+id/background"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:alpha="0"
|
||||
android:background="@color/black"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/subject_tab_container"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/subject_tab_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@color/ui_surface"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/subject_viewpager"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.gh.gamecenter.common.view.TabIndicatorView
|
||||
android:id="@+id/subject_tab_indicator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/default_tab_indicator_height"
|
||||
android:layout_alignParentBottom="true" />
|
||||
android:layout_marginEnd="8dp"
|
||||
app:disableIndicatorScaling="true"
|
||||
app:indicatorColor="@color/primary_theme"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/optionIv"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_goneMarginEnd="0dp" />
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
<com.gh.gamecenter.common.view.NoDefaultMinWidthTabLayout
|
||||
android:id="@+id/subject_tab"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:tabIndicatorColor="@color/primary_theme"
|
||||
app:tabMode="scrollable"
|
||||
app:tabIndicatorHeight="0dp"
|
||||
app:tabRippleColor="@color/transparent"
|
||||
app:tabSelectedTextColor="@color/primary_theme"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:overScrollMode="never"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/optionIv"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginEnd="0dp"
|
||||
app:tabIndicator="@null"
|
||||
app:tabTextAppearance="@style/TabLayoutTextAppearance" />
|
||||
app:tabIndicatorHeight="0dp"
|
||||
app:tabMaxWidth="0dp"
|
||||
app:tabMode="scrollable"
|
||||
app:tabRippleColor="@color/transparent"
|
||||
app:tabTextAppearance="@style/ColumnCollectionTabDetailTabTextAppearance" />
|
||||
|
||||
</RelativeLayout>
|
||||
<ImageView
|
||||
android:id="@+id/optionIv"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="@drawable/bg_shape_ui_container_2_radius_999"
|
||||
android:padding="6dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_options"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/subject_viewpager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
<View
|
||||
android:id="@+id/maskView"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/bg_game_detail_tab_gradient_mask"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/optionIv"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/settingContainer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/subject_tab_container" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/settingGuideContainer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/settingGuideIv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="36dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/guide_column_collection_custom_setting" />
|
||||
|
||||
<View
|
||||
android:id="@+id/skipView"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="64dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/settingClickView"
|
||||
app:layout_constraintEnd_toStartOf="@+id/settingClickView"
|
||||
app:layout_constraintTop_toTopOf="@+id/settingClickView" />
|
||||
|
||||
<View
|
||||
android:id="@+id/settingClickView"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/settingGuideIv"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
@ -17,44 +18,17 @@
|
||||
android:id="@+id/subject_type_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="12dp"
|
||||
app:layout_scrollFlags="scroll|enterAlwaysCollapsed" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/subject_filter_container"
|
||||
android:layout_width="wrap_content"
|
||||
<com.gh.common.view.ConfigFilterView
|
||||
android:id="@+id/filterView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:background="@drawable/subject_tiled_tab_background">
|
||||
|
||||
<CheckedTextView
|
||||
android:id="@+id/subject_tabbar_hottest"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:background="@drawable/subject_tiled_tab_selector"
|
||||
android:checked="true"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingRight="24dp"
|
||||
android:text="最热"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/subject_tiled_tab_color_selector"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<CheckedTextView
|
||||
android:id="@+id/subject_tabbar_newest"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:background="@drawable/subject_tiled_tab_selector"
|
||||
android:checked="false"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingRight="24dp"
|
||||
android:text="最新"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/subject_tiled_tab_color_selector"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<com.gh.gamecenter.common.view.Chips
|
||||
android:id="@+id/chips"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</FrameLayout>
|
||||
12
app/src/main/res/layout/item_config_filter_size.xml
Normal file
12
app/src/main/res/layout/item_config_filter_size.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/size_tv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="28dp"
|
||||
android:background="@drawable/config_filter_size_background_style"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:text="全部大小"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/subject_label_text_style"
|
||||
android:textSize="@dimen/little_secondary_size" />
|
||||
153
app/src/main/res/layout/layout_column_collection_setting.xml
Normal file
153
app/src/main/res/layout/layout_column_collection_setting.xml
Normal file
@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/background_shape_white_radius_12_bottom_only">
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="328dp"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none"
|
||||
app:layout_constraintBottom_toTopOf="@+id/actionContainer"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/followTv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="关注内容"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="@dimen/secondary_title_text_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/followDesTv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="长按拖动排序,最少添加1个内容,上限为15个"
|
||||
android:textColor="@color/text_tertiary"
|
||||
android:textSize="@dimen/little_secondary_size" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/followRv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:overScrollMode="never" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/moreContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/moreTv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="更多内容"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="@dimen/secondary_title_text_size"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/moreDesTv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="点击可添加至关注内容"
|
||||
android:textColor="@color/text_tertiary"
|
||||
android:textSize="@dimen/little_secondary_size" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/moreRv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:overScrollMode="never" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/actionContainer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/nestedScrollView">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cancelTv"
|
||||
style="@style/GrayLightButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="取消" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/saveTv"
|
||||
style="@style/PrimaryButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_weight="3"
|
||||
android:gravity="center"
|
||||
android:text="保存" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/topDivider"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/divider_1px"
|
||||
android:background="@color/ui_divider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/bottomDivider"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/divider_1px"
|
||||
android:background="@color/ui_divider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/actionContainer" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -4,47 +4,71 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/config_controller"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/default_filter_row_height"
|
||||
android:layout_height="32dp"
|
||||
android:background="@color/ui_surface"
|
||||
android:paddingLeft="@dimen/default_filter_row_padding"
|
||||
android:paddingRight="@dimen/default_filter_row_padding">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/updateTv"
|
||||
style="@style/filterOptionItem"
|
||||
android:background="@drawable/bg_tag_text"
|
||||
style="@style/ConfigFilterOptionItem"
|
||||
android:text="更新"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/dot1"
|
||||
android:layout_width="2dp"
|
||||
android:layout_height="2dp"
|
||||
android:background="@drawable/ic_filter_dot"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/recommended_tv"
|
||||
app:layout_constraintStart_toEndOf="@+id/updateTv"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/recommended_tv"
|
||||
style="@style/filterOptionItem"
|
||||
android:layout_marginLeft="@dimen/default_filter_row_item_margin"
|
||||
style="@style/ConfigFilterOptionItem"
|
||||
android:text="推荐"
|
||||
android:textColor="@color/text_757575"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toRightOf="@id/updateTv"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginLeft="0dp" />
|
||||
|
||||
<View
|
||||
android:id="@+id/dot2"
|
||||
android:layout_width="2dp"
|
||||
android:layout_height="2dp"
|
||||
android:background="@drawable/ic_filter_dot"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/newest_tv"
|
||||
app:layout_constraintStart_toEndOf="@+id/recommended_tv"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/newest_tv"
|
||||
style="@style/filterOptionItem"
|
||||
android:layout_marginLeft="@dimen/default_filter_row_item_margin"
|
||||
style="@style/ConfigFilterOptionItem"
|
||||
android:text="最新"
|
||||
android:textColor="@color/text_757575"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toRightOf="@id/recommended_tv"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/dot3"
|
||||
android:layout_width="2dp"
|
||||
android:layout_height="2dp"
|
||||
android:background="@drawable/ic_filter_dot"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/rating_tv"
|
||||
app:layout_constraintStart_toEndOf="@+id/newest_tv"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/rating_tv"
|
||||
style="@style/filterOptionItem"
|
||||
android:layout_marginLeft="@dimen/default_filter_row_item_margin"
|
||||
style="@style/ConfigFilterOptionItem"
|
||||
android:text="评分"
|
||||
android:textColor="@color/text_757575"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toRightOf="@id/newest_tv"
|
||||
@ -55,14 +79,14 @@
|
||||
<TextView
|
||||
android:id="@+id/size_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:drawableRight="@drawable/ic_filter_arrow_down"
|
||||
android:drawablePadding="8dp"
|
||||
android:layout_height="match_parent"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="center_vertical"
|
||||
android:text="全部大小"
|
||||
android:textColor="@color/text_757575"
|
||||
android:textColor="@color/text_tertiary"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"
|
||||
app:drawableEndCompat="@drawable/ic_auxiliary_arrow_down_8"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@ -1,19 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout 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"
|
||||
android:background="@color/transparent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.flexbox.FlexboxLayout
|
||||
android:id="@+id/flexbox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/ui_surface"
|
||||
android:paddingBottom="8dp"
|
||||
app:flexDirection="row"
|
||||
app:flexWrap="wrap" />
|
||||
android:background="@color/transparent">
|
||||
|
||||
<View
|
||||
android:id="@+id/background"
|
||||
@ -22,4 +12,17 @@
|
||||
android:alpha="0.3"
|
||||
android:background="@color/black" />
|
||||
|
||||
</LinearLayout>
|
||||
<com.google.android.flexbox.FlexboxLayout
|
||||
android:id="@+id/flexbox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/background_shape_white_radius_12_bottom_only"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="16dp"
|
||||
app:showDivider="middle"
|
||||
app:dividerDrawable="@drawable/shape_flexbox_divider_w8_h8"
|
||||
app:flexDirection="row"
|
||||
app:flexWrap="wrap" />
|
||||
|
||||
</FrameLayout>
|
||||
@ -1,22 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="24dp"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:scrollbars="none">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/label_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/default_filter_row_padding"
|
||||
android:paddingRight="@dimen/default_filter_row_padding" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/label_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/default_filter_row_padding"
|
||||
android:paddingRight="@dimen/default_filter_row_padding" />
|
||||
</HorizontalScrollView>
|
||||
@ -3,7 +3,6 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/label"
|
||||
style="@style/filterOptionItem"
|
||||
android:layout_marginRight="@dimen/default_filter_row_item_margin"
|
||||
android:background="@drawable/text_blue_or_white_style"
|
||||
android:textColor="@color/text_black_or_white_color_style"
|
||||
android:background="@drawable/subject_label_background_style"
|
||||
android:textColor="@color/subject_label_text_style"
|
||||
tools:text="全部" />
|
||||
|
||||
@ -2,17 +2,19 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/border_round_eee_14"
|
||||
android:gravity="center">
|
||||
|
||||
<CheckedTextView
|
||||
android:id="@+id/tab_title"
|
||||
android:layout_width="68dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:background="@drawable/subject_tab_background_selector"
|
||||
android:gravity="center"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:text="人气榜"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/text_tabbar_video_style"
|
||||
android:textColor="@color/text_tabbar_style"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
@ -199,6 +199,7 @@
|
||||
<item name="android:paddingLeft">8dp</item>
|
||||
<item name="android:paddingRight">8dp</item>
|
||||
<item name="android:textColor">@color/white</item>
|
||||
<item name="android:textAlignment">center</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
</style>
|
||||
@ -280,4 +281,15 @@
|
||||
<item name="android:textSize">16sp</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
</style>
|
||||
|
||||
<style name="ConfigFilterOptionItem">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">match_parent</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
<item name="android:paddingStart">8dp</item>
|
||||
<item name="android:paddingEnd">8dp</item>
|
||||
<item name="android:textSize">@dimen/secondary_size</item>
|
||||
</style>
|
||||
</resources>
|
||||
@ -94,7 +94,7 @@ ext {
|
||||
picasso = "2.5.2"
|
||||
lottie = "3.7.0"
|
||||
lottieCompose = "5.2.0"
|
||||
flexbox = "1.1.0"
|
||||
flexbox = "3.0.0"
|
||||
pickerView = "4.1.8"
|
||||
verifier = "1.0.6"
|
||||
skeleton = "1.1.5"
|
||||
|
||||
@ -93,7 +93,7 @@ dependencies {
|
||||
}
|
||||
api "io.github.sinaweibosdk:core:${weiboSDK}"
|
||||
api "com.lg:skeleton:${skeleton}"
|
||||
api "com.google.android:flexbox:${flexbox}"
|
||||
api "com.google.android.flexbox:flexbox:${flexbox}"
|
||||
api "com.blankj:utilcodex:${blankjUtilCodex}"
|
||||
|
||||
api(project(path: ":module_core"))
|
||||
|
||||
@ -502,4 +502,8 @@ public class Constants {
|
||||
|
||||
public static final String PUSH_MESSAGE_ID = "push_message_id";
|
||||
public static final String PUSH_LINK_ENTITY = "push_link_entity";
|
||||
|
||||
public static final String SP_COLUMN_COLLECTION_CUSTOM_TAB = "column_collection_custom_tab";
|
||||
public static final String SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_SETTING = "show_column_collection_custom_tab_setting";
|
||||
public static final String SP_SHOW_COLUMN_COLLECTION_CUSTOM_TAB_GUIDE = "show_column_collection_custom_tab_guide";
|
||||
}
|
||||
|
||||
@ -379,9 +379,9 @@ public class EntranceConsts {
|
||||
public static final String KEY_PERFORM_CONTENT_CARD_CLICK_TYPE = "perform_content_card_click_type";
|
||||
public static final String KEY_FROM = "from";
|
||||
|
||||
public static final String TAB_TYPE_DESC = "详情";
|
||||
public static final String TAB_TYPE_TRENDS = "专区";
|
||||
public static final String TAB_TYPE_ARCHIVE = "云存档";
|
||||
public static final String TAB_TYPE_RATING = "评价";
|
||||
public static final String TAB_TYPE_BBS = "论坛";
|
||||
public static final String KEY_COLUMN_COLLECTION_CUSTOM = "column_collection_custom"; //是否开启专题合集自定义设置
|
||||
public static final String KEY_COLUMN_COLLECTION_CUSTOM_SIZE = "column_collection_custom_size"; //默认显示前X个专题
|
||||
public static final String KEY_COLUMN_COLLECTION_CUSTOM_POSITION = "column_collection_custom_position"; //默认显示前X个专题
|
||||
public static final String KEY_SUBJECT_SETTING_DATA = "subject_setting_data";
|
||||
public static final String KEY_SUBJECT_SORT_SIZE = "subject_sort_size";
|
||||
}
|
||||
|
||||
@ -38,6 +38,8 @@ open class LinkEntity(
|
||||
@SerializedName("game_id")
|
||||
var gameId: String = "",
|
||||
var explain: String = "", // 游戏单合集说明
|
||||
@SerializedName("custom_limit")
|
||||
var customLimit: String = "", // 自定义限制
|
||||
|
||||
//本地字段 (埋点用)
|
||||
var blockId: String = "",
|
||||
|
||||
@ -1808,8 +1808,8 @@ object SensorsBridge {
|
||||
columnCollectionName: String,
|
||||
columnCollectionId: String,
|
||||
position: Int = -1,
|
||||
gameColumnName: String,
|
||||
gameColumnId: String,
|
||||
gameColumnName: String = "",
|
||||
gameColumnId: String = "",
|
||||
text: String,
|
||||
columnCollectionPattern: String = "",
|
||||
bottomTab: String = "",
|
||||
@ -3087,7 +3087,10 @@ object SensorsBridge {
|
||||
location: String = "",
|
||||
columnPattern: String = "",
|
||||
text: String = "",
|
||||
buttonType: String = ""
|
||||
buttonType: String = "",
|
||||
gameTag: List<String> = listOf(),
|
||||
sort: String = "",
|
||||
inclusionSize: String = "",
|
||||
) {
|
||||
val json = json {
|
||||
KEY_BOTTOM_TAB to bottomTab
|
||||
@ -3110,6 +3113,9 @@ object SensorsBridge {
|
||||
KEY_COLUMN_PATTERN to columnPattern
|
||||
KEY_TEXT to text
|
||||
KEY_BUTTON_TYPE to buttonType
|
||||
KEY_GAME_TAG to gameTag
|
||||
"sort" to sort
|
||||
"inclusion_size" to inclusionSize
|
||||
}
|
||||
trackEvent(EVENT_COLUMN_CLICK, json)
|
||||
}
|
||||
|
||||
@ -31,6 +31,13 @@ class Chips @JvmOverloads constructor(
|
||||
private var chipsStyle = STYLE_REGULAR
|
||||
private var chipsState = STATE_DEFAULT
|
||||
|
||||
val startIcon
|
||||
get() = binding.ivStart
|
||||
|
||||
val endIcon
|
||||
get() = binding.ivEnd
|
||||
|
||||
|
||||
init {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
binding = LayoutChipsBinding.inflate(inflater, this, true)
|
||||
@ -147,9 +154,9 @@ class Chips @JvmOverloads constructor(
|
||||
private const val STYLE_MINI = 2
|
||||
|
||||
// state
|
||||
private const val STATE_DEFAULT = 0
|
||||
private const val STATE_FILL = 1
|
||||
private const val STATE_SELECTED = 2
|
||||
private const val STATE_DISABLE = 3
|
||||
const val STATE_DEFAULT = 0
|
||||
const val STATE_FILL = 1
|
||||
const val STATE_SELECTED = 2
|
||||
const val STATE_DISABLE = 3
|
||||
}
|
||||
}
|
||||
@ -83,6 +83,15 @@ public class TabIndicatorView extends View implements ViewPager.OnPageChangeList
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void updateIndicatorColor(int color) {
|
||||
mIndicatorColor = ContextCompat.getColor(getContext(), color);
|
||||
mGradientDrawable = new GradientDrawable();
|
||||
mGradientDrawable.setShape(GradientDrawable.RECTANGLE);
|
||||
mGradientDrawable.setColor(mIndicatorColor);
|
||||
mGradientDrawable.setCornerRadius(Integer.MAX_VALUE);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setupWithTabLayout(final TabLayout tableLayout) {
|
||||
mTabLayout = tableLayout;
|
||||
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/text_primary" android:state_pressed="true" />
|
||||
<item android:color="@color/text_primary" android:state_focused="true" />
|
||||
<item android:color="@color/text_primary" android:state_selected="true" />
|
||||
<item android:color="@color/text_primary" android:state_checked="true" />
|
||||
<item android:color="@color/text_secondary" />
|
||||
</selector>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="999dp" />
|
||||
<solid android:color="@color/ui_container_1" />
|
||||
</shape>
|
||||
@ -12,6 +12,7 @@
|
||||
android:layout_height="8dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/tv_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@ -21,11 +22,15 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/iv_end"
|
||||
app:layout_constraintStart_toEndOf="@id/iv_start"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginStart="0dp"
|
||||
tools:text="长的标签名称" />
|
||||
tools:text="长的标签名称长的标签名称长的标签名称长的标签名称长的标签名称长的标签名称" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_end"
|
||||
@ -34,6 +39,7 @@
|
||||
android:layout_marginStart="4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/tv_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="@color/text_theme" />
|
||||
|
||||
@ -105,6 +105,13 @@
|
||||
<item name="tabMode">fixed</item>
|
||||
</style>
|
||||
|
||||
<style name="ColumnCollectionTabDetailTabTextAppearance" parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textColor">@color/tab_text_primary_secondary_selector</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
</style>
|
||||
|
||||
<style name="community_publication_animation">
|
||||
<item name="android:windowEnterAnimation">@anim/community_publication_enter</item>
|
||||
<!-- 指定显示的动画xml -->
|
||||
|
||||
Reference in New Issue
Block a user