diff --git a/app/src/main/java/com/gh/common/util/DirectUtils.kt b/app/src/main/java/com/gh/common/util/DirectUtils.kt index a64044aa6b..01ef948439 100644 --- a/app/src/main/java/com/gh/common/util/DirectUtils.kt +++ b/app/src/main/java/com/gh/common/util/DirectUtils.kt @@ -80,6 +80,7 @@ import org.greenrobot.eventbus.EventBus import retrofit2.HttpException import java.net.URLEncoder import java.util.* +import kotlin.collections.ArrayList import kotlin.math.roundToInt /** @@ -189,7 +190,7 @@ object DirectUtils { "column", "游戏专题" -> directToSubject( context, linkEntity.link - ?: "", linkEntity.text, BaseActivity.mergeEntranceAndPath(entrance, path) + ?: "", linkEntity.text, BaseActivity.mergeEntranceAndPath(entrance, path), exposureEvent ) "question", "社区问题" -> directToQuestionDetail( @@ -239,7 +240,7 @@ object DirectUtils { "catalog" -> directCatalog(context, linkEntity.link!!, linkEntity.text!!, entrance, path) - "category_v2" -> directCategoryV2(context, linkEntity.link!!, linkEntity.text!!, entrance, path) + "category_v2" -> directCategoryV2(context, linkEntity.link!!, linkEntity.text!!, entrance, path, exposureEvent) "block", "版块" -> { if (linkEntity.link.isNullOrEmpty()) return @@ -629,13 +630,14 @@ object DirectUtils { // 专栏 @JvmStatic - fun directToSubject(context: Context, id: String, subjectName: String? = "", entrance: String? = null) { + fun directToSubject(context: Context, id: String, subjectName: String? = "", entrance: String? = null, exposureEvent: ExposureEvent? = null) { if (id.isEmpty()) return val bundle = Bundle() val subjectData = SubjectData(subjectId = id, subjectName = subjectName, isOrder = false) bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER) bundle.putString(KEY_TO, SubjectActivity::class.java.name) bundle.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, subjectData) + if (exposureEvent != null) bundle.putParcelableArrayList(KEY_EXPOSURE_SOURCE_LIST, ArrayList(exposureEvent.source)) jumpActivity(context, bundle) } @@ -1179,6 +1181,7 @@ object DirectUtils { categoryTitle: String, entrance: String? = null, path: String? = "", + exposureEvent: ExposureEvent? = null, ) { if (categoryId.isEmpty()) return val bundle = Bundle() @@ -1186,6 +1189,7 @@ object DirectUtils { bundle.putString(KEY_CATEGORY_ID, categoryId) bundle.putString(KEY_CATEGORY_TITLE, categoryTitle) bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path)) + if (exposureEvent != null) bundle.putParcelableArrayList(KEY_EXPOSURE_SOURCE_LIST, ArrayList(exposureEvent.source)) jumpActivity(context, bundle) } diff --git a/app/src/main/java/com/gh/common/util/NewFlatLogUtils.kt b/app/src/main/java/com/gh/common/util/NewFlatLogUtils.kt index 4ffc0a4fc6..bafc34af00 100644 --- a/app/src/main/java/com/gh/common/util/NewFlatLogUtils.kt +++ b/app/src/main/java/com/gh/common/util/NewFlatLogUtils.kt @@ -83,4 +83,44 @@ object NewFlatLogUtils { } log(json, "event", false) } + + //游戏详情点击内容卡片 + @JvmStatic + fun logGameDetailGameContentCardClick( + title: String, + gameName: String, + gameId: String, + linkType: String, + linkId: String, + linkText: String + ) { + val json = json { + "event" to "game_detail_game_content_card_click" + "title" to title + "game_name" to gameName + "game_id" to gameId + "link_type" to linkType + "link_id" to linkId + "link_text" to linkText + parseAndPutMeta().invoke(this) + } + log(json, "event", false) + } + + //浏览自定义栏目 + @JvmStatic + fun logGameDetailColumnOrderingView( + title: String, + gameName: String, + gameId: String + ) { + val json = json { + "event" to "game_detail_column_ordering_view" + "title" to title + "game_name" to gameName + "game_id" to gameId + parseAndPutMeta().invoke(this) + } + log(json, "event", false) + } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/GameDetailActivity.kt b/app/src/main/java/com/gh/gamecenter/GameDetailActivity.kt index 7c11a0424c..c94897e465 100644 --- a/app/src/main/java/com/gh/gamecenter/GameDetailActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/GameDetailActivity.kt @@ -80,7 +80,7 @@ class GameDetailActivity : DownloadToolbarActivity() { override fun isAutoResetViewBackgroundEnabled(): Boolean = true override fun updateStaticViewBackground(view: View?) { - updateStaticView(view, listOf(R.id.menu_download_iv, R.id.gameBigEvent)) + updateStaticView(view, listOf(R.id.menu_download_iv, R.id.gameBigEvent, R.id.backgroundIv)) } companion object { diff --git a/app/src/main/java/com/gh/gamecenter/SkipActivity.java b/app/src/main/java/com/gh/gamecenter/SkipActivity.java index c98d7e6b82..e815ac95e5 100644 --- a/app/src/main/java/com/gh/gamecenter/SkipActivity.java +++ b/app/src/main/java/com/gh/gamecenter/SkipActivity.java @@ -112,7 +112,7 @@ public class SkipActivity extends BaseActivity { DirectUtils.directToGameDetail(this, path, ENTRANCE_BROWSER, "true".equals(uri.getQueryParameter("auto_download")), to, null); break; case HOST_COLUMN: - DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), ENTRANCE_BROWSER); + DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), ENTRANCE_BROWSER, null); break; case HOST_SUGGESTION: String platform = uri.getQueryParameter(KEY_PLATFORM); diff --git a/app/src/main/java/com/gh/gamecenter/catalog/SpecialCatalogFragment.kt b/app/src/main/java/com/gh/gamecenter/catalog/SpecialCatalogFragment.kt index 20093e678d..7c9788fbc6 100644 --- a/app/src/main/java/com/gh/gamecenter/catalog/SpecialCatalogFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/catalog/SpecialCatalogFragment.kt @@ -32,7 +32,7 @@ class SpecialCatalogFragment : ListFragment(application) { + private val mExposureSourceList: List?) : ListViewModel(application) { private val mApi = RetrofitManager.getInstance().api val basicExposureSource by lazy { arrayListOf().apply { - mExposureSource?.let { add(it) } + if (!mExposureSourceList.isNullOrEmpty()) { + addAll(mExposureSourceList) + } add(ExposureSource("分类", mCatalogTitle)) } } @@ -98,7 +100,7 @@ class SpecialCatalogViewModel(application: Application, class Factory(private val mCatalogId: String, private val mCatalogTitle: String, private val mIsCategoryV2: Boolean, - private val mExposureSource: ExposureSource? + private val mExposureSourceList: List? ) : ViewModelProvider.NewInstanceFactory() { override fun create(modelClass: Class): T { return SpecialCatalogViewModel( @@ -106,7 +108,7 @@ class SpecialCatalogViewModel(application: Application, mCatalogId, mCatalogTitle, mIsCategoryV2, - mExposureSource + mExposureSourceList ) as T } } diff --git a/app/src/main/java/com/gh/gamecenter/category2/CategoryV2Fragment.kt b/app/src/main/java/com/gh/gamecenter/category2/CategoryV2Fragment.kt index f8d25cbe8d..b90527d491 100644 --- a/app/src/main/java/com/gh/gamecenter/category2/CategoryV2Fragment.kt +++ b/app/src/main/java/com/gh/gamecenter/category2/CategoryV2Fragment.kt @@ -1,6 +1,5 @@ package com.gh.gamecenter.category2 -import android.graphics.Color import android.os.Bundle import android.view.MenuItem import android.view.View @@ -10,17 +9,18 @@ import androidx.core.view.GravityCompat import androidx.drawerlayout.widget.DrawerLayout import androidx.lifecycle.Observer import androidx.recyclerview.widget.LinearLayoutManager -import com.gh.gamecenter.common.base.fragment.LazyFragment -import com.gh.gamecenter.common.constant.Constants -import com.gh.common.util.* +import com.gh.common.exposure.ExposureSource import com.gh.common.util.LogUtils -import com.gh.gamecenter.common.view.FixLinearLayoutManager import com.gh.gamecenter.R import com.gh.gamecenter.SearchActivity import com.gh.gamecenter.catalog.SpecialCatalogFragment +import com.gh.gamecenter.common.base.fragment.LazyFragment +import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.common.constant.EntranceConsts import com.gh.gamecenter.common.utils.* -import com.gh.gamecenter.core.utils.* +import com.gh.gamecenter.common.view.FixLinearLayoutManager +import com.gh.gamecenter.core.utils.PageSwitchDataHelper +import com.gh.gamecenter.core.utils.SPUtils import com.gh.gamecenter.databinding.FragmentCategoryBinding import com.gh.gamecenter.entity.CategoryEntity import com.gh.gamecenter.entity.SidebarsEntity @@ -307,7 +307,7 @@ class CategoryV2Fragment : LazyFragment() { EntranceConsts.KEY_IS_CATEGORY_V2 to true, EntranceConsts.KEY_CATALOG_ID to id, EntranceConsts.KEY_CATALOG_TITLE to mCategoryTitle, - EntranceConsts.KEY_EXPOSURE_SOURCE to arguments?.getParcelable(EntranceConsts.KEY_EXPOSURE_SOURCE), + EntranceConsts.KEY_EXPOSURE_SOURCE_LIST to arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST), EntranceConsts.KEY_LAST_PAGE_DATA to mLastPageDataMap ) childFragmentManager @@ -331,7 +331,7 @@ class CategoryV2Fragment : LazyFragment() { EntranceConsts.KEY_CATEGORY_ID to id, EntranceConsts.KEY_SUB_CATEGORY_ID to sidebars[selectedCategoryPosition].categoryId, EntranceConsts.KEY_CATEGORY_TITLE to mCategoryTitle, - EntranceConsts.KEY_EXPOSURE_SOURCE to arguments?.getParcelable(EntranceConsts.KEY_EXPOSURE_SOURCE), + EntranceConsts.KEY_EXPOSURE_SOURCE_LIST to arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST), EntranceConsts.KEY_LAST_PAGE_DATA to mLastPageDataMap ) childFragmentManager @@ -360,7 +360,7 @@ class CategoryV2Fragment : LazyFragment() { EntranceConsts.KEY_CATEGORY_ID to id, EntranceConsts.KEY_SUB_CATEGORY_ID to sidebars[position].categoryId, EntranceConsts.KEY_CATALOG_TITLE to mCategoryTitle, - EntranceConsts.KEY_EXPOSURE_SOURCE to arguments?.getParcelable(EntranceConsts.KEY_EXPOSURE_SOURCE), + EntranceConsts.KEY_EXPOSURE_SOURCE_LIST to arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST), EntranceConsts.KEY_LAST_PAGE_DATA to mLastPageDataMap ) childFragmentManager @@ -378,7 +378,7 @@ class CategoryV2Fragment : LazyFragment() { EntranceConsts.KEY_IS_CATEGORY_V2 to true, EntranceConsts.KEY_CATALOG_ID to id, EntranceConsts.KEY_CATALOG_TITLE to mCategoryTitle, - EntranceConsts.KEY_EXPOSURE_SOURCE to arguments?.getParcelable(EntranceConsts.KEY_EXPOSURE_SOURCE), + EntranceConsts.KEY_EXPOSURE_SOURCE_LIST to arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST), EntranceConsts.KEY_LAST_PAGE_DATA to mLastPageDataMap ) childFragmentManager @@ -391,7 +391,7 @@ class CategoryV2Fragment : LazyFragment() { EntranceConsts.KEY_CATEGORY_ID to id, EntranceConsts.KEY_SUB_CATEGORY_ID to sidebars[position].categoryId, EntranceConsts.KEY_CATALOG_TITLE to mCategoryTitle, - EntranceConsts.KEY_EXPOSURE_SOURCE to arguments?.getParcelable(EntranceConsts.KEY_EXPOSURE_SOURCE), + EntranceConsts.KEY_EXPOSURE_SOURCE_LIST to arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST), EntranceConsts.KEY_LAST_PAGE_DATA to mLastPageDataMap ) } @@ -413,7 +413,7 @@ class CategoryV2Fragment : LazyFragment() { EntranceConsts.KEY_CATEGORY_ID to id, EntranceConsts.KEY_SUB_CATEGORY_ID to sidebars[position].categoryId, EntranceConsts.KEY_CATALOG_TITLE to mCategoryTitle, - EntranceConsts.KEY_EXPOSURE_SOURCE to arguments?.getParcelable(EntranceConsts.KEY_EXPOSURE_SOURCE), + EntranceConsts.KEY_EXPOSURE_SOURCE_LIST to arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST), EntranceConsts.KEY_LAST_PAGE_DATA to mLastPageDataMap ) } diff --git a/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListAdapter.kt b/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListAdapter.kt index 36459ce123..d612c7b9c3 100644 --- a/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListAdapter.kt @@ -110,7 +110,9 @@ class CategoryV2ListAdapter( val sortSize = mViewModel.sortSize.text val exposureSources = ArrayList() - mViewModel.exposureSource?.let { exposureSources.add(it) } + if (!mViewModel.exposureSourceList.isNullOrEmpty()) { + exposureSources.addAll(mViewModel.exposureSourceList!!) + } exposureSources.add(ExposureSource("分类", categoryTitle)) exposureSources.add(ExposureSource(selectedCategoryName)) exposureSources.add(ExposureSource("二级分类详情", "$selectedSubCatalogName+$sortType+$sortSize")) diff --git a/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListFragment.kt b/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListFragment.kt index c0ba61b88f..dee785e6b3 100644 --- a/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListFragment.kt @@ -4,9 +4,7 @@ import android.os.Bundle import android.view.View import android.view.ViewGroup import com.ethanhua.skeleton.Skeleton -import com.gh.gamecenter.common.constant.Constants import com.gh.common.exposure.ExposureListener -import com.gh.common.util.* import com.gh.common.util.DialogUtils import com.gh.common.view.CategoryFilterView import com.gh.common.xapk.XapkInstaller @@ -14,6 +12,7 @@ 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.common.constant.Constants import com.gh.gamecenter.common.constant.EntranceConsts import com.gh.gamecenter.common.utils.* import com.gh.gamecenter.databinding.FragmentCategoryListBinding @@ -57,7 +56,7 @@ class CategoryV2ListFragment : ListFragment viewModelProvider(CategoryV2ListViewModel.Factory( mCategoryId, mSubCategoryId, - arguments?.getParcelable(EntranceConsts.KEY_EXPOSURE_SOURCE))) + arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST))) override fun provideListAdapter() = mAdapter ?: CategoryV2ListAdapter( diff --git a/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListViewModel.kt b/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListViewModel.kt index 10c19a6b3b..afc2bce771 100644 --- a/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/category2/CategoryV2ListViewModel.kt @@ -20,7 +20,7 @@ import io.reactivex.Single class CategoryV2ListViewModel(application: Application, val categoryId: String, var categoryIds: String, - var exposureSource: ExposureSource?) : ListViewModel(application) { + var exposureSourceList: List?) : ListViewModel(application) { val refresh = MutableLiveData() @@ -85,13 +85,13 @@ class CategoryV2ListViewModel(application: Application, } } - class Factory(val categoryId: String, val categoryIds: String, val exposureSource: ExposureSource?): ViewModelProvider.NewInstanceFactory() { + class Factory(val categoryId: String, val categoryIds: String, val exposureSourceList: List?): ViewModelProvider.NewInstanceFactory() { override fun create(modelClass: Class): T { return CategoryV2ListViewModel( HaloApp.getInstance().application, categoryId, categoryIds, - exposureSource + exposureSourceList ) as T } } diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailContentCardContentAdapter.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailContentCardContentAdapter.kt new file mode 100644 index 0000000000..70a10a569e --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailContentCardContentAdapter.kt @@ -0,0 +1,46 @@ +package com.gh.gamecenter.gamedetail + +import android.content.Context +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.gh.gamecenter.R +import com.gh.gamecenter.common.utils.safelyGetInRelease +import com.gh.gamecenter.common.utils.toBinding +import com.gh.gamecenter.common.utils.toColor +import com.gh.gamecenter.core.utils.TimeUtils +import com.gh.gamecenter.databinding.ItemGameDetailContentCardContentBinding +import com.gh.gamecenter.gamedetail.entity.ContentCardEntity +import com.lightgame.adapter.BaseRecyclerAdapter + +class GameDetailContentCardContentAdapter(context: Context, private val linkEntity: ContentCardEntity, private val isHighlightBg: Boolean = false): BaseRecyclerAdapter(context) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder = GameDetailContentCardContentItemViewHolder(parent.toBinding()) + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is GameDetailContentCardContentItemViewHolder) { + holder.binding.root.setTextColor(if (isHighlightBg) R.color.text_subtitle.toColor(mContext) else R.color.text_subtitleDesc.toColor(mContext)) + if (linkEntity.type == "func_server" && linkEntity.server != null && linkEntity.server?.calendar?.isNotEmpty() == true) { + val calendarList = linkEntity.server!!.calendar.take(10) + val realPosition = position % calendarList.size + calendarList.safelyGetInRelease(realPosition)?.let { + val serverTime = + if (TimeUtils.isToday(it.getTime())) + it.getFormatTime("今天 HH:mm") + else if (TimeUtils.isTomorrow(it.getTime())) + it.getFormatTime("明天 HH:mm") + else + it.getFormatTime("MM-dd HH:mm") + val serverText = "$serverTime ${it.remark}" + holder.binding.root.text = serverText + } + } + if (linkEntity.type == "func_libao" && linkEntity.libao != null) { + holder.binding.root.text = "${linkEntity.libao!!.total}个游戏礼包" + } + } + } + + override fun getItemCount(): Int = Int.MAX_VALUE + + class GameDetailContentCardContentItemViewHolder(var binding: ItemGameDetailContentCardContentBinding) : RecyclerView.ViewHolder(binding.root) +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt index 5804ea8272..242f470faa 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt @@ -1,19 +1,22 @@ package com.gh.gamecenter.gamedetail +import android.animation.Animator +import android.animation.ValueAnimator import android.annotation.SuppressLint import android.content.Intent import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color import android.graphics.drawable.GradientDrawable -import android.os.Build -import android.os.Bundle +import android.os.* import android.text.SpannableStringBuilder import android.text.Spanned import android.text.TextUtils import android.view.* +import android.view.animation.AccelerateDecelerateInterpolator import android.widget.FrameLayout import android.widget.ImageView +import android.widget.LinearLayout import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.widget.ConstraintLayout @@ -23,11 +26,13 @@ import androidx.core.view.children import androidx.core.widget.TextViewCompat import androidx.fragment.app.Fragment import androidx.lifecycle.Observer +import androidx.viewpager2.widget.ViewPager2 import com.ethanhua.skeleton.Skeleton import com.ethanhua.skeleton.ViewSkeletonScreen import com.gh.common.constant.Config import com.gh.common.databind.BindingAdapters import com.gh.common.exposure.ExposureEvent +import com.gh.common.exposure.ExposureSource import com.gh.common.repository.ReservationRepository import com.gh.common.simulator.SimulatorGameManager import com.gh.common.util.* @@ -57,8 +62,10 @@ import com.gh.gamecenter.gamedetail.desc.DescFragment import com.gh.gamecenter.gamedetail.dialog.GameBigEventDialog import com.gh.gamecenter.gamedetail.dialog.GameDetailMoreDialog import com.gh.gamecenter.gamedetail.dialog.GameTagsDialog +import com.gh.gamecenter.gamedetail.entity.ContentCardEntity import com.gh.gamecenter.gamedetail.entity.NewGameDetailEntity import com.gh.gamecenter.gamedetail.fuli.FuLiFragment +import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersCalendarActivity import com.gh.gamecenter.gamedetail.rating.RatingFragment import com.gh.gamecenter.gamedetail.video.TopVideoView import com.gh.gamecenter.home.video.ScrollCalculatorHelper @@ -84,6 +91,7 @@ import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import retrofit2.HttpException +import java.lang.ref.WeakReference import java.util.* import kotlin.math.abs @@ -116,6 +124,8 @@ class GameDetailFragment : ToolbarFragment(), IScrollable { private var mRecommendDisposable: Disposable? = null private var mRecommendPopupEntity: RecommendPopupEntity? = null private var mTabClickEvent: Pair = Pair(0L, "") + private var mContentCardServerVp: ViewPager2? = null + private var mContentCardLibaoVp: ViewPager2? = null private lateinit var mBinding: FragmentGamedetailBinding private lateinit var mVideoBinding: PieceGameDetailVideoBinding @@ -129,6 +139,9 @@ class GameDetailFragment : ToolbarFragment(), IScrollable { private val mFragmentsList = ArrayList() private val mTabTitleList = ArrayList() + private val mLooperHandle = LooperHandle(this) + private val mServerLooperKey = 123 + private val mLibaoLooperKey = 124 private val dataWatcher = object : DataWatcher() { override fun onDataChanged(downloadEntity: DownloadEntity) { @@ -203,6 +216,66 @@ class GameDetailFragment : ToolbarFragment(), IScrollable { mTraceEvent ) + private val contentCardClick: (contentCard: ContentCardEntity) -> Unit = { contentCardEntity -> + NewFlatLogUtils.logGameDetailGameContentCardClick(contentCardEntity.title ?: "", mGameEntity?.name ?: "", mGameEntity?.id ?: "", contentCardEntity.type ?: "", contentCardEntity.link ?: "", contentCardEntity.text ?: "") + when (contentCardEntity.type) { + "func_server" -> { + if (contentCardEntity.server != null) { + requireContext().startActivity( + ServersCalendarActivity.getIntent( + requireContext(), + mViewModel.game!!, contentCardEntity.server!!, + mNewGameDetailEntity?.me + ) + ) + } + } + "func_libao" -> { + tabPerformClick(0) + mBodyBinding.gamedetailAppbar.setExpanded(false, true) + val fragment = mFragmentsList[0] + if (fragment is DescFragment && fragment.isAdded) { + fragment.scrollToLibao() + } + } + "func_related_version" -> { + tabPerformClick(0) + mBodyBinding.gamedetailAppbar.setExpanded(false, true) + val fragment = mFragmentsList[0] + if (fragment is DescFragment && fragment.isAdded) { + fragment.scrollToRelatedVersion() + } + } + "func_zone" -> { + val gameDetailEntity = mViewModel.gameDetailLiveData.value?.data + if (contentCardEntity.zoneTab && gameDetailEntity?.zone != null && gameDetailEntity.zone!!.style == "link") { + requireContext().startActivity(WebActivity.getIntent(requireContext(), gameDetailEntity.zone!!.link, true)) + } + } + "func_tool_kit" -> { + if (contentCardEntity.toolkit.isNotEmpty()) { + contentCardEntity.toolkit.safelyGetInRelease(0)?.let { + val url = it.url + if (url != null && url.contains(Config.URL_ARTICLE)) { + val newsId = url.substring(url.lastIndexOf("/") + 1, url.length - 5) // 5: ".html" + val intent = NewsDetailActivity.getIntentById(requireContext(), newsId, "游戏详情->内容卡片") + requireContext().startActivity(intent) + } else { + requireContext().startActivity( + WebActivity.getWebByCollectionTools( + requireContext(), + it, + false + ) + ) + } + } + } + } + else -> DirectUtils.directToLinkPage(requireContext(), contentCardEntity.toLinkEntity(), mEntrance, "游戏详情->内容卡片", ExposureEvent.createEvent(null, listOf(ExposureSource("游戏详情", mGameEntity?.id ?: ""), ExposureSource("内容卡片", contentCardEntity.id)))) + } + } + override fun getLayoutId(): Int = 0 override fun getInflatedLayout(): View { @@ -443,7 +516,7 @@ class GameDetailFragment : ToolbarFragment(), IScrollable { var changeDisplayName = false if ((lineCount == 2 && layout.getEllipsisCount(1) > 0) || (lineCount == 2 && tagView.measuredWidth > remainWidth)) { val textCount = calculateTextCountByWidth(this, 2 * gameTitleTv.width - tagView.measuredWidth) - 1 - if (textCount < text.length) { + if (textCount in text.indices) { displayName = text.substring(0, textCount) + "…" changeDisplayName = true } @@ -576,6 +649,11 @@ class GameDetailFragment : ToolbarFragment(), IScrollable { showAlertDialogIfNeeded(data) initViewPage(data) + + if (data.contentCard.size > 1) { + initGameContentCard(data.contentCard) + } + updateGameDetailTopArea() val viewHolder = detailViewHolder @@ -701,6 +779,9 @@ class GameDetailFragment : ToolbarFragment(), IScrollable { mTabTitleList.add(getString(R.string.game_detail_desc)) data.zone?.let { + data.contentCard.forEach { contentCard -> + if (data.contentCard.size > 1 && contentCard.type == "func_zone") return@let + } if (it.style == "link") {//显示web页面 val webFragment = childFragmentManager.findFragmentByTag("${tag}${INDEX_TRENDES}") ?: WebFragment() val webBundle = Bundle() @@ -959,6 +1040,103 @@ class GameDetailFragment : ToolbarFragment(), IScrollable { } } + private fun initGameContentCard(linkEntityList: List) { + mBodyBinding.contentCardContainer.removeAllViews() + mBodyBinding.contentCardContainer.visibility = View.VISIBLE + if (linkEntityList.size >= 3) { + linkEntityList.safelyGetInRelease(0)?.let { + mBodyBinding.contentCardContainer.addView(getLargeContentCardView(it, true), LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 2F)) + } + linkEntityList.safelyGetInRelease(1)?.let { + mBodyBinding.contentCardContainer.addView(getSmallContentCardView(it), LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1F)) + } + linkEntityList.safelyGetInRelease(2)?.let { + mBodyBinding.contentCardContainer.addView(getSmallContentCardView(it, true), LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1F)) + } + } else if (linkEntityList.size == 2) { + linkEntityList.safelyGetInRelease(0)?.let { + mBodyBinding.contentCardContainer.addView(getLargeContentCardView(it), LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1F)) + } + linkEntityList.safelyGetInRelease(1)?.let { + mBodyBinding.contentCardContainer.addView(getLargeContentCardView(it, isLastView = true), LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1F)) + } + } + } + + private fun getLargeContentCardView(contentCardEntity: ContentCardEntity, isHighlightBg: Boolean = false, isLastView: Boolean = false) = LayoutGameDetailContentCardLargeBinding.inflate(layoutInflater).apply { + when { + isHighlightBg && !isLastView -> backgroundIv.setImageDrawable(R.drawable.bg_content_card_large_primary.toDrawable(requireContext())) + !isHighlightBg && !isLastView -> backgroundIv.setImageDrawable(R.drawable.bg_content_card_large.toDrawable(requireContext())) + !isHighlightBg && isLastView -> backgroundIv.setImageDrawable(R.drawable.bg_content_card_large_right.toDrawable(requireContext())) + } + spaceStart.layoutParams = spaceStart.layoutParams.apply { width = if (isLastView) 20F.dip2px() else 12F.dip2px()} + spaceEnd.layoutParams = spaceEnd.layoutParams.apply { width = if (isLastView) 8F.dip2px() else 12F.dip2px()} + titleTv.text = contentCardEntity.title + ImageUtils.display(iconIv, contentCardEntity.icon) + if (contentCardEntity.des.isNotEmpty()) { + contentTv.visibility = View.VISIBLE + contentVp.visibility = View.GONE + contentTv.text = contentCardEntity.des + contentTv.setTextColor(if (isHighlightBg) R.color.text_subtitle.toColor(requireContext()) else R.color.text_subtitleDesc.toColor(requireContext())) + } else if (contentCardEntity.type == "func_server" || contentCardEntity.type == "func_libao") { + contentTv.visibility = View.GONE + contentVp.visibility = View.VISIBLE + if (contentCardEntity.type == "func_server") mContentCardServerVp = contentVp else mContentCardLibaoVp = contentVp + contentVp.run { + isUserInputEnabled = false + orientation = ViewPager2.ORIENTATION_VERTICAL + adapter = GameDetailContentCardContentAdapter(requireContext(), contentCardEntity, isHighlightBg) + startAutoPlay(if (contentCardEntity.type == "func_server") mServerLooperKey else mLibaoLooperKey) + } + } + redDotTv.goneIf(!(contentCardEntity.type == "func_server" || contentCardEntity.type == "func_libao")) + if ((contentCardEntity.type == "func_server") && (contentCardEntity.server?.calendar?.isNotEmpty() == true)) redDotTv.text = contentCardEntity.server?.calendar?.size.toString() + if ((contentCardEntity.type == "func_libao") && (contentCardEntity.libao != null)) redDotTv.text = contentCardEntity.libao?.total.toString() + root.setOnClickListener { + contentCardClick.invoke(contentCardEntity) + } + }.root + + private fun getSmallContentCardView(contentCardEntity: ContentCardEntity, isLastView: Boolean = false) = LayoutGameDetailContentCardSmallBinding.inflate(layoutInflater).apply { + backgroundIv.setImageDrawable(if (isLastView) R.drawable.bg_content_card_small_right.toDrawable(requireContext()) else R.drawable.bg_content_card_small.toDrawable(requireContext())) + titleTv.text = contentCardEntity.title + ImageUtils.display(iconIv, contentCardEntity.icon) + redDotTv.goneIf(!(contentCardEntity.type == "func_server" || contentCardEntity.type == "func_libao")) + if ((contentCardEntity.type == "func_server") && (contentCardEntity.server?.calendar?.isNotEmpty() == true)) redDotTv.text = contentCardEntity.server?.calendar?.size.toString() + if ((contentCardEntity.type == "func_libao") && (contentCardEntity.libao != null)) redDotTv.text = contentCardEntity.libao?.total.toString() + root.setOnClickListener { + contentCardClick.invoke(contentCardEntity) + } + }.root + + private fun scrollToNextContent(viewPager: ViewPager2? = null) { + viewPager?.run { + val pxToDrag: Int = height + val animator = ValueAnimator.ofInt(0, pxToDrag) + var previousValue = 0 + animator.addUpdateListener { valueAnimator -> + val currentValue = valueAnimator.animatedValue as Int + val currentPxToDrag = (currentValue - previousValue).toFloat() + fakeDragBy(-currentPxToDrag) + previousValue = currentValue + } + animator.addListener(object : Animator.AnimatorListener { + override fun onAnimationStart(animation: Animator?) { beginFakeDrag() } + override fun onAnimationEnd(animation: Animator?) { endFakeDrag() } + override fun onAnimationCancel(animation: Animator?) { } + override fun onAnimationRepeat(animation: Animator?) { } + }) + animator.interpolator = AccelerateDecelerateInterpolator() + animator.duration = 1000 + animator.start() + } + } + + private fun startAutoPlay(key: Int) { + mLooperHandle.removeMessages(key) + mLooperHandle.sendEmptyMessageDelayed(key, CONTENT_CARD_LOOP_TIME) + } + private fun setUpTopVideo(topVideo: GameDetailEntity.Video) { GSYVideoOptionBuilder() .setIsTouchWigetFull(false) @@ -1643,6 +1821,11 @@ class GameDetailFragment : ToolbarFragment(), IScrollable { } mBinding.detailLlBottom.detailLlBottom.setBackgroundColor(R.color.background.toColor(requireContext())) updateToolbarStyle(mBodyBinding.gamedetailThumbSmall.visibility == View.VISIBLE) + mViewModel.gameDetailLiveData.value?.data?.let { + if (it.contentCard.size > 1) { + initGameContentCard(it.contentCard) + } + } } override fun scrollToTop() { @@ -1667,8 +1850,27 @@ class GameDetailFragment : ToolbarFragment(), IScrollable { const val SCROLL_TO_KAIFU = "scrollToKaiFu" const val EB_SCROLLING = "EB_SCROLLING" const val INITIAL_DELAY = 500L + const val CONTENT_CARD_LOOP_TIME = 3000L private const val SP_OPENED_DIALOG_TIME_PREFIX = "opened_dialog_time_prefix_" private const val LAST_SELECTED_POSITION = "last_selected_position" } + + class LooperHandle(fragment: GameDetailFragment): Handler( + Looper.getMainLooper()) { + private val mWeakReference: WeakReference = WeakReference(fragment) + + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + val fragment = mWeakReference.get() + if (fragment != null) { + if (msg.what == fragment.mServerLooperKey) { + fragment.scrollToNextContent(fragment.mContentCardServerVp) + } else if (msg.what == fragment.mLibaoLooperKey) { + fragment.scrollToNextContent(fragment.mContentCardLibaoVp) + } + fragment.startAutoPlay(msg.what) + } + } + } } diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailViewModel.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailViewModel.kt index a86ba4a5fd..7a7e4410c3 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailViewModel.kt @@ -127,6 +127,18 @@ class GameDetailViewModel(application: Application, // 4.4以下设备不显示顶部视频 displayTopVideo = data.topVideo != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT + + data.contentCard.forEach { + if (data.contentCard.size > 1 && it.type == "func_server") { + data.detailEntity.forEach detail@{ detailEntity -> + if (detailEntity.type == DetailEntity.Type.LATEST_SERVER.value) { + data.detailEntity.remove(detailEntity) + return@detail + } + } + } + } + gameDetailLiveData.postValue(Resource.success(data)) if (CheckLoginUtils.isLogin()) { getUserRelatedInfo(data) diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescAdapter.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescAdapter.kt index ab25b5c479..8c2186c235 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescAdapter.kt @@ -26,15 +26,14 @@ import com.gh.common.databind.BindingAdapters import com.gh.common.exposure.ExposureEvent import com.gh.common.exposure.ExposureManager import com.gh.common.exposure.ExposureSource +import com.gh.common.util.* import com.gh.common.util.DialogUtils -import com.gh.common.util.DirectUtils import com.gh.common.util.LogUtils import com.gh.common.util.NewLogUtils import com.gh.gamecenter.GameNewsActivity import com.gh.gamecenter.R import com.gh.gamecenter.SuggestionActivity import com.gh.gamecenter.adapter.viewholder.FooterViewHolder -import com.gh.gamecenter.common.base.activity.BaseActivity import com.gh.gamecenter.common.callback.OnListClickListener import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.common.utils.* @@ -966,8 +965,11 @@ class DescAdapter( } } - class GameDetailCustomColumnViewHolder(var binding: GamedetailItemCustomColumnBinding, handler: Handler) : - ExposureViewHolder(binding.root, handler) + inner class GameDetailCustomColumnViewHolder(var binding: GamedetailItemCustomColumnBinding, handler: Handler) : ExposureViewHolder(binding.root, handler) { + override fun exposureLog() { + NewFlatLogUtils.logGameDetailColumnOrderingView(binding.titleTv.text.toString(), mViewModel.game?.name ?: "", mViewModel.game?.id ?: "") + } + } class GameDetailRelatedVersionViewHolder(var binding: GameGalleryListBinding, handler: Handler) : ExposureViewHolder(binding.root, handler) class GameVideoGalleryViewHolder(var binding: GameGalleryListBinding, handler: Handler) : ExposureViewHolder(binding.root, handler) diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescFragment.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescFragment.kt index 63941da7c3..679fa5e95f 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescFragment.kt @@ -270,6 +270,18 @@ class DescFragment : BaseFragment(), IScrollable { } } + fun scrollToRelatedVersion() { + if (mViewModel.getRelatedVersionPosition() != -1) { + mLayoutManager?.scrollToPositionWithOffset(mViewModel.getRelatedVersionPosition(), 0) + } + } + + fun scrollToLibao() { + if (mViewModel.getDetailLibaoPosition() != -1) { + mLayoutManager?.scrollToPositionWithOffset(mViewModel.getDetailLibaoPosition(), 0) + } + } + override fun onNightModeChange() { super.onNightModeChange() mBinding.recyclerview.setBackgroundColor(R.color.background.toColor(requireContext())) diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescViewModel.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescViewModel.kt index e9c4784768..b2eb183847 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescViewModel.kt @@ -43,6 +43,8 @@ class DescViewModel(application: Application, private var mGameInfoPosition = 0 private var mLibaoPosition = -1 private var mServerPosition = -1 + private var mDetailLibaoPosition = -1 + private var mRelatedVersionPosition = -1 private var mGameInfo: GameInfo? = null var list = MutableLiveData>() @@ -360,6 +362,15 @@ class DescViewModel(application: Application, } } + for ((index, entity) in detailEntityList.withIndex()) { + if (entity.libao != null) { + mDetailLibaoPosition = index + } + if (entity.relatedVersion != null) { + mRelatedVersionPosition = index + } + } + if (containsFirstTimeExpandCustomColumnTags) { SPUtils.setBoolean(Constants.SP_HAS_EXPANDED_GAME_DETAIL_TAGS, true) } @@ -375,6 +386,10 @@ class DescViewModel(application: Application, fun getGameInfoPosition() = mGameInfoPosition + fun getDetailLibaoPosition() = mDetailLibaoPosition + + fun getRelatedVersionPosition() = mRelatedVersionPosition + fun getGameInfo() = mGameInfo /** diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/entity/ContentCardEntity.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/entity/ContentCardEntity.kt new file mode 100644 index 0000000000..21f1485e49 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/entity/ContentCardEntity.kt @@ -0,0 +1,69 @@ +package com.gh.gamecenter.gamedetail.entity + +import com.gh.gamecenter.entity.* +import com.google.gson.annotations.SerializedName + +data class ContentCardEntity( + @SerializedName("_id") + var id: String = "", + var name: String? = "", // tag + var title: String? = "", + var image: String? = "", + @SerializedName("target", alternate = ["link", "link_id"]) + var link: String? = "", + @SerializedName("type", alternate = ["link_type"]) + var type: String? = "", + var icon: String = "", + @SerializedName("game_icon") + var gameIcon: String? = "", + @SerializedName("game_icon_subscript") + var gameIconSubscript: String? = "", + var text: String? = "", + @SerializedName("link_text") + var linkText: String? = "",//游戏详情弹窗,兼容旧版本用 + var value: String? = "", + @SerializedName("community_id") + var communityId: String? = "", + @SerializedName("link_community", alternate = ["community"]) + var community: CommunityEntity? = CommunityEntity(), + var display: Display? = null, // 板块 + @SerializedName("close_button") + var closeButton: String = "open",//用户判断h5游戏关闭按钮是否显示,hide(隐藏)、open(开启) + @SerializedName("button_link") + var buttonLink: Boolean = false, + @SerializedName("activity_id") + var activityId: String = "", + var style: String = "", + + var des: String = "", + var server: GameDetailServer? = null, + var libao: LibaoEntity? = null, + @SerializedName("zone_tab") + var zoneTab: Boolean = false, + @SerializedName("related_version") + var relatedVersion: Boolean = false, + var toolkit: ArrayList = ArrayList() +) { + fun toLinkEntity(): LinkEntity { + return LinkEntity( + name = name, + title = title, + image = image, + link = link, + type = type, + icon = icon, + gameIcon = gameIcon, + gameIconSubscript = gameIconSubscript, + text = text, + linkText = linkText, + value = value, + communityId = communityId, + community = community, + display = display, + closeButton = closeButton, + buttonLink = buttonLink, + activityId = activityId, + style = style + ) + } +} diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/entity/NewGameDetailEntity.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/entity/NewGameDetailEntity.kt index 1bdd9cb435..bcd5b27511 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/entity/NewGameDetailEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/entity/NewGameDetailEntity.kt @@ -45,7 +45,9 @@ data class NewGameDetailEntity( @SerializedName("bbs_tab") var bbsTab: LinkEntity? = null, @SerializedName("certification_tag") - var certificateTag: Screenshot? = null + var certificateTag: Screenshot? = null, + @SerializedName("content_card") + var contentCard: ArrayList = ArrayList() ) @Keep diff --git a/app/src/main/java/com/gh/gamecenter/subject/SubjectAdapter.kt b/app/src/main/java/com/gh/gamecenter/subject/SubjectAdapter.kt index e2943488dc..a65df62988 100644 --- a/app/src/main/java/com/gh/gamecenter/subject/SubjectAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/subject/SubjectAdapter.kt @@ -312,7 +312,9 @@ class SubjectAdapter( private fun generateExposureEvent(gameEntity: GameEntity, subjectStyle: String, isFilterOn: Boolean): ExposureEvent { val exposureSourceList = arrayListOf() - mViewModel.exposureSource?.let { exposureSourceList.add(it) } + if (!mViewModel.exposureSourceList.isNullOrEmpty()) { + exposureSourceList.addAll(mViewModel.exposureSourceList!!) + } if (mIsColumnCollection) { exposureSourceList.add(ExposureSource("排行榜")) exposureSourceList.add(ExposureSource("专题", subjectData.subjectName.toString())) diff --git a/app/src/main/java/com/gh/gamecenter/subject/SubjectListFragment.kt b/app/src/main/java/com/gh/gamecenter/subject/SubjectListFragment.kt index 7fabb2fdb1..9642304e6a 100644 --- a/app/src/main/java/com/gh/gamecenter/subject/SubjectListFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/subject/SubjectListFragment.kt @@ -77,7 +77,7 @@ class SubjectListFragment : LazyListFragment() val factory = SubjectListViewModel.Factory( HaloApp.getInstance().application, arguments?.getParcelable(EntranceConsts.KEY_SUBJECT_DATA)!!, - arguments?.getParcelable(EntranceConsts.KEY_EXPOSURE_SOURCE)) + arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)) if (requireContext() is SubjectActivity) { requireActivity().intent.getParcelableExtra(EntranceConsts.KEY_SUBJECT_DATA)?.let { val f = SubjectViewModel.Factory(HaloApp.getInstance().application, it) diff --git a/app/src/main/java/com/gh/gamecenter/subject/SubjectListViewModel.kt b/app/src/main/java/com/gh/gamecenter/subject/SubjectListViewModel.kt index 9016c9b951..f74d606fcb 100644 --- a/app/src/main/java/com/gh/gamecenter/subject/SubjectListViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/subject/SubjectListViewModel.kt @@ -23,7 +23,7 @@ import retrofit2.HttpException class SubjectListViewModel(application: Application, var subjectData: SubjectData, - var exposureSource: ExposureSource?) : ListViewModel(application) { + var exposureSourceList: List?) : ListViewModel(application) { // 供专题类型为 rows 时统计用 var selectedLabelList = arrayListOf() @@ -104,9 +104,9 @@ class SubjectListViewModel(application: Application, } } - class Factory(private val mApplication: Application, private val subjectData: SubjectData, private val exposureSource: ExposureSource? = null) : ViewModelProvider.NewInstanceFactory() { + class Factory(private val mApplication: Application, private val subjectData: SubjectData, private val exposureSourceList: List? = null) : ViewModelProvider.NewInstanceFactory() { override fun create(modelClass: Class): T { - return SubjectListViewModel(mApplication, subjectData, exposureSource) as T + return SubjectListViewModel(mApplication, subjectData, exposureSourceList) as T } } diff --git a/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_large.webp b/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_large.webp new file mode 100644 index 0000000000..9f0fe20aa9 Binary files /dev/null and b/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_large.webp differ diff --git a/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_large_primary.webp b/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_large_primary.webp new file mode 100644 index 0000000000..f36369f729 Binary files /dev/null and b/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_large_primary.webp differ diff --git a/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_large_right.webp b/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_large_right.webp new file mode 100644 index 0000000000..18c3726129 Binary files /dev/null and b/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_large_right.webp differ diff --git a/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_small.webp b/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_small.webp new file mode 100644 index 0000000000..6c0308686d Binary files /dev/null and b/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_small.webp differ diff --git a/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_small_right.webp b/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_small_right.webp new file mode 100644 index 0000000000..b287b70b8f Binary files /dev/null and b/app/src/main/res/drawable-night-xxxhdpi/bg_content_card_small_right.webp differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_content_card_large.webp b/app/src/main/res/drawable-xxxhdpi/bg_content_card_large.webp new file mode 100644 index 0000000000..3df87fcc26 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/bg_content_card_large.webp differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_content_card_large_primary.webp b/app/src/main/res/drawable-xxxhdpi/bg_content_card_large_primary.webp new file mode 100644 index 0000000000..1495b00358 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/bg_content_card_large_primary.webp differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_content_card_large_right.webp b/app/src/main/res/drawable-xxxhdpi/bg_content_card_large_right.webp new file mode 100644 index 0000000000..00667c8ce2 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/bg_content_card_large_right.webp differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_content_card_small.webp b/app/src/main/res/drawable-xxxhdpi/bg_content_card_small.webp new file mode 100644 index 0000000000..c067ffd380 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/bg_content_card_small.webp differ diff --git a/app/src/main/res/drawable-xxxhdpi/bg_content_card_small_right.webp b/app/src/main/res/drawable-xxxhdpi/bg_content_card_small_right.webp new file mode 100644 index 0000000000..ae0417fe79 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/bg_content_card_small_right.webp differ diff --git a/app/src/main/res/drawable/bg_hint_red_radius_999.xml b/app/src/main/res/drawable/bg_hint_red_radius_999.xml new file mode 100644 index 0000000000..f9c6f807c0 --- /dev/null +++ b/app/src/main/res/drawable/bg_hint_red_radius_999.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/gamedetail_body.xml b/app/src/main/res/layout/gamedetail_body.xml index d731de90e6..a1e2b50e0d 100644 --- a/app/src/main/res/layout/gamedetail_body.xml +++ b/app/src/main/res/layout/gamedetail_body.xml @@ -223,6 +223,16 @@ tools:text="游戏大事件游戏大事件" tools:visibility="visible" /> + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_game_detail_content_card_large.xml b/app/src/main/res/layout/layout_game_detail_content_card_large.xml new file mode 100644 index 0000000000..f3b249d5b3 --- /dev/null +++ b/app/src/main/res/layout/layout_game_detail_content_card_large.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_game_detail_content_card_small.xml b/app/src/main/res/layout/layout_game_detail_content_card_small.xml new file mode 100644 index 0000000000..a878f69ec8 --- /dev/null +++ b/app/src/main/res/layout/layout_game_detail_content_card_small.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/module_common/src/main/java/com/gh/gamecenter/common/constant/EntranceConsts.java b/module_common/src/main/java/com/gh/gamecenter/common/constant/EntranceConsts.java index c66deae246..dcf7feef6f 100644 --- a/module_common/src/main/java/com/gh/gamecenter/common/constant/EntranceConsts.java +++ b/module_common/src/main/java/com/gh/gamecenter/common/constant/EntranceConsts.java @@ -202,6 +202,7 @@ public class EntranceConsts { public static final String KEY_CONFLICT_PHONE = "conflictPhone"; public static final String KEY_CONFLICT_USER = "conflictUser"; public static final String KEY_EXPOSURE_SOURCE = "exposure_source"; + public static final String KEY_EXPOSURE_SOURCE_LIST = "exposure_source_list"; public static final String KEY_BBS_ID = "bbs_id"; public static final String KEY_DIAGNOSIS = "diagnosis"; public static final String KEY_SIMULATOR = "simulator"; diff --git a/module_core/src/main/java/com/gh/gamecenter/core/utils/TimeUtils.kt b/module_core/src/main/java/com/gh/gamecenter/core/utils/TimeUtils.kt index ebe195fc93..ee11a81c11 100644 --- a/module_core/src/main/java/com/gh/gamecenter/core/utils/TimeUtils.kt +++ b/module_core/src/main/java/com/gh/gamecenter/core/utils/TimeUtils.kt @@ -66,6 +66,18 @@ object TimeUtils { return false } + //判断是不是明天 + fun isTomorrow(timestamp: Long): Boolean { + val format = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA) + format.timeZone = TimeZone.getTimeZone("Asia/Shanghai") + val today = format.parse(format.format(Date())).time + val day = timestamp * 1000 + if (day >= today + 86400 * 1000 && day < today + 86400 * 1000 * 2) { + return true + } + return false + } + //判断是不是本周 fun isThisWeek(timestamp: Long): Boolean { val calendar = Calendar.getInstance()