Compare commits
11 Commits
fix/va-tes
...
fix/GHZSCY
| Author | SHA1 | Date | |
|---|---|---|---|
| 90a2f98712 | |||
| c6c6223697 | |||
| b931da86c4 | |||
| 5d4cff5d59 | |||
| 6a157d1d7e | |||
| 9b1598b719 | |||
| 287a725e38 | |||
| 460f20cb2d | |||
| 0f9f0b7c9a | |||
| c29efbefd7 | |||
| 56151bc38d |
@ -72,6 +72,8 @@ android_build:
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feat/GHZSCY-6866
|
||||
- fix/GHZSCY-6939
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
@ -157,3 +159,5 @@ oss-upload&send-email:
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feat/GHZSCY-6866
|
||||
- fix/GHZSCY-6939
|
||||
|
||||
@ -517,10 +517,6 @@
|
||||
android:name=".video.data.VideoDataActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".video.poster.PosterEditActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".forum.detail.ForumDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -809,6 +805,10 @@
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppCompatTheme.APP" />
|
||||
|
||||
<activity
|
||||
android:name=".video.poster.PosterEditActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<!-- <activity-->
|
||||
<!-- android:name="${applicationId}.douyinapi.DouYinEntryActivity"-->
|
||||
<!-- android:launchMode="singleTask"-->
|
||||
|
||||
@ -21,26 +21,31 @@ import com.gh.common.view.RichEditor
|
||||
import com.gh.gamecenter.CropImageActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.LocalVideoEntity
|
||||
import com.gh.gamecenter.feature.selector.LocalMediaActivity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.qa.editor.*
|
||||
import com.gh.gamecenter.entity.GamesCollectionEntity
|
||||
import com.gh.gamecenter.entity.MyVideoEntity
|
||||
import com.gh.gamecenter.entity.VideoEntity
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.feature.entity.ArticleEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.selector.ChooseType
|
||||
import com.gh.gamecenter.feature.selector.LocalMediaActivity
|
||||
import com.gh.gamecenter.qa.editor.*
|
||||
import com.gh.gamecenter.qa.entity.EditorInsertEntity
|
||||
import com.gh.gamecenter.video.poster.PosterEditActivity
|
||||
import com.gh.gamecenter.video.poster.video.VideoPosterFragment
|
||||
import com.gh.gamecenter.video.upload.UploadManager
|
||||
import com.google.gson.JsonObject
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Util_System_Keyboard
|
||||
import com.lightgame.utils.Utils
|
||||
import com.lightgame.view.CheckableImageView
|
||||
import com.therouter.TheRouter
|
||||
import io.reactivex.disposables.Disposable
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
@ -229,6 +234,7 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
|
||||
@SuppressLint("AddJavascriptInterface", "ClickableViewAccessibility")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
VideoPosterFragment.createVideoCoverFile(this)
|
||||
findView()
|
||||
onRichClick()
|
||||
mViewModel = provideViewModel()
|
||||
@ -739,9 +745,9 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
|
||||
mViewModel.id = id
|
||||
mViewModel.videoId = videoId
|
||||
val videoEntity = VideoEntity(url = url)
|
||||
val intent =
|
||||
PosterEditActivity.getIntentByVideo(this@BaseRichEditorActivity, videoEntity)
|
||||
startActivityForResult(intent, REQUEST_CODE_IMAGE_CROP)
|
||||
TheRouter.build(RouteConsts.activity.videoCoverEditActivity)
|
||||
.withParcelable(EntranceConsts.KEY_VIDEO_ENTITY, videoEntity)
|
||||
.navigation(this@BaseRichEditorActivity, REQUEST_CODE_IMAGE_CROP)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
package com.gh.common.iinterface
|
||||
|
||||
interface ISmartRefreshContent {
|
||||
/**
|
||||
* 启用/关闭 页面滑动
|
||||
* @param isScrollEnabled 是否启用
|
||||
*/
|
||||
fun setScrollEnabled(isScrollEnabled: Boolean)
|
||||
import com.scwang.smartrefresh.layout.api.RefreshLayout
|
||||
import com.scwang.smartrefresh.layout.constant.RefreshState
|
||||
|
||||
interface ISmartRefreshContent {
|
||||
fun onRefresh()
|
||||
|
||||
/**
|
||||
@ -14,4 +11,6 @@ interface ISmartRefreshContent {
|
||||
* @param isSwipeRefreshEnabled 是否启用
|
||||
*/
|
||||
fun setSwipeRefreshEnabled(isSwipeRefreshEnabled: Boolean)
|
||||
|
||||
fun onStateChanged(refreshLayout: RefreshLayout, oldState: RefreshState, newState: RefreshState)
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.gh.common.provider
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import com.gh.gamecenter.CropImageActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.core.provider.ICropImageProvider
|
||||
import com.gh.gamecenter.personalhome.background.BackgroundClipActivity
|
||||
import com.halo.assistant.fragment.user.UserPortraitCropImageActivity
|
||||
import com.lightgame.utils.Utils
|
||||
import com.zhihu.matisse.internal.utils.PathUtils
|
||||
|
||||
@com.therouter.inject.ServiceProvider
|
||||
class CropImageProviderImpl : ICropImageProvider {
|
||||
override fun getCropImageIntent(data: List<Uri>, imageType: Int, entrance: String, context: Context): Intent? {
|
||||
if (data.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
val picturePath = PathUtils.getPath(context, data[0])
|
||||
Utils.log("picturePath = $picturePath")
|
||||
return when (imageType) {
|
||||
|
||||
IMAGE_TYPE_AVATAR -> {// 上传头像
|
||||
UserPortraitCropImageActivity.getIntent(
|
||||
context,
|
||||
picturePath,
|
||||
"我的光环(选择头像)"
|
||||
)
|
||||
}
|
||||
|
||||
IMAGE_TYPE_GAME_COLLECTION_COVER -> {// 游戏单封面
|
||||
CropImageActivity.getIntent(
|
||||
context,
|
||||
picturePath,
|
||||
142 / 328F,
|
||||
false,
|
||||
R.layout.layout_game_collection_crop_image_assist,
|
||||
entrance
|
||||
)
|
||||
}
|
||||
|
||||
IMAGE_TYPE_PERSONAL_BACKGROUND -> { // 用户主页背景
|
||||
BackgroundClipActivity.getIntent(context, picturePath, entrance)
|
||||
}
|
||||
|
||||
else ->
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val IMAGE_TYPE_AVATAR = 1
|
||||
const val IMAGE_TYPE_GAME_COLLECTION_COVER = 2
|
||||
const val IMAGE_TYPE_PERSONAL_BACKGROUND = 3
|
||||
}
|
||||
}
|
||||
@ -3,26 +3,25 @@ package com.gh.gamecenter;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity;
|
||||
import com.gh.gamecenter.common.utils.BitmapUtils;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.utils.BitmapUtils;
|
||||
import com.gh.gamecenter.common.view.CropImageCustom;
|
||||
import com.gh.gamecenter.common.view.cropbox.CropBoxStyle;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* 裁剪图片
|
||||
*/
|
||||
@ -32,6 +31,8 @@ public class CropImageActivity extends ToolBarActivity {
|
||||
|
||||
public static final String RESULT_CLIP_PATH = "result_clip_path";
|
||||
|
||||
public static final String RESULT_ORIGINAL_PATH = "result_original_path";
|
||||
|
||||
private SoftReference<Bitmap> reference;
|
||||
|
||||
protected boolean mBlackTheme = false;
|
||||
@ -51,7 +52,7 @@ public class CropImageActivity extends ToolBarActivity {
|
||||
Intent intent = new Intent(context, CropImageActivity.class);
|
||||
intent.putExtra(EntranceConsts.KEY_PATH, picturePath);
|
||||
intent.putExtra(EntranceConsts.KEY_ENTRANCE, entrance);
|
||||
intent.putExtra(EntranceConsts.KEY_IMAGE_CROP_RATIO, cropRatio);
|
||||
intent.putExtra(EntranceConsts.KEY_IMAGE_CROP_STYLE, new CropBoxStyle.Rectangle(cropRatio));
|
||||
intent.putExtra(EntranceConsts.KEY_BLACK_THEME, isBlackTheme);
|
||||
intent.putExtra(EntranceConsts.KEY_ASSIST_RES, assistRes);
|
||||
return intent;
|
||||
@ -68,20 +69,14 @@ public class CropImageActivity extends ToolBarActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mCropImageCustom = findViewById(R.id.cropimage_custom);
|
||||
View statusBarView = findViewById(R.id.status_bar);
|
||||
TextView tvCancel = findViewById(R.id.tv_cancel);
|
||||
TextView tvSubmit = findViewById(R.id.tv_submit);
|
||||
|
||||
mTitleTv.setTextColor(mBlackTheme ? Color.WHITE : Color.BLACK);
|
||||
mToolbar.setBackgroundColor(getResources().getColor(mBlackTheme ? com.gh.gamecenter.common.R.color.text_28282E : com.gh.gamecenter.common.R.color.white));
|
||||
statusBarView.setBackgroundColor(getResources().getColor(mBlackTheme ? com.gh.gamecenter.common.R.color.text_28282E : com.gh.gamecenter.common.R.color.white));
|
||||
|
||||
setNavigationTitle(getString(R.string.title_crop_image));
|
||||
setToolbarMenu(R.menu.menu_positive);
|
||||
MenuItem menuItem = getMenuItem(R.id.layout_menu_positive);
|
||||
TextView menuButton = menuItem.getActionView().findViewById(R.id.menu_answer_post);
|
||||
menuButton.setTextColor(getResources().getColor(com.gh.gamecenter.common.R.color.text_theme));
|
||||
|
||||
float ratio = getIntent().getFloatExtra(EntranceConsts.KEY_IMAGE_CROP_RATIO, 1F);
|
||||
mCropImageCustom.setCropRatio(ratio);
|
||||
CropBoxStyle boxStyle = getIntent().getParcelableExtra(EntranceConsts.KEY_IMAGE_CROP_STYLE);
|
||||
if (boxStyle == null) {
|
||||
boxStyle = new CropBoxStyle.Rectangle(1F);
|
||||
}
|
||||
mCropImageCustom.setCropBoxStyle(boxStyle);
|
||||
|
||||
int assistRes = getIntent().getIntExtra(EntranceConsts.KEY_ASSIST_RES, -1);
|
||||
if (assistRes > 0) {
|
||||
@ -89,8 +84,21 @@ public class CropImageActivity extends ToolBarActivity {
|
||||
addAssistView(view);
|
||||
}
|
||||
|
||||
DisplayUtils.setLightStatusBar(this, !mBlackTheme);
|
||||
DisplayUtils.setStatusBarColor(this, com.gh.gamecenter.common.R.color.transparent, !mBlackTheme);
|
||||
DisplayUtils.setLightStatusBar(this, false);
|
||||
DisplayUtils.setStatusBarColor(this, com.gh.gamecenter.common.R.color.transparent, false);
|
||||
|
||||
tvCancel.setOnClickListener(v -> finish());
|
||||
|
||||
tvSubmit.setOnClickListener(v -> saveImage());
|
||||
}
|
||||
|
||||
protected void saveImage() {
|
||||
Intent data = new Intent();
|
||||
String clipPath = getCacheDir().getAbsolutePath() + File.separator + System.currentTimeMillis() + ".jpg";
|
||||
mCropImageCustom.savePicture(clipPath);
|
||||
data.putExtra(RESULT_CLIP_PATH, clipPath);
|
||||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -98,20 +106,6 @@ public class CropImageActivity extends ToolBarActivity {
|
||||
return mBlackTheme ? com.gh.gamecenter.common.R.drawable.ic_toolbar_back_white : com.gh.gamecenter.common.R.drawable.ic_bar_back;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == R.id.layout_menu_positive) {
|
||||
Intent data = new Intent();
|
||||
String clipPath = getCacheDir().getAbsolutePath() + File.separator + System.currentTimeMillis() + ".jpg";
|
||||
mCropImageCustom.savePicture(clipPath);
|
||||
|
||||
data.putExtra(RESULT_CLIP_PATH, clipPath);
|
||||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
}
|
||||
return super.onMenuItemClick(item);
|
||||
}
|
||||
|
||||
public void addAssistView(View view) {
|
||||
mCropImageCustom.addAssistView(view);
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.os.bundleOf
|
||||
import com.gh.common.provider.CropImageProviderImpl.Companion.IMAGE_TYPE_GAME_COLLECTION_COVER
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.common.util.NewLogUtils
|
||||
@ -45,7 +46,8 @@ class ChooseGameCollectionCoverTypeDialog : BaseDialogFragment() {
|
||||
requireContext(),
|
||||
ChooseType.IMAGE,
|
||||
1,
|
||||
"创建游戏单"
|
||||
"创建游戏单",
|
||||
IMAGE_TYPE_GAME_COLLECTION_COVER
|
||||
), REQUEST_CODE_IMAGE
|
||||
)
|
||||
}
|
||||
@ -101,7 +103,8 @@ class ChooseGameCollectionCoverTypeDialog : BaseDialogFragment() {
|
||||
com.gh.gamecenter.common.R.drawable.bg_choose_option_selector.toDrawable(requireContext())
|
||||
defaultUploadContainer.background =
|
||||
com.gh.gamecenter.common.R.drawable.bg_choose_option_selector.toDrawable(requireContext())
|
||||
cancelBtn.background = com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_999.toDrawable(requireContext())
|
||||
cancelBtn.background =
|
||||
com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_999.toDrawable(requireContext())
|
||||
recommentTv.background = R.drawable.bg_game_collection_cover_tag.toDrawable(requireContext())
|
||||
titleTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(requireContext()))
|
||||
localUploadTitleTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext()))
|
||||
|
||||
@ -313,14 +313,14 @@ class GameCollectionEditActivity : ToolBarActivity(), ChooseGamesAdapter.ItemDra
|
||||
val games = mChooseGamesViewModel.chooseGamesLiveData.value ?: arrayListOf()
|
||||
if (mIsCreateGameCollection) {
|
||||
SensorsBridge.trackEvent("GameCollectCreateSuccess", json {
|
||||
"game_collect_status" to if(mBinding.selfOnlyCb.isChecked) "仅自己可见" else "公开"
|
||||
"game_collect_status" to if (mBinding.selfOnlyCb.isChecked) "仅自己可见" else "公开"
|
||||
"game_num" to games.size
|
||||
"game_collect_title" to mBinding.gameCollectionTitleEt.text.toString().trim()
|
||||
"game_collect_id" to it.data as String
|
||||
})
|
||||
} else if (mViewModel.gameCollectionPatch != null) {
|
||||
SensorsBridge.trackEvent("GameCollectEditSuccess", json {
|
||||
"game_collect_status" to if(mBinding.selfOnlyCb.isChecked) "仅自己可见" else "公开"
|
||||
"game_collect_status" to if (mBinding.selfOnlyCb.isChecked) "仅自己可见" else "公开"
|
||||
"game_num" to games.size
|
||||
"game_collect_title" to mBinding.gameCollectionTitleEt.text.toString().trim()
|
||||
"game_collect_id" to mViewModel.gameCollectionPatch?.id
|
||||
@ -355,7 +355,7 @@ class GameCollectionEditActivity : ToolBarActivity(), ChooseGamesAdapter.ItemDra
|
||||
CheckLoginUtils.checkLogin(this, mEntrance) {}
|
||||
return@observe
|
||||
}
|
||||
ErrorHelper.handleError(this, errorMsg, false, "发布游戏单", "社区实名") {
|
||||
ErrorHelper.handleError(this, errorMsg, false, "发布游戏单", "社区实名") {
|
||||
if (::mMenuPost.isInitialized) {
|
||||
onMenuItemClick(mMenuPost)
|
||||
}
|
||||
@ -433,18 +433,6 @@ class GameCollectionEditActivity : ToolBarActivity(), ChooseGamesAdapter.ItemDra
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (data == null || resultCode != Activity.RESULT_OK) return
|
||||
when (requestCode) {
|
||||
REQUEST_CODE_IMAGE_CROP -> {
|
||||
val imagePath = data.getStringExtra(CropImageActivity.RESULT_CLIP_PATH) ?: ""
|
||||
mViewModel.imageUrl = ""
|
||||
mViewModel.imagePath = imagePath
|
||||
if (imagePath.isEmpty()) {
|
||||
mBinding.uploadPictureTv.text = "点击上传图片"
|
||||
} else {
|
||||
mBinding.uploadPictureTv.text = "图片上传中..."
|
||||
mViewModel.uploadPoster()
|
||||
}
|
||||
initPosterUI()
|
||||
}
|
||||
REQUEST_CHOOSE_TAG -> {
|
||||
val tags = data.getParcelableArrayListExtra<TagInfoEntity>(GameCollectionTagSelectFragment.SELECTED_TAG)
|
||||
?: arrayListOf()
|
||||
@ -457,20 +445,16 @@ class GameCollectionEditActivity : ToolBarActivity(), ChooseGamesAdapter.ItemDra
|
||||
fun onActivityDialogResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
if (requestCode == REQUEST_CODE_IMAGE) {
|
||||
val selectedPaths = Matisse.obtainResult(data)
|
||||
if (!selectedPaths.isNullOrEmpty()) {
|
||||
val path = PathUtils.getPath(this, selectedPaths[0])
|
||||
val intent =
|
||||
CropImageActivity.getIntent(
|
||||
this,
|
||||
path,
|
||||
142 / 328F,
|
||||
false,
|
||||
R.layout.layout_game_collection_crop_image_assist,
|
||||
mEntrance
|
||||
)
|
||||
startActivityForResult(intent, REQUEST_CODE_IMAGE_CROP)
|
||||
val imagePath = data.getStringExtra(CropImageActivity.RESULT_CLIP_PATH) ?: ""
|
||||
mViewModel.imageUrl = ""
|
||||
mViewModel.imagePath = imagePath
|
||||
if (imagePath.isEmpty()) {
|
||||
mBinding.uploadPictureTv.text = "点击上传图片"
|
||||
} else {
|
||||
mBinding.uploadPictureTv.text = "图片上传中..."
|
||||
mViewModel.uploadPoster()
|
||||
}
|
||||
initPosterUI()
|
||||
} else if (requestCode == ChooseGameCollectionDefaultCoverDialog.REQUEST_CODE_DEFAULT_IMAGE) {
|
||||
val entity = data.getParcelableExtra<GameCollectionCoverEntity>(EntranceConsts.KEY_DATA)
|
||||
if (entity != null) {
|
||||
@ -731,9 +715,17 @@ class GameCollectionEditActivity : ToolBarActivity(), ChooseGamesAdapter.ItemDra
|
||||
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
} else {
|
||||
DialogHelper.showDialog(this, "温馨提示", "游戏单会在1-2个工作日内审核完成,您可以在“我的光环-我的游戏单”查看进度", "继续提交", "取消", {
|
||||
mViewModel.uploadContent(this, requestMap)
|
||||
}, extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true))
|
||||
DialogHelper.showDialog(
|
||||
this,
|
||||
"温馨提示",
|
||||
"游戏单会在1-2个工作日内审核完成,您可以在“我的光环-我的游戏单”查看进度",
|
||||
"继续提交",
|
||||
"取消",
|
||||
{
|
||||
mViewModel.uploadContent(this, requestMap)
|
||||
},
|
||||
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -804,7 +796,8 @@ class GameCollectionEditActivity : ToolBarActivity(), ChooseGamesAdapter.ItemDra
|
||||
activityDivider.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_divider.toColor(this@GameCollectionEditActivity))
|
||||
titleDivider.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_divider.toColor(this@GameCollectionEditActivity))
|
||||
introduceDivider.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_divider.toColor(this@GameCollectionEditActivity))
|
||||
placeholderView.background = com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_8.toDrawable(this@GameCollectionEditActivity)
|
||||
placeholderView.background =
|
||||
com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_8.toDrawable(this@GameCollectionEditActivity)
|
||||
selfOnlyCb.background =
|
||||
R.drawable.border_round_stroke_0dot5_eee_999.toDrawable(this@GameCollectionEditActivity)
|
||||
uploadPictureTv.setTextColor(com.gh.gamecenter.common.R.color.text_instance.toColor(this@GameCollectionEditActivity))
|
||||
@ -912,7 +905,6 @@ class GameCollectionEditActivity : ToolBarActivity(), ChooseGamesAdapter.ItemDra
|
||||
companion object {
|
||||
|
||||
const val REQUEST_CODE_IMAGE = 100
|
||||
const val REQUEST_CODE_IMAGE_CROP = 101
|
||||
const val REQUEST_CHOOSE_GAMES = 102
|
||||
const val REQUEST_CHOOSE_TAG = 103
|
||||
const val REQUEST_CHOOSE_ACTIVITY = 105
|
||||
|
||||
@ -69,6 +69,9 @@ import com.gh.gamecenter.wrapper.SearchToolbarTabWrapperViewModel
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.scwang.smartrefresh.layout.api.RefreshLayout
|
||||
import com.scwang.smartrefresh.layout.constant.RefreshState
|
||||
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
@ -743,7 +746,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
|
||||
}
|
||||
}
|
||||
|
||||
override fun setScrollEnabled(isScrollEnabled: Boolean) {
|
||||
private fun setScrollEnabled(isScrollEnabled: Boolean) {
|
||||
if (::layoutManager.isInitialized) {
|
||||
layoutManager.isScrollVerticallyEnabled = isScrollEnabled
|
||||
}
|
||||
@ -759,6 +762,32 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStateChanged(refreshLayout: RefreshLayout, oldState: RefreshState, newState: RefreshState) {
|
||||
if (oldState == RefreshState.None && newState == RefreshState.PullDownToRefresh) {
|
||||
pauseVideo()
|
||||
} else if ((oldState == RefreshState.TwoLevelFinish || oldState == RefreshState.RefreshFinish) && newState == RefreshState.None) {
|
||||
val currentPlayer = scrollCalculatorHelper.currentPlayer
|
||||
if (currentPlayer == null) {
|
||||
scrollCalculatorHelper.playIfValid()
|
||||
} else if (currentPlayer.currentState == GSYVideoView.CURRENT_STATE_PAUSE) {
|
||||
resumeVideo()
|
||||
}
|
||||
}
|
||||
|
||||
when (newState) {
|
||||
RefreshState.TwoLevel -> {
|
||||
setScrollEnabled(false)
|
||||
}
|
||||
RefreshState.None -> {
|
||||
setScrollEnabled(true)
|
||||
}
|
||||
|
||||
else -> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun scrollToTop() {
|
||||
if (::binding.isInitialized) {
|
||||
binding.gameList.stopScroll()
|
||||
|
||||
@ -363,7 +363,7 @@ class CommonContentHomeSlideWithCardsUi(
|
||||
homeSlideCardItemBinding.cardIv.visibility = View.VISIBLE
|
||||
// 防止重复加载图片导致闪烁
|
||||
if (homeSubSlide.image != cardIv.getTag(R.string.tag_img_url_id)) {
|
||||
ImageUtils.display(cardIv, homeSubSlide.image, false, AlphaGradientProcess())
|
||||
ImageUtils.display(cardIv, homeSubSlide.image, true, AlphaGradientProcess())
|
||||
cardIv.setTag(R.string.tag_img_url_id, homeSubSlide.image)
|
||||
}
|
||||
ConstraintSet().apply {
|
||||
@ -398,7 +398,7 @@ class CommonContentHomeSlideWithCardsUi(
|
||||
descTv.text = homeSubSlide.cardDesc
|
||||
// 防止重复加载图片导致闪烁
|
||||
if (homeSubSlide.image != cardIv.getTag(R.string.tag_img_url_id)) {
|
||||
ImageUtils.display(cardIv, homeSubSlide.image, false, AlphaGradientProcess())
|
||||
ImageUtils.display(cardIv, homeSubSlide.image, true, AlphaGradientProcess())
|
||||
cardIv.setTag(R.string.tag_img_url_id, homeSubSlide.image)
|
||||
}
|
||||
ConstraintSet().apply {
|
||||
|
||||
@ -109,7 +109,9 @@ class CustomHomeGameItemViewHolder(
|
||||
item.linkColumn?.id ?: ""
|
||||
)
|
||||
}
|
||||
binding.gameBrief.text = game.recommendText
|
||||
binding.gameBrief.goneIf(game.recommendText.isEmpty()) {
|
||||
binding.gameBrief.text = game.recommendText
|
||||
}
|
||||
binding.gameImage.visibleIf(game.showImage) {
|
||||
if (game.isWechatMiniGame()) {
|
||||
ImageUtils.display(binding.gameImage, game.banner)
|
||||
|
||||
@ -29,7 +29,10 @@ class ScrollCalculatorHelper(
|
||||
|
||||
fun enableAndPlayIfValid() {
|
||||
isEnabled = true
|
||||
playIfValid()
|
||||
}
|
||||
|
||||
fun playIfValid() {
|
||||
if (mListRv.isAttachedToWindow
|
||||
&& mListRv.scrollState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
playVideo(mListRv)
|
||||
|
||||
@ -6,14 +6,16 @@ import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Bundle
|
||||
import android.widget.ImageView
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
|
||||
import com.gh.gamecenter.common.utils.BitmapUtils
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.common.provider.CropImageProviderImpl.Companion.IMAGE_TYPE_PERSONAL_BACKGROUND
|
||||
import com.gh.gamecenter.CropImageActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.BitmapUtils
|
||||
import com.gh.gamecenter.common.view.cropbox.CropBoxStyle
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.ActivityBackgroundClipBinding
|
||||
import java.io.File
|
||||
import java.lang.ref.SoftReference
|
||||
@ -33,7 +35,6 @@ class BackgroundClipActivity : BaseActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
DisplayUtils.transparentStatusBar(this)
|
||||
mBinding = ActivityBackgroundClipBinding.bind(mContentView)
|
||||
mBinding.cropImageIv.setCropRatio(392 / 360F)
|
||||
|
||||
mBinding.cancelTv.setOnClickListener {
|
||||
finish()
|
||||
@ -84,6 +85,8 @@ class BackgroundClipActivity : BaseActivity() {
|
||||
val intent = Intent(context, BackgroundClipActivity::class.java)
|
||||
intent.putExtra(EntranceConsts.KEY_PATH, picturePath)
|
||||
intent.putExtra(EntranceConsts.KEY_ENTRANCE, entrance)
|
||||
intent.putExtra(EntranceConsts.KEY_IMAGE_CROP_STYLE, CropBoxStyle.Rectangle(356F / 328))
|
||||
intent.putExtra(EntranceConsts.KEY_IMAGE_TYPE, IMAGE_TYPE_PERSONAL_BACKGROUND)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import android.view.View
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.provider.CropImageProviderImpl.Companion.IMAGE_TYPE_PERSONAL_BACKGROUND
|
||||
import com.gh.gamecenter.CropImageActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
@ -78,7 +79,8 @@ class PersonalityBackgroundFragment : ToolbarFragment() {
|
||||
requireContext(),
|
||||
ChooseType.IMAGE,
|
||||
1,
|
||||
"个性背景"
|
||||
"个性背景",
|
||||
IMAGE_TYPE_PERSONAL_BACKGROUND
|
||||
), MEDIA_STORE_REQUEST
|
||||
)
|
||||
}
|
||||
@ -89,19 +91,15 @@ class PersonalityBackgroundFragment : ToolbarFragment() {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
if (requestCode == MEDIA_STORE_REQUEST && resultCode == Activity.RESULT_OK) {
|
||||
val selectedPaths = Matisse.obtainPathResult(data)
|
||||
if (!selectedPaths.isNullOrEmpty()) {
|
||||
val intent = BackgroundClipActivity.getIntent(requireContext(), selectedPaths[0], mEntrance)
|
||||
startActivityForResult(intent, REQUEST_CODE_IMAGE_CROP)
|
||||
}
|
||||
} else if (requestCode == REQUEST_CODE_IMAGE_CROP && resultCode == Activity.RESULT_OK) {
|
||||
if (data != null) {
|
||||
val imagePath = data.getStringExtra(CropImageActivity.RESULT_CLIP_PATH)
|
||||
val intent = BackgroundPreviewActivity.getIntent(
|
||||
requireContext(), imagePath
|
||||
?: "", null
|
||||
)
|
||||
requireActivity().startActivityForResult(intent, CHANGE_BACKGROUND_SUCCESS)
|
||||
if (imagePath != null) {
|
||||
val intent = BackgroundPreviewActivity.getIntent(
|
||||
requireContext(), imagePath
|
||||
?: "", null
|
||||
)
|
||||
requireActivity().startActivityForResult(intent, CHANGE_BACKGROUND_SUCCESS)
|
||||
}
|
||||
}
|
||||
} else if (requestCode == CHANGE_BACKGROUND_SUCCESS && resultCode == Activity.RESULT_OK) {
|
||||
requireActivity().finish()
|
||||
@ -119,7 +117,6 @@ class PersonalityBackgroundFragment : ToolbarFragment() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val REQUEST_CODE_IMAGE_CROP = 100
|
||||
const val MEDIA_STORE_REQUEST = 101
|
||||
const val CHANGE_BACKGROUND_SUCCESS = 102
|
||||
}
|
||||
|
||||
@ -40,6 +40,7 @@ import com.gh.gamecenter.qa.editor.GameActivity
|
||||
import com.gh.gamecenter.qa.entity.ArticleDetailEntity
|
||||
import com.gh.gamecenter.qa.questions.edit.TagsSelectFragment
|
||||
import com.gh.gamecenter.qa.video.publish.VideoPublishFragment
|
||||
import com.gh.gamecenter.video.poster.video.VideoPosterFragment
|
||||
import com.lightgame.utils.Util_System_Keyboard
|
||||
import com.lightgame.utils.Utils
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
@ -123,6 +124,7 @@ class ArticleEditActivity : BaseRichEditorActivity<ArticleEditViewModel>(), Keyb
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
VideoPosterFragment.clearVideoCoverCache(this)
|
||||
updateStatusBarColor(com.gh.gamecenter.common.R.color.ui_surface, com.gh.gamecenter.common.R.color.ui_surface)
|
||||
mBinding = ActivityCommunityArticleEditBinding.bind(mContentView)
|
||||
setToolbarMenu(R.menu.menu_answer_post)
|
||||
@ -651,8 +653,14 @@ class ArticleEditActivity : BaseRichEditorActivity<ArticleEditViewModel>(), Keyb
|
||||
|
||||
private fun setForumUI() {
|
||||
mBinding.forumIconView.visibility = View.VISIBLE
|
||||
mBinding.forumContainer.background = ContextCompat.getDrawable(this, com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_999)
|
||||
mBinding.articleGameName.setTextColor(ContextCompat.getColor(this, com.gh.gamecenter.common.R.color.text_secondary))
|
||||
mBinding.forumContainer.background =
|
||||
ContextCompat.getDrawable(this, com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_999)
|
||||
mBinding.articleGameName.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
this,
|
||||
com.gh.gamecenter.common.R.color.text_secondary
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun setSectionUI(isEmpty: Boolean) {
|
||||
|
||||
@ -50,6 +50,7 @@ import com.gh.gamecenter.qa.entity.QuestionsDetailEntity
|
||||
import com.gh.gamecenter.qa.questions.draft.QuestionDraftActivity
|
||||
import com.gh.gamecenter.qa.questions.edit.tip.QuestionTitleTipAdapter
|
||||
import com.gh.gamecenter.qa.video.publish.VideoPublishFragment
|
||||
import com.gh.gamecenter.video.poster.video.VideoPosterFragment
|
||||
import com.lightgame.utils.Util_System_Keyboard
|
||||
import com.lightgame.utils.Utils
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
@ -147,6 +148,7 @@ class QuestionEditActivity : BaseRichEditorActivity<QuestionEditViewModel>(),
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
VideoPosterFragment.clearVideoCoverCache(this)
|
||||
updateStatusBarColor(com.gh.gamecenter.common.R.color.ui_surface, com.gh.gamecenter.common.R.color.ui_surface)
|
||||
setToolbarMenu(R.menu.menu_question_post)
|
||||
mToolbar.navigationIcon = null
|
||||
@ -280,12 +282,14 @@ class QuestionEditActivity : BaseRichEditorActivity<QuestionEditViewModel>(),
|
||||
detailEntity != null -> { // 问题编辑
|
||||
setPatchContent(detailEntity)
|
||||
}
|
||||
|
||||
draftEntity != null -> { //草稿编辑
|
||||
mViewModel.questionDraftEntity = draftEntity
|
||||
setQuestionDraft(draftEntity)
|
||||
mViewModel.getQuestionDraftContent(draftEntity.id)
|
||||
mBaseHandler.sendEmptyMessageDelayed(1, SAVE_DRAFTS_INTERVAL_TIME.toLong())
|
||||
}
|
||||
|
||||
else -> { // 新增问题
|
||||
var searchKey = intent.getStringExtra(EntranceConsts.KEY_QUESTIONS_SEARCH_KEY)
|
||||
if (!searchKey.isNullOrEmpty() && searchKey.length > QuestionEditViewModel.QUESTION_TITLE_MAX_LENGTH)
|
||||
@ -468,6 +472,7 @@ class QuestionEditActivity : BaseRichEditorActivity<QuestionEditViewModel>(),
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
SaveDraftType.AUTO -> {
|
||||
if (pair.second) {
|
||||
if (mPostDraftsCount >= SAVE_DRAFTS_TOAST_COUNT) {
|
||||
@ -478,6 +483,7 @@ class QuestionEditActivity : BaseRichEditorActivity<QuestionEditViewModel>(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SaveDraftType.SKIP -> {
|
||||
if (pair.second) {
|
||||
Utils.toast(this, "问题已保存到草稿箱")
|
||||
@ -690,7 +696,12 @@ class QuestionEditActivity : BaseRichEditorActivity<QuestionEditViewModel>(),
|
||||
return false
|
||||
}
|
||||
DialogHelper.showDialog(
|
||||
this, "提示", "确定退出修改?已编辑的内容将丢失", "继续编辑", " 退出", cancelClickCallback = { finish() },
|
||||
this,
|
||||
"提示",
|
||||
"确定退出修改?已编辑的内容将丢失",
|
||||
"继续编辑",
|
||||
" 退出",
|
||||
cancelClickCallback = { finish() },
|
||||
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
return true
|
||||
@ -847,7 +858,12 @@ class QuestionEditActivity : BaseRichEditorActivity<QuestionEditViewModel>(),
|
||||
mBinding.forumIconView.visibility = View.VISIBLE
|
||||
mBinding.forumContainer.background =
|
||||
ContextCompat.getDrawable(this, com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_999)
|
||||
mBinding.chooseForumTv.setTextColor(ContextCompat.getColor(this, com.gh.gamecenter.common.R.color.text_secondary))
|
||||
mBinding.chooseForumTv.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
this,
|
||||
com.gh.gamecenter.common.R.color.text_secondary
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun setSectionUI(isEmpty: Boolean) {
|
||||
|
||||
@ -13,6 +13,7 @@ import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.qa.BbsType
|
||||
import com.gh.gamecenter.video.poster.video.VideoPosterFragment
|
||||
|
||||
/**
|
||||
* 发视频
|
||||
@ -22,6 +23,7 @@ class VideoPublishActivity : ToolBarActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
VideoPosterFragment.clearVideoCoverCache(this)
|
||||
updateStatusBarColor(com.gh.gamecenter.common.R.color.ui_surface, com.gh.gamecenter.common.R.color.ui_surface)
|
||||
mToolbar.navigationIcon = null
|
||||
findViewById<View>(R.id.backBtn).setOnClickListener { onBackPressed() }
|
||||
|
||||
@ -23,20 +23,24 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
import com.gh.gamecenter.common.entity.LocalVideoEntity
|
||||
import com.gh.gamecenter.common.entity.NotificationUgc
|
||||
import com.gh.gamecenter.common.mvvm.Status
|
||||
import com.gh.gamecenter.feature.selector.LocalMediaActivity
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.runOnUiThread
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentVideoPublishBinding
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.entity.ActivityLabelEntity
|
||||
import com.gh.gamecenter.entity.ForumDetailEntity
|
||||
import com.gh.gamecenter.entity.VideoDraftEntity
|
||||
import com.gh.gamecenter.entity.VideoEntity
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.selector.ChooseType
|
||||
import com.gh.gamecenter.feature.selector.LocalMediaActivity
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.qa.BbsType
|
||||
import com.gh.gamecenter.qa.dialog.ChooseActivityDialogFragment
|
||||
@ -44,12 +48,12 @@ import com.gh.gamecenter.qa.dialog.ChooseForumActivity
|
||||
import com.gh.gamecenter.qa.dialog.ChooseSectionDialogFragment
|
||||
import com.gh.gamecenter.qa.dialog.InputUrlDialogFragment
|
||||
import com.gh.gamecenter.qa.editor.GameActivity
|
||||
import com.gh.gamecenter.video.poster.PosterEditActivity
|
||||
import com.gh.gamecenter.video.upload.OnUploadListener
|
||||
import com.gh.gamecenter.video.upload.UploadManager
|
||||
import com.gh.gamecenter.video.upload.view.VideoFileEntity
|
||||
import com.gh.gamecenter.video.videomanager.VideoDraftActivity
|
||||
import com.lightgame.utils.Util_System_Keyboard
|
||||
import com.therouter.TheRouter
|
||||
import java.io.File
|
||||
|
||||
class VideoPublishFragment : ToolbarFragment(), KeyboardHeightObserver {
|
||||
@ -661,7 +665,8 @@ class VideoPublishFragment : ToolbarFragment(), KeyboardHeightObserver {
|
||||
|
||||
private fun setForumUI() {
|
||||
mBinding.forumIconView.visibility = View.VISIBLE
|
||||
mBinding.forumContainer.background = com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_999.toDrawable(requireContext())
|
||||
mBinding.forumContainer.background =
|
||||
com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_999.toDrawable(requireContext())
|
||||
mBinding.chooseForumTv.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
|
||||
}
|
||||
|
||||
@ -757,29 +762,24 @@ class VideoPublishFragment : ToolbarFragment(), KeyboardHeightObserver {
|
||||
private fun startMediaStore() {
|
||||
try {
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(requireContext()) {
|
||||
var intent: Intent? = null
|
||||
val postcard = TheRouter.build(RouteConsts.activity.videoCoverEditActivity)
|
||||
when {
|
||||
mVideoFileEntity?.url?.isNotEmpty() == true -> {
|
||||
val videoEntity = VideoEntity(
|
||||
length = mVideoFileEntity?.length ?: 0, url = mVideoFileEntity?.url ?: ""
|
||||
)
|
||||
intent = PosterEditActivity.getIntentByVideo(
|
||||
requireContext(),
|
||||
videoEntity
|
||||
)
|
||||
postcard.withParcelable(EntranceConsts.KEY_VIDEO_ENTITY, videoEntity)
|
||||
}
|
||||
|
||||
mVideoFileEntity?.path?.isNotEmpty() == true -> {
|
||||
intent = PosterEditActivity.getIntentByPath(
|
||||
requireContext(), mVideoFileEntity?.url ?: ""
|
||||
)
|
||||
postcard.withString(EntranceConsts.KEY_PATH_VIDEO, mVideoFileEntity?.url ?: "")
|
||||
}
|
||||
|
||||
else -> {
|
||||
throwExceptionInDebug("video not found")
|
||||
}
|
||||
}
|
||||
startActivityForResult(intent, REQUEST_CODE_IMAGE_CROP)
|
||||
postcard.navigation(requireActivity(), REQUEST_CODE_IMAGE_CROP)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
toast(R.string.media_image_hint)
|
||||
@ -966,9 +966,11 @@ class VideoPublishFragment : ToolbarFragment(), KeyboardHeightObserver {
|
||||
super.onDarkModeChanged()
|
||||
setSectionUI(mViewModel.selectSection == null)
|
||||
mBinding.activityTv.setTextColor(
|
||||
if (mViewModel.selectActivityLabelEntity != null) com.gh.gamecenter.common.R.color.text_FA8500.toColor(requireContext()) else com.gh.gamecenter.common.R.color.text_primary.toColor(
|
||||
requireContext()
|
||||
)
|
||||
if (mViewModel.selectActivityLabelEntity != null) {
|
||||
com.gh.gamecenter.common.R.color.text_FA8500.toColor(requireContext())
|
||||
} else {
|
||||
com.gh.gamecenter.common.R.color.text_primary.toColor(requireContext())
|
||||
}
|
||||
)
|
||||
mBinding.forumContainer.background =
|
||||
if (mViewModel.communityEntity == null) R.drawable.button_round_primary_light.toDrawable(requireContext()) else com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_999.toDrawable(
|
||||
|
||||
@ -1,231 +1,34 @@
|
||||
package com.gh.gamecenter.video.poster
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.gh.gamecenter.CropImageActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity_TabLayout
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment_TabLayout
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.ActivityPosterEditBinding
|
||||
import com.gh.gamecenter.entity.VideoEntity
|
||||
import com.gh.gamecenter.video.poster.photo.PhotoAlbumsAdapter
|
||||
import com.gh.gamecenter.video.poster.photo.PhotoAlbumsSpanner
|
||||
import com.gh.gamecenter.video.poster.photo.PhotoPosterFragment
|
||||
import com.gh.gamecenter.video.poster.video.VideoPosterFragment
|
||||
import com.gh.gamecenter.video.upload.view.UploadVideoActivity
|
||||
import com.zhihu.matisse.Matisse
|
||||
import com.zhihu.matisse.MimeType
|
||||
import com.zhihu.matisse.internal.entity.Album
|
||||
import com.zhihu.matisse.internal.entity.SelectionSpec
|
||||
import com.zhihu.matisse.internal.model.AlbumCollection
|
||||
import java.io.File
|
||||
import com.therouter.TheRouter
|
||||
import com.therouter.router.Route
|
||||
|
||||
class PosterEditActivity : BaseActivity_TabLayout(), AdapterView.OnItemSelectedListener,
|
||||
AlbumCollection.AlbumCallbacks {
|
||||
|
||||
private lateinit var mBinding: ActivityPosterEditBinding
|
||||
|
||||
private val mAlbumCollection = AlbumCollection()
|
||||
|
||||
private lateinit var mAlbumsSpinner: PhotoAlbumsSpanner
|
||||
private lateinit var mAlbumsAdapter: PhotoAlbumsAdapter
|
||||
|
||||
private lateinit var mPhotoPosterFragment: PhotoPosterFragment
|
||||
private lateinit var mVideoPosterFragment: VideoPosterFragment
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (UploadVideoActivity.REQUEST_CODE_IMAGE_CROP == requestCode && resultCode == Activity.RESULT_OK) {
|
||||
setResult(Activity.RESULT_OK, data)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun provideTabView(position: Int, tabTitle: String?): View {
|
||||
val tabCustomView = BaseFragment_TabLayout.createDefaultTabCustomView(this, tabTitle)
|
||||
tabCustomView.findViewById<TextView>(R.id.tab_title)
|
||||
.setTextColor(resources.getColorStateList(R.color.poster_text_tabbar_style))
|
||||
return tabCustomView
|
||||
}
|
||||
|
||||
override fun initFragmentList(fragments: MutableList<Fragment>) {
|
||||
val videoPath = intent.getStringExtra(EntranceConsts.KEY_PATH_VIDEO)
|
||||
val videoEntity = intent.getParcelableExtra<VideoEntity>(VideoEntity::class.java.simpleName)
|
||||
mPhotoPosterFragment = PhotoPosterFragment()
|
||||
mVideoPosterFragment = VideoPosterFragment.newInstance(videoPath, videoEntity)
|
||||
fragments.add(mVideoPosterFragment)
|
||||
fragments.add(mPhotoPosterFragment)
|
||||
}
|
||||
|
||||
override fun initTabTitleList(tabTitleList: MutableList<String>) {
|
||||
tabTitleList.add("视频截图")
|
||||
tabTitleList.add("相册选择")
|
||||
}
|
||||
@Route(path = RouteConsts.activity.videoCoverEditActivity)
|
||||
class PosterEditActivity : BaseActivity() {
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.activity_poster_edit
|
||||
return R.layout.actvitity_video_cover_edit
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
TheRouter.inject(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
Matisse.from(this).choose(MimeType.ofImage()).showSingleMediaType(true)
|
||||
DisplayUtils.setLightStatusBar(this, false)
|
||||
setStatusBarColor(Color.TRANSPARENT)
|
||||
|
||||
setNavigationTitle("编辑封面")
|
||||
|
||||
initView()
|
||||
initAlbumsSpinner()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
mBinding = ActivityPosterEditBinding.bind(mContentView)
|
||||
|
||||
mBinding.activityViewPager.setScrollable(false)
|
||||
mBinding.activityViewPager.addOnPageChangeListener {
|
||||
if (VIDEO_POSTER_INDEX == it) {
|
||||
setNavigationTitle("编辑封面")
|
||||
mTitleTv.removeDrawable()
|
||||
} else {
|
||||
setPhotoNavigationTitle(false)
|
||||
}
|
||||
}
|
||||
mBinding.confirm.setOnClickListener {
|
||||
val selectImagePath = getSelectImagePath()
|
||||
if (selectImagePath != null) {
|
||||
if (mBinding.activityViewPager.currentItem == 0) {
|
||||
val data = Intent()
|
||||
data.putExtra(CropImageActivity.RESULT_CLIP_PATH, selectImagePath)
|
||||
setResult(Activity.RESULT_OK, data)
|
||||
finish()
|
||||
} else {
|
||||
val intent = CropImageActivity.getIntent(this, selectImagePath, 9 / 16F, mEntrance)
|
||||
startActivityForResult(intent, UploadVideoActivity.REQUEST_CODE_IMAGE_CROP)
|
||||
}
|
||||
} else {
|
||||
toast("请选择图片")
|
||||
}
|
||||
}
|
||||
mTitleTv.setOnClickListener {
|
||||
setPhotoNavigationTitle(true)
|
||||
mAlbumsSpinner.show(mBinding.activityViewPager.height)
|
||||
}
|
||||
|
||||
DisplayUtils.transparentStatusBar(this)
|
||||
mBaseHandler.postDelayed({
|
||||
mBinding.activityTabIndicator.generatePath(
|
||||
mBinding.activityViewPager.currentItem,
|
||||
0F
|
||||
)
|
||||
}, 10)
|
||||
}
|
||||
|
||||
private fun initAlbumsSpinner() {
|
||||
mAlbumsAdapter = PhotoAlbumsAdapter(this)
|
||||
mAlbumsSpinner = PhotoAlbumsSpanner(this)
|
||||
|
||||
mAlbumsSpinner.setPopupAnchorView(findViewById(R.id.normal_toolbar))
|
||||
mAlbumsSpinner.setAdapter(mAlbumsAdapter)
|
||||
mAlbumsSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
mAlbumCollection.setStateCurrentSelection(position)
|
||||
mAlbumsAdapter.cursor.moveToPosition(position)
|
||||
val album = Album.valueOf(mAlbumsAdapter.cursor)
|
||||
if (album.isAll && SelectionSpec.getInstance().capture) {
|
||||
album.addCaptureCount()
|
||||
}
|
||||
if (mPhotoPosterFragment.isAdded) {
|
||||
mPhotoPosterFragment.loadPhotos(album)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mAlbumsSpinner.setDismissListener(PopupWindow.OnDismissListener {
|
||||
setPhotoNavigationTitle(false)
|
||||
})
|
||||
|
||||
mAlbumCollection.onCreate(this, this)
|
||||
mAlbumCollection.loadAlbums()
|
||||
}
|
||||
|
||||
|
||||
private fun setPhotoNavigationTitle(up: Boolean) {
|
||||
if (mBinding.activityViewPager.currentItem == VIDEO_POSTER_INDEX) return
|
||||
mTitleTv.setDrawableEnd(if (up) R.drawable.poster_select_up else R.drawable.poster_select_down)
|
||||
mTitleTv.compoundDrawablePadding = 2F.dip2px()
|
||||
mTitleTv.text = "全部图片"
|
||||
}
|
||||
|
||||
private fun getSelectImagePath(): String? {
|
||||
if (mBinding.activityViewPager.currentItem == VIDEO_POSTER_INDEX) {
|
||||
val clipPath = cacheDir.absolutePath + File.separator + System.currentTimeMillis() + ".jpg"
|
||||
mVideoPosterFragment.savePicture(clipPath)
|
||||
return clipPath
|
||||
} else {
|
||||
return mPhotoPosterFragment.getSelectImagePath()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
||||
}
|
||||
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
}
|
||||
|
||||
override fun onAlbumLoad(cursor: Cursor?) {
|
||||
mAlbumsAdapter.swapCursor(cursor)
|
||||
mBaseHandler.post {
|
||||
cursor?.moveToPosition(mAlbumCollection.currentSelection)
|
||||
val album = Album.valueOf(cursor)
|
||||
if (album.isAll && SelectionSpec.getInstance().capture) {
|
||||
album.addCaptureCount()
|
||||
}
|
||||
if (::mPhotoPosterFragment.isInitialized && mPhotoPosterFragment.isAdded) {
|
||||
mPhotoPosterFragment.loadPhotos(album)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAlbumReset() {
|
||||
}
|
||||
|
||||
override fun provideNavigationIcon(): Int {
|
||||
return com.gh.gamecenter.common.R.drawable.ic_toolbar_back_white
|
||||
}
|
||||
|
||||
override fun handleBackPressed(): Boolean {
|
||||
DialogHelper.showDialog(this, "提示", "确定放弃编辑封面吗?", "确定", "暂不", { finish() })
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val VIDEO_POSTER_INDEX = 0
|
||||
private const val PHOTO_POSTER_INDEX = 1
|
||||
|
||||
fun getIntentByPath(context: Context, videoPath: String): Intent {
|
||||
val intent = Intent(context, PosterEditActivity::class.java)
|
||||
intent.putExtra(EntranceConsts.KEY_PATH_VIDEO, videoPath)
|
||||
return intent
|
||||
}
|
||||
|
||||
fun getIntentByVideo(context: Context, videoEntity: VideoEntity): Intent {
|
||||
val intent = Intent(context, PosterEditActivity::class.java)
|
||||
intent.putExtra(VideoEntity::class.java.simpleName, videoEntity)
|
||||
return intent
|
||||
}
|
||||
val tag = VideoPosterFragment::class.java.name
|
||||
val fragment = supportFragmentManager.findFragmentByTag(tag) ?: VideoPosterFragment.newInstance()
|
||||
fragment.arguments = intent.extras
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.fcv_container, fragment, tag)
|
||||
.commitNowAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
package com.gh.gamecenter.video.poster
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
|
||||
class PreviewMaskView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
defStyleRes: Int = 0
|
||||
) :
|
||||
View(context, attrs, defStyleAttr, defStyleRes) {
|
||||
|
||||
private var isLight = false
|
||||
|
||||
private var leftTopCorner = 0F
|
||||
private var rightTopCorner = 0F
|
||||
private var leftBottomCorner = 0F
|
||||
private var rightBottomCorner = 0F
|
||||
|
||||
private val paint by lazy {
|
||||
Paint().apply {
|
||||
isAntiAlias = true
|
||||
isDither = true
|
||||
}
|
||||
}
|
||||
|
||||
val defaultColor = Color.parseColor("#40000000")
|
||||
val lightColor = Color.parseColor("#000000")
|
||||
|
||||
private val xFermode by lazy {
|
||||
PorterDuffXfermode(PorterDuff.Mode.CLEAR)
|
||||
}
|
||||
|
||||
private val rectF = RectF()
|
||||
private var path = Path()
|
||||
|
||||
fun setCorners(leftTop: Float, rightTop: Float, rightBottom: Float, leftBottom: Float) {
|
||||
leftTopCorner = leftTop
|
||||
rightTopCorner = rightTop
|
||||
rightBottomCorner = rightBottom
|
||||
leftBottomCorner = leftBottom
|
||||
postInvalidateOnAnimation()
|
||||
}
|
||||
|
||||
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
||||
super.onSizeChanged(w, h, oldw, oldh)
|
||||
rectF.set(0F, 0F, w.toFloat(), h.toFloat())
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
if (isLight) {
|
||||
paint.color = lightColor
|
||||
val layerId = canvas.saveLayerAlpha(rectF, 64)
|
||||
|
||||
drawBackground(canvas)
|
||||
paint.xfermode = xFermode
|
||||
canvas.drawRoundRect(rectF, 4F.dip2px().toFloat(), 4F.dip2px().toFloat(), paint)
|
||||
paint.xfermode = null
|
||||
canvas.restoreToCount(layerId)
|
||||
} else {
|
||||
paint.color = defaultColor
|
||||
drawBackground(canvas)
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawBackground(canvas: Canvas) {
|
||||
path.reset()
|
||||
val radii = floatArrayOf(
|
||||
leftTopCorner,
|
||||
leftTopCorner,
|
||||
rightTopCorner,
|
||||
rightTopCorner,
|
||||
rightBottomCorner,
|
||||
rightBottomCorner,
|
||||
leftBottomCorner,
|
||||
leftBottomCorner,
|
||||
)
|
||||
path.addRoundRect(rectF, radii, Path.Direction.CW)
|
||||
canvas.drawPath(path, paint)
|
||||
}
|
||||
|
||||
fun setLight(isLight: Boolean) {
|
||||
this.isLight = isLight
|
||||
postInvalidateOnAnimation()
|
||||
}
|
||||
}
|
||||
@ -1,75 +1,282 @@
|
||||
package com.gh.gamecenter.video.poster.video
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContract
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.observeNonNull
|
||||
import com.gh.gamecenter.common.utils.throwExceptionInDebug
|
||||
import com.gh.gamecenter.CropImageActivity
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.FragmentVideoPosterBinding
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.PermissionHelper.checkStoragePermissionBeforeAction
|
||||
import com.gh.gamecenter.common.view.cropbox.CropBoxStyle
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.databinding.FragmentVideoCoverEditBinding
|
||||
import com.gh.gamecenter.entity.VideoEntity
|
||||
import com.gh.gamecenter.feature.selector.ChooseType
|
||||
import com.gh.gamecenter.feature.selector.LocalMediaActivity
|
||||
import com.gh.gamecenter.video.poster.video.VideoPosterViewModel.Companion.SELECTED_IMAGE_POSITION
|
||||
import com.google.android.material.shape.CornerFamily
|
||||
import com.google.android.material.shape.ShapeAppearanceModel
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.zhihu.matisse.Matisse
|
||||
import com.zhihu.matisse.internal.utils.PathUtils
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
|
||||
class VideoPosterFragment : BaseFragment<Any>() {
|
||||
|
||||
private lateinit var mBinding: FragmentVideoPosterBinding
|
||||
private lateinit var mAdapter: VideoPosterReviewAdapter
|
||||
private lateinit var binding: FragmentVideoCoverEditBinding
|
||||
private lateinit var viewModel: VideoPosterViewModel
|
||||
|
||||
private lateinit var mViewModel: VideoPosterViewModel
|
||||
var videoPath: String? = null
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.fragment_video_poster
|
||||
var videoEntity: VideoEntity? = null
|
||||
|
||||
private lateinit var adapter: VideoPosterReviewAdapter
|
||||
|
||||
private lateinit var takePhotoLauncher: ActivityResultLauncher<Unit>
|
||||
|
||||
override fun getInflatedLayout(): View {
|
||||
return View(requireContext())
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
videoPath = arguments?.getString(EntranceConsts.KEY_PATH_VIDEO)
|
||||
videoEntity = arguments?.getParcelable<VideoEntity>(EntranceConsts.KEY_VIDEO_ENTITY)
|
||||
super.onCreate(savedInstanceState)
|
||||
mBinding = FragmentVideoPosterBinding.bind(mCachedView)
|
||||
|
||||
val videoPath = arguments?.getString(EntranceConsts.KEY_PATH_VIDEO)
|
||||
val videoEntity = arguments?.getParcelable<VideoEntity>(VideoEntity::class.java.simpleName)
|
||||
val videoCoverCache =
|
||||
SPUtils.getString(Constants.SP_VIDEO_COVER_CACHE).toObject<VideoPosterViewModel.VideoCoverCache>()
|
||||
val factory =
|
||||
VideoPosterViewModel.Factory(HaloApp.getInstance().application, videoPath, videoEntity, videoCoverCache)
|
||||
viewModel = ViewModelProviders.of(this, factory).get(VideoPosterViewModel::class.java)
|
||||
|
||||
val factory = VideoPosterViewModel.Factory(HaloApp.getInstance().application, videoPath, videoEntity)
|
||||
mViewModel = ViewModelProviders.of(this, factory).get(VideoPosterViewModel::class.java)
|
||||
mViewModel.videoPreviewsLiveData.observeNonNull(this, callback = {
|
||||
mAdapter.submitList(it)
|
||||
})
|
||||
mViewModel.previewLiveData.observeNonNull(this, callback = {
|
||||
if (it.thumbs != null) {
|
||||
mBinding.receiveIv.setBitmap(it.thumbs)
|
||||
} else if (it.thumbsUrl != null) {
|
||||
ImageUtils.picasso
|
||||
.load(Uri.parse(it.thumbsUrl))
|
||||
.into(mBinding.receiveIv.cropImageZoomView)
|
||||
takePhotoLauncher = registerForActivityResult(object : ActivityResultContract<Unit, Intent?>() {
|
||||
override fun createIntent(context: Context, input: Unit): Intent {
|
||||
return LocalMediaActivity.getIntent(
|
||||
context,
|
||||
ChooseType.IMAGE,
|
||||
1,
|
||||
"视频封面编辑"
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): Intent? {
|
||||
return intent
|
||||
}
|
||||
}) {
|
||||
if (it != null) {
|
||||
val uris = Matisse.obtainResult(it)
|
||||
if (uris.isNotEmpty()) {
|
||||
val path = PathUtils.getPath(requireContext(), uris.first())
|
||||
if (path != null) {
|
||||
val ivZoom = binding.cropImageCustom.cropImageZoomView
|
||||
val bitmap = BitmapUtils.getBitmapByFile(path, ivZoom.width, ivZoom.height)
|
||||
if (bitmap != null) {
|
||||
val videoPreview = VideoPosterViewModel.VideoPreview(0, bitmap, null)
|
||||
viewModel.setSelectedImage(videoPreview)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun initView(view: View?) = Unit
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return FragmentVideoCoverEditBinding.inflate(inflater, container, false)
|
||||
.also {
|
||||
binding = it
|
||||
}.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mBinding.receiveIv.setCropRatio(9 / 16F)
|
||||
mBinding.reviewList.layoutManager = GridLayoutManager(requireContext(), 10)
|
||||
mAdapter = VideoPosterReviewAdapter(requireContext(), mViewModel)
|
||||
mBinding.reviewList.adapter = mAdapter
|
||||
|
||||
adapter = VideoPosterReviewAdapter(requireContext(), viewModel)
|
||||
binding.rvImages.layoutManager = GridLayoutManager(requireContext(), 10)
|
||||
binding.rvImages.adapter = adapter
|
||||
|
||||
binding.ivTakePhoto.shapeAppearanceModel = ShapeAppearanceModel()
|
||||
.toBuilder()
|
||||
.setAllCorners(CornerFamily.ROUNDED, 4F.dip2px().toFloat())
|
||||
.build()
|
||||
binding.ivTakePhoto.clipToOutline = true
|
||||
|
||||
binding.ivPreviewBorder.shapeAppearanceModel = ShapeAppearanceModel()
|
||||
.toBuilder()
|
||||
.setAllCorners(CornerFamily.ROUNDED, 4F.dip2px().toFloat())
|
||||
.build()
|
||||
binding.ivPreviewBorder.strokeWidth = 4F.dip2px().toFloat()
|
||||
binding.ivPreviewBorder.strokeColor = ColorStateList.valueOf(Color.parseColor("#2496FF"))
|
||||
binding.ivPreviewBorder.clipToOutline = true
|
||||
|
||||
binding.cropImageCustom.setCropBoxStyle(CropBoxStyle.Rectangle(23F / 41))
|
||||
|
||||
binding.ivTakePhoto.setOnClickListener {
|
||||
val videoPreview = viewModel.selectedImage.value
|
||||
if (videoPreview == null) {
|
||||
checkStoragePermissionBeforeAction(requireContext()) { takePhotoLauncher.launch(Unit) }
|
||||
} else {
|
||||
viewModel.setPreviewImage(SELECTED_IMAGE_POSITION, videoPreview)
|
||||
}
|
||||
}
|
||||
|
||||
binding.ivRemove.setOnClickListener {
|
||||
viewModel.setSelectedImage(null)
|
||||
if (viewModel.previewPosition.value == SELECTED_IMAGE_POSITION) {
|
||||
adapter.getItem(0)?.let {
|
||||
viewModel.setPreviewImage(0, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.tvCancel.setOnClickListener {
|
||||
activity?.finish()
|
||||
}
|
||||
|
||||
binding.tvSubmit.setOnClickListener {
|
||||
activity?.let {
|
||||
val clipPath = it.cacheDir.absolutePath + File.separator + System.currentTimeMillis() + ".jpg"
|
||||
binding.cropImageCustom.savePicture(clipPath)
|
||||
|
||||
saveVideoOriginalCoverToLocal(it)
|
||||
|
||||
val data = Intent()
|
||||
data.putExtra(CropImageActivity.RESULT_CLIP_PATH, clipPath)
|
||||
it.setResult(Activity.RESULT_OK, data)
|
||||
it.finish()
|
||||
}
|
||||
}
|
||||
|
||||
with(viewModel) {
|
||||
videoPreviewsLiveData.observeNonNull(viewLifecycleOwner, callback = {
|
||||
adapter.submitList(it)
|
||||
})
|
||||
|
||||
previewLiveData.observeNonNull(viewLifecycleOwner, callback = {
|
||||
binding.cropImageCustom.reset()
|
||||
it.values?.let(binding.cropImageCustom::setTransformationValues)
|
||||
if (it.thumbs != null) {
|
||||
binding.cropImageCustom.setBitmap(it.thumbs)
|
||||
} else if (it.thumbsUrl != null) {
|
||||
ImageUtils.picasso
|
||||
.load(Uri.parse(it.thumbsUrl))
|
||||
.into(binding.cropImageCustom.cropImageZoomView)
|
||||
}
|
||||
})
|
||||
|
||||
selectedImage.observe(viewLifecycleOwner) {
|
||||
if (it == null) {
|
||||
binding.ivTakePhoto.setImageResource(R.drawable.ic_video_cover_edit_take_photo)
|
||||
} else {
|
||||
binding.ivTakePhoto.setImageBitmap(it.thumbs)
|
||||
}
|
||||
binding.ivRemove.goneIf(it == null)
|
||||
}
|
||||
|
||||
previewPosition.observe(viewLifecycleOwner) {
|
||||
setSelectedImageSelected(it == SELECTED_IMAGE_POSITION)
|
||||
adapter.setPreviewPosition(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun savePicture(path: String) {
|
||||
if (isAdded) throwExceptionInDebug("save clip picture failure", !mBinding.receiveIv.savePicture(path))
|
||||
/**
|
||||
* 将封面原图保存在本地,以便下次编辑时显示
|
||||
*/
|
||||
private fun saveVideoOriginalCoverToLocal(context: Context) {
|
||||
val preview = viewModel.previewLiveData.value
|
||||
if (preview != null) {
|
||||
val position = viewModel.previewPosition.value ?: -2
|
||||
var cache: VideoPosterViewModel.VideoCoverCache? = null
|
||||
val values = binding.cropImageCustom.transformationValues
|
||||
if (preview.thumbs != null) {
|
||||
val path = saveToInternalStorage(context, preview.thumbs)
|
||||
if (path != null) {
|
||||
cache = VideoPosterViewModel.VideoCoverCache(position, localPath = path, values = values)
|
||||
}
|
||||
} else if (preview.thumbsUrl != null) {
|
||||
cache = VideoPosterViewModel.VideoCoverCache(position, url = preview.thumbsUrl, values = values)
|
||||
}
|
||||
val json = cache?.toJson()
|
||||
if (json != null) {
|
||||
SPUtils.setString(Constants.SP_VIDEO_COVER_CACHE, json)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setSelectedImageSelected(isSelected: Boolean) {
|
||||
if (isSelected) {
|
||||
binding.ivTakePhoto.strokeWidth = 6F.dip2px().toFloat()
|
||||
binding.ivTakePhoto.strokeColor = ColorStateList.valueOf(Color.parseColor("#232323"))
|
||||
} else {
|
||||
binding.ivTakePhoto.strokeWidth = 0F
|
||||
}
|
||||
binding.ivPreviewBorder.goneIf(!isSelected)
|
||||
}
|
||||
|
||||
// 保存到内部存储
|
||||
private fun saveToInternalStorage(
|
||||
context: Context,
|
||||
bitmap: Bitmap
|
||||
): String? {
|
||||
try {
|
||||
val file = createVideoCoverFile(context)
|
||||
// 将图片保存到文件
|
||||
FileOutputStream(file).use { fos ->
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
|
||||
fos.flush()
|
||||
}
|
||||
|
||||
return file.absolutePath
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(videoPath: String?, videoEntity: VideoEntity?): VideoPosterFragment {
|
||||
val fragment = VideoPosterFragment()
|
||||
val bundle = Bundle()
|
||||
bundle.putString(EntranceConsts.KEY_PATH_VIDEO, videoPath)
|
||||
bundle.putParcelable(VideoEntity::class.java.simpleName, videoEntity)
|
||||
fragment.arguments = bundle
|
||||
return fragment
|
||||
private const val VIDEO_COVER_DIRECTORY_NAME = "videoCover"
|
||||
|
||||
fun createVideoCoverFile(context: Context): File {
|
||||
// 获取应用私有目录
|
||||
val directory = context.getDir(VIDEO_COVER_DIRECTORY_NAME, Context.MODE_PRIVATE)
|
||||
|
||||
// 创建文件
|
||||
return File(directory, "cover_image.jpg")
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理上次裁剪图片留下的缓存文件
|
||||
*/
|
||||
fun clearVideoCoverCache(context: Context) {
|
||||
SPUtils.setString(Constants.SP_VIDEO_COVER_CACHE, "")
|
||||
context.getDir(VIDEO_COVER_DIRECTORY_NAME, Context.MODE_PRIVATE).let { directory ->
|
||||
directory.listFiles()?.forEach { it.delete() }
|
||||
}
|
||||
}
|
||||
|
||||
fun newInstance() = VideoPosterFragment()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,15 +1,19 @@
|
||||
package com.gh.gamecenter.video.poster.video
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.databinding.VideoPosterPreviewItemBinding
|
||||
import com.gh.gamecenter.video.poster.video.VideoPosterViewModel.Companion.SELECTED_IMAGE_POSITION
|
||||
import com.google.android.material.shape.CornerFamily
|
||||
import com.google.android.material.shape.ShapeAppearanceModel
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class VideoPosterReviewAdapter(
|
||||
@ -19,11 +23,7 @@ class VideoPosterReviewAdapter(
|
||||
|
||||
private var mListData: MutableList<VideoPosterViewModel.VideoPreview> = ArrayList()
|
||||
|
||||
private val mSelectMap = HashMap<Int, Boolean>()
|
||||
|
||||
init {
|
||||
mSelectMap[0] = true // default select
|
||||
}
|
||||
private var selectedPosition = 0
|
||||
|
||||
fun submitList(listData: List<VideoPosterViewModel.VideoPreview>) {
|
||||
mListData = listData.toMutableList()
|
||||
@ -41,6 +41,22 @@ class VideoPosterReviewAdapter(
|
||||
|
||||
override fun onBindViewHolder(holder: VideoPosterReviewItemViewHolder, position: Int) {
|
||||
|
||||
val builder = ShapeAppearanceModel().toBuilder()
|
||||
when (position) {
|
||||
0 -> builder.setTopLeftCorner(CornerFamily.ROUNDED, 4F.dip2px().toFloat())
|
||||
.setTopRightCorner(CornerFamily.ROUNDED, 0F)
|
||||
.setBottomRightCorner(CornerFamily.ROUNDED, 0F)
|
||||
.setBottomLeftCorner(CornerFamily.ROUNDED, 4F.dip2px().toFloat())
|
||||
|
||||
itemCount - 1 -> builder.setTopLeftCorner(CornerFamily.ROUNDED, 0F)
|
||||
.setTopRightCorner(CornerFamily.ROUNDED, 4F.dip2px().toFloat())
|
||||
.setBottomRightCorner(CornerFamily.ROUNDED, 4F.dip2px().toFloat())
|
||||
.setBottomLeftCorner(CornerFamily.ROUNDED, 0F)
|
||||
|
||||
else -> builder.setAllCorners(CornerFamily.ROUNDED, 0F)
|
||||
}
|
||||
holder.binding.preview.shapeAppearanceModel = builder.build()
|
||||
|
||||
val videoPreview = mListData[position]
|
||||
val thumbs = videoPreview.thumbs
|
||||
if (thumbs != null) {
|
||||
@ -51,41 +67,67 @@ class VideoPosterReviewAdapter(
|
||||
.into(holder.binding.preview)
|
||||
}
|
||||
holder.binding.preview.setOnClickListener {
|
||||
viewModel.previewLiveData.postValue(videoPreview)
|
||||
viewModel.setPreviewImage(position, mListData[position])
|
||||
}
|
||||
setSelected(holder, position)
|
||||
|
||||
mSelectMap[position] = true
|
||||
for (entry in mSelectMap) {
|
||||
if (entry.value && entry.key != position) {
|
||||
mSelectMap[entry.key] = false
|
||||
notifyItemChanged(entry.key)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: VideoPosterReviewItemViewHolder, position: Int, payloads: MutableList<Any>) {
|
||||
if (payloads.contains(PAYLOADS_IS_SELECTED)) {
|
||||
setSelected(holder, position)
|
||||
} else {
|
||||
super.onBindViewHolder(holder, position, payloads)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setSelected(holder: VideoPosterReviewItemViewHolder, position: Int) {
|
||||
holder.binding.preview.clipToOutline = true
|
||||
holder.binding.previewBorderInner.clipToOutline = true
|
||||
holder.binding.previewBorderOut.shapeAppearanceModel = ShapeAppearanceModel().toBuilder()
|
||||
.setAllCorners(CornerFamily.ROUNDED, 4F.dip2px().toFloat())
|
||||
.build()
|
||||
holder.binding.previewBorderOut.strokeColor = ColorStateList.valueOf(Color.parseColor("#232323"))
|
||||
holder.binding.previewBorderOut.strokeWidth = 6F.dip2px().toFloat()
|
||||
|
||||
holder.binding.previewBorderOut.clipToOutline = true
|
||||
holder.binding.previewBorderInner.shapeAppearanceModel = ShapeAppearanceModel().toBuilder()
|
||||
.setAllCorners(CornerFamily.ROUNDED, 4F.dip2px().toFloat())
|
||||
.build()
|
||||
holder.binding.previewBorderInner.strokeColor = ColorStateList.valueOf(Color.parseColor("#2496FF"))
|
||||
holder.binding.previewBorderInner.strokeWidth = 4F.dip2px().toFloat()
|
||||
|
||||
holder.binding.gPreviewBorder.goneIf(selectedPosition != position)
|
||||
fun getCorner(hasCorner: Boolean) = if (hasCorner) 4F.dip2px().toFloat() else 0F
|
||||
val leftCorner = getCorner(position == 0)
|
||||
val rightCorner = getCorner(position == itemCount - 1)
|
||||
holder.binding.vCover.setCorners(
|
||||
leftCorner,
|
||||
rightCorner,
|
||||
rightCorner,
|
||||
leftCorner,
|
||||
)
|
||||
holder.binding.vCover.setLight(selectedPosition == position)
|
||||
}
|
||||
|
||||
fun setPreviewPosition(position: Int) {
|
||||
if (selectedPosition != position) {
|
||||
val lastPosition = selectedPosition
|
||||
selectedPosition = position
|
||||
if (lastPosition != SELECTED_IMAGE_POSITION) {
|
||||
notifyItemChanged(lastPosition, PAYLOADS_IS_SELECTED)
|
||||
}
|
||||
if (selectedPosition != SELECTED_IMAGE_POSITION) {
|
||||
notifyItemChanged(position, PAYLOADS_IS_SELECTED)
|
||||
}
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
|
||||
holder.binding.previewContainer.radius = if (mSelectMap[position] == true) {
|
||||
3F.dip2px().toFloat()
|
||||
} else if (position == 0 || position == itemCount - 1) {
|
||||
4F.dip2px().toFloat()
|
||||
} else {
|
||||
0F
|
||||
}
|
||||
holder.binding.previewBorder.visibility = if (mSelectMap[position] == true) {
|
||||
View.VISIBLE
|
||||
} else View.GONE
|
||||
fun getItem(position: Int) = mListData.getOrNull(position)
|
||||
|
||||
val previewContainerLp = holder.binding.previewContainer.layoutParams as ConstraintLayout.LayoutParams
|
||||
if (position == 0) {
|
||||
previewContainerLp.rightMargin = (-4F).dip2px()
|
||||
previewContainerLp.leftMargin = 0
|
||||
} else if (position == itemCount - 1) {
|
||||
previewContainerLp.leftMargin = (-4F).dip2px()
|
||||
previewContainerLp.rightMargin = 0
|
||||
} else {
|
||||
previewContainerLp.rightMargin = 0
|
||||
previewContainerLp.leftMargin = 0
|
||||
}
|
||||
holder.binding.previewContainer.layoutParams = previewContainerLp
|
||||
companion object {
|
||||
private const val PAYLOADS_IS_SELECTED = "payloads_is_selected"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,9 +4,11 @@ import android.app.Application
|
||||
import android.graphics.Bitmap
|
||||
import android.media.MediaMetadataRetriever
|
||||
import androidx.lifecycle.*
|
||||
import com.gh.gamecenter.common.utils.BitmapUtils
|
||||
import com.gh.gamecenter.common.utils.ImageUtils
|
||||
import com.gh.gamecenter.common.utils.throwExceptionInDebug
|
||||
import com.gh.gamecenter.common.utils.tryCatchInRelease
|
||||
import com.gh.gamecenter.common.view.CropImageZoomView.TransformationValues
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.gamecenter.entity.VideoEntity
|
||||
import java.io.File
|
||||
@ -15,13 +17,33 @@ import kotlin.math.roundToLong
|
||||
class VideoPosterViewModel(
|
||||
application: Application,
|
||||
val videoPath: String?,
|
||||
val videoEntity: VideoEntity?
|
||||
val videoEntity: VideoEntity?,
|
||||
val cache: VideoCoverCache?
|
||||
) : AndroidViewModel(application) {
|
||||
|
||||
val videoPreviewsLiveData = MutableLiveData<List<VideoPreview>>()
|
||||
|
||||
val previewLiveData = MutableLiveData<VideoPreview>()
|
||||
|
||||
private val _selectedImage = MutableLiveData<VideoPreview?>()
|
||||
val selectedImage: LiveData<VideoPreview?> = _selectedImage
|
||||
fun setSelectedImage(videoPreview: VideoPreview?) {
|
||||
_selectedImage.value = videoPreview
|
||||
if (videoPreview != null) {
|
||||
setPreviewImage(SELECTED_IMAGE_POSITION, videoPreview)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val _previewPosition = MutableLiveData<Int>()
|
||||
val previewPosition: LiveData<Int> = _previewPosition
|
||||
fun setPreviewImage(position: Int, videoPreview: VideoPreview) {
|
||||
val oldPosition = _previewPosition.value
|
||||
if (oldPosition != position) {
|
||||
_previewPosition.value = position
|
||||
previewLiveData.value = videoPreview
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
if (videoPath != null) {
|
||||
@ -36,22 +58,35 @@ class VideoPosterViewModel(
|
||||
}
|
||||
val videoReviews = ArrayList<VideoPreview>()
|
||||
|
||||
val cachePreview = cache?.toVideoPreview()
|
||||
for (i in 0 until totalThumbsCount) {
|
||||
val frameTime: Long = (startPosition + interval * i).roundToLong()
|
||||
val thumbsUrl = ImageUtils.getVideoSnapshot(videoEntity.url, frameTime * 1000)
|
||||
val element = VideoPreview(frameTime, null, thumbsUrl)
|
||||
videoReviews.add(element)
|
||||
|
||||
if (videoReviews.size == 1) {
|
||||
if (cachePreview == null && videoReviews.size == 1) {
|
||||
previewLiveData.postValue(element)
|
||||
}
|
||||
}
|
||||
|
||||
videoPreviewsLiveData.postValue(videoReviews)
|
||||
|
||||
cachePreview?.let(::initFromCache)
|
||||
|
||||
} else {
|
||||
throwExceptionInDebug("video not found")
|
||||
}
|
||||
}
|
||||
|
||||
private fun initFromCache(cachePreview: VideoPreview) {
|
||||
cache ?: return
|
||||
previewLiveData.postValue(cachePreview)
|
||||
_previewPosition.postValue(cache.position)
|
||||
if (cache.position == SELECTED_IMAGE_POSITION) {
|
||||
_selectedImage.value = cachePreview
|
||||
}
|
||||
}
|
||||
|
||||
private fun getImagesByVideo() {
|
||||
throwExceptionInDebug("video file not found", !File(videoPath).exists())
|
||||
|
||||
@ -68,6 +103,7 @@ class VideoPosterViewModel(
|
||||
return
|
||||
}
|
||||
|
||||
val cachePreview = cache?.toVideoPreview()
|
||||
val duration = durationString.toLong()
|
||||
val interval = (duration / totalThumbsCount)
|
||||
val videoReviews = ArrayList<VideoPreview>()
|
||||
@ -88,23 +124,64 @@ class VideoPosterViewModel(
|
||||
val element = VideoPreview(frameTime * 1000, bitmap)
|
||||
videoReviews.add(element)
|
||||
videoPreviewsLiveData.postValue(videoReviews)
|
||||
if (videoReviews.size == 1) {
|
||||
if (cachePreview == null && videoReviews.size == 1) {
|
||||
previewLiveData.postValue(element)
|
||||
}
|
||||
}
|
||||
|
||||
cachePreview?.let(::initFromCache)
|
||||
mediaMetadataRetriever.release()
|
||||
}
|
||||
|
||||
class VideoPreview(val time: Long, val thumbs: Bitmap? = null, val thumbsUrl: String? = null)
|
||||
companion object {
|
||||
|
||||
const val SELECTED_IMAGE_POSITION = -1
|
||||
}
|
||||
|
||||
class VideoPreview(
|
||||
val time: Long,
|
||||
val thumbs: Bitmap? = null,
|
||||
val thumbsUrl: String? = null,
|
||||
val values: TransformationValues? = null
|
||||
)
|
||||
|
||||
class VideoCoverCache(
|
||||
val position: Int,
|
||||
val localPath: String? = null,
|
||||
val url: String? = null,
|
||||
val values: TransformationValues
|
||||
) {
|
||||
|
||||
fun toVideoPreview(): VideoPreview? =
|
||||
when {
|
||||
localPath != null -> {
|
||||
if (File(localPath).exists()) {
|
||||
val bitmap = BitmapUtils.getBitmapByFile(localPath, Bitmap.Config.RGB_565)
|
||||
if (bitmap != null) {
|
||||
VideoPreview(0, bitmap, null, values)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
url != null -> VideoPreview(0, null, url, values)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
class Factory(
|
||||
private val mApplication: Application,
|
||||
private val mVideoPath: String?,
|
||||
private val mVideoEntity: VideoEntity?
|
||||
private val mVideoEntity: VideoEntity?,
|
||||
private val cache: VideoCoverCache?
|
||||
) : ViewModelProvider.NewInstanceFactory() {
|
||||
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return VideoPosterViewModel(mApplication, mVideoPath, mVideoEntity) as T
|
||||
return VideoPosterViewModel(mApplication, mVideoPath, mVideoEntity, cache) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -36,6 +36,7 @@ import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
|
||||
import com.gh.gamecenter.common.callback.CancelListener
|
||||
import com.gh.gamecenter.common.callback.ConfirmListener
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.NotificationUgc
|
||||
import com.gh.gamecenter.common.entity.SimpleGameEntity
|
||||
import com.gh.gamecenter.common.mvvm.Status
|
||||
@ -49,12 +50,13 @@ import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.newsdetail.NewsDetailActivity
|
||||
import com.gh.gamecenter.qa.editor.GameActivity
|
||||
import com.gh.gamecenter.video.label.VideoLabelActivity
|
||||
import com.gh.gamecenter.video.poster.PosterEditActivity
|
||||
import com.gh.gamecenter.video.poster.video.VideoPosterFragment
|
||||
import com.gh.gamecenter.video.upload.OnUploadListener
|
||||
import com.gh.gamecenter.video.upload.UploadManager
|
||||
import com.google.android.flexbox.FlexboxLayout
|
||||
import com.lightgame.utils.Util_System_Keyboard
|
||||
import com.lightgame.utils.Utils
|
||||
import com.therouter.TheRouter
|
||||
import com.zhihu.matisse.Matisse
|
||||
import com.zhihu.matisse.internal.utils.PathUtils
|
||||
import org.json.JSONArray
|
||||
@ -96,25 +98,6 @@ class UploadVideoActivity : ToolBarActivity() {
|
||||
mBinding.gameName.text = game.name
|
||||
mBinding.gameName.setTextColor(resources.getColor(com.gh.gamecenter.common.R.color.text_primary))
|
||||
}
|
||||
} else if (requestCode == REQUEST_CODE_IMAGE_STORE && resultCode == Activity.RESULT_OK) {
|
||||
if (data != null) {
|
||||
val uris = Matisse.obtainResult(data)
|
||||
for (uri in uris) {
|
||||
val picturePath = PathUtils.getPath(application, uri)
|
||||
if (File(picturePath).length() > ImageUtils.getUploadFileMaxSize()) {
|
||||
val count = ImageUtils.getUploadFileMaxSize() / 1024 / 1024
|
||||
val application: Application = application
|
||||
Utils.toast(getApplication(), application.getString(com.gh.gamecenter.common.R.string.pic_max_hint, count))
|
||||
continue
|
||||
}
|
||||
Utils.log("picturePath = $picturePath")
|
||||
|
||||
// skip image crop
|
||||
val intent = CropImageActivity.getIntent(this@UploadVideoActivity, picturePath, 9 / 16F, mEntrance)
|
||||
startActivityForResult(intent, REQUEST_CODE_IMAGE_CROP)
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if (requestCode == REQUEST_CODE_IMAGE_CROP && resultCode == Activity.RESULT_OK) {
|
||||
if (data != null) {
|
||||
val imagePath = data.getStringExtra(CropImageActivity.RESULT_CLIP_PATH)
|
||||
@ -136,6 +119,7 @@ class UploadVideoActivity : ToolBarActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
VideoPosterFragment.clearVideoCoverCache(this)
|
||||
mVideoLink = intent.getParcelableExtra(VideoLinkEntity::class.java.simpleName)
|
||||
mEntranceLink = intent.getStringExtra(EntranceConsts.KEY_ENTRANCE_LINK) ?: ""
|
||||
mPath = intent.getStringExtra(EntranceConsts.KEY_PATH) ?: "其他"
|
||||
@ -259,7 +243,8 @@ class UploadVideoActivity : ToolBarActivity() {
|
||||
R.drawable.ic_upload_video_activity_unenable
|
||||
)
|
||||
)
|
||||
mBinding.chooseActivityIv.background = ContextCompat.getDrawable(this, com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_999)
|
||||
mBinding.chooseActivityIv.background =
|
||||
ContextCompat.getDrawable(this, com.gh.gamecenter.common.R.drawable.bg_shape_f5_radius_999)
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,14 +414,7 @@ class UploadVideoActivity : ToolBarActivity() {
|
||||
private fun startMediaStore() {
|
||||
try {
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(this) {
|
||||
// Matisse.from(this@UploadVideoActivity)
|
||||
// .choose(MimeType.ofImage())
|
||||
// .showSingleMediaType(true)
|
||||
// .countable(true)
|
||||
// .addFilter(GhMatisseFilter())
|
||||
// .maxSelectable(1)
|
||||
// .forResult(REQUEST_CODE_IMAGE_STORE)
|
||||
|
||||
val postcard = TheRouter.build(RouteConsts.activity.videoCoverEditActivity)
|
||||
|
||||
val videoPath = if (mViewModel.videoDraft != null) {
|
||||
mViewModel.videoDraft?.localPath
|
||||
@ -444,22 +422,17 @@ class UploadVideoActivity : ToolBarActivity() {
|
||||
intent.getStringExtra(EntranceConsts.KEY_PATH_VIDEO)
|
||||
}
|
||||
|
||||
var intent: Intent? = null
|
||||
if (!videoPath.isNullOrEmpty()) {
|
||||
intent = PosterEditActivity.getIntentByPath(this@UploadVideoActivity, videoPath)
|
||||
postcard.withString(EntranceConsts.KEY_PATH_VIDEO, videoPath)
|
||||
} else {
|
||||
val videoPatch = mViewModel.videoPatch
|
||||
if (videoPatch != null) {
|
||||
intent = PosterEditActivity.getIntentByVideo(this@UploadVideoActivity, videoPatch)
|
||||
postcard.withParcelable(EntranceConsts.KEY_VIDEO_ENTITY, videoPatch)
|
||||
} else {
|
||||
throwExceptionInDebug("video not found")
|
||||
}
|
||||
}
|
||||
if (intent != null) {
|
||||
startActivityForResult(intent, REQUEST_CODE_IMAGE_CROP)
|
||||
} else {
|
||||
toast("找不到相关视频")
|
||||
}
|
||||
postcard.navigation(this, REQUEST_CODE_IMAGE_CROP)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
toast(R.string.media_image_hint)
|
||||
@ -672,8 +645,16 @@ class UploadVideoActivity : ToolBarActivity() {
|
||||
flexCell.gravity = Gravity.CENTER
|
||||
flexCell.text = videoTagEntity.name
|
||||
flexCell.tag = videoTagEntity.id
|
||||
flexCell.setTextColor(DrawableView.getSelectorColorStyle(com.gh.gamecenter.common.R.color.text_secondary, com.gh.gamecenter.common.R.color.white))
|
||||
flexCell.background = DrawableView.getOvalSelectorStyle(com.gh.gamecenter.common.R.color.text_f2f2f2, com.gh.gamecenter.common.R.color.primary_theme)
|
||||
flexCell.setTextColor(
|
||||
DrawableView.getSelectorColorStyle(
|
||||
com.gh.gamecenter.common.R.color.text_secondary,
|
||||
com.gh.gamecenter.common.R.color.white
|
||||
)
|
||||
)
|
||||
flexCell.background = DrawableView.getOvalSelectorStyle(
|
||||
com.gh.gamecenter.common.R.color.text_f2f2f2,
|
||||
com.gh.gamecenter.common.R.color.primary_theme
|
||||
)
|
||||
flexCell.setPadding(12F.dip2px(), 0, 12F.dip2px(), 0)
|
||||
flexCell.setOnClickListener {
|
||||
Util_System_Keyboard.hideSoftKeyboard(this, mBinding.gameTitle)
|
||||
@ -789,7 +770,11 @@ class UploadVideoActivity : ToolBarActivity() {
|
||||
mBinding.uploadSpeed.visibility = View.VISIBLE
|
||||
mBinding.uploadButton.visibility = View.VISIBLE
|
||||
mBinding.uploadSpeed.text =
|
||||
(SpeedUtils.getSpeed(speed) + "预计还需" + SpeedUtils.getRemainTime(totalSize, currentSize, speed))
|
||||
(SpeedUtils.getSpeed(speed) + "预计还需" + SpeedUtils.getRemainTime(
|
||||
totalSize,
|
||||
currentSize,
|
||||
speed
|
||||
))
|
||||
mBinding.uploadProgress.update(((360 * currentSize) / totalSize).toInt(), "")
|
||||
}
|
||||
}
|
||||
@ -941,7 +926,6 @@ class UploadVideoActivity : ToolBarActivity() {
|
||||
private const val REQUEST_GAME_CODE = 116
|
||||
const val RESULT_CODE_VIDEO = 117
|
||||
const val RESULT_CODE_DRAFT = 118
|
||||
const val REQUEST_CODE_IMAGE_STORE = 119
|
||||
const val REQUEST_CODE_IMAGE_CROP = 120
|
||||
const val REQUEST_CODE_CHOOSE_LABEL = 121
|
||||
|
||||
|
||||
@ -43,6 +43,8 @@ import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.json.json
|
||||
import com.gh.gamecenter.common.observer.MuteCallback
|
||||
import com.gh.gamecenter.common.observer.VolumeObserver
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.TabIndicatorView
|
||||
import com.gh.gamecenter.core.iinterface.IScrollable
|
||||
@ -162,6 +164,20 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
|
||||
private val twoLinesTabToolbarHeight = 48F.dip2px()
|
||||
|
||||
private var autoVideoView: AutomaticVideoView? = null
|
||||
private val volumeObserver by lazy {
|
||||
VolumeObserver(object : MuteCallback {
|
||||
override fun onMute(isMute: Boolean) {
|
||||
if (::binding.isInitialized) {
|
||||
binding.muteIv.setImageResource(if (isMute) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
|
||||
}
|
||||
if (isMute) {
|
||||
autoVideoView?.mute()
|
||||
} else {
|
||||
autoVideoView?.unMute()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private var searchStyle: BottomTab.SearchStyle? = null
|
||||
set(value) {
|
||||
@ -552,6 +568,8 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
|
||||
oldState: RefreshState,
|
||||
newState: RefreshState
|
||||
) {
|
||||
getValidSmartRefreshContent()?.onStateChanged(refreshLayout, oldState, newState)
|
||||
|
||||
val isAutoScrollToTwoLevel = oldState == RefreshState.None && newState == RefreshState.TwoLevel
|
||||
val isDragToTwoLevel =
|
||||
oldState == RefreshState.ReleaseToRefresh && newState == RefreshState.ReleaseToTwoLevel
|
||||
@ -649,49 +667,17 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
|
||||
|
||||
if (isFinishTwoLevel) {
|
||||
pausePullDownPushVideo()
|
||||
showTwoLevel = false
|
||||
|
||||
if (isDragging) {
|
||||
autoFinishTwoLevelHandler?.removeMessages(KEY_AUTO_FINISH_TWO_LEVEL)
|
||||
elapsedHelper.pauseCounting()
|
||||
pullDownPush?.run {
|
||||
SensorsBridge.trackEvent(
|
||||
"DropDownPushClick",
|
||||
json {
|
||||
"action" to pullDownPushAction
|
||||
"button_name" to "关闭推送"
|
||||
"drop_down_push_id" to id
|
||||
"game_name" to game?.name
|
||||
"game_id" to game?.id
|
||||
"bottom_tab" to bottomTabName
|
||||
"several_tab_page_name" to multiTabNavName
|
||||
"several_tab_page_id" to multiTabNavId
|
||||
"position" to lastSelectedPosition
|
||||
"tab_content" to currentTabEntity?.name
|
||||
"custom_page_name" to currentTabEntity?.link?.text
|
||||
"custom_page_id" to currentTabEntity?.link?.link
|
||||
}
|
||||
)
|
||||
com.gh.common.util.NewFlatLogUtils.logHomePushClose(
|
||||
id,
|
||||
"主动收起",
|
||||
twoLevelOpenCount,
|
||||
game?.id ?: "",
|
||||
game?.name ?: "",
|
||||
elapsedHelper.elapsedTime
|
||||
)
|
||||
}
|
||||
finishTwoLevel("主动收起")
|
||||
}
|
||||
showTwoLevel = false
|
||||
}
|
||||
|
||||
when (newState) {
|
||||
RefreshState.TwoLevel -> {
|
||||
getValidSmartRefreshContent()?.setScrollEnabled(false)
|
||||
binding.refreshLayout.isDisableContent = false
|
||||
}
|
||||
RefreshState.None -> {
|
||||
getValidSmartRefreshContent()?.setScrollEnabled(true)
|
||||
|
||||
showTwoLevel = false
|
||||
isDragging = false
|
||||
twoLevelHeader.setFloorDuration(1000)
|
||||
@ -935,6 +921,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
|
||||
classicsHeader.visibility = View.INVISIBLE
|
||||
pullDownPushSet.add(id)
|
||||
SPUtils.setStringSet(Constants.SP_PULL_DOWN_PUSH_POP_UP_SET, pullDownPushSet)
|
||||
autoFinishTwoLevelCallback = finishCallback
|
||||
autoFinishTwoLevelHandler = object : Handler(Looper.getMainLooper()) {
|
||||
override fun handleMessage(msg: Message) {
|
||||
super.handleMessage(msg)
|
||||
@ -956,9 +943,6 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
|
||||
val autoFinishDelayTime = putAwaySwitch.toInt() * 1000L
|
||||
autoFinishTwoLevelHandler?.sendEmptyMessageDelayed(KEY_AUTO_FINISH_TWO_LEVEL, autoFinishDelayTime)
|
||||
}
|
||||
else -> {
|
||||
autoFinishTwoLevelCallback = finishCallback
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1033,6 +1017,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
|
||||
ImageUtils.display(gameImageIv, imgUrl)
|
||||
}
|
||||
autoVideoView?.onVideoReset()
|
||||
muteIv.isVisible = video != null
|
||||
autoVideoView?.goneIf(video == null) {
|
||||
if (autoVideoView?.isInPlayingState == false) {
|
||||
GSYVideoOptionBuilder()
|
||||
@ -1051,6 +1036,17 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
|
||||
headerContainer.performClick()
|
||||
}
|
||||
}
|
||||
var videoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
|
||||
muteIv.setImageResource(if (videoVoiceStatus) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
|
||||
muteIv.setDebouncedClickListener {
|
||||
videoVoiceStatus = !videoVoiceStatus
|
||||
muteIv.setImageResource(if (videoVoiceStatus) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
|
||||
if (videoVoiceStatus) {
|
||||
autoVideoView?.mute()
|
||||
} else {
|
||||
autoVideoView?.unMute()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1065,6 +1061,19 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
|
||||
pullDownPushHandler?.doPreProcess(this as? ISmartRefresh, popupPush)
|
||||
}
|
||||
|
||||
private fun observeVolume() {
|
||||
context?.applicationContext?.contentResolver?.registerContentObserver(
|
||||
android.provider.Settings.System.CONTENT_URI,
|
||||
true,
|
||||
volumeObserver
|
||||
)
|
||||
}
|
||||
|
||||
private fun unObserveVolume() {
|
||||
context?.applicationContext?.contentResolver?.unregisterContentObserver(volumeObserver)
|
||||
}
|
||||
|
||||
|
||||
private fun updateRefreshHeaderStyle(force: Boolean = false) {
|
||||
if (lightRefreshHeaderStyle == isDisplayingLightContent && !force) return
|
||||
lightRefreshHeaderStyle = isDisplayingLightContent
|
||||
@ -1109,6 +1118,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
|
||||
} else {
|
||||
resumePullDownPushVideo()
|
||||
}
|
||||
observeVolume()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1122,6 +1132,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
|
||||
if (!videoUrl.isNullOrEmpty()) {
|
||||
ScrollCalculatorHelper.savePlaySchedule(MD5Utils.getContentMD5(videoUrl), currentPosition)
|
||||
}
|
||||
unObserveVolume()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,8 @@ import com.gh.gamecenter.entity.MultiTabNav
|
||||
import com.gh.gamecenter.entity.PullDownPush
|
||||
import com.gh.gamecenter.feature.utils.SentryHelper
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.scwang.smartrefresh.layout.api.RefreshLayout
|
||||
import com.scwang.smartrefresh.layout.constant.RefreshState
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
@ -148,10 +150,6 @@ class TabWrapperFragment: BaseTabWrapperFragment(), ISmartRefresh, ISmartRefresh
|
||||
}
|
||||
}
|
||||
|
||||
override fun setScrollEnabled(isScrollEnabled: Boolean) {
|
||||
getValidSmartRefreshContent()?.setScrollEnabled(isScrollEnabled)
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
getValidSmartRefreshContent()?.onRefresh()
|
||||
}
|
||||
@ -161,6 +159,10 @@ class TabWrapperFragment: BaseTabWrapperFragment(), ISmartRefresh, ISmartRefresh
|
||||
getCurrentTabEntity()?.showPullDownPush = !isSwipeRefreshEnabled
|
||||
}
|
||||
|
||||
override fun onStateChanged(refreshLayout: RefreshLayout, oldState: RefreshState, newState: RefreshState) {
|
||||
getValidSmartRefreshContent()?.onStateChanged(refreshLayout, oldState, newState)
|
||||
}
|
||||
|
||||
override fun setSmartRefreshEnabled(isEnable: Boolean) {
|
||||
(parentFragment as? ISmartRefresh)?.setSmartRefreshEnabled(isEnable)
|
||||
}
|
||||
|
||||
@ -41,6 +41,8 @@ import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.common.json.json
|
||||
import com.gh.gamecenter.common.observer.MuteCallback
|
||||
import com.gh.gamecenter.common.observer.VolumeObserver
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.MD5Utils
|
||||
@ -108,6 +110,20 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
|
||||
private var mLightToolbar = false
|
||||
private var mAutoFinishTwoLevelHandler: Handler? = null
|
||||
private var mAutoFinishTwoLevelCallback: (() -> Unit)? = null
|
||||
private val mVolumeObserver by lazy {
|
||||
VolumeObserver(object : MuteCallback {
|
||||
override fun onMute(isMute: Boolean) {
|
||||
if (::mBinding.isInitialized) {
|
||||
mBinding.muteIv.setImageResource(if (isMute) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
|
||||
if (isMute) {
|
||||
mBinding.autoVideoView.mute()
|
||||
} else {
|
||||
mBinding.autoVideoView.unMute()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private lateinit var mElapsedHelper: TimeElapsedHelper
|
||||
|
||||
@ -227,6 +243,7 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
|
||||
gameImageIv.goneIf(video != null) {
|
||||
ImageUtils.display(gameImageIv, imgUrl)
|
||||
}
|
||||
muteIv.isVisible = video != null
|
||||
autoVideoView.goneIf(video == null) {
|
||||
if (!autoVideoView.isInPlayingState) {
|
||||
GSYVideoOptionBuilder()
|
||||
@ -258,6 +275,17 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
|
||||
headerContainer.performClick()
|
||||
}
|
||||
}
|
||||
var videoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
|
||||
muteIv.setImageResource(if (videoVoiceStatus) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
|
||||
muteIv.setDebouncedClickListener {
|
||||
videoVoiceStatus = !videoVoiceStatus
|
||||
muteIv.setImageResource(if (videoVoiceStatus) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
|
||||
if (videoVoiceStatus) {
|
||||
autoVideoView.mute()
|
||||
} else {
|
||||
autoVideoView.unMute()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -271,6 +299,18 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
|
||||
pullDownPushHandler?.doPreProcess(this as? ISmartRefresh, popupPush)
|
||||
}
|
||||
|
||||
private fun observeVolume() {
|
||||
context?.applicationContext?.contentResolver?.registerContentObserver(
|
||||
android.provider.Settings.System.CONTENT_URI,
|
||||
true,
|
||||
mVolumeObserver
|
||||
)
|
||||
}
|
||||
|
||||
private fun unObserveVolume() {
|
||||
context?.applicationContext?.contentResolver?.unregisterContentObserver(mVolumeObserver)
|
||||
}
|
||||
|
||||
override fun onFragmentPause() {
|
||||
super.onFragmentPause()
|
||||
DownloadManager.getInstance().removeObserver(mDataWatcher)
|
||||
@ -434,6 +474,8 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
|
||||
oldState: RefreshState,
|
||||
newState: RefreshState
|
||||
) {
|
||||
(mContentFragment as? ISmartRefreshContent)?.onStateChanged(refreshLayout, oldState, newState)
|
||||
|
||||
val isAutoScrollToTwoLevel = oldState == RefreshState.None && newState == RefreshState.TwoLevel
|
||||
val isDragToTwoLevel =
|
||||
oldState == RefreshState.ReleaseToRefresh && newState == RefreshState.ReleaseToTwoLevel
|
||||
@ -550,12 +592,9 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
|
||||
|
||||
when (newState) {
|
||||
RefreshState.TwoLevel -> {
|
||||
(mContentFragment as? ISmartRefreshContent)?.setScrollEnabled(false)
|
||||
mBinding.refreshLayout.isDisableContent = false
|
||||
}
|
||||
RefreshState.None -> {
|
||||
(mContentFragment as? ISmartRefreshContent)?.setScrollEnabled(true)
|
||||
|
||||
mShowTwoLevel = false
|
||||
mIsDragging = false
|
||||
twoLevelHeader.setFloorDuration(1000)
|
||||
@ -739,6 +778,7 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
|
||||
} else {
|
||||
resumePullDownPushVideo()
|
||||
}
|
||||
observeVolume()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -752,6 +792,7 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
|
||||
if (videoUrl.isNotEmpty()) {
|
||||
ScrollCalculatorHelper.savePlaySchedule(MD5Utils.getContentMD5(videoUrl), currentPosition)
|
||||
}
|
||||
unObserveVolume()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ import com.gh.gamecenter.common.utils.UploadImageUtils;
|
||||
import com.gh.gamecenter.CropImageActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.common.view.cropbox.CropBoxStyle;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -68,108 +69,104 @@ public class UserPortraitCropImageActivity extends CropImageActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == R.id.layout_menu_positive) {
|
||||
final WaitingDialogFragment postDialog = WaitingDialogFragment.newInstance(getString(R.string.post_img));
|
||||
postDialog.show(getSupportFragmentManager(), null);
|
||||
final String path = getCacheDir() + File.separator + System.currentTimeMillis() + ".jpg";
|
||||
Observable.create((ObservableOnSubscribe<String>) emitter -> {
|
||||
boolean isSuccess = savePicture(path);
|
||||
if (isSuccess) {
|
||||
UploadImageUtils.INSTANCE.uploadImage(UploadImageUtils.UploadType.icon, path, new UploadImageUtils.OnUploadImageListener() {
|
||||
@Override
|
||||
public void onSuccess(@NotNull String imageUrl) {
|
||||
emitter.onNext(imageUrl);
|
||||
emitter.onComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@Nullable Throwable e) {
|
||||
if (e != null) {
|
||||
emitter.onError(e);
|
||||
} else {
|
||||
emitter.onError(new IllegalStateException("upload image error"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(long total, long progress) {
|
||||
int percent = (int) (100 * (progress / (float) total));
|
||||
if (percent >= 100) percent = 99;
|
||||
if (postDialog != null) {
|
||||
postDialog.uploadWaitingHint("图片上传中 " + percent + "%");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}).subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(new Response<String>() {
|
||||
@Override
|
||||
public void onResponse(String url) {
|
||||
try {
|
||||
if (postDialog != null) postDialog.dismissAllowingStateLoss();
|
||||
mBaseHandler.sendEmptyMessage(0);
|
||||
|
||||
String iconCount = sp.getString("updateIconCount", null);
|
||||
|
||||
long l = System.currentTimeMillis();
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.CHINA);
|
||||
String time = format.format(new Date(l));
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("time", time);
|
||||
|
||||
if (TextUtils.isEmpty(iconCount)) {
|
||||
jsonObject.put("count", 1);
|
||||
} else {
|
||||
JSONObject json = new JSONObject(iconCount);
|
||||
String lastTime = json.getString("time");
|
||||
if (lastTime.equals(time)) {
|
||||
jsonObject.put("count", json.getInt("count") + 1);
|
||||
} else {
|
||||
jsonObject.put("count", 1);
|
||||
}
|
||||
}
|
||||
|
||||
sp.edit().putString("updateIconCount", jsonObject.toString()).apply();
|
||||
|
||||
Intent data = new Intent();
|
||||
data.putExtra(EntranceConsts.KEY_URL, url);
|
||||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
protected void saveImage() {
|
||||
final WaitingDialogFragment postDialog = WaitingDialogFragment.newInstance(getString(R.string.post_img));
|
||||
postDialog.show(getSupportFragmentManager(), null);
|
||||
final String path = getCacheDir() + File.separator + System.currentTimeMillis() + ".jpg";
|
||||
Observable.create((ObservableOnSubscribe<String>) emitter -> {
|
||||
boolean isSuccess = savePicture(path);
|
||||
if (isSuccess) {
|
||||
UploadImageUtils.INSTANCE.uploadImage(UploadImageUtils.UploadType.icon, path, new UploadImageUtils.OnUploadImageListener() {
|
||||
@Override
|
||||
public void onSuccess(@NotNull String imageUrl) {
|
||||
emitter.onNext(imageUrl);
|
||||
emitter.onComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(HttpException e) {
|
||||
@Override
|
||||
public void onError(@Nullable Throwable e) {
|
||||
if (e != null) {
|
||||
emitter.onError(e);
|
||||
} else {
|
||||
emitter.onError(new IllegalStateException("upload image error"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(long total, long progress) {
|
||||
int percent = (int) (100 * (progress / (float) total));
|
||||
if (percent >= 100) percent = 99;
|
||||
if (postDialog != null) {
|
||||
postDialog.uploadWaitingHint("图片上传中 " + percent + "%");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}).subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(new Response<String>() {
|
||||
@Override
|
||||
public void onResponse(String url) {
|
||||
try {
|
||||
if (postDialog != null) postDialog.dismissAllowingStateLoss();
|
||||
try {
|
||||
if (e != null && e.code() == HttpURLConnection.HTTP_FORBIDDEN && e.response().errorBody() != null) {
|
||||
JSONObject object = new JSONObject(e.response().errorBody().string());
|
||||
String detail = object.getString("detail");
|
||||
if ("too frequent".equals(detail)) {
|
||||
mBaseHandler.sendEmptyMessage(2);
|
||||
} else if ("INVALID PICTURE".equals(detail)) {
|
||||
mBaseHandler.sendEmptyMessage(3);
|
||||
} else {
|
||||
mBaseHandler.sendEmptyMessage(1);
|
||||
}
|
||||
mBaseHandler.sendEmptyMessage(0);
|
||||
|
||||
String iconCount = sp.getString("updateIconCount", null);
|
||||
|
||||
long l = System.currentTimeMillis();
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.CHINA);
|
||||
String time = format.format(new Date(l));
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("time", time);
|
||||
|
||||
if (TextUtils.isEmpty(iconCount)) {
|
||||
jsonObject.put("count", 1);
|
||||
} else {
|
||||
JSONObject json = new JSONObject(iconCount);
|
||||
String lastTime = json.getString("time");
|
||||
if (lastTime.equals(time)) {
|
||||
jsonObject.put("count", json.getInt("count") + 1);
|
||||
} else {
|
||||
jsonObject.put("count", 1);
|
||||
}
|
||||
}
|
||||
|
||||
sp.edit().putString("updateIconCount", jsonObject.toString()).apply();
|
||||
|
||||
Intent data = new Intent();
|
||||
data.putExtra(EntranceConsts.KEY_URL, url);
|
||||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(HttpException e) {
|
||||
if (postDialog != null) postDialog.dismissAllowingStateLoss();
|
||||
try {
|
||||
if (e != null && e.code() == HttpURLConnection.HTTP_FORBIDDEN && e.response().errorBody() != null) {
|
||||
JSONObject object = new JSONObject(e.response().errorBody().string());
|
||||
String detail = object.getString("detail");
|
||||
if ("too frequent".equals(detail)) {
|
||||
mBaseHandler.sendEmptyMessage(2);
|
||||
} else if ("INVALID PICTURE".equals(detail)) {
|
||||
mBaseHandler.sendEmptyMessage(3);
|
||||
} else {
|
||||
mBaseHandler.sendEmptyMessage(1);
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
} else {
|
||||
mBaseHandler.sendEmptyMessage(1);
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
mBaseHandler.sendEmptyMessage(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
return super.onMenuItemClick(item);
|
||||
}
|
||||
|
||||
// 用户头像压缩规则
|
||||
@ -188,11 +185,11 @@ public class UserPortraitCropImageActivity extends CropImageActivity {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Intent getIntent(Context context, String picturePath, float cropRatio, String entrance) {
|
||||
public static Intent getIntent(Context context, String picturePath, String entrance) {
|
||||
Intent intent = new Intent(context, UserPortraitCropImageActivity.class);
|
||||
intent.putExtra(EntranceConsts.KEY_PATH, picturePath);
|
||||
intent.putExtra(EntranceConsts.KEY_ENTRANCE, entrance);
|
||||
intent.putExtra(EntranceConsts.KEY_IMAGE_CROP_RATIO, cropRatio);
|
||||
intent.putExtra(EntranceConsts.KEY_IMAGE_CROP_STYLE, CropBoxStyle.Circle.INSTANCE);
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.os.bundleOf
|
||||
import com.gh.common.provider.CropImageProviderImpl.Companion.IMAGE_TYPE_AVATAR
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.gamecenter.common.base.activity.BaseActivity
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
@ -93,23 +94,13 @@ class ChangeAvatarDialog : BaseDialogFragment() {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
when (requestCode) {
|
||||
REQUEST_MEDIA_ICON -> {
|
||||
val selectedPaths = Matisse.obtainResult(data) ?: return
|
||||
val picturePath = PathUtils.getPath(requireContext(), selectedPaths[0])
|
||||
Utils.log("picturePath = $picturePath")
|
||||
// 上传头像
|
||||
val intent = UserPortraitCropImageActivity.getIntent(
|
||||
context,
|
||||
picturePath, 1F, "我的光环(选择头像)"
|
||||
)
|
||||
startActivityForResult(intent, REQUEST_CROP_ICON)
|
||||
}
|
||||
REQUEST_CROP_ICON -> {
|
||||
if (data.extras != null) {
|
||||
val url = data.extras!!.getString(EntranceConsts.KEY_URL)
|
||||
mUserViewModel?.changeUserInfo(url, UserViewModel.TYPE_PORTRAIT)
|
||||
mUploadAvatar = true
|
||||
}
|
||||
}
|
||||
|
||||
ChooseDefaultAvatarDialog.REQUEST_CODE_DEFAULT_AVATAR -> {
|
||||
val tag = requireArguments().getString(EntranceConsts.KEY_PARENT_TAG)
|
||||
requireActivity().supportFragmentManager.findFragmentByTag(tag)
|
||||
@ -145,7 +136,7 @@ class ChangeAvatarDialog : BaseDialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
val intent = LocalMediaActivity.getIntent(requireContext(), ChooseType.IMAGE, 1, "头像选择")
|
||||
val intent = LocalMediaActivity.getIntent(requireContext(), ChooseType.IMAGE, 1, "头像选择", IMAGE_TYPE_AVATAR)
|
||||
startActivityForResult(intent, REQUEST_MEDIA_ICON)
|
||||
}
|
||||
|
||||
@ -154,7 +145,6 @@ class ChangeAvatarDialog : BaseDialogFragment() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val REQUEST_CROP_ICON = 12
|
||||
const val REQUEST_MEDIA_ICON = 13
|
||||
const val REQUEST_CODE_UPLOAD_AVATAR = 100
|
||||
|
||||
|
||||
5
app/src/main/res/drawable/bg_image_clip_submit.xml
Normal file
5
app/src/main/res/drawable/bg_image_clip_submit.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="999dp" />
|
||||
<solid android:color="#2496FF" />
|
||||
</shape>
|
||||
19
app/src/main/res/drawable/ic_basic_offsound.xml
Normal file
19
app/src/main/res/drawable/ic_basic_offsound.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M11.183,5.778C11.51,5.511 12,5.744 12,6.165V8.909C12,9.461 12.448,9.909 13,9.909C13.552,9.909 14,9.461 14,8.909V6.165C14,4.056 11.549,2.895 9.917,4.23L8.756,5.181C8.328,5.53 8.265,6.16 8.615,6.588C8.965,7.015 9.595,7.078 10.022,6.728L11.183,5.778Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M20.66,7C20.384,6.522 19.772,6.358 19.294,6.634C18.816,6.91 18.652,7.522 18.928,8C19.63,9.216 20,10.596 20,12C20,12.92 19.841,13.83 19.534,14.69C19.349,15.21 19.62,15.782 20.14,15.968C20.66,16.153 21.232,15.882 21.418,15.362C21.802,14.287 22,13.15 22,12C22,10.245 21.538,8.52 20.66,7Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M17.796,10.447C17.653,9.914 17.104,9.597 16.571,9.74C16.037,9.883 15.721,10.431 15.864,10.965C15.967,11.35 16.012,11.748 15.998,12.143C15.978,12.695 16.409,13.159 16.961,13.179C17.513,13.198 17.976,12.767 17.996,12.215C18.017,11.622 17.951,11.026 17.796,10.447Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M2.224,4.869C2.572,4.441 3.202,4.376 3.631,4.724L19.631,17.724C20.059,18.072 20.124,18.702 19.776,19.131C19.428,19.559 18.798,19.624 18.369,19.276L14,15.726V17.835C14,19.944 11.549,21.105 9.917,19.77L7.143,17.5H5C3.343,17.5 2,16.157 2,14.5V9.5C2,8.476 2.513,7.571 3.297,7.03L2.369,6.276C1.941,5.928 1.876,5.298 2.224,4.869ZM5.106,8.5L12,14.101V17.835C12,18.256 11.51,18.489 11.183,18.222L8.133,15.726C7.955,15.58 7.731,15.5 7.5,15.5H5C4.448,15.5 4,15.052 4,14.5V9.5C4,8.948 4.448,8.5 5,8.5H5.106Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
16
app/src/main/res/drawable/ic_basic_onsound.xml
Normal file
16
app/src/main/res/drawable/ic_basic_onsound.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M9.917,4.23C11.549,2.895 14,4.056 14,6.165V17.835C14,19.944 11.549,21.105 9.917,19.77L7.143,17.5H5C3.343,17.5 2,16.157 2,14.5V9.5C2,7.843 3.343,6.5 5,6.5H7.143L9.917,4.23ZM12,6.165C12,5.744 11.51,5.511 11.183,5.778L8.133,8.274C7.955,8.42 7.731,8.5 7.5,8.5H5C4.448,8.5 4,8.948 4,9.5V14.5C4,15.052 4.448,15.5 5,15.5H7.5C7.731,15.5 7.955,15.58 8.133,15.726L11.183,18.222C11.51,18.489 12,18.257 12,17.835V6.165Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M16.571,9.74C17.104,9.597 17.653,9.914 17.796,10.447C18.068,11.464 18.068,12.536 17.796,13.553C17.653,14.086 17.104,14.403 16.571,14.26C16.037,14.117 15.721,13.569 15.864,13.035C16.045,12.357 16.045,11.643 15.864,10.965C15.721,10.431 16.037,9.883 16.571,9.74Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M20.66,7C20.384,6.522 19.772,6.358 19.294,6.634C18.816,6.91 18.652,7.522 18.928,8C19.63,9.216 20,10.596 20,12C20,13.404 19.63,14.784 18.928,16C18.652,16.478 18.816,17.09 19.294,17.366C19.772,17.642 20.384,17.478 20.66,17C21.538,15.48 22,13.755 22,12C22,10.245 21.538,8.52 20.66,7Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
23
app/src/main/res/drawable/ic_video_cover_edit_remove.xml
Normal file
23
app/src/main/res/drawable/ic_video_cover_edit_remove.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,0h16v16h-16z"/>
|
||||
<path
|
||||
android:pathData="M8,8m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
|
||||
android:fillColor="#232323"/>
|
||||
<path
|
||||
android:pathData="M8,8m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.1"/>
|
||||
<path
|
||||
android:pathData="M10,6L6,10M6,6L10,10"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round"/>
|
||||
</group>
|
||||
</vector>
|
||||
19
app/src/main/res/drawable/ic_video_cover_edit_take_photo.xml
Normal file
19
app/src/main/res/drawable/ic_video_cover_edit_take_photo.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="56dp"
|
||||
android:height="56dp"
|
||||
android:viewportWidth="56"
|
||||
android:viewportHeight="56">
|
||||
<path
|
||||
android:pathData="M4,0L52,0A4,4 0,0 1,56 4L56,52A4,4 0,0 1,52 56L4,56A4,4 0,0 1,0 52L0,4A4,4 0,0 1,4 0z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.1"/>
|
||||
<path
|
||||
android:pathData="M20.5,17C20.5,16.448 20.948,16 21.5,16H34.5C35.052,16 35.5,16.448 35.5,17V23.086L34.268,21.854C33.292,20.877 31.708,20.877 30.732,21.854L28.232,24.354C28.139,24.447 28.011,24.5 27.879,24.5H26.621C25.958,24.5 25.322,24.763 24.854,25.232L21.149,28.937C20.77,28.795 20.5,28.429 20.5,28V17ZM21.501,31H21.5H21.501ZM21.501,31H34.5C36.157,31 37.5,29.657 37.5,28V25.501C37.5,25.5 37.5,25.5 37.5,25.499V17C37.5,15.343 36.157,14 34.5,14H21.5C19.843,14 18.5,15.343 18.5,17V28C18.5,29.656 19.843,30.999 21.499,31M35.5,25.914V28C35.5,28.552 35.052,29 34.5,29H23.914L26.268,26.646C26.361,26.553 26.489,26.5 26.621,26.5H27.879C28.542,26.5 29.178,26.237 29.646,25.768L32.146,23.268C32.342,23.073 32.658,23.073 32.854,23.268L35.5,25.914ZM24.75,19.5C24.336,19.5 24,19.836 24,20.25C24,20.664 24.336,21 24.75,21C25.164,21 25.5,20.664 25.5,20.25C25.5,19.836 25.164,19.5 24.75,19.5ZM22,20.25C22,18.731 23.231,17.5 24.75,17.5C26.269,17.5 27.5,18.731 27.5,20.25C27.5,21.769 26.269,23 24.75,23C23.231,23 22,21.769 22,20.25Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.8"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M12.601,39.514V40.315C12.925,40.639 13.744,41.584 13.933,41.827L13.51,42.358C13.339,42.07 12.943,41.512 12.601,41.071V45.139H11.962V40.945C11.611,41.935 11.161,42.898 10.684,43.501C10.603,43.321 10.414,43.051 10.297,42.889C10.936,42.124 11.557,40.729 11.881,39.514H10.513V38.884H11.962V36.967H12.601V38.884H13.888V39.514H12.601ZM14.914,43.96H17.65V42.412H14.914V43.96ZM17.65,38.128H14.914V39.631H17.65V38.128ZM14.914,40.243V41.791H17.65V40.243H14.914ZM14.275,37.498H18.307V45.085H17.65V44.581H14.914V45.085H14.275V37.498ZM24.544,40.513H25.975V38.182H24.544V40.324V40.513ZM21.052,40.513H22.312V38.182H21.052V40.315V40.513ZM27.595,40.513V41.161H26.632V44.374C26.632,44.761 26.542,44.95 26.299,45.067C26.056,45.175 25.651,45.193 24.994,45.193C24.958,45.013 24.859,44.725 24.778,44.554C25.246,44.572 25.678,44.572 25.795,44.563C25.93,44.554 25.975,44.509 25.975,44.374V41.161H24.526C24.472,42.493 24.238,44.086 23.491,45.211C23.392,45.076 23.122,44.833 22.987,44.752C23.662,43.717 23.833,42.349 23.878,41.161H22.96V44.338C22.96,44.707 22.87,44.896 22.636,45.004C22.384,45.112 21.997,45.121 21.376,45.121C21.349,44.95 21.241,44.68 21.16,44.518C21.601,44.527 22.015,44.527 22.141,44.518C22.267,44.518 22.312,44.473 22.312,44.338V41.161H21.034C20.971,42.502 20.719,44.104 19.882,45.247C19.783,45.103 19.531,44.851 19.396,44.779C20.143,43.735 20.341,42.358 20.395,41.161H19.405V40.513H20.413V40.315V37.561H22.96V40.513H23.896V40.324V37.561H26.632V40.513H27.595ZM34.093,40.693H33.175C33.004,42.106 32.572,43.141 31.06,43.726C30.979,43.564 30.799,43.321 30.655,43.195C32.005,42.718 32.365,41.863 32.509,40.693H30.898V40.108H33.418V38.794H32.095C31.915,39.136 31.726,39.451 31.51,39.703C31.393,39.604 31.105,39.433 30.952,39.361C31.429,38.83 31.807,38.029 32.023,37.237L32.662,37.381C32.581,37.66 32.482,37.939 32.365,38.209H33.418V37.003H34.084V38.209H36.154V38.794H34.084V40.108H36.523V40.693H34.75V42.772C34.75,42.988 34.786,43.024 35.011,43.024H35.731C35.938,43.024 35.983,42.889 36.001,41.962C36.145,42.07 36.415,42.178 36.604,42.223C36.532,43.357 36.352,43.645 35.794,43.645H34.921C34.246,43.645 34.093,43.438 34.093,42.772V40.693ZM30.511,38.722L29.962,39.136C29.701,38.704 29.098,38.065 28.567,37.633L29.08,37.273C29.611,37.687 30.232,38.29 30.511,38.722ZM30.277,40.396V43.573C30.52,43.609 30.727,43.825 31.15,44.068C31.708,44.401 32.446,44.455 33.4,44.455C34.426,44.455 35.776,44.392 36.667,44.293C36.586,44.473 36.478,44.797 36.469,44.986C35.776,45.031 34.264,45.085 33.391,45.085C32.347,45.085 31.618,44.986 31.024,44.644C30.673,44.428 30.403,44.176 30.205,44.176C29.872,44.176 29.386,44.626 28.882,45.184L28.441,44.617C28.837,44.239 29.251,43.915 29.629,43.735V41.026H28.522V40.396H30.277ZM40.303,41.413L39.268,41.755V44.365C39.268,44.743 39.187,44.923 38.953,45.031C38.737,45.139 38.395,45.157 37.819,45.157C37.792,44.977 37.702,44.707 37.621,44.518C37.999,44.536 38.359,44.536 38.458,44.527C38.575,44.527 38.62,44.491 38.62,44.365V41.962C38.224,42.097 37.855,42.214 37.522,42.322L37.351,41.674C37.702,41.575 38.143,41.44 38.62,41.296V39.388H37.441V38.767H38.62V36.976H39.268V38.767H40.33V39.388H39.268V41.098L40.213,40.801L40.303,41.413ZM43.237,42.187V43.114H45.586V43.717H43.237V45.211H42.58V43.717H40.303V43.114H42.58V42.187H40.762V41.593H42.58V40.801H43.237V41.593H44.938V42.187H43.237ZM44.227,38.056H41.788C42.085,38.524 42.481,38.938 42.949,39.289C43.462,38.938 43.903,38.524 44.227,38.056ZM44.749,37.426L45.154,37.651C44.767,38.434 44.173,39.1 43.462,39.64C44.119,40.045 44.893,40.351 45.73,40.531C45.595,40.666 45.415,40.918 45.316,41.089C44.434,40.864 43.624,40.486 42.931,40.009C42.193,40.486 41.365,40.846 40.537,41.08C40.465,40.927 40.312,40.675 40.186,40.54C40.942,40.351 41.734,40.045 42.436,39.622C41.914,39.172 41.473,38.65 41.149,38.056H40.564V37.453H44.641L44.749,37.426Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.8"/>
|
||||
</vector>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="999dp" />
|
||||
<solid android:color="#2496FF" />
|
||||
</shape>
|
||||
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/white" />
|
||||
|
||||
<corners android:radius="2dp" />
|
||||
|
||||
</shape>
|
||||
@ -8,48 +8,41 @@
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:background="#1A1A1A">
|
||||
|
||||
<com.gh.gamecenter.common.view.CropImageCustom
|
||||
android:id="@+id/cropImageIv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
app:horizontalPadding="0dp"
|
||||
app:horizontalPadding="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="68dp"
|
||||
android:background="@color/black_alpha_40"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cancelTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginBottom="35dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="取消"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="13sp"
|
||||
android:textSize="12sp"
|
||||
android:gravity="center"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nextTv"
|
||||
android:layout_width="60dp"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="28dp"
|
||||
android:background="@drawable/bg_notification_open_btn_style_2"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:background="@drawable/bg_image_clip_submit"
|
||||
android:gravity="center"
|
||||
android:text="下一步"
|
||||
android:text="@string/confirm"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
||||
@ -13,27 +13,39 @@
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true" />
|
||||
|
||||
<com.gh.gamecenter.common.view.StatusBarView
|
||||
android:id="@+id/status_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
<com.gh.gamecenter.common.view.CropImageCustom
|
||||
android:id="@+id/cropimage_custom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/status_bar"
|
||||
android:orientation="vertical">
|
||||
android:background="@color/ui_background_fixed_dark" />
|
||||
|
||||
<include layout="@layout/reuse_toolbar" />
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="52dp"
|
||||
android:layout_alignParentBottom="true">
|
||||
|
||||
<com.gh.gamecenter.common.view.CropImageCustom
|
||||
android:id="@+id/cropimage_custom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black" />
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/tv_cancel"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/cancel"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_submit"
|
||||
style="@style/BtnSmallStyle"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="@drawable/bg_image_clip_submit"
|
||||
android:text="@string/confirm"
|
||||
android:textColor="@color/white"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.gh.gamecenter.common.view.MaterializedRelativeLayout>
|
||||
11
app/src/main/res/layout/actvitity_video_cover_edit.xml
Normal file
11
app/src/main/res/layout/actvitity_video_cover_edit.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fcv_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
||||
@ -164,6 +164,19 @@
|
||||
app:lottie_loop="true"
|
||||
app:lottie_repeatMode="restart" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/muteIv"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:padding="4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:srcCompat="@drawable/ic_basic_offsound"
|
||||
app:tint="@color/text_instance" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/headerBackground"
|
||||
android:layout_width="0dp"
|
||||
|
||||
@ -169,6 +169,19 @@
|
||||
app:lottie_loop="true"
|
||||
app:lottie_repeatMode="restart" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/muteIv"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:padding="4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:srcCompat="@drawable/ic_basic_offsound"
|
||||
app:tint="@color/text_instance" />
|
||||
|
||||
<View
|
||||
android:id="@+id/headerBackground"
|
||||
android:layout_width="0dp"
|
||||
|
||||
133
app/src/main/res/layout/fragment_video_cover_edit.xml
Normal file
133
app/src/main/res/layout/fragment_video_cover_edit.xml
Normal file
@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#1A1A1A">
|
||||
|
||||
<com.gh.gamecenter.common.view.StatusBarView
|
||||
android:id="@+id/status_bar_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.gh.gamecenter.common.view.CropImageCustom
|
||||
android:id="@+id/crop_image_custom"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:horizontalPadding="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/v_bottom_background"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="160dp"
|
||||
android:background="#232323"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<com.gh.gamecenter.common.view.DividerView
|
||||
android:id="@+id/v_line"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="51dp"
|
||||
android:background="#333333"
|
||||
app:divider_size="0"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_cancel"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/cancel"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/v_line" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_submit"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="@drawable/shape_video_cover_edit_submit"
|
||||
android:gravity="center"
|
||||
android:text="@string/confirm"
|
||||
android:textColor="#ffffff"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/v_line" />
|
||||
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/iv_take_photo"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_video_cover_edit_take_photo"
|
||||
app:layout_constraintBottom_toBottomOf="@id/v_line"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/iv_preview_border"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/iv_take_photo"
|
||||
app:layout_constraintEnd_toEndOf="@id/iv_take_photo"
|
||||
app:layout_constraintStart_toStartOf="@id/iv_take_photo"
|
||||
app:layout_constraintTop_toTopOf="@id/iv_take_photo" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_remove"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginTop="-6dp"
|
||||
android:layout_marginEnd="-6dp"
|
||||
android:src="@drawable/ic_video_cover_edit_remove"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="@id/iv_take_photo"
|
||||
app:layout_constraintTop_toTopOf="@id/iv_take_photo"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_images"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/iv_take_photo"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/iv_take_photo"
|
||||
app:layout_constraintTop_toTopOf="@id/iv_take_photo"
|
||||
tools:background="#1AFFFFFF" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_bottom_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="@string/select_from_album_or_select_video_screenshot"
|
||||
android:textColor="#99FFFFFF"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/iv_take_photo"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -10,6 +10,7 @@
|
||||
android:id="@+id/cv_banner_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:cardBackgroundColor="@color/transparent"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="0dp"
|
||||
app:layout_constraintDimensionRatio="41:11"
|
||||
|
||||
@ -2,38 +2,49 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp">
|
||||
android:layout_height="56dp">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/preview_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
app:cardCornerRadius="3dp"
|
||||
app:cardElevation="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/preview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/text_28282E"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<View
|
||||
android:id="@+id/preview_border"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/video_poster_preview_border"
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/preview"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/text_28282E"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/preview_border_out"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/preview_border_inner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/g_preview_border"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="preview_border_out,preview_border_inner" />
|
||||
|
||||
<com.gh.gamecenter.video.poster.PreviewMaskView
|
||||
android:id="@+id/v_cover"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@ -593,6 +593,7 @@
|
||||
<string name="dialog_vgame_installed_launch_button">啟動遊戲</string>
|
||||
<string name="dialog_vgame_installed_launch_desc_1">加載完成,馬上開始遊戲吧</string>
|
||||
<string name="dialog_vgame_installed_launch_desc_2">%1$d款遊戲加載完成,馬上開始遊戲吧</string>
|
||||
<string name="select_from_album_or_select_video_screenshot">從相簿選擇或選擇影片截圖</string>
|
||||
<string name="reverse_success_without_reminder_tips">遊戲上線後,您將在訊息中心收到通知</string>
|
||||
<string name="reverse_success_with_reminder_tips">遊戲上線後,您將在訊息中心收到通知,及以下方式提醒</string>
|
||||
<string name="sms_reminder">簡訊提醒</string>
|
||||
|
||||
@ -593,6 +593,7 @@
|
||||
<string name="dialog_vgame_installed_launch_button">启动游戏</string>
|
||||
<string name="dialog_vgame_installed_launch_desc_1">加载完成,马上开始游戏吧</string>
|
||||
<string name="dialog_vgame_installed_launch_desc_2">%1$d款游戏加载完成,马上开始游戏吧</string>
|
||||
<string name="select_from_album_or_select_video_screenshot">从相册选择或选择视频截图</string>
|
||||
<string name="reverse_success_without_reminder_tips">游戏上线后,您将在消息中心收到通知</string>
|
||||
<string name="reverse_success_with_reminder_tips">游戏上线后,您将在消息中心收到通知,及以下方式提醒</string>
|
||||
<string name="sms_reminder">短信提醒</string>
|
||||
|
||||
@ -41,13 +41,18 @@ class LocalMediaActivity : BaseActivity() {
|
||||
context: Context,
|
||||
chooseType: ChooseType,
|
||||
maxChooseCount: Int = 1,
|
||||
entrance: String
|
||||
entrance: String,
|
||||
imageType: Int = 0
|
||||
): Intent {
|
||||
return Intent(context, LocalMediaActivity::class.java).apply {
|
||||
putExtra(EntranceConsts.KEY_TYPE, chooseType.value)
|
||||
putExtra(EntranceConsts.KEY_CHOOSE_MAX_COUNT, maxChooseCount)
|
||||
putExtra(EntranceConsts.KEY_QUICK_CHOOSE, maxChooseCount == 1)
|
||||
putExtra(
|
||||
EntranceConsts.KEY_QUICK_CHOOSE,
|
||||
if (chooseType == ChooseType.VIDEO) false else maxChooseCount == 1
|
||||
)
|
||||
putExtra(EntranceConsts.KEY_ENTRANCE, entrance)
|
||||
putExtra(EntranceConsts.KEY_IMAGE_TYPE, imageType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ class LocalMediaAdapter(
|
||||
holder.binding.checkImageView.visibility = View.GONE
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
viewModel.addSelection(item)
|
||||
viewModel.setSelection(item)
|
||||
viewModel.postSelectedResult()
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -14,6 +14,7 @@ import android.widget.PopupWindow
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.gh.gamecenter.common.base.fragment.BaseFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.common.entity.LocalVideoEntity
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
@ -23,11 +24,13 @@ import com.gh.gamecenter.core.utils.MD5Utils
|
||||
import com.gh.gamecenter.common.utils.enlargeTouchArea
|
||||
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
|
||||
import com.gh.gamecenter.common.view.GridSpacingItemDecoration
|
||||
import com.gh.gamecenter.core.provider.ICropImageProvider
|
||||
import com.zhihu.matisse.Matisse
|
||||
import com.zhihu.matisse.MimeType
|
||||
|
||||
import com.gh.gamecenter.livedata.EventObserver
|
||||
import com.gh.gamecenter.selector.databinding.FragmentLocalMediaBinding
|
||||
import com.therouter.TheRouter
|
||||
|
||||
import com.zhihu.matisse.internal.entity.Album
|
||||
import com.zhihu.matisse.internal.entity.Item
|
||||
@ -60,6 +63,7 @@ class LocalMediaFragment : BaseFragment<Any>(), AlbumMediaCollection.AlbumMediaC
|
||||
|
||||
private val albumCollection = AlbumCollection()
|
||||
private var isFirstAlbumLoad = true
|
||||
private var imageType = 0
|
||||
|
||||
override fun getLayoutId(): Int = 0
|
||||
|
||||
@ -77,12 +81,15 @@ class LocalMediaFragment : BaseFragment<Any>(), AlbumMediaCollection.AlbumMediaC
|
||||
isQuickChoose = savedInstanceState?.getBoolean(EntranceConsts.KEY_QUICK_CHOOSE, false)
|
||||
?: arguments?.getBoolean(EntranceConsts.KEY_QUICK_CHOOSE, false)
|
||||
?: false
|
||||
imageType = savedInstanceState?.getInt(EntranceConsts.KEY_IMAGE_TYPE, 0)
|
||||
?: arguments?.getInt(EntranceConsts.KEY_IMAGE_TYPE, 0) ?: 0
|
||||
|
||||
viewModel = viewModelProviderFromParent(LocalMediaViewModel.Factory(maxChooseCount))
|
||||
|
||||
// 页面恢复时,恢复选中的数据
|
||||
if (savedInstanceState != null) {
|
||||
val savedSelectedItem: ArrayList<Item>? = savedInstanceState.getParcelableArrayList(EntranceConsts.KEY_VIDEO_LIST)
|
||||
val savedSelectedItem: ArrayList<Item>? =
|
||||
savedInstanceState.getParcelableArrayList(EntranceConsts.KEY_VIDEO_LIST)
|
||||
if (savedSelectedItem != null) {
|
||||
for (selectedItem in savedSelectedItem) {
|
||||
viewModel.addSelection(selectedItem)
|
||||
@ -164,14 +171,27 @@ class LocalMediaFragment : BaseFragment<Any>(), AlbumMediaCollection.AlbumMediaC
|
||||
)
|
||||
}
|
||||
intent.putExtra(LocalVideoEntity::class.java.name, localVideoList)
|
||||
|
||||
requireActivity().setResult(Activity.RESULT_OK, intent)
|
||||
requireActivity().finish()
|
||||
} else {
|
||||
val data = viewModel.selectedItemList.map { it.contentUri }.toList()
|
||||
val path = data.map { PathUtils.getPath(requireContext(), it) }.toList()
|
||||
intent.putParcelableArrayListExtra(MatisseActivity.EXTRA_RESULT_SELECTION, ArrayList<Uri>(data))
|
||||
intent.putStringArrayListExtra(MatisseActivity.EXTRA_RESULT_SELECTION_PATH, ArrayList<String>(path))
|
||||
|
||||
val imageProvider = TheRouter.get(ICropImageProvider::class.java)
|
||||
val toIntent = imageProvider?.getCropImageIntent(data, imageType, mEntrance, requireContext())
|
||||
if (toIntent != null) {
|
||||
// 需要裁剪
|
||||
startActivityForResult(toIntent, REQUEST_CROP_ICON)
|
||||
} else {
|
||||
intent.putParcelableArrayListExtra(MatisseActivity.EXTRA_RESULT_SELECTION, ArrayList(data))
|
||||
intent.putStringArrayListExtra(MatisseActivity.EXTRA_RESULT_SELECTION_PATH, ArrayList(path))
|
||||
requireActivity().setResult(Activity.RESULT_OK, intent)
|
||||
requireActivity().finish()
|
||||
}
|
||||
}
|
||||
requireActivity().setResult(Activity.RESULT_OK, intent)
|
||||
requireActivity().finish()
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,12 +216,21 @@ class LocalMediaFragment : BaseFragment<Any>(), AlbumMediaCollection.AlbumMediaC
|
||||
binding.pieceMediaControl.previewTv.isEnabled = isNotEmpty
|
||||
binding.pieceMediaControl.confirmTv.isEnabled = isNotEmpty
|
||||
if (isNotEmpty) {
|
||||
binding.pieceMediaControl.previewTv.setTextColor(com.gh.gamecenter.common.R.color.text_aw_primary.toColor(requireContext()))
|
||||
binding.pieceMediaControl.previewTv.setTextColor(
|
||||
com.gh.gamecenter.common.R.color.text_aw_primary.toColor(
|
||||
requireContext()
|
||||
)
|
||||
)
|
||||
binding.pieceMediaControl.previewTv.alpha = 1F
|
||||
binding.pieceMediaControl.confirmTv.alpha = 1F
|
||||
binding.pieceMediaControl.confirmTv.text = "${getString(com.gh.gamecenter.common.R.string.confirm)}(${it})"
|
||||
binding.pieceMediaControl.confirmTv.text =
|
||||
"${getString(com.gh.gamecenter.common.R.string.confirm)}(${it})"
|
||||
} else {
|
||||
binding.pieceMediaControl.previewTv.setTextColor(com.gh.gamecenter.common.R.color.text_aw_primary.toColor(requireContext()))
|
||||
binding.pieceMediaControl.previewTv.setTextColor(
|
||||
com.gh.gamecenter.common.R.color.text_aw_primary.toColor(
|
||||
requireContext()
|
||||
)
|
||||
)
|
||||
binding.pieceMediaControl.previewTv.alpha = 0.6F
|
||||
binding.pieceMediaControl.confirmTv.alpha = 0.6F
|
||||
binding.pieceMediaControl.confirmTv.text = getString(com.gh.gamecenter.common.R.string.confirm)
|
||||
@ -333,4 +362,25 @@ class LocalMediaFragment : BaseFragment<Any>(), AlbumMediaCollection.AlbumMediaC
|
||||
albumMediaCollection?.onDestroy()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
when (requestCode) {
|
||||
REQUEST_CROP_ICON -> {
|
||||
// 裁剪成功
|
||||
if (data != null) {
|
||||
val intent = Intent()
|
||||
intent.putExtras(data)
|
||||
requireActivity().setResult(Activity.RESULT_OK, intent)
|
||||
requireActivity().finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val REQUEST_CROP_ICON = 13
|
||||
}
|
||||
|
||||
}
|
||||
@ -61,6 +61,7 @@ import com.github.piasy.biv.view.BigImageView
|
||||
import com.github.piasy.biv.view.FrescoImageViewFactory
|
||||
import com.lightgame.listeners.OnBackPressedListener
|
||||
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
|
||||
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView.CURRENT_STATE_PLAYING
|
||||
import com.zhihu.matisse.internal.entity.Album
|
||||
import com.zhihu.matisse.internal.entity.Item
|
||||
import java.io.File
|
||||
@ -171,7 +172,12 @@ class LocalMediaPreviewFragment : BaseFragment<Any>(), OnPageChangeListener, OnB
|
||||
parentViewModel?.removeSelection(currentDisplayingItem!!)
|
||||
} else {
|
||||
if (parentViewModel?.addSelection(currentDisplayingItem!!) == false) {
|
||||
ToastUtils.showToast("至多选择${parentViewModel?.maxSelectionSize}张图片")
|
||||
val toastText = if (currentDisplayingItem?.isVideo == true) {
|
||||
ToastUtils.showToast("至多选择${parentViewModel?.maxSelectionSize}条视频")
|
||||
} else {
|
||||
ToastUtils.showToast("至多选择${parentViewModel?.maxSelectionSize}张图片")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +217,11 @@ class LocalMediaPreviewFragment : BaseFragment<Any>(), OnPageChangeListener, OnB
|
||||
binding.mediaControl.confirmTv.text = "确定(${list.size})"
|
||||
binding.mediaControl.confirmTv.alpha = 1f
|
||||
} else {
|
||||
binding.mediaControl.previewTv.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
|
||||
binding.mediaControl.previewTv.setTextColor(
|
||||
com.gh.gamecenter.common.R.color.text_secondary.toColor(
|
||||
requireContext()
|
||||
)
|
||||
)
|
||||
binding.mediaControl.confirmTv.text = "确定"
|
||||
binding.mediaControl.confirmTv.alpha = 0.6f
|
||||
}
|
||||
@ -225,7 +235,8 @@ class LocalMediaPreviewFragment : BaseFragment<Any>(), OnPageChangeListener, OnB
|
||||
}
|
||||
|
||||
if (previewItem?.isVideo != true
|
||||
&& currentDisplayingItem?.id == previewItem?.id ) {
|
||||
&& currentDisplayingItem?.id == previewItem?.id
|
||||
) {
|
||||
initEnterAnimation()
|
||||
}
|
||||
|
||||
@ -808,7 +819,9 @@ class LocalMediaPreviewFragment : BaseFragment<Any>(), OnPageChangeListener, OnB
|
||||
videoViewMap.put(position, binding.videoView)
|
||||
|
||||
binding.videoView.updateThumb(item.contentUri.toString())
|
||||
binding.videoView.setAlOnClickListener { toggleToolbarAndBottomContainer() }
|
||||
binding.videoView.setAlOnClickListener {
|
||||
binding.videoView.startButton.performClick()
|
||||
}
|
||||
setDragListener(binding.videoView)
|
||||
GSYVideoOptionBuilder()
|
||||
.setIsTouchWiget(false)
|
||||
@ -819,7 +832,12 @@ class LocalMediaPreviewFragment : BaseFragment<Any>(), OnPageChangeListener, OnB
|
||||
.setReleaseWhenLossAudio(true)
|
||||
.setLooping(false)
|
||||
.setShowFullAnimation(false)
|
||||
.setGSYStateUiListener {
|
||||
toggleToolbarAndBottomContainer(it != CURRENT_STATE_PLAYING)
|
||||
}
|
||||
.build(binding.videoView)
|
||||
|
||||
|
||||
} else {
|
||||
if (useEnterAndExitAnimation) {
|
||||
containerMap.put(position, view)
|
||||
@ -829,7 +847,9 @@ class LocalMediaPreviewFragment : BaseFragment<Any>(), OnPageChangeListener, OnB
|
||||
}
|
||||
setDragListener(binding.iv)
|
||||
|
||||
binding.iv.setOnClickListener { toggleToolbarAndBottomContainer() }
|
||||
binding.iv.setOnClickListener {
|
||||
toggleToolbarAndBottomContainer(bottomContainer.visibility != View.VISIBLE)
|
||||
}
|
||||
binding.iv.setImageLoaderCallback(object : SimpleImageLoader() {
|
||||
override fun onSuccess(image: File) {
|
||||
val ssiv = binding.iv.ssiv
|
||||
@ -868,13 +888,13 @@ class LocalMediaPreviewFragment : BaseFragment<Any>(), OnPageChangeListener, OnB
|
||||
private fun isFadeOnly() =
|
||||
currentDisplayingItem?.isVideo == true || originLeftMap?.get(currentDisplayingItem?.uri?.toString()) == null
|
||||
|
||||
private fun toggleToolbarAndBottomContainer() {
|
||||
if (bottomContainer.visibility == View.VISIBLE) {
|
||||
bottomContainer.visibility = View.GONE
|
||||
toolbarContainer.visibility = View.GONE
|
||||
} else {
|
||||
private fun toggleToolbarAndBottomContainer(showController: Boolean) {
|
||||
if (showController) {
|
||||
bottomContainer.visibility = View.VISIBLE
|
||||
toolbarContainer.visibility = View.VISIBLE
|
||||
} else {
|
||||
bottomContainer.visibility = View.GONE
|
||||
toolbarContainer.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -48,6 +48,10 @@ class LocalMediaRepository {
|
||||
_selectedItemListFlow.tryEmit(newList)
|
||||
}
|
||||
|
||||
fun setSelection(item: Item) {
|
||||
_selectedItemListFlow.tryEmit(arrayListOf(item))
|
||||
}
|
||||
|
||||
fun closeCursor() {
|
||||
albumCursor?.close()
|
||||
}
|
||||
|
||||
@ -70,6 +70,10 @@ class LocalMediaViewModel(val maxSelectionSize: Int) : ViewModel() {
|
||||
return true
|
||||
}
|
||||
|
||||
fun setSelection(item: Item) {
|
||||
localMediaRepo.setSelection(item)
|
||||
}
|
||||
|
||||
fun removeSelection(item: Item) {
|
||||
localMediaRepo.removeSelection(item)
|
||||
}
|
||||
|
||||
@ -2,9 +2,7 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="52dp"
|
||||
android:background="@color/ui_surface_fixed_dark"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp">
|
||||
android:background="@color/ui_surface_fixed_dark">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/previewTv"
|
||||
@ -14,6 +12,7 @@
|
||||
android:enabled="false"
|
||||
android:gravity="center"
|
||||
android:text="预览"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:textColor="@color/text_aw_primary"
|
||||
android:textSize="12sp" />
|
||||
|
||||
@ -24,6 +23,7 @@
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:alpha="0.6"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:background="@drawable/button_blue_oval"
|
||||
android:enabled="false"
|
||||
android:gravity="center"
|
||||
|
||||
@ -475,4 +475,6 @@ public class Constants {
|
||||
|
||||
public static final String TOOL_MAP_PACKAGE_NAME = "com.gh.toolmap";// 光环工具服务APP包名
|
||||
|
||||
public static final String SP_VIDEO_COVER_CACHE = "sp_video_cover_cache";
|
||||
|
||||
}
|
||||
|
||||
@ -209,6 +209,7 @@ public class EntranceConsts {
|
||||
public static final String KEY_OPEN_KEYBOARD = "openKeyboard";
|
||||
public static final String KEY_PATH_VIDEO = "pathVideo";
|
||||
public static final String KEY_VIDEO_ID = "videoId";
|
||||
public static final String KEY_VIDEO_ENTITY = "key_video_entity";
|
||||
public static final String KEY_DIRECT_COMMENT = "directComment";
|
||||
public static final String KEY_SORT = "sort";
|
||||
public static final String KEY_AMWAY = "amway";
|
||||
@ -219,6 +220,8 @@ public class EntranceConsts {
|
||||
|
||||
public static final String KEY_COLLECTION_NAME = "collectionName";
|
||||
public static final String KEY_NAVIGATION_TITLE = "navigationTitle";
|
||||
public static final String KEY_IMAGE_CROP_STYLE = "imageCropStyle";
|
||||
public static final String KEY_IMAGE_TYPE = "imageType";
|
||||
public static final String KEY_IMAGE_CROP_RATIO = "imageCropRatio";
|
||||
public static final String KEY_OPEN_VIDEO_STREAMING = "open_video_streaming";
|
||||
public static final String KEY_REFERER = "referer";
|
||||
|
||||
@ -14,6 +14,7 @@ object RouteConsts {
|
||||
const val forumVideoDetailActivity = "/app/forumVideoDetailActivity"
|
||||
const val libaoDetailActivity = "/app/libaoDetailActivity"
|
||||
const val fullScreenVideoActivity = "/app/FullScreenVideoActivity"
|
||||
const val videoCoverEditActivity = "/app/videoCoverEditActivity"
|
||||
|
||||
const val gameDetailActivity = "/activity/game_detail"
|
||||
const val userHomeActivity = "/activity/user_home"
|
||||
|
||||
@ -10,6 +10,8 @@ import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.gh.gamecenter.common.R;
|
||||
import com.gh.gamecenter.common.view.cropbox.CropBoxStyle;
|
||||
import com.gh.gamecenter.common.view.cropbox.CropBoxView;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
@ -19,9 +21,9 @@ import java.io.FileOutputStream;
|
||||
public class CropImageCustom extends RelativeLayout {
|
||||
|
||||
private CropImageZoomView mZoomImageView;
|
||||
private CropImageBorderView mClipImageView;
|
||||
private CropBoxView mClipImageView;
|
||||
|
||||
private int mHorizontalPadding = 20;
|
||||
private int mHorizontalPadding = 16;
|
||||
|
||||
private float mRatio = 1F; // 裁剪比例
|
||||
|
||||
@ -29,7 +31,7 @@ public class CropImageCustom extends RelativeLayout {
|
||||
super(context, attrs);
|
||||
|
||||
mZoomImageView = new CropImageZoomView(context);
|
||||
mClipImageView = new CropImageBorderView(context);
|
||||
mClipImageView = new CropBoxView(context);
|
||||
|
||||
android.view.ViewGroup.LayoutParams lp = new LayoutParams(
|
||||
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
@ -47,13 +49,21 @@ public class CropImageCustom extends RelativeLayout {
|
||||
ta.recycle();
|
||||
|
||||
mZoomImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
|
||||
mClipImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
|
||||
mClipImageView.setHorizontalPaddingBoxStyle(mHorizontalPadding, new CropBoxStyle.Rectangle(mRatio));
|
||||
mZoomImageView.setOnDragStateChangeListener(isDragging -> {
|
||||
mClipImageView.changeDragState(isDragging);
|
||||
});
|
||||
}
|
||||
|
||||
public void setCropRatio(float ratio) {
|
||||
this.mRatio = ratio;
|
||||
public void setCropBoxStyle(CropBoxStyle boxStyle) {
|
||||
if (boxStyle instanceof CropBoxStyle.Circle) {
|
||||
mRatio = 1F;
|
||||
}
|
||||
if (boxStyle instanceof CropBoxStyle.Rectangle) {
|
||||
mRatio = ((CropBoxStyle.Rectangle) boxStyle).getRadio();
|
||||
}
|
||||
mZoomImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
|
||||
mClipImageView.setHorizontalPadding(mHorizontalPadding, mRatio);
|
||||
mClipImageView.setHorizontalPaddingBoxStyle(mHorizontalPadding, boxStyle);
|
||||
}
|
||||
|
||||
public void addAssistView(View view) {
|
||||
@ -99,4 +109,16 @@ public class CropImageCustom extends RelativeLayout {
|
||||
mZoomImageView.setImageBitmap(bitmap);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
mZoomImageView.reset();
|
||||
}
|
||||
|
||||
public CropImageZoomView.TransformationValues getTransformationValues() {
|
||||
return mZoomImageView.getTransformationValues();
|
||||
}
|
||||
|
||||
public void setTransformationValues(CropImageZoomView.TransformationValues values) {
|
||||
mZoomImageView.setTransformationValues(values);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import android.view.ScaleGestureDetector;
|
||||
import android.view.ScaleGestureDetector.OnScaleGestureListener;
|
||||
import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
@ -30,11 +31,13 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
*/
|
||||
private final float[] matrixValues = new float[9];
|
||||
private final Matrix mScaleMatrix = new Matrix();
|
||||
private TransformationValues cacheValues;
|
||||
/**
|
||||
* 初始化时的缩放比例,如果图片宽或高大于屏幕,此值将小于0
|
||||
*/
|
||||
private float initScale = 1.0f;
|
||||
private boolean once = true;
|
||||
|
||||
/**
|
||||
* 缩放的手势检测
|
||||
*/
|
||||
@ -65,13 +68,17 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
|
||||
private int mWidth;
|
||||
|
||||
private boolean isDragging = false;
|
||||
|
||||
private int touchSlop;
|
||||
|
||||
public CropImageZoomView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public CropImageZoomView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
|
||||
setScaleType(ScaleType.MATRIX);
|
||||
mGestureDetector = new GestureDetector(context,
|
||||
new SimpleOnGestureListener() {
|
||||
@ -109,6 +116,20 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
return matrixValues[Matrix.MSCALE_X];
|
||||
}
|
||||
|
||||
public TransformationValues getTransformationValues() {
|
||||
mScaleMatrix.getValues(matrixValues);
|
||||
return new TransformationValues(
|
||||
matrixValues[Matrix.MSCALE_X],
|
||||
matrixValues[Matrix.MSCALE_Y],
|
||||
matrixValues[Matrix.MTRANS_X],
|
||||
matrixValues[Matrix.MTRANS_Y]
|
||||
);
|
||||
}
|
||||
|
||||
public void setTransformationValues(TransformationValues values) {
|
||||
cacheValues = values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
float scale = getScale();
|
||||
@ -252,6 +273,18 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
checkBorder();
|
||||
setImageMatrix(mScaleMatrix);
|
||||
}
|
||||
|
||||
boolean isMoving = false;
|
||||
if (Math.abs(dx) > mTouchSlop) {
|
||||
isMoving = true;
|
||||
}
|
||||
if (Math.abs(dy) > mTouchSlop) {
|
||||
isMoving = true;
|
||||
}
|
||||
if (isMoving && stateListener != null && !isDragging) {
|
||||
isDragging = true;
|
||||
stateListener.onStateChanged(true);
|
||||
}
|
||||
}
|
||||
mLastX = x;
|
||||
mLastY = y;
|
||||
@ -260,6 +293,10 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
lastPointerCount = 0;
|
||||
if (stateListener != null && isDragging) {
|
||||
isDragging = false;
|
||||
stateListener.onStateChanged(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -333,9 +370,17 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
initScale = scale;
|
||||
SCALE_MID = initScale * 2;
|
||||
SCALE_MAX = initScale * 4;
|
||||
mScaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2);// 平移至屏幕中心
|
||||
mScaleMatrix.postScale(scale, scale, getWidth() / 2,
|
||||
getHeight() / 2);// 设置缩放比例
|
||||
|
||||
// 如果有缓存,直接显示缓存
|
||||
if (cacheValues != null) {
|
||||
mScaleMatrix.postScale(cacheValues.scaleX, cacheValues.scaleY);
|
||||
mScaleMatrix.postTranslate(cacheValues.translateX, cacheValues.translateY);
|
||||
cacheValues = null;
|
||||
} else {
|
||||
mScaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2);// 平移至屏幕中心
|
||||
mScaleMatrix.postScale(scale, scale, getWidth() / 2,
|
||||
getHeight() / 2);// 设置缩放比例
|
||||
}
|
||||
// 图片移动至屏幕中心
|
||||
setImageMatrix(mScaleMatrix);
|
||||
once = false;
|
||||
@ -365,6 +410,11 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
this.mRatio = ratio;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
once = true;
|
||||
mScaleMatrix.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动缩放的任务
|
||||
*
|
||||
@ -424,4 +474,28 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
}
|
||||
}
|
||||
|
||||
private OnDragStateListener stateListener;
|
||||
|
||||
interface OnDragStateListener {
|
||||
|
||||
void onStateChanged(boolean isDragging);
|
||||
}
|
||||
|
||||
void setOnDragStateChangeListener(OnDragStateListener listener) {
|
||||
stateListener = listener;
|
||||
}
|
||||
|
||||
public static class TransformationValues {
|
||||
public final float scaleX;
|
||||
public final float scaleY;
|
||||
public final float translateX;
|
||||
public final float translateY;
|
||||
|
||||
public TransformationValues(float scaleX, float scaleY, float translateX, float translateY) {
|
||||
this.scaleX = scaleX;
|
||||
this.scaleY = scaleY;
|
||||
this.translateX = translateX;
|
||||
this.translateY = translateY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
package com.gh.gamecenter.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import com.gh.gamecenter.common.R
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
|
||||
class DividerView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
defStyleRes: Int = 0
|
||||
) : View(context, attrs, defStyleAttr, defStyleRes) {
|
||||
|
||||
private var size = DIVIDER_SIZE_THIN
|
||||
|
||||
init {
|
||||
initAttrs(context, attrs)
|
||||
}
|
||||
|
||||
private fun initAttrs(context: Context, attrs: AttributeSet?) {
|
||||
attrs ?: return
|
||||
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.DividerView)
|
||||
size = typedArray.getInt(R.styleable.DividerView_divider_size, DIVIDER_SIZE_REGULAR)
|
||||
typedArray.recycle()
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
val height = when (size) {
|
||||
DIVIDER_SIZE_THIN -> 1
|
||||
DIVIDER_SIZE_MEDIUM -> 0.5F.dip2px()
|
||||
else -> 1F.dip2px()
|
||||
}
|
||||
setMeasuredDimension(widthMeasureSpec, height)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val DIVIDER_SIZE_THIN = 0
|
||||
private const val DIVIDER_SIZE_MEDIUM = 1
|
||||
private const val DIVIDER_SIZE_REGULAR = 12
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
package com.gh.gamecenter.common.view.cropbox
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.graphics.Color
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
|
||||
class CropBoxAnimator(private val block: (Int) -> Unit) {
|
||||
|
||||
private var currentState: AnimatorState = AnimatorState.Default
|
||||
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
|
||||
private val valueAnimator by lazy {
|
||||
val startColor = Color.parseColor("#CC000000")
|
||||
val endColor = Color.parseColor("#33000000")
|
||||
ValueAnimator.ofArgb(startColor, endColor)
|
||||
.setDuration(ANIMATOR_DURATION)
|
||||
.apply {
|
||||
interpolator = AccelerateDecelerateInterpolator()
|
||||
addUpdateListener { animator ->
|
||||
val animatedColor = animator.animatedValue as Int
|
||||
block(animatedColor)
|
||||
val time = animator.currentPlayTime
|
||||
if (time >= ANIMATOR_DURATION) {
|
||||
if (currentState is AnimatorState.Playing) {
|
||||
currentState = AnimatorState.Dragging
|
||||
}
|
||||
if (currentState is AnimatorState.Reversing) {
|
||||
currentState = AnimatorState.Default
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private val task = Runnable {
|
||||
// 延时结束,执行反向渐变动画
|
||||
currentState = AnimatorState.Reversing
|
||||
valueAnimator.reverse()
|
||||
}
|
||||
|
||||
|
||||
fun changeDragState(isDragging: Boolean) {
|
||||
when (currentState) {
|
||||
is AnimatorState.Default -> {
|
||||
// 执行正向渐变动画
|
||||
if (isDragging) {
|
||||
currentState = AnimatorState.Playing
|
||||
valueAnimator.start()
|
||||
}
|
||||
}
|
||||
|
||||
is AnimatorState.Playing -> {
|
||||
if (!isDragging) {
|
||||
currentState = AnimatorState.Delay
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
handler.postDelayed(task, DELAY_DURATION)
|
||||
}
|
||||
}
|
||||
|
||||
is AnimatorState.Dragging -> {
|
||||
if (!isDragging) {
|
||||
currentState = AnimatorState.Delay
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
handler.postDelayed(task, DELAY_DURATION)
|
||||
}
|
||||
}
|
||||
|
||||
is AnimatorState.Delay -> {
|
||||
if (isDragging) {
|
||||
currentState = AnimatorState.Dragging
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
}
|
||||
}
|
||||
|
||||
is AnimatorState.Reversing -> {
|
||||
if (isDragging) {
|
||||
currentState = AnimatorState.Playing
|
||||
valueAnimator.reverse()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ANIMATOR_DURATION = 200L
|
||||
private const val DELAY_DURATION = 500L
|
||||
}
|
||||
|
||||
sealed class AnimatorState {
|
||||
object Default : AnimatorState()
|
||||
object Playing : AnimatorState()
|
||||
object Dragging : AnimatorState()
|
||||
object Delay : AnimatorState()
|
||||
object Reversing : AnimatorState()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.gh.gamecenter.common.view.cropbox
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.RectF
|
||||
|
||||
interface CropBoxDrawer {
|
||||
|
||||
fun onDraw(rectF: RectF, canvas: Canvas, paint: Paint)
|
||||
|
||||
fun onDrawDecoration(rectF: RectF, canvas: Canvas, paint: Paint)
|
||||
|
||||
class CircleDrawer : CropBoxDrawer {
|
||||
|
||||
override fun onDraw(rectF: RectF, canvas: Canvas, paint: Paint) {
|
||||
canvas.drawCircle(rectF.centerX(), rectF.centerY(), rectF.width() / 2, paint)
|
||||
}
|
||||
|
||||
override fun onDrawDecoration(rectF: RectF, canvas: Canvas, paint: Paint) {
|
||||
canvas.drawCircle(rectF.centerX(), rectF.centerY(), (rectF.width() - paint.strokeWidth) / 2, paint)
|
||||
}
|
||||
}
|
||||
|
||||
class RectangleDrawer : CropBoxDrawer {
|
||||
override fun onDraw(rectF: RectF, canvas: Canvas, paint: Paint) {
|
||||
canvas.drawRect(rectF, paint)
|
||||
}
|
||||
|
||||
override fun onDrawDecoration(rectF: RectF, canvas: Canvas, paint: Paint) {
|
||||
val realRectF = RectF(
|
||||
rectF.left + paint.strokeWidth / 2,
|
||||
rectF.top,
|
||||
rectF.right - paint.strokeWidth / 2,
|
||||
rectF.bottom
|
||||
)
|
||||
canvas.drawRect(realRectF, paint)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.gh.gamecenter.common.view.cropbox
|
||||
|
||||
import android.graphics.RectF
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
sealed class CropBoxStyle : Parcelable {
|
||||
|
||||
fun getRect(width: Int, height: Int, horizontalPadding: Int): RectF {
|
||||
// 计算矩形区域的宽度
|
||||
val boxWidth = width - 2 * horizontalPadding
|
||||
val boxHeight = getBoxHeight(boxWidth)
|
||||
val left = width - boxWidth - horizontalPadding
|
||||
val top = (height - boxHeight) / 2
|
||||
val right = left + boxWidth
|
||||
val bottom = top + boxHeight
|
||||
return RectF(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat())
|
||||
}
|
||||
|
||||
abstract fun getBoxHeight(boxWidth: Int): Int
|
||||
|
||||
object Circle : CropBoxStyle() {
|
||||
|
||||
override fun getBoxHeight(boxWidth: Int): Int {
|
||||
return boxWidth
|
||||
}
|
||||
}
|
||||
|
||||
class Rectangle(val radio: Float) : CropBoxStyle() {
|
||||
override fun getBoxHeight(boxWidth: Int): Int {
|
||||
return (boxWidth * radio).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
package com.gh.gamecenter.common.view.cropbox
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
|
||||
class CropBoxView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) :
|
||||
View(context, attrs, defStyleAttr) {
|
||||
|
||||
private var horizontalPadding = 0
|
||||
private var boxStyle: CropBoxStyle = CropBoxStyle.Rectangle(1F)
|
||||
private var drawer: CropBoxDrawer = CropBoxDrawer.RectangleDrawer()
|
||||
|
||||
private val paint by lazy {
|
||||
Paint().apply {
|
||||
isAntiAlias = true
|
||||
isDither = true
|
||||
color = Color.parseColor("#CC000000")
|
||||
}
|
||||
}
|
||||
|
||||
private val borderPaint by lazy {
|
||||
Paint().apply {
|
||||
style = Paint.Style.STROKE
|
||||
isAntiAlias = true
|
||||
setColor(Color.WHITE)
|
||||
strokeWidth = 0.5F.dip2px().toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
private val xFermode by lazy {
|
||||
val mode = PorterDuff.Mode.CLEAR
|
||||
PorterDuffXfermode(mode)
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
|
||||
val rect = boxStyle.getRect(width, height, horizontalPadding)
|
||||
val layerId = canvas.saveLayer(0f, 0f, width.toFloat(), height.toFloat(), paint, Canvas.ALL_SAVE_FLAG)
|
||||
|
||||
canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paint)
|
||||
paint.xfermode = xFermode
|
||||
drawer.onDraw(rect, canvas, paint)
|
||||
paint.xfermode = null
|
||||
|
||||
canvas.restoreToCount(layerId)
|
||||
|
||||
// 绘制裁剪框边框
|
||||
drawer.onDrawDecoration(rect, canvas, borderPaint)
|
||||
}
|
||||
|
||||
fun setHorizontalPaddingBoxStyle(horizontalPadding: Int, boxStyle: CropBoxStyle) {
|
||||
this.horizontalPadding = horizontalPadding
|
||||
this.boxStyle = boxStyle
|
||||
drawer = createDrawer(boxStyle)
|
||||
}
|
||||
|
||||
private val cropBoxAnimator by lazy {
|
||||
CropBoxAnimator {
|
||||
paint.color = it
|
||||
postInvalidateOnAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun changeDragState(isDragging: Boolean) {
|
||||
cropBoxAnimator.changeDragState(isDragging)
|
||||
}
|
||||
|
||||
private fun createDrawer(boxStyle: CropBoxStyle) = when (boxStyle) {
|
||||
is CropBoxStyle.Circle -> CropBoxDrawer.CircleDrawer()
|
||||
is CropBoxStyle.Rectangle -> CropBoxDrawer.RectangleDrawer()
|
||||
}
|
||||
|
||||
}
|
||||
@ -249,15 +249,22 @@
|
||||
|
||||
<declare-styleable name="FadingEdgeLayout">
|
||||
<attr name="fel_edge" format="integer">
|
||||
<flag name="top" value="1"/>
|
||||
<flag name="bottom" value="2"/>
|
||||
<flag name="left" value="4"/>
|
||||
<flag name="right" value="8"/>
|
||||
<flag name="top" value="1" />
|
||||
<flag name="bottom" value="2" />
|
||||
<flag name="left" value="4" />
|
||||
<flag name="right" value="8" />
|
||||
</attr>
|
||||
<attr name="fel_size_top" format="dimension"/>
|
||||
<attr name="fel_size_bottom" format="dimension"/>
|
||||
<attr name="fel_size_left" format="dimension"/>
|
||||
<attr name="fel_size_right" format="dimension"/>
|
||||
<attr name="fel_size_top" format="dimension" />
|
||||
<attr name="fel_size_bottom" format="dimension" />
|
||||
<attr name="fel_size_left" format="dimension" />
|
||||
<attr name="fel_size_right" format="dimension" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="DividerView">
|
||||
<attr name="divider_size" format="integer">
|
||||
<flag name="thin" value="0" />
|
||||
<flag name="medium" value="1" />
|
||||
<flag name="regular" value="2" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
@ -0,0 +1,10 @@
|
||||
package com.gh.gamecenter.core.provider
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
|
||||
interface ICropImageProvider {
|
||||
|
||||
fun getCropImageIntent(data: List<Uri>, imageType: Int, entrance: String, context: Context): Intent?
|
||||
}
|
||||
Reference in New Issue
Block a user