diff --git a/app/src/main/java/com/gh/common/view/ExpendTextView.java b/app/src/main/java/com/gh/common/view/ExpendTextView.java index 682787e358..0f1f6d1361 100644 --- a/app/src/main/java/com/gh/common/view/ExpendTextView.java +++ b/app/src/main/java/com/gh/common/view/ExpendTextView.java @@ -19,30 +19,30 @@ import androidx.appcompat.widget.AppCompatTextView; import androidx.core.content.ContextCompat; public class ExpendTextView extends AppCompatTextView { - + private CharSequence mSnapshotText; private CharSequence mCloseText; - + private String mExpendText = "...全文"; - + private int mMaxLines = 3; // 由于sdk版本限制(getMaxLines) 这里设置默认值 - + private boolean mInitLayout = false; private boolean mOpenLayout = false; - + private ExpandCallback mExpandCallback; - + public ExpendTextView(Context context) { super(context); } - + public ExpendTextView(Context context, AttributeSet attrs) { super(context, attrs); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { mMaxLines = getMaxLines(); } } - + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); @@ -53,30 +53,30 @@ public class ExpendTextView extends AppCompatTextView { showExpendButton(); } } - + public void setExpendText(String text) { this.mExpendText = text; } - + public void setExpandCallback(ExpandCallback callback) { this.mExpandCallback = callback; } - + @Override public void setText(CharSequence text, BufferType type) { mInitLayout = true; super.setText(text, type); } - + private void showExpendButton() { Layout layout = getLayout(); int start = layout.getLineStart(0); int lastLineEnd = layout.getLineEnd(mMaxLines - 1); int lastLineStart = layout.getLineStart(mMaxLines - 1); float lastLineRight = layout.getLineRight(mMaxLines - 1); - + int viewWidth = getWidth() - getPaddingRight() - getPaddingLeft(); - + TextPaint paint = getPaint(); float expendTextWidth = paint.measureText(mExpendText); CharSequence content = mSnapshotText.subSequence(start, lastLineEnd); @@ -98,47 +98,39 @@ public class ExpendTextView extends AppCompatTextView { int startPosition = content.length() - mExpendText.length(); startPosition = startPosition < 0 ? 0 : startPosition; msp.replace(startPosition, length, mExpendText); - msp.setSpan( - new ClickableSpan() { - @Override - public void updateDrawState(TextPaint ds) { - super.updateDrawState(ds); - ds.setColor(ContextCompat.getColor(getContext(), R.color.theme)); - ds.setUnderlineText(false); - } - - @Override - public void onClick(View widget) { - mOpenLayout = true; - setMaxLines(Integer.MAX_VALUE); - setText(mSnapshotText); - - if (mExpandCallback != null) { - mExpandCallback.onExpand(); - } - } - }, - startPosition, - msp.length(), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - msp.setSpan( - new BackgroundColorSpan(Color.WHITE), - startPosition, - msp.length(), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - + msp.setSpan(new ClickableSpan() { + @Override + public void updateDrawState(TextPaint ds) { + super.updateDrawState(ds); + ds.setColor(ContextCompat.getColor(getContext(), R.color.theme)); + ds.setUnderlineText(false); + } + + @Override + public void onClick(View widget) { + mOpenLayout = true; + setMaxLines(Integer.MAX_VALUE); + setText(mSnapshotText); + + if (mExpandCallback != null) { + mExpandCallback.onExpand(); + } + } + }, startPosition, msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + msp.setSpan(new BackgroundColorSpan(Color.WHITE), startPosition, msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + setText(msp); setMovementMethod(CustomLinkMovementMethod.getInstance()); } - - + + public void setExpendMaxLines(int maxLines) { mMaxLines = maxLines; setMaxLines(maxLines); } - + public interface ExpandCallback { void onExpand(); } - + } diff --git a/app/src/main/java/com/gh/common/view/MaterializedRelativeLayout.kt b/app/src/main/java/com/gh/common/view/MaterializedRelativeLayout.kt new file mode 100644 index 0000000000..3bcbf89a2c --- /dev/null +++ b/app/src/main/java/com/gh/common/view/MaterializedRelativeLayout.kt @@ -0,0 +1,25 @@ +package com.gh.common.view + +import android.annotation.TargetApi +import android.content.Context +import android.os.Build +import android.util.AttributeSet +import android.view.WindowInsets +import android.widget.RelativeLayout + +class MaterializedRelativeLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) + : RelativeLayout(context, attrs) { + + /** + * 将 windowInsets 传递给子 view [https://medium.com/androiddevelopers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec#.raoa9t506] + */ + @TargetApi(Build.VERSION_CODES.KITKAT_WATCH) + override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets { + val childCount = childCount + for (index in 0 until childCount) { + getChildAt(index).dispatchApplyWindowInsets(insets) + } + return insets + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/GameDetailActivity.java b/app/src/main/java/com/gh/gamecenter/GameDetailActivity.java index 601b73930e..3ac424e1d2 100644 --- a/app/src/main/java/com/gh/gamecenter/GameDetailActivity.java +++ b/app/src/main/java/com/gh/gamecenter/GameDetailActivity.java @@ -9,6 +9,7 @@ import com.gh.common.exposure.ExposureManager; import com.gh.common.exposure.ExposureTraceUtils; import com.gh.common.exposure.ExposureType; import com.gh.common.util.DataUtils; +import com.gh.common.util.DisplayUtils; import com.gh.common.util.EntranceUtils; import com.gh.gamecenter.entity.GameEntity; import com.gh.gamecenter.gamedetail.GameDetailFragment; @@ -18,12 +19,24 @@ import com.gh.gamecenter.gamedetail.GameDetailFragment; * 游戏详情适配器 */ public class GameDetailActivity extends NormalActivity { - + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + DisplayUtils.transparentStatusAndNavigation(this); + } + @Override protected Intent provideNormalIntent() { return getTargetIntent(this, GameDetailActivity.class, GameDetailFragment.class); } - + + @Override + protected int getLayoutId() { + return R.layout.activity_game_detail; + } + /** * 启动游戏详情页面 */ diff --git a/app/src/main/java/com/gh/gamecenter/entity/GameDetailEntity.kt b/app/src/main/java/com/gh/gamecenter/entity/GameDetailEntity.kt index 22a7b3e985..6228f48b77 100644 --- a/app/src/main/java/com/gh/gamecenter/entity/GameDetailEntity.kt +++ b/app/src/main/java/com/gh/gamecenter/entity/GameDetailEntity.kt @@ -80,6 +80,12 @@ class GameDetailEntity( @SerializedName("server_label") val serverLabel: ColorEntity? = null, + @SerializedName("top_video") + var topVideo: Video? = null, + + @SerializedName("intro_video") + var introVideo: Video? = null, + @SerializedName("direct_comment") val directComment: Boolean = false) : Parcelable { @@ -114,6 +120,16 @@ class GameDetailEntity( const val TAG: String = "GameDetailEntity" } + @Parcelize + data class Video( + @SerializedName("video_id") + var videoId: String = "", + @SerializedName("video_count") + var videoCount: Int = 0, + var poster: String = "", + var url: String = "" + ) : Parcelable + @Parcelize data class RelatedVersion( var first: Boolean = false, 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 83e256aab9..fcc47b72bc 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt @@ -5,10 +5,13 @@ import android.content.Intent import android.graphics.drawable.ColorDrawable import android.os.Build import android.os.Bundle +import android.text.TextUtils import android.view.* import android.widget.CheckedTextView import android.widget.RelativeLayout import android.widget.TextView +import androidx.appcompat.widget.Toolbar +import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.fragment.app.Fragment import butterknife.BindView @@ -35,6 +38,7 @@ import com.gh.gamecenter.eventbus.EBReuse import com.gh.gamecenter.gamedetail.desc.DescFragment import com.gh.gamecenter.gamedetail.fuli.FuLiFragment import com.gh.gamecenter.gamedetail.rating.RatingFragment +import com.gh.gamecenter.gamedetail.video.TopVideoView import com.gh.gamecenter.manager.PackagesManager import com.gh.gamecenter.mvvm.Status import com.gh.gamecenter.normal.NormalFragment @@ -47,6 +51,12 @@ import com.lightgame.download.DataWatcher import com.lightgame.download.DownloadEntity import com.lightgame.view.NoScrollableViewPager import com.qq.gdt.action.ActionType +import com.shuyu.gsyvideoplayer.GSYVideoManager +import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder +import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack +import com.shuyu.gsyvideoplayer.utils.OrientationUtils +import kotlinx.android.synthetic.main.gamedetail_body.* +import kotlinx.android.synthetic.main.piece_game_detail_video.* import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode @@ -102,6 +112,10 @@ class GameDetailFragment : NormalFragment() { lateinit var mBasicTag: TextView @BindView(R.id.gamedetail_name_container) lateinit var mNameContainer: View + @BindView(R.id.toolbar) + lateinit var mToolbar: Toolbar + @BindView(R.id.player) + lateinit var mTopVideoView: TopVideoView private var mSkeleton: ViewSkeletonScreen? = null @@ -111,8 +125,10 @@ class GameDetailFragment : NormalFragment() { private var mDownloadEntity: DownloadEntity? = null private var mGameDetailEntity: GameDetailEntity? = null private var mTraceEvent: ExposureEvent? = null + private var mOrientationUtils: OrientationUtils? = null private var mConcernMenuItem: MenuItem? = null + private var mMoreMenuItem: MenuItem? = null private var downloadAddWord: String? = null private var downloadOffText: String? = null @@ -155,8 +171,31 @@ class GameDetailFragment : NormalFragment() { override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - initMenu(R.menu.menu_game_detail) - mConcernMenuItem = getItemMenu(R.id.menu_concern) + mToolbar.inflateMenu(R.menu.menu_game_detail) + mMoreMenuItem = mToolbar.menu.findItem(R.id.menu_more) + mConcernMenuItem = mToolbar.menu.findItem(R.id.menu_concern) + + mConcernMenuItem?.setOnMenuItemClickListener { + consume { + checkReadPhoneStatePermissionBeforeAction { + ifLogin("游戏详情-[关注]") { + if (mGameDetailEntity != null && mGameDetailEntity!!.me.isGameConcerned) { + DialogUtils.showCancelDialog(context!!, { mViewModel.concernCommand(false) }, null) + } else { + mViewModel.concernCommand(true) + } + } + } + } + } + + mMoreMenuItem?.setOnMenuItemClickListener { + consume { + if (mGameEntity != null && mGameDetailEntity != null) { + showMoreMenuDialog() + } + } + } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { @@ -209,22 +248,48 @@ class GameDetailFragment : NormalFragment() { } mAppBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset -> + val absVerticalOffset = abs(verticalOffset) val total = appBarLayout.totalScrollRange - if (abs(verticalOffset) > total / 2) { - setNavigationTitle(if (mGameEntity != null) mGameEntity!!.name else "") + + if (absVerticalOffset > total * 4 / 5) { + updateToolbarStyle(isLightTheme = true) + mToolbar.title = mGameEntity?.name ?: "" } else { - setNavigationTitle("") + updateToolbarStyle(isLightTheme = false) + mToolbar.title = "" } - if (abs(verticalOffset) == total && mIsScrollToKaiFu) { - mIsScrollToKaiFu = false - EventBus.getDefault().post(EBReuse(SCROLL_TO_KAIFU)) + if (absVerticalOffset == total) { + toolbar.setTitleTextColor(ContextCompat.getColor(requireContext(), R.color.black)) + + if (mIsScrollToKaiFu) { + mIsScrollToKaiFu = false + EventBus.getDefault().post(EBReuse(SCROLL_TO_KAIFU)) + } } }) observeData() } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + mOrientationUtils = OrientationUtils(requireActivity(), player) + mOrientationUtils?.isEnable = false + + // toolbar 消费 fitsSystemWindows 避免在 collapsingToolbar 下面出现多出来的 padding + // [https://stackoverflow.com/questions/48137666/viewgroup-inside-collapsingtoolbarlayout-show-extra-bottom-padding-when-set-fits] + ViewCompat.setOnApplyWindowInsetsListener(mAppBarLayout) { _, insets -> + (mToolbar.layoutParams as ViewGroup.MarginLayoutParams).topMargin = insets.systemWindowInsetTop + insets.consumeSystemWindowInsets() + } + + mToolbar.setNavigationOnClickListener { requireActivity().finish() } + + updateToolbarStyle(isLightTheme = true) + } + override fun onResume() { super.onResume() if (mGameEntity != null && (mGameEntity!!.getApk().size == 1 || mGameEntity!!.isReservable)) { @@ -312,6 +377,8 @@ class GameDetailFragment : NormalFragment() { mAutoDownload = false } + data.topVideo?.let { setUpTopVideo(it) } + mSkeleton?.hide() } else if (detailResource.status == Status.ERROR) { loadErrorControl(detailResource.exception) @@ -326,11 +393,9 @@ class GameDetailFragment : NormalFragment() { DataUtils.onEvent(context, "游戏关注", mGameEntity!!.name, kv) MtaHelper.onEvent("游戏详情_新", "关注", mGameEntity!!.name) DataCollectionUtils.uploadConcern(context, mGameEntity!!.name, mGameEntity!!.id, "关注") - GdtHelper.logAction(ActionType.ADD_TO_WISHLIST, - GdtHelper.CONTENT_TYPE, "GAME", - GdtHelper.CONTENT_ID, mGameEntity!!.id) + GdtHelper.logAction(ActionType.ADD_TO_WISHLIST, GdtHelper.CONTENT_TYPE, "GAME", GdtHelper.CONTENT_ID, mGameEntity!!.id) - mConcernMenuItem!!.setIcon(R.drawable.ic_menu_gamedetail_collected) + updateConcernIcon(isConcerned = true) toast(R.string.concern_success) } else { toast(R.string.concern_failure) @@ -341,11 +406,10 @@ class GameDetailFragment : NormalFragment() { kv["状态"] = "取消关注" DataUtils.onEvent(context, "游戏关注", mGameEntity!!.name, kv) - DataCollectionUtils.uploadConcern(context, - mGameEntity!!.name, mGameEntity!!.id, "取消关注") + DataCollectionUtils.uploadConcern(context, mGameEntity!!.name, mGameEntity!!.id, "取消关注") MtaHelper.onEvent("游戏详情_新", "取消关注", mGameEntity!!.name) - mConcernMenuItem!!.setIcon(R.drawable.ic_menu_gamedetail_collect) + updateConcernIcon(isConcerned = false) } else { toast(R.string.cancel_concern_failure) } @@ -389,7 +453,7 @@ class GameDetailFragment : NormalFragment() { mLoading.visibility = View.GONE mNoConnection.visibility = View.GONE mNoneDataView.visibility = View.VISIBLE - mConcernMenuItem!!.isVisible = false + mConcernMenuItem?.isVisible = false toast("内容可能已被删除") } else { mLoading.visibility = View.GONE @@ -400,23 +464,6 @@ class GameDetailFragment : NormalFragment() { mSkeleton?.hide() } - override fun onMenuItemClick(menuItem: MenuItem) { - when (menuItem.itemId) { - R.id.menu_concern -> checkReadPhoneStatePermissionBeforeAction { - ifLogin("游戏详情-[关注]") { - if (mGameDetailEntity != null && mGameDetailEntity!!.me.isGameConcerned) { - DialogUtils.showCancelDialog(context!!, { mViewModel.concernCommand(false) }, null) - } else { - mViewModel.concernCommand(true) - } - } - } - R.id.menu_more -> if (mGameEntity != null && mGameDetailEntity != null) { - showMoreMenuDialog() - } - } - } - private fun showMoreMenuDialog() { if (!isVisible) return @@ -475,11 +522,7 @@ class GameDetailFragment : NormalFragment() { tabParams.width = mMaxWidth * 2 / 3 } - if (mGameDetailEntity!!.me.isGameConcerned) { - mConcernMenuItem!!.setIcon(R.drawable.ic_menu_gamedetail_collected) - } else { - mConcernMenuItem!!.setIcon(R.drawable.ic_menu_gamedetail_collect) - } + updateConcernIcon(mGameDetailEntity!!.me.isGameConcerned) if (mGameDetailEntity!!.topTag != null && !mGameDetailEntity!!.topTag!!.isEmpty()) { mBasicTag.visibility = View.VISIBLE @@ -541,22 +584,57 @@ class GameDetailFragment : NormalFragment() { } } - if (mGameEntity!!.isLibaoExists) { - mLibaoIcon.visibility = View.VISIBLE + mLibaoIcon.goneIf(!mGameEntity!!.isLibaoExists) + } + + private fun setUpTopVideo(topVideo: GameDetailEntity.Video) { + GSYVideoOptionBuilder() + .setIsTouchWigetFull(false) + .setIsTouchWiget(false) + .setRotateViewAuto(false) + .setShowFullAnimation(false) + .setSeekRatio(1f) + .setUrl(topVideo.url) + .setCacheWithPlay(true) + .setVideoAllCallBack(object : GSYSampleCallBack() { + override fun onQuitFullscreen(url: String?, vararg objects: Any) { + mOrientationUtils?.backToProtVideo() + } + }) + .build(mTopVideoView) + + mTopVideoView.gameName = mGameEntity?.name ?: "" + mTopVideoView.updateThumb("${topVideo.url}?x-oss-process=video/snapshot,t_0,f_jpg,w_0,h_0") + + mTopVideoView.fullscreenButton.setOnClickListener { + mOrientationUtils?.resolveByClick() + player.startWindowFullscreen(requireContext(), true, true) + } + + mTopVideoView.observeVolume(this) + } + + private fun updateToolbarStyle(isLightTheme: Boolean) { + if (isLightTheme) { + mToolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_material) + updateConcernIcon(mGameDetailEntity?.me?.isGameConcerned ?: false) + mConcernMenuItem?.setIcon(R.drawable.ic_menu_gamedetail_collect) + mMoreMenuItem?.setIcon(R.drawable.ic_menu_gamedetail_more) } else { - mLibaoIcon.visibility = View.GONE + mToolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_material) + updateConcernIcon(mGameDetailEntity?.me?.isGameConcerned ?: false) + mConcernMenuItem?.setIcon(R.drawable.ic_game_detail_follow_light) + mMoreMenuItem?.setIcon(R.drawable.ic_game_detail_more_light) } } private fun share() { - if (mGameDetailEntity != null) { + mGameDetailEntity?.let { DataCollectionUtils.uploadClick(context, "分享", "游戏详情", mGameEntity!!.name) - GdtHelper.logAction(ActionType.SHARE, - GdtHelper.CONTENT_TYPE, "GAME", - GdtHelper.CONTENT_ID, mGameEntity!!.id) + GdtHelper.logAction(ActionType.SHARE, GdtHelper.CONTENT_TYPE, "GAME", GdtHelper.CONTENT_ID, mGameEntity!!.id) - val url = "http://www.ghzs666.com/game/" + mGameDetailEntity!!.shareCode!! + val url = "http://www.ghzs666.com/game/" + it.shareCode!! if (activity is BaseActivity) { var shareType: ShareUtils.ShareType = ShareUtils.ShareType.game @@ -682,10 +760,38 @@ class GameDetailFragment : NormalFragment() { } } + private fun updateConcernIcon(isConcerned: Boolean) { + if (isConcerned) { + if (TextUtils.isEmpty(mToolbar.title)) { + // 有文字,显示黑色图标 + mConcernMenuItem?.setIcon(R.drawable.ic_game_detail_followed_light) + } else { + mConcernMenuItem?.setIcon(R.drawable.ic_menu_gamedetail_collected) + } + } else { + if (TextUtils.isEmpty(mToolbar.title)) { + // 有文字,显示黑色图标 + mConcernMenuItem?.setIcon(R.drawable.ic_game_detail_follow_light) + } else { + mConcernMenuItem?.setIcon(R.drawable.ic_menu_gamedetail_collect) + } + } + } + private fun tabPerformClick(view: View?) { if (!mIsPageChanged) view!!.performClick() } + override fun onBackPressed(): Boolean { + mOrientationUtils?.backToProtVideo() + + if (GSYVideoManager.backFromWindowFull(requireContext())) { + return true + } + + return super.onBackPressed() + } + companion object { const val INDEX_TRENDES = 0 const val INDEX_DESC = 1 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 c353f84823..b384f95aa4 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailViewModel.kt @@ -9,6 +9,7 @@ import com.gh.common.history.HistoryHelper import com.gh.common.util.ApkActiveUtils import com.gh.common.util.ConcernUtils import com.gh.common.util.DataUtils +import com.gh.common.util.testChannelOnly import com.gh.gamecenter.entity.GameDetailEntity import com.gh.gamecenter.entity.GameEntity import com.gh.gamecenter.mvvm.Resource @@ -85,7 +86,7 @@ class GameDetailViewModel(application: Application, } } - + testChannelOnly { response.topVideo = GameDetailEntity.Video(url = "https://resource.ghzs.com/video/game/5d26e984c391ca0c9a16121c.mp4") } gameDetailLiveData.postValue(Resource.success(response)) } diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/video/TopVideoView.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/video/TopVideoView.kt new file mode 100644 index 0000000000..3377be4ab3 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/video/TopVideoView.kt @@ -0,0 +1,167 @@ +package com.gh.gamecenter.gamedetail.video + +import android.content.Context +import android.os.Handler +import android.util.AttributeSet +import android.view.GestureDetector +import android.view.MotionEvent +import android.view.Surface +import android.view.View +import android.widget.ImageView +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import com.gh.common.observer.MuteCallback +import com.gh.common.observer.VolumeObserver +import com.gh.common.util.MtaHelper +import com.gh.gamecenter.R +import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer +import com.shuyu.gsyvideoplayer.video.base.GSYVideoView +import com.squareup.picasso.Picasso +import kotlinx.android.synthetic.main.piece_video_control.view.* +import kotlinx.android.synthetic.main.piece_video_replay.view.* + +class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : StandardGSYVideoPlayer(context, attrs) { + + var gameName = "" + + private var mMuteCallback : MuteCallback + private var mVolumeObserver : VolumeObserver + + init { + post { + gestureDetector = GestureDetector(getContext().applicationContext, object : GestureDetector.SimpleOnGestureListener() { + override fun onSingleTapConfirmed(e: MotionEvent): Boolean { + if (!mChangePosition && !mChangeVolume && !mBrightness) { + onClickUiToggle() + } + return super.onSingleTapConfirmed(e) + } + }) + } + + mMuteCallback = object : MuteCallback { + override fun onMute(isMute: Boolean) { + if (isMute) { + volume.setImageResource(R.drawable.ic_game_detail_volume_off) + } else { + volume.setImageResource(R.drawable.ic_game_detail_volume_on) + } + } + } + + mVolumeObserver = VolumeObserver(context, Handler(), mMuteCallback) + } + + //这个必须配置最上面的构造才能生效 + override fun getLayoutId(): Int { + return if (mIfCurrentIsFullscreen) R.layout.layout_game_detail_video_landscape else R.layout.layout_game_detail_video_portrait + } + + fun observeVolume(fragment: Fragment?) { + fragment?.context?.applicationContext?.contentResolver?.registerContentObserver( + android.provider.Settings.System.CONTENT_URI, true, mVolumeObserver) + + fragment?.fragmentManager?.registerFragmentLifecycleCallbacks( + object : FragmentManager.FragmentLifecycleCallbacks() { + override fun onFragmentPaused(fm: FragmentManager, f: Fragment) { + if (f === fragment) { + fragment.context?.applicationContext?.contentResolver?.unregisterContentObserver(mVolumeObserver) + fragment.fragmentManager?.unregisterFragmentLifecycleCallbacks(this) + } + } + }, false) + } + + private fun mute() { + volume.setImageResource(R.drawable.ic_game_detail_volume_off) + try { + + } catch (e: Exception) { + e.printStackTrace() + } + MtaHelper.onEvent("游戏详情_新", "视频_点击静音", gameName) + } + + private fun unmute() { + volume.setImageResource(R.drawable.ic_game_detail_volume_on) + try { + + } catch (e: Exception) { + e.printStackTrace() + } + MtaHelper.onEvent("游戏详情_新", "视频_解除静音", gameName) + } + + + fun updateThumb(url: String) { + Picasso.with(context).load(url).into(findViewById(R.id.thumbImage)) + } + + /******************* 下方两个重载方法,在播放开始前不屏蔽封面,不需要可屏蔽 ********************/ + + override fun onSurfaceUpdated(surface: Surface) { + super.onSurfaceUpdated(surface) + if (mThumbImageViewLayout != null && mThumbImageViewLayout.visibility == View.VISIBLE) { + mThumbImageViewLayout.visibility = View.INVISIBLE + } + } + + override fun setViewShowState(view: View?, visibility: Int) { + if (view === mThumbImageViewLayout && visibility != View.VISIBLE) { + return + } + super.setViewShowState(view, visibility) + } + + override fun onCompletion() { + super.onAutoCompletion() + } + + override fun touchDoubleUp() { + // we do not need double click to play or pause + } + + override fun updateStartImage() { + if (mIfCurrentIsFullscreen) { + if (mStartButton is ImageView) { + val imageView = mStartButton as ImageView + when (mCurrentState) { + GSYVideoView.CURRENT_STATE_PLAYING -> imageView.setImageResource(R.drawable.ic_game_detail_pause) + GSYVideoView.CURRENT_STATE_ERROR -> imageView.setImageResource(R.drawable.ic_game_detail_play) + else -> imageView.setImageResource(R.drawable.ic_game_detail_play) + } + } + } else { + super.updateStartImage() + } + } + + override fun setStateAndUi(state: Int) { + super.setStateAndUi(state) + + if (state == CURRENT_STATE_AUTO_COMPLETE) { + hideAllWidget() + replayContainer.visibility = View.VISIBLE + replayIv.setOnClickListener { + startButton.performClick() + } + } else { + replayContainer.visibility = View.GONE + } + } + + override fun getEnlargeImageRes(): Int { + return R.drawable.ic_game_detail_enter_full_screen + } + + override fun getShrinkImageRes(): Int { + return R.drawable.ic_game_detail_exit_full_screen + } + + override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { + if (!isIfCurrentIsFullscreen) { + parent.requestDisallowInterceptTouchEvent(true) + } + return super.onInterceptTouchEvent(ev) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/bg_game_detail_seekbar.xml b/app/src/main/res/drawable-xxhdpi/bg_game_detail_seekbar.xml new file mode 100644 index 0000000000..1974b3d4e6 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/bg_game_detail_seekbar.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/bg_video_control.xml b/app/src/main/res/drawable-xxhdpi/bg_video_control.xml new file mode 100644 index 0000000000..9d9d3ff74d --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/bg_video_control.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_download_light.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_download_light.png new file mode 100644 index 0000000000..885ce6b5dc Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_download_light.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_enter_full_screen.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_enter_full_screen.png new file mode 100644 index 0000000000..7fdd6e824a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_enter_full_screen.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_exit_full_screen.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_exit_full_screen.png new file mode 100644 index 0000000000..25beb95964 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_exit_full_screen.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_follow_light.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_follow_light.png new file mode 100644 index 0000000000..dc5cb19b2e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_follow_light.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_followed_light.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_followed_light.png new file mode 100644 index 0000000000..ba420556c2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_followed_light.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_more_light.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_more_light.png new file mode 100644 index 0000000000..85d8e79939 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_more_light.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_pause.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_pause.png new file mode 100644 index 0000000000..3587a87870 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_pause.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_play.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_play.png new file mode 100644 index 0000000000..0d279a3156 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_play.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_replay.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_replay.png new file mode 100644 index 0000000000..a2a1526f67 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_replay.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_share_light.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_share_light.png new file mode 100644 index 0000000000..f808126774 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_share_light.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_volume_off.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_volume_off.png new file mode 100644 index 0000000000..9f832f5d2c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_volume_off.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_game_detail_volume_on.png b/app/src/main/res/drawable-xxhdpi/ic_game_detail_volume_on.png new file mode 100644 index 0000000000..bdfba06d8b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_game_detail_volume_on.png differ diff --git a/app/src/main/res/layout/activity_game_detail.xml b/app/src/main/res/layout/activity_game_detail.xml new file mode 100644 index 0000000000..3206851478 --- /dev/null +++ b/app/src/main/res/layout/activity_game_detail.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_gamedetail.xml b/app/src/main/res/layout/fragment_gamedetail.xml index 16927e6910..f3eaa826bd 100644 --- a/app/src/main/res/layout/fragment_gamedetail.xml +++ b/app/src/main/res/layout/fragment_gamedetail.xml @@ -1,7 +1,8 @@ - + android:layout_height = "match_parent" + android:fitsSystemWindows = "true"> - - \ No newline at end of file + \ 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 3d16f34f4e..2bb8bbe216 100644 --- a/app/src/main/res/layout/gamedetail_body.xml +++ b/app/src/main/res/layout/gamedetail_body.xml @@ -5,6 +5,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:fitsSystemWindows="true" android:orientation="vertical"> - - - - - - - - - + android:layout_height="match_parent" + android:fitsSystemWindows="true" + app:contentScrim="@color/white" + app:expandedTitleGravity="top" + app:layout_scrollFlags="scroll|exitUntilCollapsed" + app:scrimAnimationDuration="50" + app:scrimVisibleHeightTrigger="105dp" + app:titleEnabled="false"> - + + - - - - - - - - + android:gravity="center_vertical" + android:orientation="horizontal" + android:paddingLeft="16dp" + android:paddingTop="20dp" + android:paddingRight="20dp" + android:paddingBottom="10dp"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/layout_game_detail_video_portrait.xml b/app/src/main/res/layout/layout_game_detail_video_portrait.xml new file mode 100644 index 0000000000..e33b1fbb04 --- /dev/null +++ b/app/src/main/res/layout/layout_game_detail_video_portrait.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/piece_game_detail_video.xml b/app/src/main/res/layout/piece_game_detail_video.xml new file mode 100644 index 0000000000..c95dca7a04 --- /dev/null +++ b/app/src/main/res/layout/piece_game_detail_video.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/piece_video_control.xml b/app/src/main/res/layout/piece_video_control.xml new file mode 100644 index 0000000000..e7d29e5ba3 --- /dev/null +++ b/app/src/main/res/layout/piece_video_control.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/piece_video_replay.xml b/app/src/main/res/layout/piece_video_replay.xml new file mode 100644 index 0000000000..d06a2bcc43 --- /dev/null +++ b/app/src/main/res/layout/piece_video_replay.xml @@ -0,0 +1,26 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index ecf7dd69e1..bbb5fab131 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -226,6 +226,14 @@ @android:style/Animation.Dialog + +