diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ee2dc85167..b0189bf029 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -27,6 +27,8 @@
+
+
+
+
+
+
{
+ dialog.dismiss();
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ intent.setData(Uri.parse("package:" + finalContext.getPackageName()));
+ finalContext.startActivity(intent);
+ });
+
+ contentView.findViewById(R.id.dialog_negative).setOnClickListener(v -> {
+ dialog.dismiss();
+ });
+
+ dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ dialog.setContentView(contentView);
+ dialog.show();
+ }
+
/**
* @param context may be is application context
* @return activity context
diff --git a/app/src/main/java/com/gh/common/util/DownloadObserver.kt b/app/src/main/java/com/gh/common/util/DownloadObserver.kt
index f757d78362..ab3e8e32dd 100644
--- a/app/src/main/java/com/gh/common/util/DownloadObserver.kt
+++ b/app/src/main/java/com/gh/common/util/DownloadObserver.kt
@@ -3,6 +3,7 @@ package com.gh.common.util
import android.content.pm.PackageManager
import android.os.Build
import android.preference.PreferenceManager
+import android.util.Log
import com.gh.base.BaseActivity
import com.gh.common.constant.Constants
import com.gh.common.exposure.ExposureUtils
@@ -107,6 +108,7 @@ object DownloadObserver {
}
}
if (DownloadStatus.done == downloadEntity.status) {
+ Log.i("LYRR", "d1")
if (downloadEntity.name.contains(mApplication.getString(R.string.app_name))) {
MtaHelper.onEvent("软件更新", "下载完成")
// 会有 ActivityNotFoundException 异常,catch 掉不管了
@@ -117,6 +119,7 @@ object DownloadObserver {
}
}
} else {
+ Log.i("LYRR", "d2")
statDoneEvent(downloadEntity)
val platform = PlatformUtils.getInstance(mApplication)
@@ -132,13 +135,17 @@ object DownloadObserver {
Utils.toast(mApplication, downloadEntity.name + " - 下载完成")
}
if (!downloadEntity.isPluggable) {
+ Log.i("LYRR", "d3")
if (downloadEntity.isSimulatorGame()) {
+ Log.i("LYRR", "d4")
val gameEntity = HaloApp.get(GameEntity::class.java.simpleName, true) as? GameEntity
if (gameEntity?.simulator != null) {
+ Log.i("LYRR", "d5")
val isInstalled = PackageUtils.isInstalled(HaloApp.getInstance().application, gameEntity.simulator!!.apk!!.packageName)
if (!isInstalled) {
SimulatorDownloadManager.getInstance().showDownloadDialog(AppManager.getInstance().currentActivity(), gameEntity.simulator)
}
+ Log.i("LYRR", "d6")
SimulatorGameManager.recordDownloadSimulatorGames(gameEntity.id)
}
} else {
diff --git a/app/src/main/java/com/gh/common/util/EntranceUtils.java b/app/src/main/java/com/gh/common/util/EntranceUtils.java
index 04e7b9e1d8..98241ecdca 100644
--- a/app/src/main/java/com/gh/common/util/EntranceUtils.java
+++ b/app/src/main/java/com/gh/common/util/EntranceUtils.java
@@ -212,6 +212,7 @@ public class EntranceUtils {
public static final String KEY_CONFLICT_PHONE = "conflictPhone";
public static final String KEY_CONFLICT_USER = "conflictUser";
public static final String KEY_BBS_ID = "bbs_id";
+ public static final String KEY_SIMULATOR = "simulator";
public static void jumpActivity(Context context, Bundle bundle) {
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
diff --git a/app/src/main/java/com/gh/common/util/PermissionHelper.kt b/app/src/main/java/com/gh/common/util/PermissionHelper.kt
index 0577383b73..2bb0abce77 100644
--- a/app/src/main/java/com/gh/common/util/PermissionHelper.kt
+++ b/app/src/main/java/com/gh/common/util/PermissionHelper.kt
@@ -8,6 +8,7 @@ import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.Settings
+import android.util.Log
import androidx.annotation.RequiresApi
import androidx.fragment.app.FragmentActivity
import com.tbruyelle.rxpermissions2.RxPermissions
@@ -177,6 +178,31 @@ object PermissionHelper {
}
}
+ @SuppressLint("CheckResult")
+ @JvmStatic
+ fun checkShortPermissionBeforeAction(context: Context) {
+ if (context is FragmentActivity) {
+ val rxPermission = RxPermissions(context)
+
+ tryWithDefaultCatch {
+ rxPermission
+ .requestEachCombined(Manifest.permission.INSTALL_SHORTCUT)
+ .subscribe { permission ->
+ Log.i("LYRR", "per = " + permission)
+ when {
+ permission.granted -> {
+ Log.i("LYRR", "granted")
+ }
+// permission.shouldShowRequestPermissionRationale -> { }
+ else -> {
+ DialogUtils.showShortCutPermissionDialog(context)
+ }
+ }
+ }
+ }
+ }
+ }
+
/**
* 跳转到权限设置
*
diff --git a/app/src/main/java/com/gh/common/util/ToastUtils.kt b/app/src/main/java/com/gh/common/util/ToastUtils.kt
index c8efd690cb..b1ec966bf4 100644
--- a/app/src/main/java/com/gh/common/util/ToastUtils.kt
+++ b/app/src/main/java/com/gh/common/util/ToastUtils.kt
@@ -56,4 +56,10 @@ object ToastUtils {
}
mOneTime = mTwoTime
}
+
+ fun toast(message: String) {
+ if (mToast != null) mToast?.cancel()
+ mToast = ToastHandler.INSTANCE.getToastInstance(HaloApp.getInstance().application, message, Toast.LENGTH_SHORT)
+ mToast?.show()
+ }
}
diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/SimulatorHeaderViewHolder.kt b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/SimulatorHeaderViewHolder.kt
new file mode 100644
index 0000000000..45c9a6fd48
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/SimulatorHeaderViewHolder.kt
@@ -0,0 +1,12 @@
+package com.gh.gamecenter.adapter.viewholder
+
+import android.view.View
+import android.widget.TextView
+import com.gh.base.BaseRecyclerViewHolder
+import com.gh.gamecenter.R
+import kotterknife.bindView
+
+class SimulatorHeaderViewHolder(view: View) : BaseRecyclerViewHolder(view) {
+ val managerBtn by bindView(R.id.btn_manager)
+ val simulatorBtn by bindView(R.id.btn_simulator)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/SimulatorManagementViewHolder.kt b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/SimulatorManagementViewHolder.kt
new file mode 100644
index 0000000000..502a10e3cb
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/SimulatorManagementViewHolder.kt
@@ -0,0 +1,12 @@
+package com.gh.gamecenter.adapter.viewholder
+
+import android.view.View
+import android.widget.TextView
+import com.gh.base.BaseRecyclerViewHolder
+import com.gh.gamecenter.R
+import kotterknife.bindView
+
+class SimulatorManagementViewHolder(view: View) : BaseRecyclerViewHolder(view) {
+ val simulatorName by bindView(R.id.simulator_name)
+ val simulatorInstallBtn by bindView(R.id.simulator_install_btn)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/entity/GameEntity.kt b/app/src/main/java/com/gh/gamecenter/entity/GameEntity.kt
index 5c6159b91b..fe92e0dad4 100644
--- a/app/src/main/java/com/gh/gamecenter/entity/GameEntity.kt
+++ b/app/src/main/java/com/gh/gamecenter/entity/GameEntity.kt
@@ -220,6 +220,8 @@ data class GameEntity(
var simulator: SimulatorEntity? = null,
@SerializedName("simulator_type")
var simulatorType: String = "",
+ @SerializedName("is_recently_played")
+ var isRecentlyPlayed: Boolean = false,
// 本地字段,使用镜像信息
var useMirrorInfo: Boolean = false,
diff --git a/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt b/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt
index 640c5ec854..dbc190674e 100644
--- a/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt
+++ b/app/src/main/java/com/gh/gamecenter/personal/PersonalFunctionAdapter.kt
@@ -25,6 +25,7 @@ import com.gh.gamecenter.message.MessageUnreadRepository
import com.gh.gamecenter.mygame.MyGameActivity
import com.gh.gamecenter.qa.myqa.MyAskActivity
import com.gh.gamecenter.security.SecurityActivity
+import com.gh.gamecenter.simulatorgame.SimulatorGameActivity
import com.gh.gamecenter.user.UserViewModel
import com.gh.gamecenter.video.videomanager.VideoManagerActivity
import com.halo.assistant.HaloApp
@@ -158,6 +159,9 @@ class PersonalFunctionAdapter(val context: Context, val groupName: String, var m
CheckLoginUtils.checkLogin(context, "我的光环-账号安全") {}
}
}
+ "模拟器游戏" -> {
+ context.startActivity(SimulatorGameActivity.getIntent(context))
+ }
"游戏评论" -> {
if (UserManager.getInstance().isLoggedIn) {
context.startActivity(MyRatingActivity.getIntent(context, "", "我的光环-游戏评论"))
diff --git a/app/src/main/java/com/gh/gamecenter/personal/PersonalViewModel.kt b/app/src/main/java/com/gh/gamecenter/personal/PersonalViewModel.kt
index ea31b84ebd..fe7207ccf0 100644
--- a/app/src/main/java/com/gh/gamecenter/personal/PersonalViewModel.kt
+++ b/app/src/main/java/com/gh/gamecenter/personal/PersonalViewModel.kt
@@ -22,7 +22,8 @@ class PersonalViewModel(application: Application) : AndroidViewModel(application
Triple("视频投稿", R.drawable.personal_video_submission, "视频投稿"),
Triple("我的收藏", R.drawable.personal_my_collect, "我的收藏"),
Triple("浏览记录", R.drawable.personal_browsing_history, "浏览记录"),
- Triple("账号安全", R.drawable.personal_account_security, "账号安全")
+ Triple("账号安全", R.drawable.personal_account_security, "账号安全"),
+ Triple("模拟器游戏", R.drawable.personal_simulator_game, "模拟器游戏")
)
private val contentCenterFuncs = arrayListOf(
Triple("游戏动态", R.drawable.personal_game_dynamic, "游戏动态"),
diff --git a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
index f78cb1f618..e72895e14f 100644
--- a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
+++ b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
@@ -59,6 +59,7 @@ import com.gh.gamecenter.entity.ServersGameCategory;
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.SubjectEntity;
import com.gh.gamecenter.entity.SubjectRecommendEntity;
import com.gh.gamecenter.entity.SubjectRefreshEntity;
@@ -2684,4 +2685,15 @@ public interface ApiService {
@POST("devices/{device_id}/played_simulator_games")
Single playedSimulatorGames(@Path("device_id") String deviceId,@Body RequestBody body);
+ /**
+ * 获取模拟器列表
+ */
+ @GET("games/simulators")
+ Single> getSimulators();
+
+ /**
+ * 获取设备下载的模拟器游戏列表
+ */
+ @GET("devices/{device_id}/download_simulator_games")
+ Single> getSimulatorGames(@Path("device_id") String deviceId, @Query("page") int page, @Query("filter") String filter);
}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameActivity.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameActivity.kt
new file mode 100644
index 0000000000..97a2bdad5f
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameActivity.kt
@@ -0,0 +1,22 @@
+package com.gh.gamecenter.simulatorgame
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import com.gh.gamecenter.NormalActivity
+
+class SimulatorGameActivity : NormalActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setNavigationTitle("模拟器游戏")
+ }
+
+ companion object {
+ @JvmStatic
+ fun getIntent(context: Context): Intent {
+ return getTargetIntent(context, SimulatorGameActivity::class.java, SimulatorGameFragment::class.java)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameFragment.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameFragment.kt
new file mode 100644
index 0000000000..ff28236a06
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameFragment.kt
@@ -0,0 +1,98 @@
+package com.gh.gamecenter.simulatorgame
+
+import android.os.Bundle
+import android.view.MenuItem
+import android.view.View
+import android.widget.LinearLayout
+import androidx.core.os.bundleOf
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.Observer
+import androidx.viewpager.widget.ViewPager
+import com.gh.base.adapter.FragmentAdapter
+import com.gh.base.fragment.BaseFragment_TabLayout
+import com.gh.common.util.EntranceUtils
+import com.gh.common.util.toColor
+import com.gh.common.util.viewModelProvider
+import com.gh.common.view.TabIndicatorView
+import com.gh.gamecenter.R
+import com.gh.gamecenter.normal.NormalFragment
+import com.google.android.material.tabs.TabLayout
+import com.halo.assistant.HaloApp
+import kotterknife.bindView
+
+class SimulatorGameFragment : NormalFragment() {
+
+ private val mTabContainer by bindView(R.id.fragment_tab_container)
+ private val mViewPager by bindView(R.id.fragment_view_pager)
+ private val mTabLayout by bindView(R.id.fragment_tab_layout)
+ private val mTabIndicatorView by bindView(R.id.fragment_tab_indicator)
+ private val mReuseNoData by bindView(R.id.reuse_none_data)
+
+ private lateinit var mViewModel: SimulatorGameViewModel
+ private var mFragmentsList = ArrayList()
+ private var mTabTitleList = ArrayList()
+
+ override fun getLayoutId() = R.layout.fragment_simulator_game
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ mViewModel = viewModelProvider()
+ mViewModel.getSimulators()
+ }
+
+ override fun onActivityCreated(savedInstanceState: Bundle?) {
+ super.onActivityCreated(savedInstanceState)
+ initMenu(R.menu.menu_simulator_manager)
+ }
+
+ override fun onMenuItemClick(menuItem: MenuItem) {
+ super.onMenuItemClick(menuItem)
+ if (menuItem.itemId == R.id.menu_simulator_manager) {
+ startActivity(SimulatorManagementActivity.getIntent(requireContext()))
+ }
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ mViewModel.simulators.observe(viewLifecycleOwner, Observer { list ->
+ if (list.isEmpty()) {
+ mReuseNoData.run {
+ visibility = View.VISIBLE
+ setBackgroundColor(R.color.background.toColor())
+ }
+ } else {
+ list.forEach {
+// mTabContainer.goneIf(list.size == 1)
+ mTabTitleList.add(it.name)
+ mFragmentsList.add(SimulatorGameListFragment().apply {
+ with(bundleOf(EntranceUtils.KEY_SIMULATOR to it))
+ })
+ }
+ initViewPager()
+ }
+ })
+ }
+
+ private fun initViewPager() {
+ mViewPager.run {
+ offscreenPageLimit = mFragmentsList.size
+ adapter = FragmentAdapter(childFragmentManager, mFragmentsList, mTabTitleList)
+ }
+ mTabLayout.setupWithViewPager(mViewPager)
+ mTabIndicatorView.run {
+ setupWithTabLayout(mTabLayout)
+ setupWithViewPager(mViewPager)
+ setIndicatorWidth(20)
+ }
+
+ for (i in 0 until mTabLayout.tabCount) {
+ val tab = mTabLayout.getTabAt(i) ?: continue
+ val tabTitle = if (tab.text != null) tab.text.toString() else ""
+ val tabView = BaseFragment_TabLayout.createDefaultTabCustomView(tabTitle)
+ tab.customView = tabView
+ }
+ BaseFragment_TabLayout.initTabStyle(mTabLayout, mViewPager.currentItem)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListAdapter.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListAdapter.kt
new file mode 100644
index 0000000000..2a67b2de96
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListAdapter.kt
@@ -0,0 +1,309 @@
+package com.gh.gamecenter.simulatorgame
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Intent
+import android.content.pm.ShortcutInfo
+import android.content.pm.ShortcutManager
+import android.graphics.Bitmap
+import android.graphics.drawable.Icon
+import android.os.Build
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.PopupWindow
+import androidx.recyclerview.widget.RecyclerView
+import com.g00fy2.versioncompare.Version
+import com.gh.common.constant.ItemViewType
+import com.gh.common.simulator.SimulatorDownloadManager
+import com.gh.common.simulator.SimulatorGameManager
+import com.gh.common.util.*
+import com.gh.common.view.BugFixedPopupWindow
+import com.gh.gamecenter.GameDetailActivity
+import com.gh.gamecenter.MainActivity
+import com.gh.gamecenter.R
+import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
+import com.gh.gamecenter.adapter.viewholder.GameViewHolder
+import com.gh.gamecenter.adapter.viewholder.SimulatorHeaderViewHolder
+import com.gh.gamecenter.baselist.ListAdapter
+import com.gh.gamecenter.databinding.SimulatorGameItemBinding
+import com.gh.gamecenter.entity.GameEntity
+import com.gh.gamecenter.entity.SimulatorEntity
+
+class SimulatorGameListAdapter(context: Context, var simulator: SimulatorEntity, var fragment: SimulatorGameListFragment, var decorView: View) : ListAdapter(context) {
+
+ private var mCurrentOption = OPTION_MANAGER
+ private var mShowSelectFlag = false
+ private var mSelectList = ArrayList()
+ private val mEntrance = "模拟器游戏"
+
+ override fun setListData(updateData: MutableList?) {
+ mSelectList.clear()
+ updateData?.forEach { _ ->
+ mSelectList.add(false)
+ }
+ super.setListData(updateData)
+ }
+
+ override fun getItemCount(): Int {
+ return if (mEntityList == null || mEntityList.isEmpty()) return 0 else mEntityList.size + 2
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ return when (viewType) {
+ ItemViewType.ITEM_HEADER -> {
+ SimulatorHeaderViewHolder(mLayoutInflater.inflate(R.layout.simulator_header_view, parent, false))
+ }
+
+ ItemViewType.GAME_NORMAL -> {
+ SimulatorGameViewHolder(SimulatorGameItemBinding.bind(mLayoutInflater.inflate(R.layout.simulator_game_item, parent, false)))
+ }
+
+ else -> {
+ FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false))
+ }
+ }
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ when (holder) {
+ is SimulatorHeaderViewHolder -> {
+ holder.managerBtn.run {
+ text = when (mCurrentOption) {
+ OPTION_MANAGER -> "管理"
+ OPTION_ALL_SELECT -> "全选"
+ OPTION_CANCEL_SELECT -> "取消全选"
+ else -> "管理"
+ }
+ setOnClickListener {
+ when (mCurrentOption) {
+ OPTION_MANAGER -> {
+ mShowSelectFlag = true
+ showOptionWindow()
+ notifyDataSetChanged()
+ mCurrentOption = OPTION_ALL_SELECT
+ }
+
+ OPTION_ALL_SELECT -> {
+ resetSelectList(true)
+ notifyDataSetChanged()
+ mCurrentOption = OPTION_CANCEL_SELECT
+ }
+
+ OPTION_CANCEL_SELECT -> {
+ resetSelectList(false)
+ notifyDataSetChanged()
+ mCurrentOption = OPTION_ALL_SELECT
+ }
+ }
+ }
+ }
+
+ holder.simulatorBtn.run {
+ if (PackageUtils.isInstalled(context, simulator.apk?.packageName)) {
+ val versionFromInstalledApp = PackageUtils.getVersionByPackage(simulator.apk?.packageName)
+ val shouldShowUpdate = Version(simulator.apk?.version).isHigherThan(versionFromInstalledApp)
+ text = if (shouldShowUpdate) "更新模拟器" else "模拟器已安装"
+ setTextColor(if (shouldShowUpdate) R.color.theme.toColor() else R.color.text_999999.toColor())
+ if (shouldShowUpdate) {
+ setOnClickListener {
+ SimulatorDownloadManager.getInstance().showDownloadDialog(context, simulator)
+ }
+ }
+ } else {
+ text = "安装模拟器"
+ setTextColor(R.color.theme.toColor())
+ setOnClickListener {
+ SimulatorDownloadManager.getInstance().showDownloadDialog(context, simulator)
+ }
+ }
+ }
+ }
+
+ is SimulatorGameViewHolder -> {
+ val gameEntity = mEntityList[position - 1]
+ holder.binding.run {
+ gameItemIncluded.game = gameEntity
+ gameItemIncluded.recentPlayedTag.goneIf(!gameEntity.isRecentlyPlayed)
+ gameItemIncluded.selectIv.goneIf(!mShowSelectFlag)
+ gameItemIncluded.selectIv.isChecked = mSelectList[position - 1]
+ gameItemIncluded.selectIv.setOnClickListener {
+ gameItemIncluded.selectIv.isChecked = !gameItemIncluded.selectIv.isChecked
+ mSelectList[position - 1] = gameItemIncluded.selectIv.isChecked
+ }
+
+ DownloadItemUtils.setOnClickListener(mContext,
+ holder.binding.gameItemIncluded.downloadBtn,
+ gameEntity,
+ position,
+ this@SimulatorGameListAdapter,
+ "(${mEntrance})",
+ StringUtils.buildString(mEntrance, ":", gameEntity.name))
+ DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding.gameItemIncluded), true)
+
+ optionsIv.setOnClickListener {
+ showSingleOptionWindow(optionsIv, gameEntity?.name ?: "", gameEntity?.icon ?: "")
+ }
+
+ root.setOnClickListener {
+ GameDetailActivity.startGameDetailActivity(mContext, gameEntity.id, "(${mEntrance})")
+ }
+ }
+ }
+
+ is FooterViewHolder -> {
+ holder.initItemPadding()
+ holder.initFooterViewHolder(mIsLoading, mIsNetworkError, mIsOver, R.string.ask_loadover_hint)
+ }
+ }
+ }
+
+ fun resetSelectList(value: Boolean) {
+ for (i in 0 until mSelectList.size) {
+ mSelectList[i] = value
+ }
+ }
+
+ fun showOptionWindow() {
+ val contentView = View.inflate(mContext, R.layout.popup_simulator_option, null)
+ contentView.isFocusable = true
+ contentView.isFocusableInTouchMode = true
+ val deleteItem = contentView.findViewById(R.id.item_delete)
+ val completeItem = contentView.findViewById(R.id.item_complete)
+
+ val popWindow = PopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
+ popWindow.showAtLocation(decorView, Gravity.BOTTOM, 0, 0)
+
+ completeItem.setOnClickListener {
+ popWindow.dismiss()
+ resetStatus()
+ notifyDataSetChanged()
+ }
+
+ deleteItem.setOnClickListener {
+ val list = ArrayList()
+ mSelectList.forEachIndexed { index, b ->
+ if (b) list.add(mEntityList[index]?.name ?: "")
+ }
+
+ if (list.isEmpty()) {
+ ToastUtils.toast("未选择游戏")
+ } else {
+ DialogUtils.showNewAlertDialog(mContext, "删除游戏", "即将删除游戏记录和本地文件,是否确定删除", "取消", "确定", null) {
+ popWindow.dismiss()
+ resetStatus()
+ SimulatorGameManager.deleteLocalGames(list)
+ fragment.onLoadRefresh()
+ }
+ }
+ }
+ }
+
+ private fun resetStatus() {
+ mShowSelectFlag = false
+ mCurrentOption = OPTION_MANAGER
+ resetSelectList(false)
+ }
+
+ private fun showSingleOptionWindow(view: View, gameName: String, gameIcon: String) {
+ val inflater = LayoutInflater.from(mContext)
+ val layout = inflater.inflate(R.layout.popup_simulator_option_single, null)
+ val popupWindow = BugFixedPopupWindow(
+ layout,
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ )
+
+ val container = layout.findViewById(R.id.container)
+ val shortCutItem = container.findViewById(R.id.item_shortcut)
+ val deleteGameItem = container.findViewById(R.id.item_delete_game)
+
+ shortCutItem.setOnClickListener {
+ popupWindow.dismiss()
+ DialogUtils.showShortCutPermissionDialog(mContext)
+ createShortcut(gameName, gameIcon)
+ }
+
+ deleteGameItem.setOnClickListener {
+ popupWindow.dismiss()
+ DialogUtils.showNewAlertDialog(mContext, "删除游戏", "即将删除游戏记录和本地文件,是否确定删除", "取消", "确定", null) {
+ SimulatorGameManager.deleteLocalGame(gameName)
+ fragment.onLoadRefresh()
+ }
+ }
+ popupWindow.isTouchable = true
+ popupWindow.isFocusable = true
+
+ popupWindow.showAutoOrientation(view)
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return when (position) {
+ 0 -> ItemViewType.ITEM_HEADER
+ itemCount - 1 -> ItemViewType.ITEM_FOOTER
+ else -> ItemViewType.GAME_NORMAL
+ }
+ }
+
+ @SuppressLint("CheckResult")
+ fun createShortcut(gameName: String, gameIcon: String) {
+ // Api26以上要使用ShortcutManager才能创建桌面快捷方式
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ ImageUtils.getBitmap(gameIcon, object : BiCallback {
+ override fun onFirst(first: Bitmap) {
+ val shortcutManager = mContext.getSystemService(Context.SHORTCUT_SERVICE) as ShortcutManager
+ if (shortcutManager.isRequestPinShortcutSupported) {
+
+ var shortcutInfoIntent = Intent(mContext, MainActivity::class.java)
+ shortcutInfoIntent.run {
+ action = Intent.ACTION_VIEW
+// putExtra(INTENT_TYPE, INTENT_H5_SHORTCUT)
+// putExtra(KEY_DATA, gameUrl)
+// putExtra(KEY_LANDSCAPE, mContext.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
+ var info = ShortcutInfo.Builder(mContext, gameName)
+ .setIcon(Icon.createWithBitmap(first))
+ .setShortLabel(gameName).setIntent(this).build()
+ // var shortcutCallbackIntent = PendingIntent.getBroadcast(linearLayout.context, 0,
+ // Intent(linearLayout.context, MainActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
+ shortcutManager.requestPinShortcut(info, null)
+ }
+ }
+ }
+
+ override fun onSecond(second: Boolean) {
+ ToastUtils.toast("创建快捷方式失败")
+ }
+ })
+ } else {
+ val shortcutIntent = Intent("com.android.launcher.action.INSTALL_SHORTCUT")
+ shortcutIntent.run {
+ // 不允许重复创建,不是根据快捷方式的名字判断重复的
+ putExtra("duplicate", false)
+ // 名字
+ putExtra(Intent.EXTRA_SHORTCUT_NAME, gameName)
+ // 图标
+ putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(mContext, android.R.mipmap.sym_def_app_icon))
+ // 设置关联程序
+ val launcherIntent = Intent()
+ launcherIntent.setClass(mContext, MainActivity::class.java)
+// launcherIntent.putExtra(INTENT_TYPE, INTENT_H5_SHORTCUT)
+// launcherIntent.putExtra(KEY_DATA, gameUrl)
+ putExtra(Intent.EXTRA_SHORTCUT_INTENT, launcherIntent)
+ // 发送广播
+ mContext.sendBroadcast(this)
+ }
+ }
+ }
+
+ class SimulatorGameViewHolder(var binding: SimulatorGameItemBinding) : RecyclerView.ViewHolder(binding.root) {
+
+ }
+
+ companion object {
+ const val OPTION_MANAGER = 100
+ const val OPTION_ALL_SELECT = 101
+ const val OPTION_CANCEL_SELECT = 102
+ }
+}
\ 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
new file mode 100644
index 0000000000..1ab49fcd54
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListFragment.kt
@@ -0,0 +1,43 @@
+package com.gh.gamecenter.simulatorgame
+
+import android.os.Bundle
+import com.gh.common.util.EntranceUtils
+import com.gh.common.util.viewModelProvider
+import com.gh.gamecenter.baselist.ListFragment
+import com.gh.gamecenter.entity.GameEntity
+import com.gh.gamecenter.entity.SimulatorEntity
+import com.gh.gamecenter.eventbus.EBPackage
+import com.halo.assistant.HaloApp
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+class SimulatorGameListFragment : ListFragment() {
+
+ private lateinit var mSimulatorEntity: SimulatorEntity
+ private var mAdapter: SimulatorGameListAdapter? = null
+
+ //安装、卸载事件
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ fun onEventMainThread(busFour: EBPackage) {
+ if ("安装" == busFour.type || "卸载" == busFour.type) {
+ mAdapter?.notifyItemChanged(0)
+ }
+ }
+
+ override fun getItemDecoration() = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ arguments?.apply {
+ mSimulatorEntity = getParcelable(EntranceUtils.KEY_SIMULATOR) ?: SimulatorEntity()
+ }
+ super.onCreate(savedInstanceState)
+ }
+
+ override fun provideListAdapter() = mAdapter ?: SimulatorGameListAdapter(requireContext(), mSimulatorEntity, this, requireActivity().window.decorView).apply { mAdapter = this }
+
+
+ override fun provideListViewModel(): SimulatorGameListViewModel {
+ return viewModelProvider(SimulatorGameListViewModel.Factory(HaloApp.getInstance().application, mSimulatorEntity.type))
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListViewModel.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListViewModel.kt
new file mode 100644
index 0000000000..dc4380a51b
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListViewModel.kt
@@ -0,0 +1,39 @@
+package com.gh.gamecenter.simulatorgame
+
+import android.app.Application
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.gh.common.util.UrlFilterUtils
+import com.gh.gamecenter.baselist.ListViewModel
+import com.gh.gamecenter.entity.GameEntity
+import com.gh.gamecenter.retrofit.RetrofitManager
+import com.halo.assistant.HaloApp
+import io.reactivex.Observable
+import io.reactivex.Single
+
+class SimulatorGameListViewModel(application: Application, var type: String) : ListViewModel(application) {
+
+ private val mApi = RetrofitManager.getInstance(getApplication()).api
+
+ override fun mergeResultLiveData() {
+ mResultLiveData.addSource>(mListLiveData) { mResultLiveData.postValue(it) }
+ }
+
+ override fun provideDataObservable(page: Int): Observable>? = null
+
+ override fun provideDataSingle(page: Int): Single> {
+ return mApi.getSimulatorGames(HaloApp.getInstance().gid, page, getFilter())
+ }
+
+ private fun getFilter(): String {
+ return UrlFilterUtils.getFilterQuery("type", type)
+ }
+
+
+ class Factory(private val mApplication: Application,
+ private val mType: String) : ViewModelProvider.NewInstanceFactory() {
+ override fun create(modelClass: Class): T {
+ return SimulatorGameListViewModel(mApplication, mType) as T
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameViewModel.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameViewModel.kt
new file mode 100644
index 0000000000..92b2b54e55
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameViewModel.kt
@@ -0,0 +1,29 @@
+package com.gh.gamecenter.simulatorgame
+
+import android.annotation.SuppressLint
+import android.app.Application
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.MutableLiveData
+import com.gh.gamecenter.entity.SimulatorEntity
+import com.gh.gamecenter.retrofit.BiResponse
+import com.gh.gamecenter.retrofit.RetrofitManager
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+
+class SimulatorGameViewModel(application: Application) : AndroidViewModel(application) {
+
+ private val api = RetrofitManager.getInstance(getApplication()).api
+ var simulators = MutableLiveData>()
+
+ @SuppressLint("CheckResult")
+ fun getSimulators() {
+ api.simulators
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(object : BiResponse>() {
+ override fun onSuccess(data: List) {
+ simulators.postValue(data)
+ }
+ })
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementActivity.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementActivity.kt
new file mode 100644
index 0000000000..f758a0b021
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementActivity.kt
@@ -0,0 +1,22 @@
+package com.gh.gamecenter.simulatorgame
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import com.gh.gamecenter.NormalActivity
+
+class SimulatorManagementActivity : NormalActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setNavigationTitle("模拟器管理")
+ }
+
+ companion object {
+ @JvmStatic
+ fun getIntent(context: Context): Intent {
+ return getTargetIntent(context, SimulatorManagementActivity::class.java, SimulatorManagementFragment::class.java)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementAdapter.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementAdapter.kt
new file mode 100644
index 0000000000..506c06d44c
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementAdapter.kt
@@ -0,0 +1,41 @@
+package com.gh.gamecenter.simulatorgame
+
+import android.content.Context
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.gh.common.simulator.SimulatorDownloadManager
+import com.gh.common.util.PackageUtils
+import com.gh.common.util.toColor
+import com.gh.gamecenter.R
+import com.gh.gamecenter.adapter.viewholder.SimulatorManagementViewHolder
+import com.gh.gamecenter.baselist.ListAdapter
+import com.gh.gamecenter.entity.SimulatorEntity
+
+class SimulatorManagementAdapter(context: Context) : ListAdapter(context) {
+
+ override fun getItemCount() = mEntityList.size
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
+ = SimulatorManagementViewHolder(mLayoutInflater.inflate(R.layout.simulator_item, parent, false))
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ when (holder) {
+ is SimulatorManagementViewHolder -> {
+ holder.simulatorInstallBtn.run {
+ val simulator = mEntityList[position]
+ holder.simulatorName.text = simulator.name
+ if (PackageUtils.isInstalled(mContext, simulator.apk?.packageName)) {
+ text = "已安装"
+ setTextColor(R.color.text_999999.toColor())
+ } else {
+ text = "安装"
+ setTextColor(R.color.theme.toColor())
+ setOnClickListener {
+ SimulatorDownloadManager.getInstance().showDownloadDialog(mContext, simulator)
+ }
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementFragment.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementFragment.kt
new file mode 100644
index 0000000000..65e53aeace
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementFragment.kt
@@ -0,0 +1,41 @@
+package com.gh.gamecenter.simulatorgame
+
+import android.os.Bundle
+import com.gh.common.util.EntranceUtils
+import com.gh.common.util.dip2px
+import com.gh.common.util.viewModelProvider
+import com.gh.common.view.SpacingItemDecoration
+import com.gh.gamecenter.baselist.ListFragment
+import com.gh.gamecenter.entity.SimulatorEntity
+import com.gh.gamecenter.eventbus.EBPackage
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+class SimulatorManagementFragment : ListFragment() {
+
+ private lateinit var mSimulatorEntity: SimulatorEntity
+ private var mAdapter: SimulatorManagementAdapter? = null
+
+ //安装、卸载事件
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ fun onEventMainThread(busFour: EBPackage) {
+ if ("安装" == busFour.type || "卸载" == busFour.type) {
+ mAdapter?.notifyDataSetChanged()
+ }
+ }
+
+ override fun getItemDecoration() = SpacingItemDecoration(onlyDecorateTheFirstItem = true, top = 8F.dip2px())
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ arguments?.apply {
+ mSimulatorEntity = getParcelable(EntranceUtils.KEY_SIMULATOR) ?: SimulatorEntity()
+ }
+ super.onCreate(savedInstanceState)
+ }
+
+ override fun provideListAdapter() = mAdapter ?: SimulatorManagementAdapter(requireContext()).apply { mAdapter = this }
+
+
+ override fun provideListViewModel() = viewModelProvider()
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementViewModel.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementViewModel.kt
new file mode 100644
index 0000000000..d3c57f3b9c
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorManagementViewModel.kt
@@ -0,0 +1,24 @@
+package com.gh.gamecenter.simulatorgame
+
+import android.app.Application
+import com.gh.gamecenter.baselist.ListViewModel
+import com.gh.gamecenter.entity.SimulatorEntity
+import com.gh.gamecenter.retrofit.RetrofitManager
+import io.reactivex.Observable
+import io.reactivex.Single
+
+class SimulatorManagementViewModel(application: Application) : ListViewModel(application) {
+
+ private val mApi = RetrofitManager.getInstance(getApplication()).api
+
+ override fun mergeResultLiveData() {
+ mResultLiveData.addSource>(mListLiveData) { mResultLiveData.postValue(it) }
+ }
+
+ override fun provideDataObservable(page: Int): Observable>? = null
+
+ override fun provideDataSingle(page: Int): Single> {
+ return mApi.simulators
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-xxhdpi/ic_complete.png b/app/src/main/res/drawable-xxhdpi/ic_complete.png
new file mode 100644
index 0000000000..4dd33ca5ad
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_complete.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_delete_game.png b/app/src/main/res/drawable-xxhdpi/ic_delete_game.png
new file mode 100644
index 0000000000..5555f276ab
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_delete_game.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_shortcut_simulator.png b/app/src/main/res/drawable-xxhdpi/ic_shortcut_simulator.png
new file mode 100644
index 0000000000..3818251980
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_shortcut_simulator.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_simulator_game_option.png b/app/src/main/res/drawable-xxhdpi/ic_simulator_game_option.png
new file mode 100644
index 0000000000..1b08fb8eda
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_simulator_game_option.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_simulator_manager.png b/app/src/main/res/drawable-xxhdpi/ic_simulator_manager.png
new file mode 100644
index 0000000000..d16a191835
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_simulator_manager.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_simulator_selected.png b/app/src/main/res/drawable-xxhdpi/ic_simulator_selected.png
new file mode 100644
index 0000000000..a2f8009ecf
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_simulator_selected.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_simulator_unselect.png b/app/src/main/res/drawable-xxhdpi/ic_simulator_unselect.png
new file mode 100644
index 0000000000..cd62b5f972
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_simulator_unselect.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/personal_simulator_game.png b/app/src/main/res/drawable-xxhdpi/personal_simulator_game.png
new file mode 100644
index 0000000000..5c49049dc9
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/personal_simulator_game.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/pic_dialog_shortcut.png b/app/src/main/res/drawable-xxhdpi/pic_dialog_shortcut.png
new file mode 100644
index 0000000000..ea8c92e98c
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/pic_dialog_shortcut.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_complete.png b/app/src/main/res/drawable-xxxhdpi/ic_complete.png
new file mode 100644
index 0000000000..c8705f3849
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_complete.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_delete_game.png b/app/src/main/res/drawable-xxxhdpi/ic_delete_game.png
new file mode 100644
index 0000000000..0c4fc748cd
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_delete_game.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_shortcut_simulator.png b/app/src/main/res/drawable-xxxhdpi/ic_shortcut_simulator.png
new file mode 100644
index 0000000000..64a97afbc5
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_shortcut_simulator.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_simulator_game_option.png b/app/src/main/res/drawable-xxxhdpi/ic_simulator_game_option.png
new file mode 100644
index 0000000000..89132c5d59
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_simulator_game_option.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_simulator_manager.png b/app/src/main/res/drawable-xxxhdpi/ic_simulator_manager.png
new file mode 100644
index 0000000000..25a2d83f6c
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_simulator_manager.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_simulator_selected.png b/app/src/main/res/drawable-xxxhdpi/ic_simulator_selected.png
new file mode 100644
index 0000000000..f37fb18b24
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_simulator_selected.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_simulator_unselect.png b/app/src/main/res/drawable-xxxhdpi/ic_simulator_unselect.png
new file mode 100644
index 0000000000..95291954fb
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_simulator_unselect.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/personal_simulator_game.png b/app/src/main/res/drawable-xxxhdpi/personal_simulator_game.png
new file mode 100644
index 0000000000..1a61c1df34
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/personal_simulator_game.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/pic_dialog_shortcut.png b/app/src/main/res/drawable-xxxhdpi/pic_dialog_shortcut.png
new file mode 100644
index 0000000000..5ef2d981d7
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/pic_dialog_shortcut.png differ
diff --git a/app/src/main/res/drawable/button_round_1affa142.xml b/app/src/main/res/drawable/button_round_1affa142.xml
new file mode 100644
index 0000000000..d739378a87
--- /dev/null
+++ b/app/src/main/res/drawable/button_round_1affa142.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/selector_ic_simulator.xml b/app/src/main/res/drawable/selector_ic_simulator.xml
new file mode 100644
index 0000000000..d084d93c05
--- /dev/null
+++ b/app/src/main/res/drawable/selector_ic_simulator.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shortcut_dialog_btn_bg.xml b/app/src/main/res/drawable/shortcut_dialog_btn_bg.xml
new file mode 100644
index 0000000000..76811a7e0e
--- /dev/null
+++ b/app/src/main/res/drawable/shortcut_dialog_btn_bg.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_shortcut_permission.xml b/app/src/main/res/layout/dialog_shortcut_permission.xml
new file mode 100644
index 0000000000..82c08cc72d
--- /dev/null
+++ b/app/src/main/res/layout/dialog_shortcut_permission.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_simulator_game.xml b/app/src/main/res/layout/fragment_simulator_game.xml
new file mode 100644
index 0000000000..4fbaaf4aab
--- /dev/null
+++ b/app/src/main/res/layout/fragment_simulator_game.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_user_comment_history.xml b/app/src/main/res/layout/fragment_user_comment_history.xml
index 04e8111f8b..19ccdbab9b 100644
--- a/app/src/main/res/layout/fragment_user_comment_history.xml
+++ b/app/src/main/res/layout/fragment_user_comment_history.xml
@@ -1,6 +1,5 @@
diff --git a/app/src/main/res/layout/game_item.xml b/app/src/main/res/layout/game_item.xml
index a2469aff6f..d72185c872 100644
--- a/app/src/main/res/layout/game_item.xml
+++ b/app/src/main/res/layout/game_item.xml
@@ -50,6 +50,15 @@
android:textSize="12sp"
android:visibility="gone" />
+
+
@@ -100,6 +109,18 @@
android:textColor="@color/text_333333"
android:textSize="14sp"
android:textStyle="bold" />
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/popup_simulator_option.xml b/app/src/main/res/layout/popup_simulator_option.xml
new file mode 100644
index 0000000000..090647a205
--- /dev/null
+++ b/app/src/main/res/layout/popup_simulator_option.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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
new file mode 100644
index 0000000000..ca66ae801b
--- /dev/null
+++ b/app/src/main/res/layout/popup_simulator_option_single.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/simulator_game_item.xml b/app/src/main/res/layout/simulator_game_item.xml
new file mode 100644
index 0000000000..e731647c02
--- /dev/null
+++ b/app/src/main/res/layout/simulator_game_item.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/simulator_header_view.xml b/app/src/main/res/layout/simulator_header_view.xml
new file mode 100644
index 0000000000..6608f71ddf
--- /dev/null
+++ b/app/src/main/res/layout/simulator_header_view.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/simulator_item.xml b/app/src/main/res/layout/simulator_item.xml
new file mode 100644
index 0000000000..1629a8d023
--- /dev/null
+++ b/app/src/main/res/layout/simulator_item.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/tab_item_user_home.xml b/app/src/main/res/layout/tab_item_user_home.xml
index ed639dca48..2e423e6966 100644
--- a/app/src/main/res/layout/tab_item_user_home.xml
+++ b/app/src/main/res/layout/tab_item_user_home.xml
@@ -11,7 +11,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:textColor="@color/text_tabbar_style"
- android:textSize="14dp"
+ android:textSize="14sp"
tools:text="详情" />
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 07df800443..4d92d55fc5 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -115,6 +115,7 @@
#ECF6FF
#EDEDED
#F2F2F2
+ #F4F5F6
#80000000
#404040
#ededed
@@ -205,6 +206,7 @@
#06CEA8
#FFA142
#06CCF4
+ #F8A142
#99666666