diff --git a/app/src/main/java/com/gh/common/constant/Constants.java b/app/src/main/java/com/gh/common/constant/Constants.java index 6c41de907c..cc033ba513 100644 --- a/app/src/main/java/com/gh/common/constant/Constants.java +++ b/app/src/main/java/com/gh/common/constant/Constants.java @@ -32,7 +32,7 @@ public class Constants { public static final String XPOSED_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer"; public static final String EB_QUIT_LOGIN = "quit_login"; - + public static final String EB_SHOW_AD = "show_ad"; // 用于避免历史下载影响到部分依赖名字作为数据更新条件的修饰符 @@ -70,7 +70,7 @@ public class Constants { public static final String SP_IMEI = "imei"; public static final String SP_ANDROID_ID = "android_id"; - + public static final String LAST_INSTALL_GAME = "last_install_game"; //引导设置 “通知管理” 引导弹窗 @@ -146,6 +146,11 @@ public class Constants { public static final String SP_XAPK_UNZIP_ACTIVITY = "xapk_unzip_activity"; public static final String SP_XAPK_URL = "xapk_url"; + //模拟器管理引导 + public static final String SP_SIMULATOR_GUIDE = "simulator_guide"; + //模拟器游戏引导 + public static final String SP_SIMULATOR_GAME_GUIDE = "simulator_game_guide"; + //首页视频播放进度 public static final String SP_HOME_VIDEO_PLAY_RECORD = "home_video_play_record"; diff --git a/app/src/main/java/com/gh/common/util/Extensions.kt b/app/src/main/java/com/gh/common/util/Extensions.kt index e07422f945..0678b272f6 100644 --- a/app/src/main/java/com/gh/common/util/Extensions.kt +++ b/app/src/main/java/com/gh/common/util/Extensions.kt @@ -4,6 +4,8 @@ import android.animation.Animator import android.content.ClipData import android.content.ClipboardManager import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas import android.graphics.drawable.GradientDrawable import android.os.Build import android.text.* @@ -942,4 +944,11 @@ fun singleToMain(): SingleTransformer { upstream.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) } +} + +fun View.getBitmapFromView(): Bitmap? { + val bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + this.draw(canvas) + return bitmap } \ 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 0b911039c1..1ba7db495d 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt @@ -1066,7 +1066,7 @@ class GameDetailFragment : NormalFragment() { if (mGameEntity != null && SimulatorGameManager.isSimulatorGame(mGameEntity!!)) { mReserveBtn.visibility = View.VISIBLE mReserveBtn.text = "管理" - mReserveBtn.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(requireContext(), R.drawable.ic_gamedetail_reserve), null, null) + mReserveBtn.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(requireContext(), R.drawable.ic_gamedetail_simulator_manage), null, null) return } diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameFragment.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameFragment.kt index d86487f55c..27490bd192 100644 --- a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameFragment.kt @@ -1,11 +1,17 @@ package com.gh.gamecenter.simulatorgame +import android.app.Dialog +import android.graphics.Color import android.graphics.Paint +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.ColorDrawable import android.os.Bundle +import android.view.Gravity +import android.view.LayoutInflater import android.view.MenuItem import android.view.View -import android.widget.LinearLayout -import android.widget.TextView +import android.widget.* +import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentStatePagerAdapter @@ -13,10 +19,15 @@ import androidx.lifecycle.Observer import androidx.viewpager.widget.PagerAdapter import androidx.viewpager.widget.ViewPager import com.gh.base.fragment.BaseFragment_TabLayout +import com.gh.common.AppExecutor +import com.gh.common.constant.Constants import com.gh.common.util.* import com.gh.common.util.DirectUtils.directToLinkPage +import com.gh.common.view.BugFixedPopupWindow import com.gh.common.view.TabIndicatorView import com.gh.gamecenter.R +import com.gh.gamecenter.databinding.DialogSimulaorGameGuideBinding +import com.gh.gamecenter.databinding.PopupSimulatorGuideBinding import com.gh.gamecenter.normal.NormalFragment import com.google.android.material.tabs.TabLayout import kotterknife.bindView @@ -39,7 +50,7 @@ class SimulatorGameFragment : NormalFragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - mViewModel = viewModelProvider() + mViewModel = viewModelProviderFromParent() } override fun onResume() { @@ -74,7 +85,10 @@ class SimulatorGameFragment : NormalFragment() { if (list.isEmpty()) { // 只剩一个tab然后删除了该tab所有游戏后刷新adapter mViewPager.adapter?.notifyDataSetChanged() - + if (mViewModel.isSimulatorGameFirstLoad) { + mViewModel.simulatorGameLoadSuccess.postValue(false) + mViewModel.isSimulatorGameFirstLoad = false + } mReuseNoData.visibility = View.VISIBLE AdHelper.getAdForLocation(AdHelper.LOCATION_SIMULATOR_GAME)?.let { ad -> mAdTv.run { @@ -93,8 +107,8 @@ class SimulatorGameFragment : NormalFragment() { list.forEachIndexed { index, entity -> mTabContainer.goneIf(list.size == 1) mTypeAliasList.add(entity.typeAlias) - mFragmentsList.add(childFragmentManager.findFragmentByTag("android:switcher:${mViewPager.id}:$index") ?: - SimulatorGameListFragment().apply { with(bundleOf(EntranceUtils.KEY_SIMULATOR to entity)) }) + mFragmentsList.add(childFragmentManager.findFragmentByTag("android:switcher:${mViewPager.id}:$index") + ?: SimulatorGameListFragment().apply { with(bundleOf(EntranceUtils.KEY_SIMULATOR to entity)) }) } if (mViewPager.adapter != null) { @@ -106,6 +120,11 @@ class SimulatorGameFragment : NormalFragment() { } } }) + mViewModel.simulatorGameLoadSuccess.observe(viewLifecycleOwner, Observer { + AppExecutor.uiExecutor.executeWithDelay(Runnable { + showSimulatorGuide(it) + },500) + }) } private fun initViewPager() { @@ -152,4 +171,69 @@ class SimulatorGameFragment : NormalFragment() { tab.customView = tabView } } + + private fun showSimulatorGuide(hasSimulatorGame: Boolean = false) { + val isSimulatorGuide = SPUtils.getBoolean(Constants.SP_SIMULATOR_GUIDE, false) + val isSimulatorGameGuide = SPUtils.getBoolean(Constants.SP_SIMULATOR_GAME_GUIDE, false) + + if (!isSimulatorGuide) { + val binding = PopupSimulatorGuideBinding.inflate(LayoutInflater.from(requireContext()), null, false) + val popupWindow = BugFixedPopupWindow(binding.root, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT) + popupWindow.apply { + isOutsideTouchable = false + isTouchable = true + isFocusable = false + } + (binding.simulatorGuideView.layoutParams as RelativeLayout.LayoutParams).apply { + topMargin = 50f.dip2px() + binding.simulatorGuideView.layoutParams = this + } + popupWindow.showAtLocation(requireActivity().window.decorView, Gravity.TOP, 0, 0) + binding.guideCloseIv.setOnClickListener { + SPUtils.setBoolean(Constants.SP_SIMULATOR_GUIDE, true) + popupWindow.dismiss() + if (hasSimulatorGame) { + showSimulatorGameGuide() + } + } + return + } + + if (!isSimulatorGameGuide) { + showSimulatorGameGuide() + } + } + + private fun showSimulatorGameGuide() { + if (mFragmentsList.isNullOrEmpty()) return + val simulatorGameListFragment = mFragmentsList[mCurrentPage] as SimulatorGameListFragment + val itemView = simulatorGameListFragment.getFirstItemView() ?: return + val location = IntArray(2) + itemView.getLocationInWindow(location) + val dialog = Dialog(requireContext(), R.style.DialogWindowTransparent) + val binding = DialogSimulaorGameGuideBinding.inflate(LayoutInflater.from(requireContext()), null, false) + dialog.setContentView(binding.root) + val bitmap = itemView.getBitmapFromView() + binding.simulatorGameSnapshot.setImageBitmap(bitmap) + (binding.snapshotContainer.layoutParams as RelativeLayout.LayoutParams).apply { + topMargin = location[1] - DisplayUtils.getStatusBarHeight(requireContext().resources) + binding.snapshotContainer.layoutParams = this + } + dialog.show() + val window = dialog.window + if (window != null) { + val params = window.attributes + params.width = requireContext().resources.displayMetrics.widthPixels + window.attributes = params + window.setGravity(Gravity.TOP) + } + + binding.root.setOnClickListener { + dialog.dismiss() + } + dialog.setOnDismissListener { + SPUtils.setBoolean(Constants.SP_SIMULATOR_GAME_GUIDE, true) + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListFragment.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListFragment.kt index 6a3e8aca8d..fdf5beab41 100644 --- a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListFragment.kt @@ -1,9 +1,11 @@ package com.gh.gamecenter.simulatorgame import android.os.Bundle +import android.view.View import com.gh.common.util.EntranceUtils import com.gh.common.util.safelyGetInRelease import com.gh.common.util.viewModelProvider +import com.gh.common.util.viewModelProviderFromParent import com.gh.download.DownloadManager import com.gh.gamecenter.baselist.ListFragment import com.gh.gamecenter.baselist.LoadType @@ -23,6 +25,7 @@ class SimulatorGameListFragment : ListFragment>() private val mSimulatorGameDao = AppDatabase.getInstance(HaloApp.getInstance()).simulatorGameDao() + var simulatorGameLoadSuccess = MutableLiveData() + var isSimulatorGameFirstLoad = true fun getSimulators() { val isNetworkConnected = NetworkUtils.isNetworkConnected(HaloApp.getInstance()) @@ -68,7 +70,7 @@ class SimulatorGameViewModel(application: Application) : AndroidViewModel(applic .compose(singleToMain()) .subscribe({ simulators.postValue(it) - },{ + }, { simulators.postValue(mResultSimulatorsList) it.printStackTrace() }) diff --git a/app/src/main/res/drawable-xhdpi/bg_simulator_guide.9.png b/app/src/main/res/drawable-xhdpi/bg_simulator_guide.9.png new file mode 100644 index 0000000000..b5e0cc2108 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/bg_simulator_guide.9.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_gamedetail_simulator_manage.webp b/app/src/main/res/drawable-xxhdpi/ic_gamedetail_simulator_manage.webp new file mode 100644 index 0000000000..411dbdc970 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_gamedetail_simulator_manage.webp differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_guide_line.png b/app/src/main/res/drawable-xxhdpi/ic_guide_line.png new file mode 100644 index 0000000000..580bef0c8e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_guide_line.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_simulator_game_detail.png b/app/src/main/res/drawable-xxhdpi/ic_simulator_game_detail.png new file mode 100644 index 0000000000..ea406dae9a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_simulator_game_detail.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_simulator_game_guide.png b/app/src/main/res/drawable-xxhdpi/ic_simulator_game_guide.png new file mode 100644 index 0000000000..1a55e6ffd5 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_simulator_game_guide.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_simulator_guide_close.png b/app/src/main/res/drawable-xxhdpi/ic_simulator_guide_close.png new file mode 100644 index 0000000000..739847849b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_simulator_guide_close.png differ diff --git a/app/src/main/res/layout/dialog_simulaor_game_guide.xml b/app/src/main/res/layout/dialog_simulaor_game_guide.xml new file mode 100644 index 0000000000..019395e904 --- /dev/null +++ b/app/src/main/res/layout/dialog_simulaor_game_guide.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popup_simulator_guide.xml b/app/src/main/res/layout/popup_simulator_guide.xml new file mode 100644 index 0000000000..4119b418f6 --- /dev/null +++ b/app/src/main/res/layout/popup_simulator_guide.xml @@ -0,0 +1,31 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popup_simulator_option_single.xml b/app/src/main/res/layout/popup_simulator_option_single.xml index 017fffd653..d8b88118e4 100644 --- a/app/src/main/res/layout/popup_simulator_option_single.xml +++ b/app/src/main/res/layout/popup_simulator_option_single.xml @@ -52,7 +52,7 @@ android:layout_width="14dp" android:layout_height="14dp" android:layout_marginLeft="13dp" - android:src="@drawable/ic_shortcut_simulator_blue" /> + android:src="@drawable/ic_simulator_game_detail" />