完成光环助手V4.5.0-新分类功能(前端)https://gitlab.ghzs.com/pm/halo-app-issues/-/issues/1055
This commit is contained in:
@ -9,7 +9,6 @@ import android.text.TextUtils
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.base.BaseActivity
|
||||
import com.gh.base.BaseActivity_TabLayout
|
||||
import com.gh.base.ToolBarActivity
|
||||
import com.gh.base.fragment.BaseFragment_TabLayout
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.constant.Config
|
||||
@ -22,6 +21,7 @@ import com.gh.common.exposure.ExposureType
|
||||
import com.gh.common.util.EntranceUtils.*
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.amway.AmwayActivity
|
||||
import com.gh.gamecenter.catalog.CatalogActivity
|
||||
import com.gh.gamecenter.category.CategoryDirectoryActivity
|
||||
import com.gh.gamecenter.download.DownloadFragment.Companion.INDEX_UPDATE
|
||||
import com.gh.gamecenter.entity.*
|
||||
@ -47,7 +47,6 @@ import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
|
||||
import com.gh.gamecenter.qa.subject.CommunitySubjectActivity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.servers.GameServersActivity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.gh.gamecenter.suggest.SuggestType
|
||||
import com.gh.gamecenter.tag.TagsActivity
|
||||
@ -133,7 +132,9 @@ object DirectUtils {
|
||||
"server",
|
||||
"top_game_comment",
|
||||
"wechat_bind",
|
||||
"video")
|
||||
"video",
|
||||
"catalog"
|
||||
)
|
||||
|
||||
fun directToLinkPage(context: Context,
|
||||
linkEntity: LinkEntity,
|
||||
@ -200,6 +201,8 @@ object DirectUtils {
|
||||
|
||||
"category", "分类" -> directCategoryDirectory(context, linkEntity.link!!, linkEntity.text!!)
|
||||
|
||||
"catalog" -> directCatalog(context, linkEntity.link!!, linkEntity.text!!)
|
||||
|
||||
"block", "版块" -> {
|
||||
if (linkEntity.link.isNullOrEmpty()) return
|
||||
directToBlock(context,
|
||||
@ -889,6 +892,21 @@ object DirectUtils {
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转新分类
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directCatalog(context: Context, catalogId: String, catalogTitle: String, entrance: String? = null, path: String? = "") {
|
||||
if (catalogId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, CategoryDirectoryActivity::class.java.name)
|
||||
bundle.putString(KEY_CATALOG_ID, catalogId)
|
||||
bundle.putString(KEY_CATALOG_TITLE, catalogTitle)
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到问题标签详情
|
||||
*/
|
||||
|
||||
@ -215,6 +215,10 @@ public class EntranceUtils {
|
||||
public static final String KEY_BBS_ID = "bbs_id";
|
||||
public static final String KEY_DIAGNOSIS = "diagnosis";
|
||||
public static final String KEY_SIMULATOR = "simulator";
|
||||
public static final String KEY_CATALOG_ID = "catalogId";
|
||||
public static final String KEY_PRIMARY_CATALOG_ID = "primaryCatalogId";
|
||||
public static final String KEY_CATALOG_TITLE = "catalog_title";
|
||||
public static final String KEY_CATALOG_INIT_TITLE = "catalog_init_title";
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
320
app/src/main/java/com/gh/common/view/CatalogFilterView.kt
Normal file
320
app/src/main/java/com/gh/common/view/CatalogFilterView.kt
Normal file
@ -0,0 +1,320 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.util.toColor
|
||||
import com.gh.common.util.visibleIf
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.CatalogSwitch
|
||||
import com.gh.gamecenter.entity.SubCatalogEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.google.android.flexbox.FlexboxLayout
|
||||
|
||||
class CatalogFilterView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : LinearLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private var mTypeTv: TextView
|
||||
private var mCatalogTv: TextView
|
||||
private var mSizeTv: TextView
|
||||
private var mTypeContainer: View
|
||||
private var mCatalogContainer: View
|
||||
private var mSizeContainer: View
|
||||
|
||||
private var mTypeFilterArray = ArrayList<SortType>()
|
||||
private var mCatalogFilterArray = ArrayList<SubCatalogEntity>()
|
||||
private var sizeFilterArray: ArrayList<SubjectSettingEntity.Size>? = null
|
||||
|
||||
private var mOnCatalogFilterSetupListener: OnCatalogFilterSetupListener? = null
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.layout_catalog_filter, this)
|
||||
|
||||
mTypeTv = findViewById(R.id.type_tv)
|
||||
mCatalogTv = findViewById(R.id.catalog_tv)
|
||||
mSizeTv = findViewById(R.id.size_tv)
|
||||
mTypeContainer = findViewById(R.id.container_type)
|
||||
mCatalogContainer = findViewById(R.id.container_catalog)
|
||||
mSizeContainer = findViewById(R.id.container_size)
|
||||
|
||||
mTypeContainer.setOnClickListener {
|
||||
showSelectTypePopupWindow(this, mTypeTv, mTypeTv.text.toString())
|
||||
}
|
||||
|
||||
mCatalogContainer.setOnClickListener {
|
||||
showSelectCatalogPopupWindow(this, mCatalogTv, mCatalogTv.text.toString())
|
||||
}
|
||||
|
||||
mSizeContainer.setOnClickListener {
|
||||
showSelectSizePopupWindow(this, mSizeTv, mSizeTv.text.toString())
|
||||
}
|
||||
|
||||
// ratingTv.setOnClickListener {
|
||||
// mOnConfigFilterSetupListener?.onSetupSortType(SortType.RATING)
|
||||
// toggleHighlightedTextView(ratingTv, true)
|
||||
// toggleHighlightedTextView(newestTv, false)
|
||||
// toggleHighlightedTextView(recommendedTv, false)
|
||||
// }
|
||||
//
|
||||
// newestTv.setOnClickListener {
|
||||
// mOnConfigFilterSetupListener?.onSetupSortType(SortType.NEWEST)
|
||||
// toggleHighlightedTextView(ratingTv, false)
|
||||
// toggleHighlightedTextView(newestTv, true)
|
||||
// toggleHighlightedTextView(recommendedTv, false)
|
||||
// }
|
||||
//
|
||||
// recommendedTv.setOnClickListener {
|
||||
// mOnConfigFilterSetupListener?.onSetupSortType(SortType.RECOMMENDED)
|
||||
// toggleHighlightedTextView(ratingTv, false)
|
||||
// toggleHighlightedTextView(newestTv, false)
|
||||
// toggleHighlightedTextView(recommendedTv, true)
|
||||
// }
|
||||
}
|
||||
|
||||
fun setTypeList(switch: CatalogSwitch) {
|
||||
switch.run {
|
||||
if ("on" == hotSort) mTypeFilterArray.add(SortType.RECOMMENDED)
|
||||
if ("on" == newSort) mTypeFilterArray.add(SortType.NEWEST)
|
||||
if ("on" == starSort) mTypeFilterArray.add(SortType.RATING)
|
||||
}
|
||||
if (mTypeFilterArray.isNotEmpty()) mTypeTv.text = mTypeFilterArray[0].value
|
||||
}
|
||||
|
||||
fun setCatalogList(subCatalogList: List<SubCatalogEntity>, initCatalogName: String) {
|
||||
mCatalogFilterArray = ArrayList(subCatalogList)
|
||||
mCatalogTv.text = initCatalogName
|
||||
}
|
||||
|
||||
fun setOnConfigSetupListener(onCatalogFilterSetupListener: OnCatalogFilterSetupListener) {
|
||||
mOnCatalogFilterSetupListener = onCatalogFilterSetupListener
|
||||
}
|
||||
|
||||
private fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
|
||||
if (highlightIt) {
|
||||
targetTextView.background = ContextCompat.getDrawable(targetTextView.context, R.drawable.bg_tag_text)
|
||||
targetTextView.setTextColor(Color.WHITE)
|
||||
} else {
|
||||
targetTextView.background = null
|
||||
targetTextView.setTextColor(ContextCompat.getColor(targetTextView.context, R.color.text_757575))
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSelectTypePopupWindow(containerView: View, typeTv: TextView, typeText: String) {
|
||||
val drawableUp = ContextCompat.getDrawable(typeTv.context, R.drawable.ic_filter_arrow_up)
|
||||
val drawableDown = ContextCompat.getDrawable(typeTv.context, R.drawable.ic_filter_arrow_down)
|
||||
drawableUp?.setBounds(0, 0, drawableUp.minimumWidth, drawableUp.minimumHeight)
|
||||
drawableDown?.setBounds(0, 0, drawableDown.minimumWidth, drawableDown.minimumHeight)
|
||||
|
||||
typeTv.setTextColor(R.color.theme_font.toColor())
|
||||
typeTv.setCompoundDrawables(null, null, drawableUp, null)
|
||||
|
||||
val inflater = LayoutInflater.from(typeTv.context)
|
||||
val layout = inflater.inflate(R.layout.layout_filter_size, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT)
|
||||
|
||||
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
|
||||
val backgroundView = layout.findViewById<View>(R.id.background)
|
||||
|
||||
backgroundView.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
|
||||
for (type in mTypeFilterArray) {
|
||||
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
|
||||
|
||||
// 单列 3 个,强行设置宽度为屏幕的 1/3
|
||||
val width = typeTv.context.resources.displayMetrics.widthPixels / 3
|
||||
val height = item.layoutParams.height
|
||||
|
||||
item.layoutParams = ViewGroup.LayoutParams(width, height)
|
||||
flexboxLayout.addView(item)
|
||||
|
||||
val tv = item.findViewById<TextView>(R.id.size_tv)
|
||||
tv.text = type.value
|
||||
|
||||
toggleHighlightedTextView(tv, typeText == type.value)
|
||||
|
||||
tv.tag = type.value
|
||||
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(tv, true)
|
||||
popupWindow.dismiss()
|
||||
typeTv.text = type.value
|
||||
|
||||
mOnCatalogFilterSetupListener?.onSetupSortType(type)
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
typeTv.setTextColor(R.color.text_757575.toColor())
|
||||
typeTv.setCompoundDrawables(null, null, drawableDown, null)
|
||||
}
|
||||
|
||||
popupWindow.isTouchable = true
|
||||
popupWindow.isFocusable = true
|
||||
popupWindow.showAsDropDown(containerView, 0, 0)
|
||||
}
|
||||
|
||||
private fun showSelectCatalogPopupWindow(containerView: View, catalogTv: TextView, catalogText: String) {
|
||||
val drawableUp = ContextCompat.getDrawable(catalogTv.context, R.drawable.ic_filter_arrow_up)
|
||||
val drawableDown = ContextCompat.getDrawable(catalogTv.context, R.drawable.ic_filter_arrow_down)
|
||||
drawableUp?.setBounds(0, 0, drawableUp.minimumWidth, drawableUp.minimumHeight)
|
||||
drawableDown?.setBounds(0, 0, drawableDown.minimumWidth, drawableDown.minimumHeight)
|
||||
|
||||
catalogTv.setTextColor(R.color.theme_font.toColor())
|
||||
catalogTv.setCompoundDrawables(null, null, drawableUp, null)
|
||||
|
||||
val inflater = LayoutInflater.from(catalogTv.context)
|
||||
val layout = inflater.inflate(R.layout.layout_filter_size, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT)
|
||||
|
||||
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
|
||||
val backgroundView = layout.findViewById<View>(R.id.background)
|
||||
|
||||
backgroundView.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
|
||||
for (entity in mCatalogFilterArray) {
|
||||
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
|
||||
|
||||
// 单列 3 个,强行设置宽度为屏幕的 1/3
|
||||
val width = catalogTv.context.resources.displayMetrics.widthPixels / 3
|
||||
val height = item.layoutParams.height
|
||||
|
||||
item.layoutParams = ViewGroup.LayoutParams(width, height)
|
||||
flexboxLayout.addView(item)
|
||||
|
||||
val tv = item.findViewById<TextView>(R.id.size_tv)
|
||||
val iv = item.findViewById<ImageView>(R.id.recommend_iv)
|
||||
tv.text = entity.name
|
||||
iv.visibleIf(entity.recommended)
|
||||
|
||||
toggleHighlightedTextView(tv, catalogText == entity.name)
|
||||
|
||||
tv.tag = entity.name
|
||||
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(tv, true)
|
||||
popupWindow.dismiss()
|
||||
catalogTv.text = entity.name
|
||||
|
||||
mOnCatalogFilterSetupListener?.onSetupSortCatalog(entity)
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
catalogTv.setTextColor(R.color.text_757575.toColor())
|
||||
catalogTv.setCompoundDrawables(null, null, drawableDown, null)
|
||||
}
|
||||
|
||||
popupWindow.isTouchable = true
|
||||
popupWindow.isFocusable = true
|
||||
popupWindow.showAsDropDown(containerView, 0, 0)
|
||||
}
|
||||
|
||||
private fun showSelectSizePopupWindow(containerView: View, sizeTv: TextView, sizeText: String) {
|
||||
val drawableUp = ContextCompat.getDrawable(sizeTv.context, R.drawable.ic_filter_arrow_up)
|
||||
val drawableDown = ContextCompat.getDrawable(sizeTv.context, R.drawable.ic_filter_arrow_down)
|
||||
drawableUp?.setBounds(0, 0, drawableUp.minimumWidth, drawableUp.minimumHeight)
|
||||
drawableDown?.setBounds(0, 0, drawableDown.minimumWidth, drawableDown.minimumHeight)
|
||||
|
||||
sizeTv.setTextColor(R.color.theme_font.toColor())
|
||||
sizeTv.setCompoundDrawables(null, null, drawableUp, null)
|
||||
|
||||
val inflater = LayoutInflater.from(sizeTv.context)
|
||||
val layout = inflater.inflate(R.layout.layout_filter_size, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT)
|
||||
|
||||
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
|
||||
val backgroundView = layout.findViewById<View>(R.id.background)
|
||||
|
||||
sizeFilterArray = if (sizeFilterArray == null) {
|
||||
getDefaultSizeFilterArray()
|
||||
} else {
|
||||
sizeFilterArray?.apply {
|
||||
if (firstOrNull()?.text != "全部大小") {
|
||||
add(0, SubjectSettingEntity.Size(min = -1, max = -1, text = "全部大小"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backgroundView.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
|
||||
for (size in sizeFilterArray!!) {
|
||||
val item = inflater.inflate(R.layout.item_filter_size, flexboxLayout, false)
|
||||
|
||||
// 单列 3 个,强行设置宽度为屏幕的 1/3
|
||||
val width = sizeTv.context.resources.displayMetrics.widthPixels / 3
|
||||
val height = item.layoutParams.height
|
||||
|
||||
item.layoutParams = ViewGroup.LayoutParams(width, height)
|
||||
flexboxLayout.addView(item)
|
||||
|
||||
val tv = item.findViewById<TextView>(R.id.size_tv)
|
||||
tv.text = size.text
|
||||
|
||||
toggleHighlightedTextView(tv, sizeText == size.text)
|
||||
|
||||
tv.tag = size.text
|
||||
|
||||
item.setOnClickListener {
|
||||
toggleHighlightedTextView(tv, true)
|
||||
popupWindow.dismiss()
|
||||
sizeTv.text = size.text
|
||||
|
||||
mOnCatalogFilterSetupListener?.onSetupSortSize(size)
|
||||
}
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
sizeTv.setTextColor(R.color.text_757575.toColor())
|
||||
sizeTv.setCompoundDrawables(null, null, drawableDown, null)
|
||||
}
|
||||
|
||||
popupWindow.isTouchable = true
|
||||
popupWindow.isFocusable = true
|
||||
popupWindow.showAsDropDown(containerView, 0, 0)
|
||||
}
|
||||
|
||||
private fun getDefaultSizeFilterArray(): ArrayList<SubjectSettingEntity.Size> {
|
||||
return arrayListOf<SubjectSettingEntity.Size>().apply {
|
||||
add(SubjectSettingEntity.Size(min = -1, max = -1, text = "全部大小"))
|
||||
add(SubjectSettingEntity.Size(min = -1, max = 20, text = "20M以下"))
|
||||
add(SubjectSettingEntity.Size(min = 20, max = 50, text = "20-50M"))
|
||||
add(SubjectSettingEntity.Size(min = 50, max = 100, text = "50-100M"))
|
||||
add(SubjectSettingEntity.Size(min = 100, max = 500, text = "100-500M"))
|
||||
add(SubjectSettingEntity.Size(min = 500, max = -1, text = "500M以上"))
|
||||
}
|
||||
}
|
||||
|
||||
interface OnCatalogFilterSetupListener {
|
||||
fun onSetupSortSize(sortSize: SubjectSettingEntity.Size)
|
||||
fun onSetupSortType(sortType: SortType)
|
||||
fun onSetupSortCatalog(sortCatalog: SubCatalogEntity)
|
||||
}
|
||||
|
||||
enum class SortType(val value: String) {
|
||||
RECOMMENDED("热门推荐"),
|
||||
NEWEST("最新上线"),
|
||||
RATING("最高评分")
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.NormalActivity
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
class CatalogActivity : NormalActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setToolbarMenu(R.menu.menu_download)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun provideNormalIntent(): Intent {
|
||||
return getTargetIntent(this, CatalogActivity::class.java, CatalogFragment::class.java)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context, catalogId: String, catalogTitle: String): Intent {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceUtils.KEY_CATALOG_ID, catalogId)
|
||||
bundle.putString(EntranceUtils.KEY_CATALOG_TITLE, catalogTitle)
|
||||
return getTargetIntent(context, CatalogActivity::class.java, CatalogFragment::class.java, bundle)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.common.util.toColor
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.CatalogItemBinding
|
||||
import com.gh.gamecenter.entity.SubCatalogEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class CatalogAdapter(context: Context, private val mFragment: CatalogFragment, private val mList: List<SubCatalogEntity>) : BaseRecyclerAdapter<CatalogAdapter.CatalogItemViewHolder>(context) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CatalogItemViewHolder {
|
||||
val view = mLayoutInflater.inflate(R.layout.catalog_item, parent, false)
|
||||
return CatalogItemViewHolder(CatalogItemBinding.bind(view))
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mList.size
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: CatalogItemViewHolder, position: Int) {
|
||||
holder.binding.run {
|
||||
val catalogEntity = mList[position]
|
||||
entity = catalogEntity
|
||||
executePendingBindings()
|
||||
if (catalogEntity.name == mFragment.selectedCatalogName) {
|
||||
selectedTag.visibility = View.VISIBLE
|
||||
root.setBackgroundColor(R.color.white.toColor())
|
||||
} else {
|
||||
selectedTag.visibility = View.GONE
|
||||
root.setBackgroundColor(R.color.text_F5F5F5.toColor())
|
||||
}
|
||||
root.setOnClickListener {
|
||||
if (catalogEntity.name != mFragment.selectedCatalogName) {
|
||||
mFragment.selectedCatalogName = catalogEntity.name
|
||||
mFragment.changeCatalog(position)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CatalogItemViewHolder(val binding: CatalogItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
119
app/src/main/java/com/gh/gamecenter/catalog/CatalogFragment.kt
Normal file
119
app/src/main/java/com/gh/gamecenter/catalog/CatalogFragment.kt
Normal file
@ -0,0 +1,119 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.common.util.viewModelProvider
|
||||
import com.gh.common.view.FixLinearLayoutManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.entity.SubCatalogEntity
|
||||
import com.gh.gamecenter.normal.NormalFragment
|
||||
import kotterknife.bindView
|
||||
|
||||
class CatalogFragment : NormalFragment() {
|
||||
|
||||
private val mReuseLoading by bindView<LinearLayout>(R.id.reuse_ll_loading)
|
||||
private val mReuseNoConnection by bindView<View>(R.id.reuse_no_connection)
|
||||
private val mReuseNoData by bindView<View>(R.id.reuse_none_data)
|
||||
private val mCatalogContainer by bindView<View>(R.id.container_catalog)
|
||||
private val mCatalogRv by bindView<RecyclerView>(R.id.rv_catalog)
|
||||
|
||||
private lateinit var mViewModel: CatalogViewModel
|
||||
private lateinit var mEntity: CatalogEntity
|
||||
private lateinit var mSpecialCatalogFragment: SpecialCatalogFragment
|
||||
private lateinit var mSubCatalogFragment: SubCatalogFragment
|
||||
private var mCatalogId: String = ""
|
||||
private var mSelectedPosition = 0
|
||||
var selectedCatalogName: String = ""
|
||||
|
||||
override fun getLayoutId() = R.layout.fragment_catalog
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mCatalogId = arguments?.getString(EntranceUtils.KEY_CATALOG_ID) ?: ""
|
||||
mViewModel = viewModelProvider(CatalogViewModel.Factory(mCatalogId))
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setNavigationTitle(arguments?.getString(EntranceUtils.KEY_CATALOG_TITLE))
|
||||
mViewModel.catalogs.observe(viewLifecycleOwner, Observer {
|
||||
mReuseLoading.visibility = View.GONE
|
||||
if (it != null) {
|
||||
mReuseNoConnection.visibility = View.GONE
|
||||
if (it.subCatalog.isNotEmpty()) {
|
||||
mCatalogContainer.visibility = View.VISIBLE
|
||||
mReuseNoData.visibility = View.GONE
|
||||
mEntity = it
|
||||
if (mEntity.hasSpecial) {
|
||||
val specialEntity = SubCatalogEntity(name = "精选")
|
||||
(mEntity.subCatalog as ArrayList).add(0, specialEntity)
|
||||
}
|
||||
initView()
|
||||
} else {
|
||||
mCatalogContainer.visibility = View.GONE
|
||||
mReuseNoData.visibility = View.VISIBLE
|
||||
}
|
||||
} else {
|
||||
mCatalogContainer.visibility = View.GONE
|
||||
mReuseNoData.visibility = View.GONE
|
||||
mReuseNoConnection.visibility = View.VISIBLE
|
||||
mReuseNoConnection.setOnClickListener {
|
||||
mReuseLoading.visibility = View.VISIBLE
|
||||
mViewModel.getCatalogs()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
mEntity.run {
|
||||
if (subCatalog.isNotEmpty()) {
|
||||
selectedCatalogName = subCatalog[0].name
|
||||
mCatalogRv.layoutManager = FixLinearLayoutManager(requireContext())
|
||||
mCatalogRv.adapter = CatalogAdapter(requireContext(), this@CatalogFragment, subCatalog)
|
||||
|
||||
if (hasSpecial) {
|
||||
mSpecialCatalogFragment = childFragmentManager.findFragmentByTag(SpecialCatalogFragment::class.java.simpleName) as? SpecialCatalogFragment ?: SpecialCatalogFragment()
|
||||
mSpecialCatalogFragment.arguments = bundleOf(EntranceUtils.KEY_CATALOG_ID to mEntity.id)
|
||||
childFragmentManager.beginTransaction().replace(R.id.container_sub_catalog, mSpecialCatalogFragment, SpecialCatalogFragment::class.java.simpleName).commitAllowingStateLoss()
|
||||
} else {
|
||||
mSubCatalogFragment = childFragmentManager.findFragmentByTag(SubCatalogFragment::class.java.simpleName) as? SubCatalogFragment ?: SubCatalogFragment()
|
||||
mSubCatalogFragment.arguments = bundleOf(EntranceUtils.KEY_CATALOG_ID to mEntity.id, EntranceUtils.KEY_PRIMARY_CATALOG_ID to subCatalog[0].id)
|
||||
childFragmentManager.beginTransaction().replace(R.id.container_sub_catalog, mSubCatalogFragment, SubCatalogFragment::class.java.simpleName).commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun changeCatalog(position: Int) {
|
||||
mEntity.run {
|
||||
if (hasSpecial) {
|
||||
if (mSelectedPosition == 0) {
|
||||
mSubCatalogFragment = childFragmentManager.findFragmentByTag(SubCatalogFragment::class.java.simpleName) as? SubCatalogFragment ?: SubCatalogFragment()
|
||||
mSubCatalogFragment.arguments = bundleOf(EntranceUtils.KEY_CATALOG_ID to mEntity.id, EntranceUtils.KEY_PRIMARY_CATALOG_ID to subCatalog[position].id)
|
||||
childFragmentManager.beginTransaction().replace(R.id.container_sub_catalog, mSubCatalogFragment, SubCatalogFragment::class.java.simpleName).commitAllowingStateLoss()
|
||||
} else {
|
||||
if (position == 0) {
|
||||
mSpecialCatalogFragment = childFragmentManager.findFragmentByTag(SpecialCatalogFragment::class.java.simpleName) as? SpecialCatalogFragment ?: SpecialCatalogFragment()
|
||||
mSpecialCatalogFragment.arguments = bundleOf(EntranceUtils.KEY_CATALOG_ID to mEntity.id)
|
||||
childFragmentManager.beginTransaction().replace(R.id.container_sub_catalog, mSpecialCatalogFragment, SpecialCatalogFragment::class.java.simpleName).commitAllowingStateLoss()
|
||||
} else {
|
||||
mSubCatalogFragment.changeSubCatalog(subCatalog[position].id)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mSubCatalogFragment.changeSubCatalog(subCatalog[position].id)
|
||||
}
|
||||
mSelectedPosition = position
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
class CatalogViewModel(application: Application, private val catalogId: String) : AndroidViewModel(application) {
|
||||
|
||||
private val api = RetrofitManager.getInstance(getApplication()).api
|
||||
var catalogs = MutableLiveData<CatalogEntity>()
|
||||
|
||||
init {
|
||||
getCatalogs()
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun getCatalogs() {
|
||||
api.getCatalogs(catalogId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<CatalogEntity>() {
|
||||
override fun onSuccess(data: CatalogEntity) {
|
||||
catalogs.postValue(data)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
super.onFailure(exception)
|
||||
catalogs.postValue(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
class Factory(private val catalogId: String) : ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return CatalogViewModel(HaloApp.getInstance().application, catalogId) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.NormalActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
|
||||
class NewCatalogListActivity : NormalActivity() {
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context, catalogTitle: String, catalog: CatalogEntity, initTitle: String): Intent {
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable(EntranceUtils.KEY_DATA, catalog)
|
||||
bundle.putString(EntranceUtils.KEY_NAME, catalog.name)
|
||||
bundle.putString(EntranceUtils.KEY_CATALOG_TITLE, catalogTitle)
|
||||
bundle.putString(EntranceUtils.KEY_CATALOG_INIT_TITLE, initTitle)
|
||||
return getTargetIntent(context, NewCatalogListActivity::class.java, NewCatalogListFragment::class.java, bundle)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setToolbarMenu(R.menu.menu_download)
|
||||
}
|
||||
|
||||
override fun showDownloadMenu(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,168 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.util.SparseArray
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.constant.ItemViewType
|
||||
import com.gh.common.exposure.ExposureEvent
|
||||
import com.gh.common.exposure.ExposureSource
|
||||
import com.gh.common.exposure.ExposureType
|
||||
import com.gh.common.exposure.IExposable
|
||||
import com.gh.common.util.DownloadItemUtils
|
||||
import com.gh.common.util.StringUtils
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.baselist.ListAdapter
|
||||
import com.gh.gamecenter.baselist.LoadType
|
||||
import com.gh.gamecenter.databinding.GameItemBinding
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.game.GameItemViewHolder
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import java.util.*
|
||||
|
||||
class NewCatalogListAdapter(context: Context,
|
||||
private val mViewModel: NewCatalogListViewModel,
|
||||
private val mEntrance: String?) : ListAdapter<GameEntity>(context), IExposable {
|
||||
|
||||
private val mExposureEventSparseArray: SparseArray<ExposureEvent> = SparseArray()
|
||||
|
||||
val positionAndPackageMap = HashMap<String, Int>()
|
||||
|
||||
override fun setListData(updateData: MutableList<GameEntity>?) {
|
||||
// 记录游戏位置
|
||||
if (updateData != null) {
|
||||
for (i in 0 until updateData.size) {
|
||||
val gameEntity = updateData[i]
|
||||
var packages = gameEntity.id
|
||||
for (apkEntity in gameEntity.getApk()) {
|
||||
packages += apkEntity.packageName
|
||||
}
|
||||
positionAndPackageMap[packages + i] = i
|
||||
}
|
||||
}
|
||||
super.setListData(updateData)
|
||||
}
|
||||
|
||||
fun clearPositionAndPackageMap() {
|
||||
positionAndPackageMap.clear()
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
if (position == itemCount - 1) {
|
||||
return ItemViewType.ITEM_FOOTER
|
||||
}
|
||||
return ItemViewType.GAME_NORMAL
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return when (viewType) {
|
||||
ItemViewType.GAME_NORMAL -> {
|
||||
GameItemViewHolder(GameItemBinding.bind(mLayoutInflater.inflate(R.layout.game_item, parent, false)))
|
||||
}
|
||||
else -> {
|
||||
FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (mEntityList == null || mEntityList.isEmpty()) return 0 else mEntityList.size + 1
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is GameItemViewHolder) {
|
||||
val gameEntity = mEntityList[position]
|
||||
|
||||
holder.binding.game = gameEntity
|
||||
holder.initServerType(gameEntity)
|
||||
holder.binding.hideSize = true
|
||||
holder.binding.executePendingBindings()
|
||||
|
||||
val padTop = if (position == 0) 16F.dip2px() else 8F.dip2px()
|
||||
holder.itemView.setPadding(16F.dip2px(), padTop, 16F.dip2px(), 8F.dip2px())
|
||||
|
||||
gameEntity.sequence = position + 1
|
||||
|
||||
val sortType = mViewModel.sortType.value
|
||||
val toolbarTitle = mViewModel.title
|
||||
val categoryTitle = mViewModel.categoryTitle
|
||||
val selectedCatalogName = mViewModel.selectedCatalog.name
|
||||
|
||||
val exposureSources = ArrayList<ExposureSource>()
|
||||
exposureSources.add(ExposureSource(categoryTitle, selectedCatalogName))
|
||||
exposureSources.add(ExposureSource("二级分类", "$selectedCatalogName+$sortType"))
|
||||
gameEntity.sequence = position + 1
|
||||
|
||||
val event = ExposureEvent.createEvent(gameEntity, exposureSources, null, ExposureType.EXPOSURE)
|
||||
mExposureEventSparseArray.put(position, event)
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
gameEntity,
|
||||
StringUtils.buildString(mEntrance, "+(", toolbarTitle, ":列表[", selectedCatalogName, "=", sortType, "=", (position + 1).toString(), "])"),
|
||||
event)
|
||||
}
|
||||
DownloadItemUtils.setOnClickListener(mContext,
|
||||
holder.binding.downloadBtn,
|
||||
gameEntity,
|
||||
position,
|
||||
this,
|
||||
StringUtils.buildString(StringUtils.buildString(mEntrance, "+(", toolbarTitle, ":列表[", selectedCatalogName, "=", sortType, "=", (position + 1).toString(), "])")),
|
||||
StringUtils.buildString(selectedCatalogName, ":", gameEntity.name),
|
||||
event)
|
||||
|
||||
DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding), true, "star&brief")
|
||||
} else if (holder is FooterViewHolder) {
|
||||
holder.initItemPadding()
|
||||
holder.initFooterViewHolder(mIsLoading, mIsNetworkError, mIsOver, R.string.ask_loadover_hint)
|
||||
holder.itemView.setOnClickListener {
|
||||
if (mIsNetworkError) {
|
||||
mViewModel.load(LoadType.RETRY)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyItemByDownload(download: DownloadEntity) {
|
||||
for (key in positionAndPackageMap.keys) {
|
||||
if (key.contains(download.packageName) && key.contains(download.gameId)) {
|
||||
val position = positionAndPackageMap[key]
|
||||
if (position != null && mEntityList != null && position < mEntityList.size) {
|
||||
mEntityList[position].getEntryMap()[download.platform] = download
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyItemAndRemoveDownload(status: EBDownloadStatus) {
|
||||
for (key in positionAndPackageMap.keys) {
|
||||
if (key.contains(status.packageName) && key.contains(status.gameId)) {
|
||||
val position = positionAndPackageMap[key]
|
||||
if (position != null && mEntityList != null && position < mEntityList.size) {
|
||||
mEntityList[position].getEntryMap().remove(status.platform)
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getEventByPosition(pos: Int): ExposureEvent? {
|
||||
return mExposureEventSparseArray.get(pos)
|
||||
}
|
||||
|
||||
override fun getEventListByPosition(pos: Int): List<ExposureEvent>? {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,154 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.ethanhua.skeleton.Skeleton
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.exposure.ExposureListener
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.view.CatalogFilterView
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.baselist.ListFragment
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import kotterknife.bindView
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
class NewCatalogListFragment : ListFragment<GameEntity, NewCatalogListViewModel>() {
|
||||
|
||||
private val mSkeletonView by bindView<View>(R.id.list_skeleton)
|
||||
private val mFilterView by bindView<CatalogFilterView>(R.id.filter_container)
|
||||
|
||||
private var mPrimeCatalog: CatalogEntity? = null
|
||||
private var mSubCatalogList = arrayListOf<SubCatalogEntity>()
|
||||
private var mInitCatalogName = ""
|
||||
|
||||
private var mAdapter: NewCatalogListAdapter? = null
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
mAdapter?.notifyItemByDownload(downloadEntity)
|
||||
|
||||
if (downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS] == XapkUnzipStatus.FAILURE.name) {
|
||||
showUnzipFailureDialog(downloadEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var mExposureListener: ExposureListener
|
||||
private lateinit var mViewModel: NewCatalogListViewModel
|
||||
|
||||
override fun getLayoutId() = R.layout.fragment_catalog_list
|
||||
|
||||
override fun provideListViewModel() = viewModelProvider<NewCatalogListViewModel>()
|
||||
|
||||
override fun provideListAdapter() = mAdapter ?: NewCatalogListAdapter(requireContext(), mViewModel, mEntrance).apply { mAdapter = this }
|
||||
|
||||
override fun getItemDecoration() = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mViewModel = provideListViewModel()
|
||||
|
||||
mViewModel.title = arguments?.getString(EntranceUtils.KEY_NAME) ?: ""
|
||||
mViewModel.categoryTitle = arguments?.getString(EntranceUtils.KEY_CATALOG_TITLE) ?: ""
|
||||
mEntrance = arguments?.getString(EntranceUtils.KEY_ENTRANCE) ?: Constants.ENTRANCE_UNKNOWN
|
||||
mPrimeCatalog = arguments?.getParcelable(EntranceUtils.KEY_DATA)
|
||||
mSubCatalogList = mPrimeCatalog?.subCatalog as ArrayList<SubCatalogEntity>
|
||||
|
||||
mInitCatalogName = arguments?.getString(EntranceUtils.KEY_CATALOG_INIT_TITLE) ?: ""
|
||||
|
||||
mViewModel.selectedCatalog = mSubCatalogList.find { entity -> entity.name == mInitCatalogName }
|
||||
?: SubCatalogEntity()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setNavigationTitle(mViewModel.title)
|
||||
|
||||
initFilterView()
|
||||
|
||||
mViewModel.refresh.observeNonNull(this) { onRefresh() }
|
||||
|
||||
mExposureListener = ExposureListener(this, mAdapter!!)
|
||||
mListRv.addOnScrollListener(mExposureListener)
|
||||
|
||||
mSkeletonScreen = Skeleton.bind(mSkeletonView).shimmer(false).load(R.layout.fragment_subject_skeleton).show()
|
||||
}
|
||||
|
||||
private fun initFilterView() {
|
||||
mFilterView.run {
|
||||
visibility = View.VISIBLE
|
||||
setTypeList(mPrimeCatalog?.switch ?: CatalogSwitch())
|
||||
setCatalogList(mSubCatalogList, mInitCatalogName)
|
||||
setOnConfigSetupListener(object : CatalogFilterView.OnCatalogFilterSetupListener {
|
||||
override fun onSetupSortSize(sortSize: SubjectSettingEntity.Size) {
|
||||
mViewModel.updateSortConfig(sortSize = sortSize)
|
||||
}
|
||||
|
||||
override fun onSetupSortType(sortType: CatalogFilterView.SortType) {
|
||||
mViewModel.updateSortConfig(sortType = sortType)
|
||||
}
|
||||
|
||||
override fun onSetupSortCatalog(sortCatalog: SubCatalogEntity) {
|
||||
mViewModel.updateSortConfig(sortCatalog = sortCatalog)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
if (isEverPause && mAdapter != null) mAdapter?.notifyDataSetChanged()
|
||||
super.onResume()
|
||||
DownloadManager.getInstance(context).addObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
DownloadManager.getInstance(context).removeObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
mAdapter?.clearPositionAndPackageMap()
|
||||
|
||||
super.onRefresh()
|
||||
}
|
||||
|
||||
// 下载被删除事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(status: EBDownloadStatus) {
|
||||
if ("delete" == status.status) {
|
||||
mAdapter?.notifyItemAndRemoveDownload(status)
|
||||
}
|
||||
}
|
||||
|
||||
// 安装/卸载 事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(busFour: EBPackage) {
|
||||
if ("安装" == busFour.type || "卸载" == busFour.type) {
|
||||
mAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
fun showUnzipFailureDialog(downloadEntity: DownloadEntity) {
|
||||
val data = mAdapter?.positionAndPackageMap ?: return
|
||||
for (gameAndPosition in data) {
|
||||
if (gameAndPosition.key.contains(downloadEntity.packageName)) {
|
||||
val targetView = mLayoutManager.findViewByPosition(gameAndPosition.value)
|
||||
if (targetView != null) {
|
||||
DialogUtils.showUnzipFailureDialog(requireContext(), downloadEntity)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.util.UrlFilterUtils
|
||||
import com.gh.common.view.CatalogFilterView
|
||||
import com.gh.gamecenter.baselist.ListViewModel
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubCatalogEntity
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
||||
class NewCatalogListViewModel(application: Application) : ListViewModel<GameEntity, GameEntity>(application) {
|
||||
|
||||
var title = "" // 显示在 Toolbar 的标题
|
||||
var categoryTitle = "" // 跳转进来的分类的标题
|
||||
|
||||
val refresh = MutableLiveData<Boolean>()
|
||||
|
||||
var selectedCatalog = SubCatalogEntity()
|
||||
var sortType = CatalogFilterView.SortType.RECOMMENDED
|
||||
private var mSortSize = SubjectSettingEntity.Size()
|
||||
private val api = RetrofitManager.getInstance(getApplication()).api
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<List<GameEntity>>? = null
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<List<GameEntity>> {
|
||||
return if (selectedCatalog.link.type == "column") {
|
||||
api.getColumn(selectedCatalog.link.link, getSortType(), getSortSize(), page)
|
||||
} else {
|
||||
api.getGamesWithSpecificTag(getSortSize(), getSortType(), page)
|
||||
}
|
||||
}
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData) { mResultLiveData.postValue(it) }
|
||||
}
|
||||
|
||||
fun updateSortConfig(sortSize: SubjectSettingEntity.Size? = null,
|
||||
sortType: CatalogFilterView.SortType? = null,
|
||||
sortCatalog: SubCatalogEntity? = null) {
|
||||
when {
|
||||
sortSize != null && sortSize != mSortSize -> {
|
||||
mSortSize = sortSize
|
||||
refresh.postValue(true)
|
||||
}
|
||||
|
||||
sortType != null && sortType != this.sortType -> {
|
||||
this.sortType = sortType
|
||||
refresh.postValue(true)
|
||||
}
|
||||
|
||||
sortCatalog != null && sortCatalog != selectedCatalog -> {
|
||||
selectedCatalog = sortCatalog
|
||||
refresh.postValue(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSortSize(): String? {
|
||||
return if (selectedCatalog.link.type == "column") {
|
||||
UrlFilterUtils.getFilterQuery(
|
||||
"min_size", mSortSize.min.toString(),
|
||||
"max_size", mSortSize.max.toString())
|
||||
} else {
|
||||
UrlFilterUtils.getFilterQuery(
|
||||
"tag_id", selectedCatalog.link.link,
|
||||
"min_size", mSortSize.min.toString(),
|
||||
"max_size", mSortSize.max.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSortType(): String? {
|
||||
return when (sortType) {
|
||||
CatalogFilterView.SortType.RECOMMENDED -> "download:-1"
|
||||
CatalogFilterView.SortType.NEWEST -> "publish:-1"
|
||||
CatalogFilterView.SortType.RATING -> "star:-1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,148 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.common.constant.ItemViewType
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
|
||||
import com.gh.gamecenter.baselist.ListAdapter
|
||||
import com.gh.gamecenter.databinding.CatalogHeaderItemBinding
|
||||
import com.gh.gamecenter.databinding.CatalogImageItemBinding
|
||||
import com.gh.gamecenter.databinding.CatalogSubjectCollectionItemBinding
|
||||
import com.gh.gamecenter.databinding.CatalogSubjectItemBinding
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.subject.SubjectActivity.Companion.startSubjectActivity
|
||||
|
||||
class SpecialCatalogAdapter(context: Context) : ListAdapter<SpecialCatalogItemData>(context) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
val view: View
|
||||
return when (viewType) {
|
||||
ItemViewType.ITEM_FOOTER -> {
|
||||
view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false)
|
||||
FooterViewHolder(view)
|
||||
}
|
||||
|
||||
TYPE_HEADER -> CatalogHeaderItemHolder(DataBindingUtil.inflate(mLayoutInflater, R.layout.catalog_header_item, parent, false))
|
||||
|
||||
TYPE_BIG_IMAGE -> CatalogImageItemHolder(DataBindingUtil.inflate(mLayoutInflater, R.layout.catalog_image_item, parent, false))
|
||||
|
||||
TYPE_SUBJECT -> CatalogSubjectItemHolder(DataBindingUtil.inflate(mLayoutInflater, R.layout.catalog_subject_item, parent, false))
|
||||
|
||||
TYPE_SUBJECT_COLLECTION -> CatalogSubjectCollectionItemHolder(DataBindingUtil.inflate(mLayoutInflater, R.layout.catalog_subject_collection_item, parent, false))
|
||||
|
||||
else -> throw NullPointerException()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is CatalogImageItemHolder -> {
|
||||
val imageEntity = mEntityList[position].bigImage!!
|
||||
holder.binding.run {
|
||||
entity = imageEntity.image
|
||||
root.setOnClickListener { DirectUtils.directToLinkPage(mContext, imageEntity.link, "新分类-精选分类", "图片") }
|
||||
}
|
||||
}
|
||||
|
||||
is CatalogHeaderItemHolder -> {
|
||||
val entity = mEntityList[position].header!!
|
||||
val specialLink = entity.link
|
||||
holder.binding.run {
|
||||
link = specialLink
|
||||
headMore.setOnClickListener {
|
||||
if (entity.type == "专题合集") {
|
||||
DirectUtils.directToColumnCollection(mContext, specialLink.link ?: "", -1, "(游戏-专题:" + specialLink.text + "-全部)")
|
||||
} else {
|
||||
startSubjectActivity(mContext, specialLink.link, specialLink.text, false, "(游戏-专题:" + specialLink.text + "-全部)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is CatalogSubjectItemHolder -> {
|
||||
val subject = mEntityList[position].subject!!
|
||||
holder.bindSubject(subject.link.data)
|
||||
}
|
||||
|
||||
is CatalogSubjectCollectionItemHolder -> {
|
||||
val subjectCollection = mEntityList[position].subjectCollection!!
|
||||
holder.bindSubjectCollection(subjectCollection.link.data)
|
||||
}
|
||||
|
||||
is FooterViewHolder -> {
|
||||
holder.initFooterViewHolder(mIsLoading, mIsNetworkError, mIsOver, R.string.ask_loadover_hint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position == itemCount - 1) {
|
||||
ItemViewType.ITEM_FOOTER
|
||||
} else {
|
||||
val item = mEntityList[position]
|
||||
when {
|
||||
item.header != null -> TYPE_HEADER
|
||||
item.bigImage != null -> TYPE_BIG_IMAGE
|
||||
item.subject != null -> TYPE_SUBJECT
|
||||
item.subjectCollection != null -> TYPE_SUBJECT_COLLECTION
|
||||
else -> TYPE_SUBJECT_COLLECTION
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = if (mEntityList.isNullOrEmpty()) 0 else mEntityList.size + FOOTER_ITEM_COUNT
|
||||
|
||||
class CatalogImageItemHolder(val binding: CatalogImageItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
|
||||
class CatalogHeaderItemHolder(val binding: CatalogHeaderItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
|
||||
class CatalogSubjectItemHolder(val binding: CatalogSubjectItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bindSubject(gameList: List<GameEntity>) {
|
||||
binding.gameList.run {
|
||||
var subjectAdapter = adapter
|
||||
if (subjectAdapter is SpecialCatalogSubjectAdapter) {
|
||||
subjectAdapter.checkResetData(gameList)
|
||||
return
|
||||
}
|
||||
subjectAdapter = SpecialCatalogSubjectAdapter(context, gameList)
|
||||
layoutManager = GridLayoutManager(context, 3)
|
||||
adapter = subjectAdapter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CatalogSubjectCollectionItemHolder(val binding: CatalogSubjectCollectionItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bindSubjectCollection(subjectCollection: List<GameEntity>) {
|
||||
binding.subjectCollectionList.run {
|
||||
var collectionAdapter = adapter
|
||||
if (collectionAdapter is SpecialCatalogSubjectCollectionAdapter) {
|
||||
collectionAdapter.checkResetData(subjectCollection)
|
||||
return
|
||||
}
|
||||
collectionAdapter = SpecialCatalogSubjectCollectionAdapter(context, subjectCollection)
|
||||
layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
adapter = collectionAdapter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TYPE_HEADER = 900
|
||||
|
||||
private const val TYPE_BIG_IMAGE = 901
|
||||
|
||||
private const val TYPE_SUBJECT = 902
|
||||
|
||||
private const val TYPE_SUBJECT_COLLECTION = 903
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.baselist.ListFragment
|
||||
|
||||
class SpecialCatalogFragment : ListFragment<SpecialCatalogItemData, SpecialCatalogViewModel>() {
|
||||
|
||||
private var mCatalogId = ""
|
||||
|
||||
private var mAdapter: SpecialCatalogAdapter? = null
|
||||
|
||||
override fun provideListViewModel() = viewModelProvider<SpecialCatalogViewModel>(SpecialCatalogViewModel.Factory(mCatalogId))
|
||||
|
||||
override fun provideListAdapter() = mAdapter ?: SpecialCatalogAdapter(requireContext()).apply { mAdapter = this }
|
||||
|
||||
override fun getItemDecoration() = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
mCatalogId = arguments?.getString(EntranceUtils.KEY_CATALOG_ID) ?: ""
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
mListRv.setBackgroundColor(Color.WHITE)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import com.gh.gamecenter.entity.SpecialCatalogEntity
|
||||
|
||||
data class SpecialCatalogItemData(
|
||||
val header: SpecialCatalogEntity? = null,
|
||||
val bigImage: SpecialCatalogEntity? = null,
|
||||
val subject: SpecialCatalogEntity? = null,
|
||||
val subjectCollection: SpecialCatalogEntity? = null
|
||||
)
|
||||
@ -0,0 +1,57 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.CatalogSubjectGameItemBinding
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class SpecialCatalogSubjectAdapter(context: Context, private var mList: List<GameEntity>) : BaseRecyclerAdapter<SpecialCatalogSubjectAdapter.CatalogSubjectGameItemViewHolder>(context) {
|
||||
|
||||
private val mEntrance = "精选分类"
|
||||
private var countAndKey: Pair<Int, String>? = null
|
||||
|
||||
init {
|
||||
var dataIds = ""
|
||||
mList.forEach {
|
||||
dataIds += it.id
|
||||
}
|
||||
if (dataIds.isNotEmpty()) countAndKey = Pair(mList.size, dataIds)
|
||||
}
|
||||
|
||||
override fun getItemCount() = mList.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
|
||||
= CatalogSubjectGameItemViewHolder(DataBindingUtil.inflate(mLayoutInflater, R.layout.catalog_subject_game_item, parent, false))
|
||||
|
||||
override fun onBindViewHolder(holder: CatalogSubjectGameItemViewHolder, position: Int) {
|
||||
holder.binding.run {
|
||||
val entity = mList[position]
|
||||
game = entity
|
||||
root.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(mContext, entity, "(${mEntrance})")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkResetData(update: List<GameEntity>) {
|
||||
var dataIds = ""
|
||||
mList.forEach { dataIds += it.id }
|
||||
|
||||
mList = update
|
||||
if (countAndKey?.first == update.size && countAndKey?.second != dataIds) { // 数量不变,内容发生改变
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
} else if (countAndKey?.first != update.size) { // 数量发生改变
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
// 重新刷新数据标识
|
||||
countAndKey = Pair(update.size, dataIds)
|
||||
}
|
||||
|
||||
class CatalogSubjectGameItemViewHolder(val binding: CatalogSubjectGameItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.ImageUtils
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.CatalogSubjectCollectionListItemBinding
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.LinkEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class SpecialCatalogSubjectCollectionAdapter(context: Context, private var mList: List<GameEntity>) : BaseRecyclerAdapter<SpecialCatalogSubjectCollectionAdapter.CatalogSubjectCollectionListItemViewHolder>(context) {
|
||||
|
||||
private var countAndKey: Pair<Int, String>? = null
|
||||
|
||||
init {
|
||||
var dataIds = ""
|
||||
mList.forEach {
|
||||
dataIds += it.id
|
||||
}
|
||||
if (dataIds.isNotEmpty()) countAndKey = Pair(mList.size, dataIds)
|
||||
}
|
||||
|
||||
override fun getItemCount() = mList.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
|
||||
= CatalogSubjectCollectionListItemViewHolder(DataBindingUtil.inflate(mLayoutInflater, R.layout.catalog_subject_collection_list_item, parent, false))
|
||||
|
||||
|
||||
override fun onBindViewHolder(holder: CatalogSubjectCollectionListItemViewHolder, position: Int) {
|
||||
holder.binding.run {
|
||||
root.layoutParams = (root.layoutParams as ViewGroup.MarginLayoutParams).apply {
|
||||
leftMargin = if (position == 0) 16F.dip2px() else 0
|
||||
}
|
||||
val entity = mList[position]
|
||||
ImageUtils.display(subjectCollectionImage, entity.image)
|
||||
root.setOnClickListener { DirectUtils.directToLinkPage(mContext, LinkEntity(link = entity.link, type = entity.type), "精选分类", "专题合集") }
|
||||
}
|
||||
}
|
||||
|
||||
fun checkResetData(update: List<GameEntity>) {
|
||||
var dataIds = ""
|
||||
mList.forEach { dataIds += it.id }
|
||||
|
||||
mList = update
|
||||
if (countAndKey?.first == update.size && countAndKey?.second != dataIds) { // 数量不变,内容发生改变
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
} else if (countAndKey?.first != update.size) { // 数量发生改变
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
// 重新刷新数据标识
|
||||
countAndKey = Pair(update.size, dataIds)
|
||||
}
|
||||
|
||||
class CatalogSubjectCollectionListItemViewHolder(val binding: CatalogSubjectCollectionListItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.gamecenter.baselist.ListViewModel
|
||||
import com.gh.gamecenter.entity.SpecialCatalogEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
||||
class SpecialCatalogViewModel(application: Application, private val catalogId: String): ListViewModel<SpecialCatalogEntity, SpecialCatalogItemData>(application) {
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<List<SpecialCatalogEntity>>? = null
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<List<SpecialCatalogEntity>> {
|
||||
return RetrofitManager.getInstance(getApplication())
|
||||
.sensitiveApi
|
||||
.getSpecialCatalogs(catalogId, page)
|
||||
}
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData) { list ->
|
||||
val itemDataList = arrayListOf<SpecialCatalogItemData>()
|
||||
list.forEach {
|
||||
when (it.type) {
|
||||
"图片" -> itemDataList.add(SpecialCatalogItemData(bigImage = it))
|
||||
|
||||
"专题" -> {
|
||||
itemDataList.add(SpecialCatalogItemData(header = it))
|
||||
itemDataList.add(SpecialCatalogItemData(subject = it))
|
||||
}
|
||||
|
||||
"专题合集" -> {
|
||||
itemDataList.add(SpecialCatalogItemData(header = it))
|
||||
itemDataList.add(SpecialCatalogItemData(subjectCollection = it))
|
||||
}
|
||||
}
|
||||
}
|
||||
mResultLiveData.postValue(itemDataList)
|
||||
}
|
||||
}
|
||||
|
||||
class Factory(private val catalogId: String) : ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return SpecialCatalogViewModel(HaloApp.getInstance().application, catalogId) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.SubCatalogItemBinding
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.entity.SubCatalogEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class SubCatalogAdapter(context: Context, private val mPrimaryCatalog: CatalogEntity, private var mList: List<SubCatalogEntity>) : BaseRecyclerAdapter<SubCatalogAdapter.SubCatalogItemViewHolder>(context) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SubCatalogItemViewHolder {
|
||||
val view = mLayoutInflater.inflate(R.layout.sub_catalog_item, parent, false)
|
||||
return SubCatalogItemViewHolder(SubCatalogItemBinding.bind(view))
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return mList.size
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: SubCatalogItemViewHolder, position: Int) {
|
||||
holder.binding.run {
|
||||
val catalogEntity = mList[position]
|
||||
entity = catalogEntity
|
||||
root.setOnClickListener {
|
||||
root.context.startActivity(NewCatalogListActivity.getIntent(mContext, catalogEntity.name, mPrimaryCatalog, catalogEntity.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SubCatalogItemViewHolder(val binding: SubCatalogItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.common.util.viewModelProvider
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.normal.NormalFragment
|
||||
import kotterknife.bindView
|
||||
|
||||
class SubCatalogFragment : NormalFragment() {
|
||||
|
||||
private val mReuseLoading by bindView<LinearLayout>(R.id.reuse_ll_loading)
|
||||
private val mReuseNoConnection by bindView<View>(R.id.reuse_no_connection)
|
||||
private val mReuseNoData by bindView<View>(R.id.reuse_none_data)
|
||||
private val mSubCatalogRv by bindView<RecyclerView>(R.id.rv_sub_catalog)
|
||||
|
||||
private lateinit var mViewModel: SubCatalogViewModel
|
||||
private lateinit var mSubCatalogAdapter: SubCatalogAdapter
|
||||
private lateinit var mEntity: CatalogEntity
|
||||
private var mCatalogId: String = ""
|
||||
private var mPrimaryCatalogId: String = ""
|
||||
|
||||
override fun getLayoutId() = R.layout.fragment_sub_catalog
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mCatalogId = arguments?.getString(EntranceUtils.KEY_CATALOG_ID) ?: ""
|
||||
mPrimaryCatalogId = arguments?.getString(EntranceUtils.KEY_PRIMARY_CATALOG_ID) ?: ""
|
||||
mViewModel = viewModelProvider(SubCatalogViewModel.Factory(mCatalogId))
|
||||
mViewModel.getSubCatalogs(mPrimaryCatalogId)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
mViewModel.catalogs.observe(viewLifecycleOwner, Observer {
|
||||
mReuseLoading.visibility = View.GONE
|
||||
if (it != null) {
|
||||
mReuseNoConnection.visibility = View.GONE
|
||||
if (it.subCatalog.isNotEmpty()) {
|
||||
mSubCatalogRv.visibility = View.VISIBLE
|
||||
mReuseNoData.visibility = View.GONE
|
||||
mEntity = it
|
||||
initView()
|
||||
} else {
|
||||
mSubCatalogRv.visibility = View.GONE
|
||||
mReuseNoData.visibility = View.VISIBLE
|
||||
}
|
||||
} else {
|
||||
mSubCatalogRv.visibility = View.GONE
|
||||
mReuseNoData.visibility = View.GONE
|
||||
mReuseNoConnection.visibility = View.VISIBLE
|
||||
mReuseNoConnection.setOnClickListener {
|
||||
mReuseLoading.visibility = View.VISIBLE
|
||||
mViewModel.getSubCatalogs(mPrimaryCatalogId)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
mEntity.run {
|
||||
mSubCatalogRv.layoutManager = GridLayoutManager(requireContext(), 3)
|
||||
mSubCatalogAdapter = SubCatalogAdapter(requireContext(), mEntity, subCatalog)
|
||||
mSubCatalogRv.adapter = mSubCatalogAdapter
|
||||
}
|
||||
}
|
||||
|
||||
fun changeSubCatalog(primaryCatalogId: String) {
|
||||
mPrimaryCatalogId = primaryCatalogId
|
||||
mSubCatalogRv.visibility = View.GONE
|
||||
mReuseNoData.visibility = View.GONE
|
||||
mReuseNoConnection.visibility = View.GONE
|
||||
mReuseLoading.visibility = View.VISIBLE
|
||||
mViewModel.getSubCatalogs(mPrimaryCatalogId)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package com.gh.gamecenter.catalog
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.gamecenter.entity.CatalogEntity
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
class SubCatalogViewModel(application: Application, private val catalogId: String): AndroidViewModel(application) {
|
||||
|
||||
private val api = RetrofitManager.getInstance(getApplication()).api
|
||||
var catalogs = MutableLiveData<CatalogEntity>()
|
||||
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun getSubCatalogs(primaryCatalogId: String) {
|
||||
api.getSubCatalogs(catalogId, primaryCatalogId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<CatalogEntity>() {
|
||||
override fun onSuccess(data: CatalogEntity) {
|
||||
catalogs.postValue(data)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
super.onFailure(exception)
|
||||
catalogs.postValue(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
class Factory(private val catalogId: String) : ViewModelProvider.NewInstanceFactory() {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return SubCatalogViewModel(HaloApp.getInstance().application, catalogId) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,7 +4,6 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.NormalActivity
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
|
||||
59
app/src/main/java/com/gh/gamecenter/entity/CatalogEntity.kt
Normal file
59
app/src/main/java/com/gh/gamecenter/entity/CatalogEntity.kt
Normal file
@ -0,0 +1,59 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class CatalogEntity(
|
||||
@SerializedName("_id")
|
||||
var id: String = "",
|
||||
var name: String = "",
|
||||
var switch: CatalogSwitch = CatalogSwitch(),
|
||||
@SerializedName("has_special")
|
||||
var hasSpecial: Boolean = false,
|
||||
@SerializedName("sub_catalogs")
|
||||
var subCatalog: List<SubCatalogEntity> = emptyList()
|
||||
): Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class SubCatalogEntity(
|
||||
@SerializedName("_id")
|
||||
var id: String = "",
|
||||
var name: String = "",
|
||||
var icon: String = "",
|
||||
var link: LinkEntity = LinkEntity(),
|
||||
var recommended: Boolean = false
|
||||
): Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class CatalogSwitch(
|
||||
@SerializedName("sort_hot")
|
||||
var hotSort: String = "",
|
||||
@SerializedName("sort_new")
|
||||
var newSort: String = "",
|
||||
@SerializedName("sort_star")
|
||||
var starSort: String = ""
|
||||
): Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class SpecialCatalogEntity(
|
||||
@SerializedName("_id")
|
||||
var id: String = "",
|
||||
var type: String = "",
|
||||
var link: SpecialLink = SpecialLink(),
|
||||
var image: Image = Image()
|
||||
): Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class SpecialLink(
|
||||
@SerializedName("_id")
|
||||
var id: String = "",
|
||||
var data: List<GameEntity> = emptyList()
|
||||
): LinkEntity(), Parcelable
|
||||
|
||||
@Parcelize
|
||||
data class Image(
|
||||
var url: String = "",
|
||||
var title: String = ""
|
||||
): Parcelable
|
||||
@ -24,6 +24,7 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.adapter.ImagePagerAdapter
|
||||
import com.gh.gamecenter.adapter.viewholder.*
|
||||
import com.gh.gamecenter.baselist.LoadStatus
|
||||
import com.gh.gamecenter.catalog.CatalogActivity
|
||||
import com.gh.gamecenter.category.CategoryDirectoryActivity
|
||||
import com.gh.gamecenter.databinding.*
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
@ -419,6 +420,7 @@ class GameFragmentAdapter(context: Context,
|
||||
entity.type == "column_collection" -> DirectUtils.directToColumnCollection(mContext, entity.link!!, -1, "(推荐入口)")
|
||||
entity.type == "block" -> mContext.startActivity(BlockActivity.getIntent(mContext, entity, "(推荐入口)"))
|
||||
entity.type == "category" -> mContext.startActivity(CategoryDirectoryActivity.getIntent(mContext, entity.link!!, entity.text!!))
|
||||
entity.type == "catalog" -> mContext.startActivity(CatalogActivity.getIntent(mContext, entity.link!!, entity.text!!))
|
||||
entity.type == "column" -> {
|
||||
SubjectActivity.startSubjectActivity(mContext, entity.link, entity.text, entity.order
|
||||
, StringUtils.buildString("(游戏-专题:", entity.name, "[1-", (data + 1).toString(), "]", ")"))
|
||||
|
||||
@ -11,6 +11,7 @@ import com.gh.gamecenter.entity.AuthDialogEntity;
|
||||
import com.gh.gamecenter.entity.AvatarBorderEntity;
|
||||
import com.gh.gamecenter.entity.BackgroundImageEntity;
|
||||
import com.gh.gamecenter.entity.BadgeEntity;
|
||||
import com.gh.gamecenter.entity.CatalogEntity;
|
||||
import com.gh.gamecenter.entity.CategoryEntity;
|
||||
import com.gh.gamecenter.entity.CommentEntity;
|
||||
import com.gh.gamecenter.entity.CommentnumEntity;
|
||||
@ -60,6 +61,7 @@ import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.entity.SignEntity;
|
||||
import com.gh.gamecenter.entity.SimpleGameEntity;
|
||||
import com.gh.gamecenter.entity.SimulatorEntity;
|
||||
import com.gh.gamecenter.entity.SpecialCatalogEntity;
|
||||
import com.gh.gamecenter.entity.SubjectEntity;
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity;
|
||||
import com.gh.gamecenter.entity.SubjectRefreshEntity;
|
||||
@ -301,7 +303,7 @@ public interface ApiService {
|
||||
* 获取专题数据
|
||||
*/
|
||||
@GET("columns/{column_id}/games")
|
||||
Observable<List<GameEntity>> getColumn(@Path("column_id") String column_id, @Query("sort") String sort, @Query("filter") String order, @Query("page") int page);
|
||||
Single<List<GameEntity>> getColumn(@Path("column_id") String column_id, @Query("sort") String sort, @Query("filter") String order, @Query("page") int page);
|
||||
|
||||
/**
|
||||
* 获取专题数据标题
|
||||
@ -2720,4 +2722,22 @@ public interface ApiService {
|
||||
*/
|
||||
@GET("devices/{device_id}/download_simulator_games")
|
||||
Single<List<GameEntity>> getSimulatorGames(@Path("device_id") String deviceId, @Query("page") int page, @Query("filter") String filter);
|
||||
|
||||
/**
|
||||
* 获取一级分类数据
|
||||
*/
|
||||
@GET("catalogs/{catalog_id}")
|
||||
Single<CatalogEntity> getCatalogs(@Path("catalog_id") String catalogId);
|
||||
|
||||
/**
|
||||
* 获取一级分类数据 及其 二级分类数据
|
||||
*/
|
||||
@GET("catalogs/{catalog_id}/{primary_catalog_id}")
|
||||
Single<CatalogEntity> getSubCatalogs(@Path("catalog_id") String catalogId, @Path("primary_catalog_id") String primaryCatalogId);
|
||||
|
||||
/**
|
||||
* 获取精选分类
|
||||
*/
|
||||
@GET("catalogs/{catalog_id}/special")
|
||||
Single<List<SpecialCatalogEntity>> getSpecialCatalogs(@Path("catalog_id") String catalogId, @Query("page") int page);
|
||||
}
|
||||
@ -12,6 +12,7 @@ import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import retrofit2.HttpException
|
||||
@ -23,7 +24,9 @@ class SubjectListViewModel(application: Application,
|
||||
var selectedLabelList = arrayListOf<String>()
|
||||
var selectedFilterSize = SubjectSettingEntity.Size(text = "全部大小")
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<List<GameEntity>> {
|
||||
override fun provideDataObservable(page: Int): Observable<List<GameEntity>>? = null
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<MutableList<GameEntity>> {
|
||||
return RetrofitManager.getInstance(getApplication()).sensitiveApi.getColumn(
|
||||
subjectData.subjectId,
|
||||
subjectData.sort,
|
||||
|
||||
Reference in New Issue
Block a user