Commit 426d3ddf by 霍志良

Merge branch 'release' into fix/zl_fixbug

# Conflicts:
#	config.gradle
parents 20c1d2ff 4981bbee
......@@ -30,6 +30,9 @@ import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.ToastUtil
import com.yidianling.consultant.api.IConsultantService
import com.yidianling.fm.api.service.IFMService
import com.yidianling.muse.event.MeditationFloatEvent
import com.yidianling.muse.helper.MediaPlayerManager
import com.yidianling.muse.service.MeditationWindowService
import com.yidianling.tests.home.NewTestHomeActivity
import com.yidianling.user.StatusUtils
import com.yidianling.user.ui.collect.CollectSexAndBirthActivity
......@@ -37,6 +40,7 @@ import com.yidianling.user.ui.login.OneKeyLoginHelp
import com.yidianling.user.widget.SecretDescriptionDialog
import com.yidianling.user.widget.SecretDialog
import com.yidianling.user.widget.SecretDialog.OnSecretDialogListener
import de.greenrobot.event.EventBus
import kotlinx.android.synthetic.main.activity_main.*
......@@ -49,9 +53,14 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
DemoContract.View {
private var secretDescriptionDialog: SecretDescriptionDialog? = null
private var serviceConnection: ServiceConnection? = null
private var meditationServiceConnection:ServiceConnection? = null
private var secretDialog: SecretDialog? = null
protected var playService: PlayService? = null
protected var meditationService:MeditationWindowService?=null
override fun getContentViewId(): Int {
return R.id.lce_content_view
}
......@@ -74,6 +83,7 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
override fun initDataAndEvent() {
EventBus.getDefault().register(this)
// YDLavManager.instances.init(this, "3387e9b251f3491e9221a9877e8f7830")
YdlCommonRouterManager.initYdlCommonRoute(PlatformTempCommonRouteImpl())
......@@ -82,6 +92,8 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
// 初始化一键登录sdk
OneKeyLoginHelp.sdkInit(this, OneKeyLoginHelp.YDL_USER_APP, PhoneNumberAuthHelper.SERVICE_TYPE_LOGIN)
bindService()
bindMeditationService()
reLoadData()
requestPermission()
bt_mdt.setOnClickListener {
......@@ -154,6 +166,9 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
ModularServiceManager.provide(IConsultantService::class.java).requestGuideData()
bt_to_muse.setOnClickListener {
ARouter.getInstance().build("/muse/play")
.navigation()
val list =
ModularServiceManager.provide(IConsultantService::class.java).getGuideImage(1)
list?.forEach {
......@@ -250,6 +265,13 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
}
private fun bindMeditationService(){
val intent = Intent()
intent.setClass(this,MeditationWindowService::class.java)
meditationServiceConnection = MeditationServiceConnection()
bindService(intent,meditationServiceConnection,Context.BIND_AUTO_CREATE)
}
override fun onResume() {
super.onResume()
MobclickAgent.onResume(this)
......@@ -265,11 +287,22 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
// ModularServiceManager.provide(IConsultantService::class.java).hideConsultAssistantDialog()
}
fun onEvent(event:MeditationFloatEvent){
}
override fun onDestroy() {
if (serviceConnection != null) {
unbindService(serviceConnection)
}
if(meditationServiceConnection!=null){
EventBus.getDefault().post(MeditationFloatEvent(false))
MediaPlayerManager.getInstance(this)?.stop()
unbindService(meditationServiceConnection)
}
if(EventBus.getDefault().isRegistered(this)){
EventBus.getDefault().unregister(this)
}
super.onDestroy()
}
......@@ -283,6 +316,16 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
}
}
private inner class MeditationServiceConnection:ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
meditationService = (service as MeditationWindowService.MeditationBinder).service
}
override fun onServiceDisconnected(name: ComponentName?) {
}
}
private fun showEnsureDialog() {
secretDialog = SecretDialog(this, object : OnSecretDialogListener {
......
......@@ -22,11 +22,13 @@ import com.ydl.media.view.PlayTypeEnum;
import com.ydl.media.view.PlayerFloatHelper;
import com.ydl.ydlcommon.utils.LogUtil;
import com.yidianling.common.tools.ToastUtil;
import com.yidianling.muse.event.MeditationFloatEvent;
import java.util.HashMap;
import java.util.Locale;
import java.util.Objects;
/**
* Created by haorui on 2019-10-28 .
* Des:
......@@ -62,6 +64,7 @@ public class PlayFragment extends Fragment implements View.OnClickListener,
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initPlayMode();
onChangeImpl(AudioPlayer.Companion.get().getPlayMusic());
AudioPlayer.Companion.get().addOnPlayEventListener(this);
}
......@@ -290,4 +293,6 @@ public class PlayFragment extends Fragment implements View.OnClickListener,
ivPrev = bindSource.findViewById(R.id.iv_prev);
ivCover = bindSource.findViewById(R.id.iv_cover);
}
}
......@@ -9,9 +9,14 @@ import com.ydl.confide.home.event.ChangeAnotherExpertEvent;
import com.ydl.webview.H5JsBean;
import com.ydl.webview.H5Params;
import com.ydl.webview.NewH5Activity;
import com.ydl.ydl_router.manager.YDLRouterManager;
import com.ydl.ydl_router.manager.YDLRouterParams;
import com.ydl.ydlcommon.modular.ModularServiceManager;
import com.yidianling.common.tools.LogUtil;
import com.yidianling.im.api.service.IImService;
import com.yidianling.muse.activity.ChooseMusicActivity;
//import static com.ydl.ydlcommon.router.IYDLRouterConstant.ROUTER_MUSE_PLAY;
import de.greenrobot.event.EventBus;
......@@ -324,7 +329,9 @@ public class WVClickAbstractListener implements WebViewClientClickListener {
@Override
public void switchDownRefresh(H5JsBean.H5JsCmd.Params params) {
if (mContext != null && mContext instanceof NewH5Activity) {
((NewH5Activity) mContext).hasShowDownRefresh(params.getSwitch());
}
}
@Override
......@@ -408,7 +415,9 @@ public class WVClickAbstractListener implements WebViewClientClickListener {
@Override
public void closeWebKit() {
if (mContext instanceof NewH5Activity) {
((NewH5Activity) mContext).finish();
}
}
@Override
......@@ -450,9 +459,55 @@ public class WVClickAbstractListener implements WebViewClientClickListener {
}
@Override
public void playMeditation(int mediaId, long meditationId, int meditationType, String mediaCoverUrl) {
public void getNextExpertStatus(String doctorID, String title,String uid) {
EventBus.getDefault().post(new ChangeAnotherExpertEvent(doctorID,title,uid));
}
if (mContext instanceof NewH5Activity) {
// YDLRouterManager.Companion.router(ROUTER_MUSE_PLAY,
// new YDLRouterParams().putExtra("MEDITATION_ID", String.valueOf(meditationId))
// .putExtra("MEDIA_ID", String.valueOf(mediaId))
// .putExtra("MEDITATION_TYPE", String.valueOf(meditationType))
// .putExtra("MEDIA_COVER_URL", mediaCoverUrl));
ARouter.getInstance().build("/muse/play")
.withLong("MEDITATION_ID", meditationId)
.withLong("MEDIA_ID", mediaId)
.withInt("MEDITATION_TYPE", meditationType)
.withString("MEDIA_COVER_URL", mediaCoverUrl)
.navigation();
}
}
@Override
public void switchSound(int mediaId, long meditationId, int meditationType, int businessType,
String buried, String mediaUrl, String mediaCoverUrl,
String title, String desc, int status) {
if (mContext instanceof NewH5Activity) {
((NewH5Activity) mContext).switchSound(mediaId, meditationId, meditationType,
businessType, buried, mediaUrl, mediaCoverUrl, title, desc, status);
} else if (mContext instanceof ChooseMusicActivity) {
((ChooseMusicActivity) mContext).switchSound(mediaId, meditationId, meditationType,
businessType, buried, mediaUrl, mediaCoverUrl, title, desc, status);
}
}
@Override
public void reloadUrl(String url) {
if (mContext instanceof NewH5Activity) {
((NewH5Activity) mContext).loadUrl(url);
}
}
@Override
public void setWebViewBG(String rgb, String alpha) {
if (mContext instanceof NewH5Activity){
((NewH5Activity)mContext).setBG(rgb, alpha);
}
}
}
......@@ -391,6 +391,55 @@ class WebJavascriptHandler : IJavascriptHandler{
wvEnventPro?.setSelfPageType(it.selfPageType)
}
}
"meditation_play" -> {
jsData.cmd!!.params?.let{
val mediaId = it.mediaId
val meditationId = it.meditationId
val meditationType = it.meditionType
val mediaCoverUrl = it.coverImageUrl
if (mediaId != null && meditationId!=null && meditationType!=null) {
wvEnventPro?.playMeditation(mediaId,meditationId.toLong(),
meditationType,mediaCoverUrl)
}
}
}
"switch_sound" -> {
jsData.cmd!!.params?.let{
val mediaId = it.mediaId
val meditationId = it.meditationId
val meditationType = it.meditionType
val businessType = it.businessType
val buried = it.buried
val mediaUrl = it.mediaUrl
val mediaCoverUrl = it.coverImageUrl
val title = it.title
val desc = it.desc
val status = it.status
if (mediaId != null && meditationId!=null && meditationType!=null) {
wvEnventPro?.switchSound(mediaId,meditationType.toLong(),businessType!!,
meditationId,buried,mediaUrl,mediaCoverUrl,title,desc,status)
}
}
}
"loadUrl" -> {
jsData.cmd?.params?.let{
wvEnventPro?.reloadUrl(jsData.cmd?.params?.url)
}
}
"webViewBackgroundColor" -> {
jsData.cmd?.params?.let{
val rgb = it.color
val alpha = it.alpha
wvEnventPro?.setWebViewBG(rgb,alpha)
}
}
//再换一位
"get_next_doctor"->{
wvEnventPro?.getNextExpertStatus(jsData.cmd?.params?.doctorId.toString(),jsData.cmd?.params?.title,jsData.cmd?.params?.uid.toString())
......@@ -405,6 +454,7 @@ class WebJavascriptHandler : IJavascriptHandler{
findRouteService(IConfideService::class.java).showExpertDetailDialog(topActivity, url, doctorId, uid ?: "")
}
}
}
}
}
......@@ -181,5 +181,21 @@ public interface WebViewClientClickListener {
//设置当前页面类型
void setSelfPageType(int selfType);
default void playMeditation(int mediaId,long meditationId,int meditationType,String mediaCoverUrl){}
default void switchSound(int mediaId,long meditationId,int meditationType,int businessType,
String buried,String mediaUrl,String mediaCoverUrl,String title,
String desc,int status){
}
//页面内跳转url
void reloadUrl(String url);
default void setWebViewBG(String rgb,String alpha){}
void getNextExpertStatus(String doctorID,String title,String uid);
}
......@@ -35,14 +35,17 @@ ext {
//mdt 组件
"ydl-tuicore" : "0.0.23",
//第一步
"ydl-platform" : "0.0.41.22",
"ydl-platform" : "0.0.41.32",
//第二步 若干
"ydl-webview" : "0.0.38.80",
"ydl-media" : "0.0.21.45",
"ydl-webview" : "0.0.38.92",
"ydl-media" : "0.0.21.52",
"ydl-pay" : "0.0.18.19",
"m-audioim" : "0.0.49.30.12",
"m-audioim" : "0.0.49.30.12",
"m-audioim" : "0.0.49.30.11",
"ydl-flutter-base": "0.0.14.38",
//以下 几乎不会动
......
......@@ -100,5 +100,6 @@ dependencies {
}
api rootProject.ext.dependencies["ydl-webview"]
api rootProject.ext.dependencies["ydl-media"]
api rootProject.ext.dependencies["ydl-media"]
}
}
package com.yidianling.home
//import com.ydl.ydlcommon.router.IYDLRouterConstant.Companion.ROUTER_MUSE_PLAY
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.alibaba.android.arouter.launcher.ARouter
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.ydl.ydlcommon.utils.Utils
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.yidianling.home.constants.HomeBIConstants
import com.yidianling.home.model.bean.MeditationModuleBean
import com.yidianling.user.api.service.IUserService
import kotlinx.android.synthetic.ydl.home_fragment.*
class MeditationTypeAdapter(
private val context: Context,
private val data: List<MeditationModuleBean.MeditationDetail>?,
private val moreLink: String?,
private val homeLink: String? = null,
private val cateId: Long? = null,
private val buried: String? = null,
private val mark: Int? = null,
private val meditationType: Int? = null
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
CONTENT_TYPE -> {
MeditationTypeViewHolder(
LayoutInflater.from(context)
.inflate(R.layout.layout_meditation_item, parent, false)
)
}
else -> {
MeditationTypeMoreViewHolder(
LayoutInflater.from(context)
.inflate(R.layout.layout_meditation_more_type, parent, false)
)
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is MeditationTypeViewHolder -> {
holder.ivType?.let {
Glide.with(context)
.load(data?.get(position)?.coverImageUrl)
.thumbnail(0.1f)
.transition(DrawableTransitionOptions.withCrossFade())
.into(it)
}
holder.tvName?.let {
it.text = data?.get(position)?.title ?: ""
}
holder.cvLayout?.setOnClickListener {
ActionCountUtils.baiDuCountSign3(
HomeBIConstants.YDL_USER_MAIN_PAGE_MUSE,
HomeBIConstants.YDL_HOME_MEDITATION_CLICK,
buried ?: "",
(position + 1).toString(),
""
)
if (meditationType == 0) {
if (Utils.isFastClick()) {
//防止连击
return@setOnClickListener
}
if (!ModularServiceManager.provide(IUserService::class.java)
.loginByOneKeyLogin(context, true)
) {
return@setOnClickListener
}
if (data == null) {
return@setOnClickListener
}
ARouter.getInstance().build("/muse/play")
.withLong("MEDITATION_ID", data[position]?.meditationId)
.withInt("MEDITATION_TYPE", meditationType)
.withFloat("MEDIA_DURATION", data[position].duration ?: 0.0f)
.withString("MEDIA_URL", data[position].mediaIdCoverImageUrl)
.withString("MEDIA_COVER_URL", data[position].mediaIdCoverImageUrl)
.navigation()
// YDLRouterManager.router(ROUTER_MUSE_PLAY,
// YDLRouterParams().putExtra("MEDITATION_ID" , data[position]?.meditationId.toString())
// .putExtra("MEDITATION_TYPE", meditationType.toString())
// .putExtra("MEDIA_DURATION", (data[position].duration?:0).toString())
// .putExtra("MEDIA_URL", data[position].mediaIdCoverImageUrl.toString())
// .putExtra("MEDIA_COVER_URL", data[position].mediaIdCoverImageUrl.toString()))
} else {
if (Utils.isFastClick()) {
//防止连击
return@setOnClickListener
}
if (data == null) {
return@setOnClickListener
}
val homeLink =
"${homeLink}mark=$mark&cateId=$cateId&meditationId=${data[position]?.meditationId}"
if (!homeLink.isNullOrBlank()) {
NewH5Activity.start(context, H5Params(homeLink, null))
}
}
}
}
is MeditationTypeMoreViewHolder -> {
holder.llMoreLayout?.setOnClickListener {
if (Utils.isFastClick()) {
//防止连击
return@setOnClickListener
}
//冥想助眠更多点击事件
ActionCountUtils.count(
HomeBIConstants.YDL_HOME_MEDITATION_VOICE_MORE_CLICK,
buried ?: ""
)
val moreLink = "${moreLink}mark=$mark&cateId=$cateId"
if (!moreLink.isNullOrBlank()) {
NewH5Activity.start(context, H5Params(moreLink, null))
}
}
}
}
}
override fun getItemCount(): Int {
return if (data?.isNotEmpty() == true) {
data.size + 1
} else {
0
}
}
override fun getItemId(position: Int) = position.toLong()
override fun getItemViewType(position: Int): Int {
return if (data?.isNotEmpty() == true && position == data.size) {
FOOTER_TYPE
} else {
CONTENT_TYPE
}
}
inner class MeditationTypeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val cvLayout: FrameLayout? = itemView.findViewById(R.id.fl_layout)
val ivType: ImageView? = itemView.findViewById(R.id.iv_meditation_type)
val tvName: TextView? = itemView.findViewById(R.id.tv_meditation_type)
}
inner class MeditationTypeMoreViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val llMoreLayout: LinearLayout? = itemView.findViewById(R.id.ll_more_type)
}
companion object {
const val CONTENT_TYPE = 0
const val FOOTER_TYPE = 1
}
}
\ No newline at end of file
package com.yidianling.home
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.yidianling.home.model.bean.MeditationModuleBean
class MeditationViewPagerAdapter(private val context: Context, private val data:
MeditationModuleBean)
:RecyclerView.Adapter<MeditationViewPagerAdapter.MeditationViewPagerViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MeditationViewPagerViewHolder {
return MeditationViewPagerViewHolder(LayoutInflater
.from(context).inflate(R.layout.layout_meditation_entrance,parent,false))
}
override fun onBindViewHolder(holder: MeditationViewPagerViewHolder, position: Int) {
holder.rv?.also { rv->
rv.layoutManager = LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL,false)
rv.adapter =
data.mditationListResponse?.get(position)?.let {
MeditationTypeAdapter(context = context,
data = it.mditationResponseList,
moreLink = it.lowerFloorMore?:"",
homeLink = it.mditationDetailUrl,
cateId = it.cateId,
buried = it.buried,
mark = it.mark,
meditationType = it.meditionType)
}
}
}
override fun getItemCount(): Int {
return data.mditationListResponse?.size?:0
}
inner class MeditationViewPagerViewHolder(itemView: View):RecyclerView.ViewHolder(itemView){
val rv:RecyclerView? = itemView.findViewById(R.id.rv_meditation_type)
}
}
......@@ -42,10 +42,17 @@ class HomeBIConstants {
const val YDL_HOME_SEARCH_TAG: String = YDL_USER_MAIN_PAGE + "ydl_user_search_tag" // 首页_定制咨询点击tag
const val YDL_HOME_SEARCH_TAG_CLICK: String = YDL_USER_MAIN_PAGE + "ydl_user_search_tag_click" // 首页_定制咨询点击tag
const val YDL_HOME_POPUPWINDOWS_PAGE_POPUP: String = YDL_USER_MAIN_PAGE + "popupwindows_page_popup" // 首页弹窗页面弹出事件(99元3小时弹出事件)
const val YDL_HOME_POPUPWINDOWS_PAGE_POPUP_CLICK: String = YDL_USER_MAIN_PAGE + "popupwindows_page_popup_click" // 首页弹窗页面弹出事件(99元3小时弹出事件)
const val YDL_HOME_POPUPWINDOWS_PAGE_POPUP_CLICK: String = YDL_USER_MAIN_PAGE + "popupwindows_page_popup_click"
// 首页弹窗页面弹出事件(99元3小时弹出事件)
//首页_冥想(ydl_user_main_page)
const val YDL_USER_MAIN_PAGE_MUSE: String = "ydl_user_main_page"//壹点灵用户版首页 partId
const val YDL_HOME_MEDITATION_MORE_CLICK: String = YDL_USER_MAIN_PAGE + "main_meditation_more_click" // 冥想助眠更多点击事件
const val YDL_HOME_MEDITATION_SUBJECT_CLICK: String = YDL_USER_MAIN_PAGE + "main_meditation_subject_click" // 冥想|声音|睡眠点击事件
const val YDL_HOME_MEDITATION_VOICE_MORE_CLICK: String = YDL_USER_MAIN_PAGE + "main_meditation_voice_more_click" // 冥想|声音|睡眠_更多点击事件
const val YDL_HOME_MEDITATION_CLICK: String = "main_meditation_meditation_click" // 冥想_声音点击事件
}
......
......@@ -178,5 +178,6 @@ class IHomeBaseContract {
* 首页问答 - 关注
*/
fun askFocus(id: String): Observable<AskResultBean>
}
}
\ No newline at end of file
......@@ -101,4 +101,5 @@ class HomeBaseHttp {
val cmd = AskRequestParamBean.FocusCmd(id, "1")
return RxUtils.mapObservable(cmd).flatMap { getHomePagerApi().askFocus(it) }
}
}
\ No newline at end of file
......@@ -87,4 +87,6 @@ open class BaseHomeModelImpl : IHomeBaseContract.Model {
return HomeBaseHttp.getInstance().newHomeHeaderRequest().compose(RxUtils.resultJavaData())
.onErrorReturn { HomeHeaderBean(true) }
}
}
\ No newline at end of file
......@@ -53,6 +53,12 @@ class HomePagerDataBean() {
* 冥想模块数据
*/
var museBean: MuseModuleBean? = null
/**
* 冥想改版
*/
var meditationBean:MeditationModuleBean?=null
/**
* 电台模块数据
*/
......
package com.yidianling.home.model.bean
/**
* 冥想模块所有数据
* Created by xj on 2019/9/16.
*/
class MeditationModuleBean : HomeItemBaseBean {
constructor():super(false)
constructor(isRealEmpty:Boolean):super(isRealEmpty)
var mditationIndexInfo:MeditationSlogan? = null
data class MeditationSlogan(
val greetings:String?=null,
val mditationDay:Int = 0,
val desc:String?=null,
val videoLink:String?=null,
val uid:Int,
val mditationIndexUrl:String?=null,
val upperFloorMore:String?=null
)
/**
* 冥想数据
*/
var mditationListResponse: ArrayList<MeditationList>? = null
data class MeditationList(
val comment:String,
val meditionType:Int,
val cateId:Long,
val mark:Int,
val buried:String?=null,
val lowerFloorMore:String?=null,
val mditationDetailUrl:String?=null,
val mditationResponseList:ArrayList<MeditationDetail>
)
data class MeditationDetail(
val meditationId:Long,
val title:String,
val coverImageUrl:String,
val tagId:Int,
val mediaUrl:String?=null,
val duration:Float? = null,
val mediaId:Int,
val mediaIdCoverImageUrl:String?=null
)
}
\ No newline at end of file
package com.yidianling.home.router
import android.app.Activity
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.yidianling.im.api.service.IImService
import com.yidianling.user.api.service.IAppService
import com.yidianling.user.api.service.IUserService
/**
* author : liupeng
*/
object HomeIn {
fun getImService(): IImService {
return ModularServiceManager.provide(IImService::class.java)
}
fun getUserService(): IUserService {
return ModularServiceManager.provide(IUserService::class.java)
}
fun isLogin(): Boolean {
return getUserService()?.isLogin()?:false
}
fun loginWayIntent(activity: Activity): Intent? {
return getUserService()?.loginWayIntent(activity)
}
/**
* 私聊
*/
fun startChat(context: AppCompatActivity, toUid: String, flag: Int, canTalk: Int) {
getImService().startChat(context,toUid,flag,canTalk)
}
/**
* 调用优先使用一键登录,并返回调用时的登录状态,
* @param isOpenDialog true:一键登录使用弹窗展示 false:一键登录使用全屏模式
* @return true:已登录,不触发登录跳转,false:未登录,优先一键登录
* */
fun loginByOneKeyLogin(context: Context, isOpenDialog: Boolean) :Boolean{
return getUserService().loginByOneKeyLogin(context,isOpenDialog)
}
}
\ No newline at end of file
package com.yidianling.home.widget
import android.content.Context
import android.util.AttributeSet
import android.widget.VideoView
class AdaptiveVideoView:VideoView {
constructor(context: Context):this(context,null)
constructor(context: Context,attributeSet: AttributeSet?):this(context,attributeSet,0)
constructor(context: Context,attributeSet: AttributeSet?,defStyle:Int):super(context,attributeSet,defStyle){
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val width = getDefaultSize(0,widthMeasureSpec)
val height = getDefaultSize(0,heightMeasureSpec)
setMeasuredDimension(width,height)
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:width="105dp" android:height="30dp">
<shape android:shape="rectangle">
<gradient android:type="linear"
android:useLevel="true"
android:startColor="#88000000"
android:endColor="#00282727"
android:angle="90"/>
<corners android:topLeftRadius="0dp"
android:topRightRadius="0dp"
android:bottomLeftRadius="8dp"
android:bottomRightRadius="8dp" />
</shape>
</item>
</layer-list>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="15dp"
android:height="10dp"
android:viewportWidth="15"
android:viewportHeight="10">
<path
android:pathData="M12.1864,5.6796L0.9072,5.6796C0.4062,5.6796 0,5.2735 0,4.7724C-0,4.2714 0.4062,3.8652 0.9072,3.8652L12.1864,3.8652C12.6874,3.8652 13.0936,4.2714 13.0936,4.7724C13.0936,5.2735 12.6874,5.6796 12.1864,5.6796Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M8.1304,8.7724C8.0454,8.6876 7.9976,8.5725 7.9976,8.4524C7.9976,8.3324 8.0454,8.2172 8.1304,8.1324L11.4904,4.7724L8.1304,1.4124C7.9538,1.2357 7.9538,0.9492 8.1304,0.7724L8.7704,0.1324C8.9472,-0.0441 9.2336,-0.0441 9.4104,0.1324L13.3433,4.0653C13.7338,4.4559 13.7338,5.089 13.3433,5.4796L9.4104,9.4124L9.4104,9.4124C9.2336,9.589 8.9472,9.589 8.7704,9.4124L8.1304,8.7724Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
......@@ -11,4 +11,13 @@
<item name="colorAccent">@color/platform_main_theme</item>
</style>
<style name="MeditationTabLayoutStyle" parent="Widget.Design.TabLayout">
<item name="tabIndicatorColor">@color/white</item>
<item name="tabIndicatorHeight">2dp</item>
<item name="tabIndicatorFullWidth">false</item>
<item name="tabSelectedTextColor">@color/white</item>
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/white_60</item>
</style>
</resources>
\ No newline at end of file
package com.yidianling.home.adapter
import android.content.Context
import android.graphics.Color
import android.media.MediaPlayer
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import com.ydl.ydl_image.module.GlideApp
import com.yidianling.common.tools.LogUtil
import com.yidianling.home.R
import com.yidianling.home.constract.HomeViewConfig
import com.yidianling.home.event.HomeImpl
import com.yidianling.home.model.bean.*
import com.yidianling.home.ui.view.*
import kotlin.properties.Delegates
import kotlinx.android.synthetic.ydl.home_muse_view.view.*
/**
......@@ -227,7 +228,16 @@ class YdlHomeAdapter(private val mContext: Context,
}
//壹点*冥想模块
is HomeMuseViewHolder -> {
holder.museViewView.initData(list[holder.viewType].museBean)
holder.museViewView.video_view?.setOnInfoListener { mp, what, extra ->
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START){
holder.museViewView.video_view?.setBackgroundColor(Color.TRANSPARENT)
}
true
}
holder.museViewView.video_view?.start()
holder.museViewView.initData(list[holder.viewType].meditationBean)
}
//心灵*电台模块
is HomeIntelligentViewHolder -> {
......
package com.yidianling.home.constract
import com.yidianling.home.constants.IHomeBaseContract
import com.yidianling.home.model.bean.MeditationModuleBean
import com.yidianling.home.model.bean.MuseModuleBean
import io.reactivex.Observable
......@@ -20,5 +21,7 @@ class IHomeContract {
* 首页冥想请求
*/
fun museRequest(): Observable<MuseModuleBean>
fun getMeditation():Observable<MeditationModuleBean>
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package com.yidianling.home.http
import com.ydl.ydlcommon.data.http.BaseAPIResponse
import com.ydl.ydlnet.YDLHttpUtils
import com.yidianling.home.model.bean.MeditationModuleBean
import com.yidianling.home.model.bean.MuseModuleBean
import io.reactivex.Observable
......@@ -37,4 +38,9 @@ class HomeHttp {
fun newMuseRequest(): Observable<BaseAPIResponse<MuseModuleBean>> {
return getHomePagerApi().getMuseData()
}
fun getMeditationInfo():Observable<BaseAPIResponse<MeditationModuleBean>>{
return getHomePagerApi().getMeditation()
}
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ package com.yidianling.home.http
import com.ydl.ydlcommon.base.config.YDL_DOMAIN
import com.ydl.ydlcommon.base.config.YDL_DOMAIN_JAVA
import com.ydl.ydlcommon.data.http.BaseAPIResponse
import com.yidianling.home.model.bean.MeditationModuleBean
import com.yidianling.home.model.bean.MuseModuleBean
import io.reactivex.Observable
import retrofit2.http.GET
......@@ -21,4 +22,9 @@ interface HomePagerApi {
@GET("meditation/meditation/list")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA)
fun getMuseData(): Observable<BaseAPIResponse<MuseModuleBean>>
@GET("cms/meditation/index")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA)
fun getMeditation(): Observable<BaseAPIResponse<MeditationModuleBean>>
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ package com.yidianling.home.model
import com.ydl.ydlcommon.data.http.RxUtils
import com.yidianling.home.constract.IHomeContract
import com.yidianling.home.http.HomeHttp
import com.yidianling.home.model.bean.MeditationModuleBean
import com.yidianling.home.model.bean.MuseModuleBean
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
......@@ -26,5 +27,11 @@ class HomeModelImpl : BaseHomeModelImpl(), IHomeContract.Model {
.onErrorReturn { MuseModuleBean(true) }
}
override fun getMeditation(): Observable<MeditationModuleBean> {
return HomeHttp.getInstance().getMeditationInfo().compose(RxUtils.resultJavaData())
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.onErrorReturn { MeditationModuleBean(true) }
}
}
\ No newline at end of file
......@@ -112,6 +112,12 @@ class HomePresenterImpl: BaseHomePresenterImpl<IHomeContract.View, IHomeContract
homeList.add(getHomeItemFromTempData(it, HomeViewConfig.getOrder().museIndex!!))
}
val meditationObservable = mModel.getMeditation()
.compose(RxUtils.applySchedulers(mView)).map {
homeList.add(getHomeItemFromTempData(it,HomeViewConfig.getOrder().museIndex!!))
}
val fmObservable = mModel.fmRequest()
.compose(RxUtils.applySchedulers(mView)).map {
//首页电台数据
......@@ -134,6 +140,7 @@ class HomePresenterImpl: BaseHomePresenterImpl<IHomeContract.View, IHomeContract
if (HomeViewConfig.getOrder().bannerIndex!=null){
mergeArrays.add(headerObservable)
}
if (HomeViewConfig.getOrder().consultIndex!=null){
mergeArrays.add(consultObservable)
}
......@@ -150,8 +157,11 @@ class HomePresenterImpl: BaseHomePresenterImpl<IHomeContract.View, IHomeContract
mergeArrays.add(askObservable)
}
if (HomeViewConfig.getOrder().museIndex!=null){
mergeArrays.add(museObservable)
mergeArrays.add(meditationObservable)
}
// if (HomeViewConfig.getOrder().museIndex!=null){
// mergeArrays.add(museObservable)
// }
if (HomeViewConfig.getOrder().fmIndex!=null){
mergeArrays.add(fmObservable)
}
......@@ -297,9 +307,13 @@ class HomePresenterImpl: BaseHomePresenterImpl<IHomeContract.View, IHomeContract
if (dataBean.isRealEmpty || dataBean !is HomeAskBean) homeTempData.askBean else dataBean
mHomeAskBean = item.askBean
}
// HomeViewConfig.getOrder().museIndex -> {
// item.museBean =
// if (dataBean.isRealEmpty || dataBean !is MuseModuleBean) homeTempData.museBean else dataBean
// }
HomeViewConfig.getOrder().museIndex -> {
item.museBean =
if (dataBean.isRealEmpty || dataBean !is MuseModuleBean) homeTempData.museBean else dataBean
item.meditationBean =
if (dataBean.isRealEmpty || dataBean !is MeditationModuleBean) homeTempData.meditationBean else dataBean
}
HomeViewConfig.getOrder().fmIndex -> {
item.fmBean =
......
......@@ -2,7 +2,9 @@ package com.yidianling.home.ui.fragment
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.media.MediaPlayer
import android.os.Build
import android.text.TextUtils
import android.view.View
......@@ -41,6 +43,11 @@ import com.yidianling.home.ui.view.HomeSpaceItemDecoration
import com.yidianling.home.utils.HomeAnimUtils
import com.yidianling.user.api.service.IUserService
import kotlinx.android.synthetic.ydl.home_fragment.*
import kotlinx.android.synthetic.ydl.home_fragment.tab_layout
import kotlinx.android.synthetic.ydl.home_muse_view.*
import kotlinx.android.synthetic.ydl.home_muse_view.view.*
import kotlin.properties.Delegates
/**
......@@ -523,6 +530,14 @@ open class YdlHomeFragment : BaseMvpFragment<IHomeContract.View, HomePresenterIm
ActionCountUtils.count(HomeBIConstants.YDL_USER_MAIN_PAGE_VISIT)
ActionCountUtils.count("daoyi_advertisement_page|daoyi_advertisement_visit","1")
showConsultAssistantDialog()
video_view?.setOnInfoListener { mp, what, extra ->
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START){
video_view?.setBackgroundColor(Color.TRANSPARENT)
}
true
}
video_view?.start()
}
}
......@@ -533,6 +548,7 @@ open class YdlHomeFragment : BaseMvpFragment<IHomeContract.View, HomePresenterIm
ActionCountUtils.count(HomeBIConstants.YDL_HOME_DWELL_TIME,(endTime-startTime).toString())
startTime=0L
}
video_view?.pause()
}
/**
......
......@@ -2,15 +2,28 @@ package com.yidianling.home.ui.view
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.media.MediaPlayer
import android.text.SpannableString
import android.text.Spanned
import android.text.style.StyleSpan
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.recyclerview.widget.RecyclerView
import com.google.gson.Gson
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity
import com.ydl.ydlcommon.utils.Utils
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.yidianling.home.MeditationViewPagerAdapter
import com.yidianling.home.R
import com.yidianling.home.constants.HomeBIConstants
import com.yidianling.home.constract.HomeViewConfig
import com.yidianling.home.event.IHomeEvent
import com.yidianling.home.model.bean.MuseModuleBean
import com.yidianling.home.model.bean.MeditationModuleBean
import kotlinx.android.synthetic.ydl.home_muse_view.view.*
/**
......@@ -23,7 +36,7 @@ import kotlinx.android.synthetic.ydl.home_muse_view.view.*
class HomeMuseView(private val mContext: Context, private var homeEvent: IHomeEvent?) :
LinearLayout(mContext) {
private var cacheList: ArrayList<HomeMuseView> = ArrayList()
private val meditationTitles = mutableListOf<String>()
init {
initView()
......@@ -41,59 +54,108 @@ class HomeMuseView(private val mContext: Context, private var homeEvent: IHomeEv
homeModuleMuseViewHomeCommonTitleView.setTitle(HomeViewConfig.getOrder().museTitle)
}
fun initData(bean: MuseModuleBean?) {
fun initData(bean: MeditationModuleBean?) {
if (null != bean) {
var dataJson = Gson().toJson(bean)
val moreLink = bean.mditationIndexInfo?.upperFloorMore
homeModuleMuseViewHomeCommonTitleView.setOnClickListener {
homeEvent?.museMoreClick(Gson().toJson(bean))
}
if (null != bean.muses) {
if (bean.muses?.size!! > 0) {
muse_first.setOnClickListener {
homeEvent?.museClick(bean.muses!![0].audioUrl, dataJson,muse_first_text.text.toString())
}
}
if (bean.muses?.size!! > 1) {
muse_second.setOnClickListener {
homeEvent?.museClick(bean.muses!![1].audioUrl, dataJson,muse_second_text.text.toString())
if (Utils.isFastClick()) {
//防止连击
return@setOnClickListener
}
//冥想助眠更多点击事件
ActionCountUtils.count(HomeBIConstants.YDL_HOME_MEDITATION_MORE_CLICK)
if (!moreLink.isNullOrBlank()) {
NewH5Activity.start(context, H5Params(moreLink, null))
}
if (bean.muses?.size!! > 2) {
muse_third.setOnClickListener {
homeEvent?.museClick(bean.muses!![2].audioUrl, dataJson,muse_third_text.text.toString())
}
}
if (bean.muses?.size!! > 3) {
muse_forth.setOnClickListener {
homeEvent?.museClick(bean.muses!![3].audioUrl, dataJson,muse_forth_text.text.toString())
}
fl_layout?.setOnClickListener {
if (Utils.isFastClick()) {
//防止连击
return@setOnClickListener
}
if (!moreLink.isNullOrBlank()) {
NewH5Activity.start(context, H5Params(moreLink, null))
}
if (null != bean.sleeps) {
if (bean.sleeps?.size!! > 0) {
sleeps_first.setOnClickListener {
homeEvent?.museClick(bean.sleeps!![0].audioUrl, dataJson,sleeps_first_text.text.toString())
}
val greeting = bean.mditationIndexInfo?.greetings ?: "你好"
tv_time.text = greeting
val slogan =
if (bean.mditationIndexInfo?.desc.isNullOrBlank()) {
"无常的日子里,呼吸间拾起力量"
} else {
bean.mditationIndexInfo?.desc
}
tv_meditation_slogan.text = slogan
val videoUrl = bean.mditationIndexInfo?.videoLink
video_view?.setVideoPath(videoUrl)
video_view?.setOnErrorListener { mp, what, extra ->
true
}
if (bean.sleeps?.size!! > 1) {
sleeps_second.setOnClickListener {
homeEvent?.museClick(bean.sleeps!![1].audioUrl, dataJson,sleeps_second_text.toString())
video_view?.setOnPreparedListener {
it?.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING)
video_view?.setOnInfoListener { mp, what, extra ->
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
video_view.setBackgroundColor(Color.TRANSPARENT)
}
true
}
if (bean.sleeps?.size!! > 2) {
sleeps_third.setOnClickListener {
homeEvent?.museClick(bean.sleeps!![2].audioUrl, dataJson,sleeps_third_text.text.toString())
it?.start()
it?.setVolume(0.0F, 0.0F)
}
video_view?.setOnCompletionListener { video_view?.start() }
bean.mditationListResponse?.forEach {
meditationTitles.add(it.comment)
}
if (bean.sleeps?.size!! > 3) {
sleeps_forth.setOnClickListener {
homeEvent?.museClick(bean.sleeps!![3].audioUrl, dataJson,sleeps_forth_text.text.toString())
view_pager.isUserInputEnabled = false
view_pager.adapter = MeditationViewPagerAdapter(mContext, bean)
tab_layout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
//冥想|声音|睡眠点击事件
ActionCountUtils.count(HomeBIConstants.YDL_HOME_MEDITATION_SUBJECT_CLICK,
tab?.let { bean?.mditationListResponse?.get(it.position)?.buried } ?:"")
var text: String? = tab?.text.toString().trim()
val spStr = SpannableString(text)
val styleSpan = StyleSpan(Typeface.BOLD)
spStr.setSpan(styleSpan, 0, text?.length ?: 0, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
tab?.text = spStr
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
var text: String? = tab?.text.toString().trim()
val spStr = SpannableString(text)
val styleSpan = StyleSpan(Typeface.NORMAL)
spStr.setSpan(styleSpan, 0, text?.length ?: 0, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
tab?.text = spStr
}
override fun onTabReselected(tab: TabLayout.Tab?) {
}
})
TabLayoutMediator(tab_layout, view_pager) { tab, position ->
tab.text = meditationTitles[position]
}.attach()
}
}
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#33FFFFFF"/>
<corners android:radius="8dp"/>
</shape>
\ No newline at end of file
......@@ -12,325 +12,95 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="88dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
android:id="@+id/muse_first"
android:layout_width="0dp"
android:layout_height="78dp"
android:layout_marginLeft="@dimen/platform_dp_15"
android:layout_marginRight="5dp"
android:layout_weight="1"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/platform_dp_4">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="394dp"
android:layout_marginHorizontal="16dp"
app:cardCornerRadius="8dp"
app:cardElevation="0dp">
<ImageView
<FrameLayout
android:id="@+id/fl_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/home_muse_first_img" />
android:background="@drawable/bg_meditation_video">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="13dp"
android:gravity="center_vertical"
android:layout_marginRight="@dimen/platform_dp_15"
android:orientation="horizontal">
<TextView
android:id="@+id/muse_first_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="深度睡眠"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/platform_black"
android:textSize="@dimen/platform_dp_16" />
<ImageView
android:layout_width="18dp"
android:layout_height="@dimen/platform_dp_18"
android:layout_marginLeft="@dimen/platform_dp_4"
android:src="@drawable/home_muse_play" />
</LinearLayout>
</RelativeLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/muse_second"
android:layout_width="0dp"
android:layout_height="78dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="@dimen/platform_dp_15"
android:layout_weight="1"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/platform_dp_4">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/muse_animation_view"
<com.yidianling.home.widget.AdaptiveVideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:lottie_autoPlay="true"
app:lottie_loop="true"
app:lottie_imageAssetsFolder="images"
app:lottie_fileName="pinna.json"
android:scaleType="centerCrop"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="@dimen/platform_dp_15"
android:layout_marginTop="13dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/muse_second_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="节奏调整"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/platform_black"
android:textSize="@dimen/platform_dp_16" />
<ImageView
android:layout_width="18dp"
android:layout_height="@dimen/platform_dp_18"
android:layout_marginLeft="@dimen/platform_dp_4"
android:src="@drawable/home_muse_play" />
</LinearLayout>
</RelativeLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="88dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
android:id="@+id/muse_third"
android:layout_width="0dp"
android:layout_height="78dp"
android:layout_marginLeft="@dimen/platform_dp_15"
android:layout_marginRight="5dp"
android:layout_weight="1"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/platform_dp_4">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:focusable="false"
android:focusableInTouchMode="false"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/home_muse_third_img" />
android:src="@drawable/bg_meditation_video"/>
<LinearLayout
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="@dimen/platform_dp_15"
android:layout_marginTop="13dp"
android:gravity="center_vertical"
android:orientation="horizontal">
android:layout_height="match_parent">
<TextView
android:id="@+id/muse_third_text"
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="身体扫描"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/platform_black"
android:textSize="@dimen/platform_dp_16"/>
<ImageView
android:layout_width="18dp"
android:layout_height="@dimen/platform_dp_18"
android:layout_marginLeft="@dimen/platform_dp_4"
android:src="@drawable/home_muse_play" />
</LinearLayout>
</RelativeLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/muse_forth"
android:layout_width="0dp"
android:layout_height="78dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="@dimen/platform_dp_15"
android:layout_weight="1"
app:cardElevation="0dp"
app:cardCornerRadius="@dimen/platform_dp_4">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/home_muse_fouth_img" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="@dimen/platform_dp_15"
android:layout_marginTop="13dp"
android:gravity="center_vertical"
android:orientation="horizontal">
android:layout_marginTop="26dp"
android:layout_marginStart="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="下午好"
android:textColor="@color/white"
android:textStyle="bold"
android:textSize="24sp" />
<TextView
android:id="@+id/muse_forth_text"
android:id="@+id/tv_meditation_slogan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="压力缓冲"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/platform_black"
android:textSize="@dimen/platform_dp_16" />
<ImageView
android:layout_width="18dp"
android:layout_height="@dimen/platform_dp_18"
android:layout_marginLeft="@dimen/platform_dp_4"
android:src="@drawable/home_muse_play" />
</LinearLayout>
</RelativeLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
android:layout_marginTop="4dp"
android:text="无常的日子里,呼吸间拾起力量"
android:textColor="@color/white"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@id/tv_time"
app:layout_constraintTop_toBottomOf="@id/tv_time" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/platform_dp_7"
android:orientation="horizontal"
android:paddingLeft="6.5dp"
android:paddingRight="6.5dp"
android:layout_marginBottom="16dp">
<RelativeLayout
android:id="@+id/sleeps_first"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_weight="1">
android:layout_height="170dp"
app:layout_constraintBottom_toBottomOf="parent"
android:orientation="vertical">
<com.ydl.ydlcommon.view.widgets.RoundImageView
android:layout_width="72dp"
android:layout_height="72dp"
android:scaleType="centerCrop"
android:src="@drawable/home_muse_circle_first"
android:layout_centerInParent="true"
app:pa_type="pa_circle"/>
<TextView
android:id="@+id/sleeps_first_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="篝火"
android:textColor="@color/platform_black"
android:textSize="@dimen/platform_dp_14"
android:textStyle="bold" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/sleeps_second"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_weight="1">
<com.ydl.ydlcommon.view.widgets.RoundImageView
android:layout_width="72dp"
android:layout_height="72dp"
android:scaleType="centerCrop"
android:src="@drawable/home_muse_circle_second"
android:layout_centerInParent="true"
app:pa_type="pa_circle"/>
<TextView
android:id="@+id/sleeps_second_text"
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="溪流"
android:textColor="@color/platform_black"
android:textSize="@dimen/platform_dp_14"
android:textStyle="bold" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/sleeps_third"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_weight="1">
android:layout_height="40dp"
app:tabTextColor="#88FFFFFF"
app:tabSelectedTextColor="#FFFFFF"
app:tabBackground="@color/transparent"
app:tabRippleColor="@color/transparent"
app:tabMode="auto"
app:tabIndicatorFullWidth="false"
style="@style/MeditationTabLayoutStyle" />
<com.ydl.ydlcommon.view.widgets.RoundImageView
android:layout_width="72dp"
android:layout_height="72dp"
android:scaleType="centerCrop"
android:src="@drawable/home_muse_circle_third"
android:layout_centerInParent="true"
app:pa_type="pa_circle"/>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginBottom="14dp"
android:background="#33FFFFFF"/>
<TextView
android:id="@+id/sleeps_third_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="风声"
android:textColor="@color/platform_black"
android:textSize="@dimen/platform_dp_14"
android:textStyle="bold" />
</RelativeLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:id="@+id/sleeps_forth"
android:layout_width="0dp"
android:layout_height="80dp"
android:layout_weight="1">
</LinearLayout>
<com.ydl.ydlcommon.view.widgets.RoundImageView
android:layout_width="72dp"
android:layout_height="72dp"
android:scaleType="centerCrop"
android:src="@drawable/home_muse_circle_fouth"
android:layout_centerInParent="true"
app:pa_type="pa_circle"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/sleeps_forth_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="落雨"
android:textColor="@color/platform_black"
android:textSize="@dimen/platform_dp_14"
android:textStyle="bold" />
</RelativeLayout>
</LinearLayout>
</FrameLayout>
</androidx.cardview.widget.CardView>
</merge>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_meditation_type"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"
android:clipToPadding="false"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
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:id="@+id/fl_layout"
android:layout_width="105dp"
android:layout_height="102dp"
android:layout_marginBottom="20dp"
android:layout_marginEnd="12dp">
<androidx.cardview.widget.CardView
android:id="@+id/card_view"
android:layout_width="105dp"
android:layout_height="102dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:cardCornerRadius="8dp"
app:cardElevation="0dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_meditation_type"
android:layout_width="105dp"
android:layout_height="102dp"
android:scaleType="centerCrop"/>
<!-- <View-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="30dp"-->
<!-- android:background="#88000000"-->
<!-- android:layout_gravity="bottom|start" />-->
<TextView
android:id="@+id/tv_meditation_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:background="@drawable/bg_meditation_type"
tools:text="溪流溪流溪流溪流溪流"
android:singleLine="true"
android:ellipsize="end"
android:textColor="@color/white"
android:textSize="14sp"
android:paddingHorizontal="6dp"
android:paddingVertical="5dp"/>
</FrameLayout>
</androidx.cardview.widget.CardView>
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:background="@color/baby_blue">
<LinearLayout
android:id="@+id/ll_more_type"
android:layout_width="40dp"
android:layout_height="102dp"
android:background="@drawable/bg_more_meditation"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:layout_marginTop="25dp"
android:layout_marginHorizontal="13dp"
android:text="更多"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold"
android:layout_marginBottom="8dp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_more_arrow_right" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="white_60">#99FFFFFF</color>
<color name="white">#FFFFFF</color>
</resources>
......@@ -23,6 +23,9 @@ android {
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
flavorDimensions "versionCode"
renderscriptTargetApi 19
renderscriptSupportModeEnabled true
}
lintOptions {
......@@ -58,6 +61,14 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.github.weidongjian:androidWheelView:1.0.0'
implementation 'com.github.feeeei:CircleSeekbar:v1.1.2'
// implementation 'jp.wasabeef:blurry:4.0.1'
// solve build problem
// cannot access 'androidx.lifecycle.hasdefaultviewmodelproviderfactory'
// Comment out when compiling
implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
implementation "com.alibaba:arouter-api:$arouter_api"
// 注意此处的依赖方式:kotlin中使用和java中使用方式有不同
kapt "com.alibaba:arouter-compiler:$arouter_compiler"
......@@ -66,11 +77,17 @@ dependencies {
//开发时使用
api project(":ydl-platform")
implementation project(':ydl-media')
implementation modularPublication('com.ydl:m-user-api')
implementation project(':ydl-flutter-base')
implementation project(':ydl-webview')
} else {
//发布时使用
api rootProject.ext.dependencies["ydl-media"]
compileOnly rootProject.ext.dependencies["ydl-m-user-api"]
api (rootProject.ext.dependencies["ydl-webview"]){
transitive = true
}
api (rootProject.ext.dependencies["ydl-platform"]) {
transitive = true
}
......
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yidianling.muse">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application>
<activity
android:name=".activity.MuseActivity"
android:screenOrientation="portrait"/>
android:screenOrientation="portrait" />
<activity
android:name=".activity.MuseCenterActivity"
android:screenOrientation="portrait"
android:theme="@style/muse_Transparent"/>
android:theme="@style/muse_Transparent" />
<activity
android:name=".activity.PlayMeditationActivity"
android:screenOrientation="portrait"
android:theme="@style/muse_Transparent" />
<activity
android:name=".activity.MeditationTimeOffActivity"
android:screenOrientation="portrait"
android:theme="@style/muse_Transparent" />
<activity android:name=".activity.ChooseMusicActivity"
android:screenOrientation="portrait"
android:theme="@style/un_full_screen_activity"/>
<service android:name=".service.MeditationWindowService"/>
</application>
</manifest>
package com.yidianling.muse.activity
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import com.ydl.utils.WebUrlParamsUtils
import com.ydl.webview.H5Params
import com.ydl.webview.IJavascriptHandler
import com.ydl.webview.TellData
import com.ydl.webview.WebModularServiceUtils.Companion.getWebService
import com.ydl.ydlcommon.base.BaseActivity
import com.ydl.ydlcommon.event.MeditationEvent
import com.yidianling.common.tools.LogUtil
import com.yidianling.muse.R
import de.greenrobot.event.EventBus
import kotlinx.android.synthetic.main.dialog_choose_music.*
import org.json.JSONException
import org.json.JSONObject
/**
* Created by Ykai on 2022/5/26.
*/
class ChooseMusicActivity : BaseActivity() {
private val TAG = ChooseMusicActivity::class.java.simpleName
protected var jtoJHandle: IJavascriptHandler? = null
/*** 路由传递过来的参数 */
val ROUTER_PARAMS = "routerParam"
companion object{
const val PARAMS = "h5Params"
/***接收参数 */
private var h5Params: H5Params? = null
fun launch(context: Context, h5Params:H5Params) {
Intent(context, ChooseMusicActivity::class.java).apply {
putExtra(PARAMS, h5Params)
context.startActivity(this)
}
}
}
override fun initDataAndEvent() {
//正常获取入参
}
override fun layoutResId(): Int {
return R.layout.dialog_choose_music
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
getParam()
var tellData = TellData()
jtoJHandle = getWebService().getJavascripHandler(this, tellData.also { tellData = it })
initView()
}
@SuppressLint("SetJavaScriptEnabled", "JavascriptInterface")
private fun initView() {
// 移除有漏洞的系统接口
wv_choose_music.removeJavascriptInterface("searchBoxJavaBridge_")
wv_choose_music.removeJavascriptInterface("accessibility")
wv_choose_music.removeJavascriptInterface("accessibilityTraversal")
val mWebSettings: WebSettings = wv_choose_music.settings
mWebSettings.javaScriptEnabled = true //支持js
mWebSettings.defaultTextEncodingName = "GBK" //设置字符编码
mWebSettings.domStorageEnabled = true
mWebSettings.textZoom = 100 //设置字体不跟随字体变化而变化
mWebSettings.allowFileAccessFromFileURLs = true
mWebSettings.blockNetworkImage = false // 解决图片不显示
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mWebSettings.mixedContentMode = WebSettings.LOAD_NORMAL
}
wv_choose_music.scrollBarStyle = View.SCROLLBARS_INSIDE_OVERLAY //滚动条风格,为0指滚动条不占用空间,直接覆盖在网页上
wv_choose_music.addJavascriptInterface(jtoJHandle, "javascriptHandler")
val url = setUrlHeightParams(h5Params?.url)
LogUtil.e(url)
loadUrl(url,wv_choose_music)
wv_choose_music.webViewClient=object : WebViewClient(){
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
}
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
loadUrl(request.url.toString(),view)
} else {
loadUrl(request.toString(),view)
}
return true
}
}
ll_close.setOnClickListener {
finish()
}
}
private fun getParam() {
if (null != intent) {
//正常获取入参
h5Params = intent.getSerializableExtra(PARAMS) as H5Params
//路由传递的入参
if (intent.hasExtra(ROUTER_PARAMS)) {
val json = intent.getStringExtra(ROUTER_PARAMS)
try {
val jsonObject = JSONObject(json)
h5Params = H5Params(jsonObject.getString("url"), "")
} catch (e: JSONException) {
e.printStackTrace()
}
}
}
}
fun switchSound(
mediaId: Int, meditationId: Long, meditationType: Int, businessType: Int,
buried: String?, mediaUrl: String?, mediaCoverUrl: String?,
title: String?, desc: String?, status: Int
) {
val event = MeditationEvent(
mediaId, meditationId, meditationType, businessType,
status, buried!!, mediaUrl!!, mediaCoverUrl!!, title!!, desc!!
)
EventBus.getDefault().post(event)
}
fun loadUrl(url: String?,web:WebView) {
if (TextUtils.isEmpty(url)) {
return
}
val resultUrl = if (h5Params?.suffix == true) WebUrlParamsUtils.getSuffix(
url,
jtoJHandle?.getUriAppendSuffix()
) else url
Log.e(TAG, resultUrl)
web.loadUrl(resultUrl)
}
/**
* 专家详情页改版 需要url后面拼接状态栏高度 并且隐藏导航栏
*
* @param url
* @return
*/
private fun setUrlHeightParams(url: String?): String {
var resultUrl: String? = url
try {
val uri = Uri.parse(url)
val host = uri.host
if (!TextUtils.isEmpty(host) && host.contains("nodeapi.ydl")) {
//马亮的需求,在nodeapi.ydl.com 地址后面拼上公共参数,用于判断是否为app
//马亮的需求,在nodeapi.ydl.com 地址后面拼上公共参数,用于判断是否为app
val uriAppendSuffix = jtoJHandle?.getUriAppendSuffix()
resultUrl = WebUrlParamsUtils.getSuffix(url, uriAppendSuffix)
}
} catch (e: Exception) {
e.printStackTrace()
}
return pinjie(resultUrl)
}
private fun pinjie(jumpUrl: String?): String {
var useUrl = StringBuffer().append(jumpUrl).toString()
val res: Resources = resources
val doctorUrlArray = res.getStringArray(R.array.platform_doctorUrls)
for (url in doctorUrlArray) {
if (useUrl.contains(url)) {
var lastUrl = useUrl.replace(url.toRegex(), "")
if (lastUrl.contains("?")) {
lastUrl = lastUrl.substring(0, lastUrl.indexOf("?"))
}
try {
//不报错就说明可以转成long,就说明是专家详情页地址
lastUrl.toLong()
if (!lastUrl.contains("/")) {
if (useUrl.endsWith("?")) {
useUrl = useUrl.substring(0, useUrl.indexOf("?"))
}
}
} catch (e: NumberFormatException) {
e.printStackTrace()
}
}
}
return useUrl
}
}
\ No newline at end of file
package com.yidianling.muse.activity
import android.content.Intent
import android.os.Bundle
import com.blankj.utilcode.util.SPUtils
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestOptions
import com.ydl.ydlcommon.base.BaseActivity
import com.yidianling.muse.R
import jp.wasabeef.glide.transformations.BlurTransformation
import kotlinx.android.synthetic.main.activity_play_meditation_time_off.*
class MeditationTimeOffActivity : BaseActivity() {
private lateinit var mBGImageUrl:String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBGImageUrl = intent?.getStringExtra("BG_IMAGE_URL")?:""
initView()
}
private fun initView() {
val options = RequestOptions.bitmapTransform(BlurTransformation(25,1))
Glide.with(this)
.load(mBGImageUrl)
.transition(DrawableTransitionOptions.withCrossFade())
.apply(options)
.into(iv_bg)
iv_close?.setOnClickListener { finish() }
tv_save_setting?.setOnClickListener {
val hour = wheel_hour.selectedItem
val minute = wheel_minute.selectedItem
val selectedHour = wheel_hour.selectedItem
val selectedMinute = wheel_minute.selectedItem
SPUtils.getInstance().put("SELECT_H",selectedHour)
SPUtils.getInstance().put("SELECT_M",selectedMinute)
val intent = Intent()
if (hour is Int && minute is Int){
val minute = (hour *60).plus(minute*5)
intent.putExtra("TIME_OFF_MINUTE", minute)
}
setResult(RESULT_OK, intent)
finish()
}
tv_cancel_time_off?.setOnClickListener {
SPUtils.getInstance().put("SELECT_H",0)
SPUtils.getInstance().put("SELECT_M",1)
val intent = Intent()
intent.putExtra("TIME_OFF_MINUTE", 0)
setResult(RESULT_OK, intent)
finish()
}
initWheel()
}
private fun initWheel() {
val selectionH = SPUtils.getInstance().getInt("SELECT_H",0)
val selectionM = SPUtils.getInstance().getInt("SELECT_M",1)
createHours()
createMinutes()
wheel_hour.setItems(hours)
wheel_minute.setItems(minutes)
wheel_hour.setInitPosition(selectionH)
wheel_minute.setInitPosition(selectionM)
wheel_hour.setListener { index ->
if (index == 0 && wheel_minute.selectedItem == 0) {
wheel_minute.setCurrentPosition(1)
}
}
wheel_minute.setListener { index ->
if (index == 0 && wheel_hour.selectedItem == 0) {
wheel_minute.setCurrentPosition(1)
}
}
}
override fun initDataAndEvent() {
}
override fun layoutResId(): Int {
return R.layout.activity_play_meditation_time_off
}
private var hours = mutableListOf<String>()
private var minutes = mutableListOf<String>()
private fun createHours() {
for (i in 0..23) {
hours.add("" + i)
}
}
private fun createMinutes() {
var i = 0
while (i < 60) {
if (i < 10) {
minutes.add("0$i")
} else {
minutes.add("" + i)
}
i += 5
}
}
}
\ No newline at end of file
package com.yidianling.muse.activity
//import com.yidianling.muse.dialog.ChooseMusicDialog
import android.content.Intent
import android.media.MediaPlayer
import android.os.Bundle
import android.os.Handler
import android.view.View
import android.widget.SeekBar
import com.alibaba.android.arouter.facade.annotation.Route
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.view.PlayerFloatHelper
import com.ydl.webview.H5Params
import com.ydl.ydlcommon.base.BaseActivity
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.ydl.ydlcommon.event.MeditationEvent
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.ydl.ydlcommon.utils.Utils
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.ydl.ydlcommon.utils.remind.ToastHelper.Companion.show
import com.yidianling.common.tools.ToastUtil
import com.yidianling.home.http.MuseHttp
import com.yidianling.muse.R
import com.yidianling.muse.bean.MeditationPlayModuleBean
import com.yidianling.muse.constants.MuseBIConstants
import com.yidianling.muse.event.MeditationFloatEvent
import com.yidianling.muse.helper.MediaPlayerManager
import com.yidianling.muse.utils.MediaPlayerTimeUtil
import com.yidianling.muse.utils.MeditationFloatPermissionUtil
import com.yidianling.muse.widget.QuitMeditationDialog
import com.yidianling.muse.widget.ShareMeditationDialog
import com.yidianling.user.api.service.IUserService
import de.greenrobot.event.EventBus
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_play_meditation.*
import kotlinx.android.synthetic.main.activity_play_meditation.iv_close
import kotlinx.android.synthetic.main.activity_play_meditation.tv_title
import kotlinx.android.synthetic.main.layout_meditation_play_float_view.*
import kotlinx.android.synthetic.main.player_control_view.*
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt
@Route(path = "/muse/play")
class PlayMeditationActivity : BaseActivity() {
private var mMeditationId: Long? = null
private var mMeditationType: Int? = null
private var mMediaId: Long? = null
private var mMediaUrl = ""
private var mMediaCoverUrl = ""
private var mTitle = ""
private var mDesc = ""
private var mStatus = 0
private var mBusinessType = 0
private var mediaListLink = ""
private var meditations = mutableListOf<MeditationPlayModuleBean.MeditationDetail>()
private var currentMeditation: MeditationPlayModuleBean.MeditationDetail? = null
private var currentMeditationIndex = 0
private var collected = false
private var isPlaying = false
private var shareDialog: ShareMeditationDialog? = null
private var quitDialog: QuitMeditationDialog? = null
private var mTimer = Timer()
private var mMediaPlayer: MediaPlayer? = null
private var duration = 0
private var isSeekbarChanging = false
private var mDisposable: Disposable? = null
private lateinit var mObservable: Observable<Long>
private var mObserver: Observer<Long>? = null
private var mBuried: String? = null
/**
* 传递过来的mediaId 用于判断正在播放的是否是同一条音频
*/
private var mMediaIdFromLocal: Long? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
PlayerFloatHelper.removeView(mContext)
PlayerFloatHelper.playTempData.clear()
AudioPlayer.get().stopPlayer()
mMediaPlayer = MediaPlayerManager.getInstance(this)?.getMediaPlayer()
EventBus.getDefault().register(this)
mMediaIdFromLocal = intent?.getLongExtra("MEDIA_ID", 0L)
mMeditationId = intent?.getLongExtra("MEDITATION_ID", 0L)
mMeditationType = intent?.getIntExtra("MEDITATION_TYPE", 0)
mMediaUrl = intent?.getStringExtra("MEDIA_URL") ?: ""
mMediaCoverUrl = intent?.getStringExtra("MEDIA_COVER_URL") ?: ""
initView()
getData()
}
override fun initDataAndEvent() {
}
private fun getData() {
updateUIByMeditationType()
if (mMeditationId == null || (mMediaIdFromLocal == null && mMeditationType != 0)) {
return
}
// 声音详情
if (mMeditationType == 0) {
MuseHttp.getInstance().getPureMusicPlayDetail(
meditionType = mMeditationType!!,
meditationId = mMeditationId!!
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer {
if (it.code.equals("200") && it.data != null) {
val module = it.data
mMediaId = module.mediaId
mediaListLink = module.playDetailUrl?:""
val mediaList = module.mediaList
if(!mediaList.isNullOrEmpty()){
val meditation = mediaList[0]
currentMeditation = meditation.copy(meditationType = mMeditationType,meditationId = mMeditationId!!)
mTitle = meditation.title
mDesc = meditation.desc?:""
mMediaUrl = meditation.mediaUrl
mMediaCoverUrl = meditation.coverImageUrl
val currentPosition = meditation.broadcastTime
mBusinessType = meditation.businessType
mBuried = meditation.buried
mStatus = meditation.status
updateUI()
initMediaPlayer(
mMediaUrl,
currentPosition,
mMediaIdFromLocal == mMediaId
)
//快进点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_PAGE_VISIT,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
}
}
}, object : ThrowableConsumer() {
override fun accept(msg: String) {
show(msg)
}
})
} else {
MuseHttp.getInstance().getMeditationPlayDetail(
meditionType = 1,
mediaId = mMediaIdFromLocal!!,
meditationId = mMeditationId!!
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer {
if (it.code.equals("200") && it.data != null) {
val module = it.data
mMediaId = module.mediaId
meditations.clear()
module.mediaList?.forEach { meditationPlayBean ->
meditations.add(meditationPlayBean)
if (meditationPlayBean.mediaId == mMediaId) {
currentMeditation =
meditationPlayBean.copy(meditationType = mMeditationType,meditationId = mMeditationId!!)
mMediaId = module?.mediaId ?: 0L
mTitle = meditationPlayBean.title
mDesc = meditationPlayBean.desc ?: ""
mMediaCoverUrl = meditationPlayBean.coverImageUrl
mMediaUrl = meditationPlayBean.mediaUrl
val currentPosition = meditationPlayBean.broadcastTime
mBusinessType = meditationPlayBean.businessType
mStatus = meditationPlayBean.status
mBuried = meditationPlayBean.buried
collected = mStatus == 1
updateUI()
initMediaPlayer(mMediaUrl, currentPosition,mMediaIdFromLocal == mMediaId)
}
}
}
}, object : ThrowableConsumer() {
override fun accept(msg: String) {
show(msg)
}
})
}
}
private fun updateUIByMeditationType() {
val event = MeditationFloatEvent(false)
EventBus.getDefault().post(event)
// 声音类型
if (mMeditationType == 0) {
exo_rew.visibility = View.GONE
exo_ffwd.visibility = View.GONE
exo_prev.visibility = View.GONE
exo_next.visibility = View.GONE
iv_time_off.visibility = View.GONE
tv_time_off.visibility = View.GONE
ll_pure_music_time_off.visibility = View.VISIBLE
iv_pure_music_list.visibility = View.VISIBLE
} else {
exo_rew.visibility = View.VISIBLE
exo_ffwd.visibility = View.VISIBLE
exo_prev.visibility = View.VISIBLE
exo_next.visibility = View.VISIBLE
iv_time_off.visibility = View.VISIBLE
tv_time_off.visibility = View.VISIBLE
ll_pure_music_time_off.visibility = View.GONE
iv_pure_music_list.visibility = View.GONE
}
initClickListener()
}
private fun initClickListener() {
iv_pure_music_list.setOnClickListener {
if (Utils.isFastClick()) {
//防止连击
return@setOnClickListener
}
//列表点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_LIST_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
if (!mediaListLink.isNullOrBlank()) {
ChooseMusicActivity.launch(this, H5Params(mediaListLink,"") )
// val chooseMusicDialog = ChooseMusicDialog(this,H5Params(mediaListLink!!, null))
// chooseMusicDialog.show()
}
}
iv_collect.setOnClickListener {
if (Utils.isFastClick()) {
//防止连击
return@setOnClickListener
}
//快进点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_COLLECT_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
if (!ModularServiceManager.provide(IUserService::class.java)
.loginByOneKeyLogin(this, true)
) {
return@setOnClickListener
}
if (mMeditationId == null || mMediaId == null) return@setOnClickListener
MuseHttp.getInstance().collectMeditation(
meditationId = mMeditationId!!,
mediaId = mMediaId!!,
status = if (collected) 0 else 1, businessType = mBusinessType
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ result ->
if (result != null && result.code == "200") {
collected = !collected
if (collected) {
show("收藏成功!")
iv_collect.setImageResource(R.drawable.icon_meditation_collected)
} else {
show("取消收藏!")
iv_collect.setImageResource(R.drawable.icon_play_meditation_collect)
}
} else {
}
}, {
object : ThrowableConsumer() {
override fun accept(msg: String) {
}
}
})
}
}
override fun layoutResId(): Int {
return R.layout.activity_play_meditation
}
private fun initView() {
iv_close.setOnClickListener {
//关闭点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_CLOSE_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
if(mMeditationType == 0){
if (mMeditationId != null && mMediaId != null) {
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = mMeditationId!!.toInt(),
isQuit = 1, mediaId = mMediaId!!,
playTime = (seekbar_play_progress.progress / 1000.00).roundToInt(),
isComplete = 0
)
stopPlay()
finish()
} else {
stopPlay()
finish()
}
}else{
if (quitDialog == null) {
quitDialog = QuitMeditationDialog.newInstance()
}
if (quitDialog != null && quitDialog?.isAdded == false) {
quitDialog?.setListener(object : QuitMeditationDialog.ClickListener {
override fun quit() {
if (mMeditationId != null && mMediaId != null) {
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = mMeditationId!!.toInt(),
isQuit = 1, mediaId = mMediaId!!,
playTime = (seekbar_play_progress.progress / 1000.00).roundToInt(),
isComplete = 0
)
}
stopPlay()
finish()
}
})
quitDialog?.show(supportFragmentManager, QuitMeditationDialog.TAG)
}
}
}
iv_back.setOnClickListener {
//收起点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_PACK_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
val event = MeditationFloatEvent(true,
meditation = currentMeditation?.copy(meditationType = mMeditationType,meditationId =
mMeditationId?:0))
EventBus.getDefault().post(event)
Handler().postDelayed({
finish()
}, 300)
}
iv_share.setOnClickListener {
//分享点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_SHARE_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
if (shareDialog == null) {
shareDialog = ShareMeditationDialog
.newInstance(
shareTitle = mTitle,
shareContent = mDesc,
shareUrl = mMediaUrl,
shareImageUrl = mMediaCoverUrl
)
}
if (shareDialog != null && shareDialog?.isAdded == false) {
shareDialog?.show(supportFragmentManager, ShareMeditationDialog.TAG)
}
}
iv_time_off.setOnClickListener {
//定时 ioc点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_IOC_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
val intent = Intent(this, MeditationTimeOffActivity::class.java)
intent.putExtra("BG_IMAGE_URL",mMediaCoverUrl)
startActivityForResult(intent, request_code)
}
ll_pure_music_time_off.setOnClickListener {
//定时 ioc点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_IOC_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
val intent = Intent(this, MeditationTimeOffActivity::class.java)
intent.putExtra("BG_IMAGE_URL",mMediaCoverUrl)
startActivityForResult(intent, request_code)
}
exo_play.setOnClickListener {
if (Utils.isFastClick()) return@setOnClickListener
if (isPlaying) {
mMediaPlayer?.pause()
if (mMeditationId == null || mMediaId == null) return@setOnClickListener
val playTime = (seekbar_play_progress.progress / 1000.00).roundToInt()
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = mMeditationId?.toInt(),
mediaId = mMediaId,
isQuit = 0,
playTime = playTime,
isComplete = 0
)
//暂停埋点
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_PAUSE_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
} else {
val duration = mMediaPlayer?.duration
MediaPlayerManager.getInstance(this@PlayMeditationActivity)?.play()
if (duration != null) {
seekbar_play_progress.max = duration
}
mTimer.schedule(object : TimerTask() {
override fun run() {
if (!isSeekbarChanging) {
seekbar_play_progress.progress = MediaPlayerManager
.getInstance(this@PlayMeditationActivity)
?.getMediaPlayer()?.currentPosition ?: 0
}
}
}, 0, 50)
//播放埋点
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_PLAY_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
}
isPlaying = !isPlaying
if (isPlaying) {
exo_play.setImageResource(R.drawable.icon_pause_play)
} else {
exo_play.setImageResource(R.drawable.icon_pause_meditation)
}
}
exo_prev.setOnClickListener {
if (Utils.isFastClick()) return@setOnClickListener
//上一曲埋点
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_LAST_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
var currentPosition = 0
meditations?.forEachIndexed { index, meditationDetail ->
if (meditationDetail.mediaId == mMediaId){
currentPosition = index
}
}
if (currentPosition > 0) {
if (mMeditationId == null || mMediaId == null) return@setOnClickListener
val playTime = (seekbar_play_progress.progress / 1000.00).roundToInt()
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = mMeditationId?.toInt(),
mediaId = mMediaId,
isQuit = 0,
playTime = playTime,
isComplete = 0
)
val meditation = meditations[currentPosition - 1]
currentMeditation = meditation.copy(meditationId = mMeditationId!!)
mMediaId = meditation.mediaId
mMediaCoverUrl = meditation.coverImageUrl
mMediaUrl = meditation.mediaUrl
val currentPosition = meditation.broadcastTime
mStatus = meditation.status
mTitle = meditation.title
mDesc = meditation.title
updateUI(needRefresh = false)
initMediaPlayer(mMediaUrl, currentPosition, mMediaIdFromLocal == mMediaId)
} else {
ToastUtil.toastShort("暂无内容")
}
}
exo_next.setOnClickListener {
if (Utils.isFastClick()) return@setOnClickListener
//下一个点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_NEXT_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
var currentPosition = 0
meditations?.forEachIndexed { index, meditationDetail ->
if (meditationDetail.mediaId == mMediaId){
currentPosition = index
}
}
if (currentPosition < meditations.size - 1) {
if (mMeditationId == null || mMediaId == null) return@setOnClickListener
val playTime = (seekbar_play_progress.progress / 1000.00).roundToInt()
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = mMeditationId?.toInt(),
mediaId = mMediaId,
isQuit = 0,
playTime = playTime,
isComplete = 0
)
val meditation = meditations[currentPosition + 1]
currentMeditation = meditation.copy(meditationId = mMeditationId!!)
mMediaId = meditation.mediaId
mMediaCoverUrl = meditation.coverImageUrl
mMediaUrl = meditation.mediaUrl
val currentPosition = meditation.broadcastTime
mStatus = meditation.status
mTitle = meditation.title
mDesc = meditation.title
updateUI(needRefresh = false)
initMediaPlayer(mMediaUrl, currentPosition, mMediaIdFromLocal == mMediaId)
} else {
ToastUtil.toastShort("暂无内容")
}
}
exo_rew.setOnClickListener {
if (Utils.isFastClick()) return@setOnClickListener
//快退点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_REW_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
val currentPosition = MediaPlayerManager
.getInstance(this@PlayMeditationActivity)?.getMediaPlayer()?.currentPosition
val seekPosition = 0.coerceAtLeast(currentPosition?.minus(15000) ?: 0)
MediaPlayerManager.getInstance(this@PlayMeditationActivity)?.getMediaPlayer()
?.seekTo(seekPosition)
}
exo_ffwd.setOnClickListener {
if (Utils.isFastClick()) return@setOnClickListener
//快进点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_SPEED_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
val currentPosition = MediaPlayerManager
.getInstance(this@PlayMeditationActivity)?.getMediaPlayer()?.currentPosition
val seekPosition = duration.coerceAtMost(currentPosition?.plus(15000) ?: 0)
MediaPlayerManager
.getInstance(this@PlayMeditationActivity)?.getMediaPlayer()?.seekTo(seekPosition)
}
seekbar_play_progress.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (mMediaPlayer != null) {
val totalDuration = mMediaPlayer!!.duration / 1000
val position = mMediaPlayer!!.currentPosition
exo_position.text = MediaPlayerTimeUtil.calculateTime(position / 1000)
exo_duration.text = MediaPlayerTimeUtil.calculateTime(totalDuration)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
//进度条点击事件
ActionCountUtils.baiDuCountSign3(
MuseBIConstants.YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE,
MuseBIConstants.YDL_MUSE_PLAY_PROGRESS_CLICK,
currentMeditation?.title ?: "",
mBuried ?: "",
""
)
isSeekbarChanging = true
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
isSeekbarChanging = false
seekBar?.progress?.let {
MediaPlayerManager.getInstance(this@PlayMeditationActivity)?.seekTo(
it
)
if (mMediaPlayer != null) {
exo_position.text = MediaPlayerTimeUtil.calculateTime(
mMediaPlayer!!.currentPosition / 1000
)
}
}
}
})
initPlayCompletionListener()
MeditationFloatPermissionUtil.checkSuspendedWindowPermission(this){
}
}
private fun initPlayCompletionListener(isLoop: Boolean = false, isSingle: Boolean = false) {
mMediaPlayer?.setOnCompletionListener {
val duration = currentMeditation?.duration?.toInt()?:0
val currentDuration = (mMediaPlayer?.currentPosition?:0)/1000
if(currentDuration==duration){
val playTime = (seekbar_play_progress.progress / 1000.00).roundToInt()
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = mMeditationId?.toInt(),
mediaId = mMediaId,
isQuit = 0,
playTime = playTime,
isComplete = 1
)
}
if (isLoop){
if (isSingle || meditations.size == 1){
MediaPlayerManager
.getInstance(this)?.setAudioPath(currentMeditation?.mediaUrl?:"",isLoop = true)
}else{
currentMeditationIndex = meditations.indexOf(currentMeditation)
if(currentMeditationIndex == meditations.size - 1){
currentMeditationIndex = 0
}else{
currentMeditationIndex++
}
currentMeditation = meditations[currentMeditationIndex]
val event = MeditationEvent(
currentMeditation?.mediaId?.toInt()?:0,
mMeditationId?:0L,
mMeditationType?:0,
mBusinessType,
status = mStatus,
buried = mBuried?:"",
mediaUrl = currentMeditation?.mediaUrl?:"",
mediaCoverUrl = currentMeditation?.coverImageUrl?:"",
title = currentMeditation?.title?:"",
desc = currentMeditation?.desc?:""
)
EventBus.getDefault().post(event)
}
}
isPlaying = if (it.isPlaying) {
exo_play.setImageResource(R.drawable.icon_pause_play)
true
} else {
exo_play.setImageResource(R.drawable.icon_pause_meditation)
false
}
if (mMediaPlayer?.isPlaying == true) {
mMediaPlayer?.pause()
}
}
}
private fun initMediaPlayer(path: String, current: Int, isSameOne: Boolean = false) {
if (MediaPlayerManager.getInstance(this)?.getAudioPath()!=null &&
MediaPlayerManager.getInstance(this)?.getMediaId() == mMediaId
) {
if (mMediaPlayer?.isPlaying == true) {
exo_play.setImageResource(R.drawable.icon_pause_play)
} else {
exo_play.setImageResource(R.drawable.icon_pause_meditation)
}
val currentPosition = mMediaPlayer?.currentPosition
duration = mMediaPlayer?.duration ?: 0
if (current > 0) {
seekbar_play_progress.max = duration
seekbar_play_progress.progress = current
exo_position.text = MediaPlayerTimeUtil.calculateTime(current)
} else if (currentPosition != null) {
seekbar_play_progress.max = duration
seekbar_play_progress.progress = current
exo_position.text = MediaPlayerTimeUtil.calculateTime(currentPosition / 1000)
}
exo_duration.text = MediaPlayerTimeUtil.calculateTime(duration / 1000)
seekbar_play_progress.max = duration
mTimer.schedule(object : TimerTask() {
override fun run() {
if (!isSeekbarChanging) {
seekbar_play_progress.progress = mMediaPlayer?.currentPosition ?: 0
}
}
}, 0, 50)
} else {
MediaPlayerManager.getInstance(this)?.setAudioPath(path)
MediaPlayerManager.getInstance(this)
?.setOnPreparedListener(object : MediaPlayerManager.OnMediaPlayerManagerListener {
override fun onPrepared(mediaPlayer: MediaPlayer) {
MediaPlayerManager.getInstance(this@PlayMeditationActivity)?.play()
if (mMediaPlayer?.isPlaying == true) {
exo_play.setImageResource(R.drawable.icon_pause_play)
} else {
exo_play.setImageResource(R.drawable.icon_pause_meditation)
}
val currentPosition = mMediaPlayer?.currentPosition
duration = mMediaPlayer?.duration ?: 0
if (current > 0) {
mMediaPlayer?.seekTo(current * 1000)
seekbar_play_progress.max = duration
seekbar_play_progress.progress = current
exo_position.text = MediaPlayerTimeUtil.calculateTime(current)
} else if (currentPosition != null) {
seekbar_play_progress.max = duration
seekbar_play_progress.progress = current
exo_position.text =
MediaPlayerTimeUtil.calculateTime(currentPosition / 1000)
}
exo_duration.text = MediaPlayerTimeUtil.calculateTime(duration / 1000)
mTimer.schedule(object : TimerTask() {
override fun run() {
if (!isSeekbarChanging) {
seekbar_play_progress.progress = mMediaPlayer?.currentPosition ?: 0
}
}
}, 0, 50)
}
})
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK && request_code == requestCode) {
val minute = data?.extras?.getInt("TIME_OFF_MINUTE", 0)
if (minute != null && minute > 0) {
if (mMeditationType == 0) {
initPlayCompletionListener(isLoop = true, isSingle = true)
tv_time_off_pure_music.visibility = View.VISIBLE
tv_time_off.visibility = View.GONE
mDisposable?.dispose()
mDisposable = null
MediaPlayerManager.getInstance(this)?.setTimeOffStatus(true)
initRxTimeOff((minute * 60 * 1000).toLong(), 0)
} else {
initPlayCompletionListener(isLoop = true, isSingle = false)
tv_time_off_pure_music.visibility = View.GONE
tv_time_off.visibility = View.VISIBLE
mDisposable?.dispose()
mDisposable = null
MediaPlayerManager.getInstance(this)?.setTimeOffStatus(true)
initRxTimeOff((minute * 60 * 1000).toLong(), 1)
}
val event = MeditationFloatEvent(false,time = (minute * 60 * 1000).toLong())
EventBus.getDefault().post(event)
} else {
initPlayCompletionListener()
MediaPlayerManager.getInstance(this)?.setTimeOffStatus(false)
mDisposable?.dispose()
mDisposable = null
tv_time_off.visibility = View.GONE
tv_time_off_pure_music.visibility = View.GONE
mMediaPlayer?.isLooping = false
val event = MeditationFloatEvent(false,time = 0)
EventBus.getDefault().post(event)
}
}
}
private fun updateUI(needRefresh:Boolean = true){
tv_title.text = mTitle
tv_content.text = mDesc
Glide.with(this)
.load(mMediaCoverUrl)
.transition(DrawableTransitionOptions.withCrossFade())
.into(iv_bg)
iv_collect.setImageResource(
if (mStatus == 0) {
R.drawable.icon_play_meditation_collect
} else {
R.drawable.icon_meditation_collected
}
)
if(needRefresh){
if(MediaPlayerManager.getInstance(this)?.getTimeOffStatus() == true){
val timeOff = MediaPlayerManager.getInstance(this)?.getTimeOff()
if (timeOff!=null && timeOff>0 && mMeditationType!=null){
initRxTimeOff(timeOff, mMeditationType!!)
}
}
}
}
private fun initRxTimeOff(time: Long, meditationType: Int) {
MediaPlayerManager.getInstance(this)?.initRxTimeOff(time)
mObservable = Observable.interval(0, 1, TimeUnit.SECONDS)
.take(time / 1000 + 1)
.map { t -> time - t * 1000 }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
mObserver = object : Observer<Long> {
override fun onSubscribe(d: Disposable) {
mDisposable = d
}
override fun onNext(t: Long) {
if (meditationType == 0) {
tv_time_off_pure_music.text = MediaPlayerTimeUtil.formatTimeOff(t)
} else {
tv_time_off.text = MediaPlayerTimeUtil.formatTimeOff(t)
}
}
override fun onError(e: Throwable) {
mDisposable?.dispose()
}
override fun onComplete() {
if (mMediaPlayer?.isPlaying == true) {
mMediaPlayer?.stop()
exo_play.setImageResource(R.drawable.icon_pause_meditation)
}
if (meditationType == 0) {
tv_time_off_pure_music.text = ""
} else {
tv_time_off.text = ""
}
finish()
}
}
if (mObserver != null && mObserver is Observer<Long>) {
mObservable.subscribe(mObserver as Observer<Long>)
}
if (mDisposable?.isDisposed == true && mObserver != null && mObserver is Observer<Long>) {
mObservable?.subscribe(mObserver as Observer<Long>)
}
}
fun onEventMainThread(event: MeditationEvent) {
if (event != null) {
mTitle = event.title
mDesc = event.desc
mMediaUrl = event.mediaUrl
mMediaCoverUrl = event.mediaCoverUrl
mStatus = event.status
updateUI(needRefresh = false)
if (event.mediaUrl == MediaPlayerManager.getInstance(this)?.getAudioPath()) {
return
}
initMediaPlayer(event.mediaUrl, 0, mMediaIdFromLocal == mMediaId)
}
}
override fun onBackPressed() {
val event = MeditationFloatEvent(true, meditation = currentMeditation)
EventBus.getDefault().post(event)
super.onBackPressed()
}
override fun onDestroy() {
super.onDestroy()
if (EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this)
}
mDisposable?.dispose()
mTimer.cancel()
}
private fun stopPlay() {
MediaPlayerManager.getInstance(this)?.stop()
}
companion object {
const val request_code = 0x0001
}
}
\ No newline at end of file
package com.yidianling.muse.bean
data class CollectResultModule(
val code:String,
val data:String,
val msg:String,
val errMsg:String
){
override fun toString(): String {
return "CollectResultModule(code='$code', data='$data', msg='$msg', errMsg='$errMsg')"
}
}
data class MeditationCollectRequestModule(
val meditationId: Long,
val mediaId: Long,
val status: Int,
val businessType:Int
)
data class MeditationPlayRecordRequestModule(
val meditationId:Int,
val isQuit:Int,
val mediaId:Long,
val playTime:Int,
val isComplete:Int
)
data class MeditationPlayRecordResponseModule(
val code: String,
val data: String? = null,
val msg: String? = null,
val errMsg: String? = null
)
package com.yidianling.muse.bean
/**
* 冥想模块所有数据
* Created by xj on 2019/9/16.
*/
class MeditationPlayModuleBean : HomeItemBaseBean {
constructor():super(false)
constructor(isRealEmpty:Boolean):super(isRealEmpty)
var meditationId:Long? = null
var mediaId:Long? = null
var mediaType:Int?=null
var playDetailUrl:String? = null
var mediaList: ArrayList<MeditationDetail>? = null
data class MeditationDetail(
val meditationType:Int? = null,
val mediaId:Long?=null,
val meditationId:Long,
val title:String,
val author:String,
val coverImageUrl:String,
val mediaUrl:String,
val duration:Float?=null,
val status:Int,
val broadcastTime:Int,
val businessType:Int,
val buried:String?=null,
val desc:String?=null,
val coverImageUrlIcon:String
)
override fun toString(): String {
return "MeditationPlayModuleBean(meditationId=$meditationId, mediaId=$mediaId, mediaType=$mediaType, playDetailUrl=$playDetailUrl, mediaList=$mediaList)"
}
}
\ No newline at end of file
package com.yidianling.muse.constants
/**
* @author liunpeng
* */
class MuseBIConstants {
companion object {
//音乐播放页(meditation_music_play_page)
const val YDL_MUSE_MEDITATION_MUSIC_PLAY_PAGE: String =
"meditation_music_play_page"//音乐播放页(meditation_music_play_page)
const val YDL_MUSE_PLAY_PACK_CLICK: String =
"music_play_pack_click"//收起点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_CLOSE_CLICK: String =
"music_play_close_click" //关闭点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_COLLECT_CLICK: String =
"music_play_collect_click"//收藏点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_SHARE_CLICK: String =
"music_play_share_click"//分享点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_IOC_CLICK: String =
"music_play_ioc_click"//定时 ioc点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_PROGRESS_CLICK: String =
"music_play_progress_click"//进度条点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_SPEED_CLICK: String =
"music_play_speed_click"//快进点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_REW_CLICK: String =
"music_play_rew_click"//快退点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_NEXT_CLICK: String =
"music_play_next_click"//下一个点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_LAST_CLICK: String =
"music_play_last_click"//上一个点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_PAUSE_CLICK: String =
"music_play_pause_click"//暂停点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_PLAY_CLICK: String =
"music_play_play_click"//播放点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_PAGE_VISIT: String =
"music_play_page_visit"//曝光事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_CHANGE_CLICK: String =
"music_play_change_click"//切换音频点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
const val YDL_MUSE_PLAY_LIST_CLICK: String =
"music_play_list_click"//列表点击事件 sign1: 内容标题 sign2(传入字符串): meditation(冥想播放), voice(轻音乐播放), sleep(睡眠播放)
//悬浮窗(meditation_floating_window_play)
private const val YDL_MUSE_MEDITATION_FLOATING_WINDOW: String =
"meditation_floating_window_play|"//悬浮窗
const val YDL_MUSE_MEDITATION_WINDOW_PLAY_CLICK: String =
YDL_MUSE_MEDITATION_FLOATING_WINDOW + "meditation_floating_window_play_click"//悬浮窗播放点击事件
const val YDL_MUSE_MEDITATION_WINDOW_PAUSE_CLICK: String =
YDL_MUSE_MEDITATION_FLOATING_WINDOW + "meditation_floating_window_pause_click"//悬浮窗暂停点击事件
const val YDL_MUSE_MEDITATION_WINDOW_CLOSE_CLICK: String =
YDL_MUSE_MEDITATION_FLOATING_WINDOW + "meditation_floating_window_close_click"//悬浮窗关闭点击事件
const val YDL_MUSE_MEDITATION_WINDOW_CLICK: String =
YDL_MUSE_MEDITATION_FLOATING_WINDOW + "meditation_floating_window_click"//悬浮窗播放区域点击 事件
}
}
\ No newline at end of file
package com.yidianling.muse.dialog
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Dialog
import android.content.res.Resources
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import android.webkit.WebSettings
import com.ydl.utils.WebUrlParamsUtils
import com.ydl.webview.H5Params
import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.muse.R
import com.yidianling.muse.activity.PlayMeditationActivity
import kotlinx.android.synthetic.main.dialog_choose_music.*
/**
* Created by Ykai on 2022/5/26.
*
* 选择音乐弹窗,内部是h5页面
*/
class ChooseMusicDialog(activity: Activity,h5Params: H5Params) : Dialog(activity, R.style.music_dialog_style) {
private val mActivity = activity
private val h5Params: H5Params = h5Params
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 设置宽度全屏
//dialog去除默认边距,宽度占满全屏
val window = window!!
window.setWindowAnimations(R.style.dialog_anim)
// 把 DecorView 的默认 padding 取消,同时 DecorView 的默认大小也会取消
window.decorView.setPadding(0, 0, 0, 0)
val layoutParams = window.attributes
layoutParams.gravity = Gravity.BOTTOM
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT
layoutParams.height = (RxDeviceTool.getScreenHeight(context)*0.89).toInt()
window.attributes = layoutParams
setContentView(R.layout.dialog_choose_music)
initView()
}
@SuppressLint("SetJavaScriptEnabled")
private fun initView() {
// 移除有漏洞的系统接口
wv_choose_music.removeJavascriptInterface("searchBoxJavaBridge_")
wv_choose_music.removeJavascriptInterface("accessibility")
wv_choose_music.removeJavascriptInterface("accessibilityTraversal")
val mWebSettings: WebSettings = wv_choose_music.settings
mWebSettings.javaScriptEnabled = true //支持js
mWebSettings.defaultTextEncodingName = "GBK" //设置字符编码
mWebSettings.domStorageEnabled = true
mWebSettings.textZoom = 100 //设置字体不跟随字体变化而变化
mWebSettings.allowFileAccessFromFileURLs = true
mWebSettings.blockNetworkImage = false // 解决图片不显示
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mWebSettings.mixedContentMode = WebSettings.LOAD_NORMAL
}
wv_choose_music.scrollBarStyle = View.SCROLLBARS_INSIDE_OVERLAY //滚动条风格,为0指滚动条不占用空间,直接覆盖在网页上
// val jsInterface = JsInterface(mActivity as PlayMeditationActivity)
// wv_choose_music.addJavascriptInterface(jsInterface, "javascriptHandler")
val url = setUrlHeightParams(h5Params.url)
wv_choose_music.loadUrl(url)
ll_close.setOnClickListener {
dismiss()
}
}
/**
* 专家详情页改版 需要url后面拼接状态栏高度 并且隐藏导航栏
*
* @param url
* @return
*/
private fun setUrlHeightParams(url: String): String {
var resultUrl: String? = url
try {
val uri = Uri.parse(url)
val host = uri.host
if (!TextUtils.isEmpty(host) && host.contains("nodeapi.ydl")) {
//马亮的需求,在nodeapi.ydl.com 地址后面拼上公共参数,用于判断是否为app
val uriAppendSuffix = ""
resultUrl = WebUrlParamsUtils.getSuffix(url, uriAppendSuffix)
}
} catch (e: Exception) {
e.printStackTrace()
}
return pinjie(resultUrl)
}
private fun pinjie(jumpUrl: String?): String {
var useUrl = StringBuffer().append(jumpUrl).toString()
val res: Resources = mActivity.resources
val doctorUrlArray = res.getStringArray(R.array.platform_doctorUrls)
for (url in doctorUrlArray) {
if (useUrl.contains(url)) {
var lastUrl = useUrl.replace(url.toRegex(), "")
if (lastUrl.contains("?")) {
lastUrl = lastUrl.substring(0, lastUrl.indexOf("?"))
}
try {
//不报错就说明可以转成long,就说明是专家详情页地址
lastUrl.toLong()
if (!lastUrl.contains("/")) {
if (useUrl.endsWith("?")) {
useUrl = useUrl.substring(0, useUrl.indexOf("?"))
}
}
} catch (e: NumberFormatException) {
e.printStackTrace()
}
}
}
return useUrl
}
}
\ No newline at end of file
package com.yidianling.muse.event
import com.yidianling.muse.bean.MeditationPlayModuleBean
class MeditationFloatEvent(
val show: Boolean,
val stop: Boolean? = null,
val time: Long? = null,
val meditation: MeditationPlayModuleBean.MeditationDetail? = null,
val meditations: ArrayList<MeditationPlayModuleBean.MeditationDetail>? = null
)
package com.yidianling.muse.helper
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import com.ydl.ydlcommon.utils.LogUtil
class FloatViewTouchListener(val wl: WindowManager.LayoutParams, val windowManager: WindowManager) :
View.OnTouchListener {
private var x = 0
private var y = 0
override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
when (motionEvent.action) {
MotionEvent.ACTION_DOWN -> {
x = motionEvent.rawX.toInt()
y = motionEvent.rawY.toInt()
}
MotionEvent.ACTION_MOVE -> {
val nowX = motionEvent.rawX.toInt()
val nowY = motionEvent.rawY.toInt()
val movedX = nowX - x
val movedY = nowY - y
x = nowX
y = nowY
wl.apply {
x += movedX
y += movedY
}
//更新悬浮窗位置
windowManager.updateViewLayout(view, wl)
}
else -> {
}
}
return true
}
}
\ No newline at end of file
package com.yidianling.muse.helper
import android.content.Context
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.MediaPlayer
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.TimeUnit
import kotlin.properties.Delegates
class MediaPlayerManager private constructor() {
private var listener:OnMediaPlayerManagerListener?=null
private var mCurrentListIndex = 0
private var mAudioPaths = mutableListOf<String>()
private var mMediaId:Long? = null
private var mTime = 0L
private var mTimeOffStatus = false
private var mDisposable:Disposable? = null
private var mObservable: Observable<Long>? = null
private var mObserver: Observer<Long>? = null
fun setMediaId(mediaId:Long?){
mMediaId = mediaId
}
fun getMediaId():Long? = mMediaId
fun getTimeOff():Long = mTime
fun getTimeOffStatus():Boolean = mTimeOffStatus
fun setTimeOffStatus(timeOffStatus:Boolean){
mTimeOffStatus = timeOffStatus
}
fun setTimeOff(time:Long){
mTime = time
}
fun setAudioPath(path: String,isLoop:Boolean = false){
val attrs = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.setLegacyStreamType(AudioManager.STREAM_MUSIC)
.build()
mPath = path
mMediaPlayer?.reset()
mMediaPlayer?.setAudioAttributes(attrs)
mMediaPlayer?.setDataSource(path)
mMediaPlayer?.prepareAsync()
mMediaPlayer?.setOnPreparedListener {
listener?.onPrepared(it)
if (isLoop){
mMediaPlayer?.seekTo(0)
}
}
}
fun getMediaPlayer():MediaPlayer? = mMediaPlayer
fun getAudioPath():String? = mPath
fun isPlaying() = mMediaPlayer?.isPlaying
fun play() {
if (mMediaPlayer?.isPlaying == true) return
mMediaPlayer?.start()
}
fun pause() {
if (mMediaPlayer?.isPlaying == true) mMediaPlayer?.pause()
}
fun seekTo(position: Int) {
mMediaPlayer?.seekTo(position)
}
fun stop() {
mMediaPlayer?.stop()
}
fun release() {
mMediaPlayer?.stop()
}
fun setOnPreparedListener(listener: OnMediaPlayerManagerListener){
this.listener = listener
}
fun initRxTimeOff(time: Long) {
if (time ==null && time <=0){
mDisposable?.dispose()
}
mObservable = Observable.interval(0, 1, TimeUnit.SECONDS)
.take(time / 1000 + 1)
.map { t -> time - t * 1000 }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
mObserver = object : Observer<Long> {
override fun onSubscribe(d: Disposable) {
mDisposable = d
}
override fun onNext(t: Long) {
mTime = t
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
}
}
if (mObserver != null && mObserver is Observer<Long>) {
mObservable?.subscribe(mObserver as Observer<Long>)
}
if (mDisposable?.isDisposed == true && mObserver != null && mObserver is Observer<Long>) {
mObservable?.subscribe(mObserver as Observer<Long>)
}
}
fun dispose() {
mTime = 0
mDisposable?.dispose()
}
companion object {
private var mContext: Context by Delegates.notNull()
private var mMediaPlayer:MediaPlayer? = null
private var mPath:String? = null
@Volatile
private var instance: MediaPlayerManager? = null
fun getInstance(context: Context): MediaPlayerManager? {
return when{
instance != null -> instance
else -> synchronized(this) {
if (instance == null){
mContext = context
mMediaPlayer = MediaPlayer()
instance = MediaPlayerManager()
}
instance
}
}
}
}
interface OnMediaPlayerManagerListener{
fun onPrepared(mediaPlayer: MediaPlayer)
}
}
\ No newline at end of file
package com.yidianling.muse.helper
import android.annotation.SuppressLint
import android.content.Context
import android.os.Handler
import android.os.Message
import android.text.TextUtils
import android.util.Log
import android.view.*
import android.widget.*
import androidx.constraintlayout.widget.ConstraintLayout
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.audio.OnPlayerEventListener
import com.ydl.media.audio.model.Music
import com.ydl.media.view.PlayTypeEnum
import com.ydl.media.view.PlayerFloatHelper
import com.ydl.ydl_image.module.GlideApp
import com.ydl.ydl_image.transform.GlideRoundTransform
import com.yidianling.muse.R
import kotlinx.android.synthetic.main.layout_meditation_play_float_view.view.*
import java.util.*
import java.util.concurrent.CopyOnWriteArraySet
class MeditationFloatWindow(var mContext: Context) : FrameLayout(mContext) {
private var mTouchStartX: Float = 0.toFloat()
private var mTouchStartY: Float = 0.toFloat()
private var mCurrX: Float = 0.toFloat()
private var mCurrY: Float = 0.toFloat()
private var playState: ImageView? = null
private var mRootLayout: ConstraintLayout? = null
private var playClose: ImageView? = null
private var playHead: ImageView? = null
private var titleView: TextView? = null
private var llMeditationInfo: LinearLayout? = null
private var mTouchSlop: Int = 0
private var time: Int = 0
private var allTime: Int = 0
private var isMove: Boolean = false
private var wm: WindowManager? = null
//此wmParams为获取的全局变量,用以保存悬浮窗口的属性
var wmParams = WindowManager.LayoutParams()
private var myHandler: Handler? = null
private val UPDATE_VIEW_STATE = 1
private val UPDATE_VIEW_COMPLETE = 2
private val UPDATE_PLAY_TIME = 3//更新播放时间
private var listeners: CopyOnWriteArraySet<FloatViewPlayListener> = CopyOnWriteArraySet()
private var mStateChangeListener: OnPlayerEventListener? = null
private var playData: HashMap<String, String> = hashMapOf<String, String>()
init {
init(context)
}
fun resetWm(context: Context) {
wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
wmParams = WindowManager.LayoutParams()
}
fun resetView() {
resetAudioView()
}
@SuppressLint("ClickableViewAccessibility")
private fun init(context: Context) {
wm = getContext().getSystemService(Context.WINDOW_SERVICE) as WindowManager
mTouchSlop = (ViewConfiguration.get(getContext()).scaledTouchSlop + 8) * 3
val view = View.inflate(context, R.layout.layout_meditation_play_float_view, this)
mRootLayout = view.findViewById(R.id.csl_root_layout)
playState = view.findViewById(R.id.iv_play_status)
playHead = view.findViewById(R.id.iv_cover)
playClose = view.findViewById(R.id.iv_close)
titleView = view.findViewById(R.id.tv_title)
llMeditationInfo = view.findViewById(R.id.ll_meditation_info)
resetAudioView()
if (!TextUtils.isEmpty(AudioPlayer.get().playMusic?.coverPath)) {
GlideApp.with(context.applicationContext)
.load(AudioPlayer.get().playMusic?.coverPath)
.transform(GlideRoundTransform(context, 4))
.error(com.ydl.media.R.drawable.ico_play_float_pic)
.into(playHead!!)
}
myHandler = MyHandler()
playHead!!.setOnTouchListener { _, event ->
mCurrX = event.rawX
mCurrY = event.rawY - 25
when (event.action) {
MotionEvent.ACTION_DOWN -> {
//获取相对View的坐标,即以此View左上角为原点
mTouchStartX = event.x
mTouchStartY = event.y
}
MotionEvent.ACTION_MOVE -> {
if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop) {
updateViewPosition()
isMove = true
}
}
MotionEvent.ACTION_UP -> {
if (Math.abs(event.x - mTouchStartX) > mTouchSlop ||
Math.abs(event.y - mTouchStartY) > mTouchSlop || isMove
) {
updateViewPosition()
} else {
if (!isMove) {
if (PlayerFloatHelper.isCanClick) {
PlayerFloatHelper.startPlayingActivity(context)
}
}
}
isMove = false
mTouchStartY = 0f
mTouchStartX = mTouchStartY
}
}
true
}
titleView!!.setOnTouchListener { _, event ->
mCurrX = event.rawX
mCurrY = event.rawY - 25
when (event.action) {
MotionEvent.ACTION_DOWN -> {
//获取相对View的坐标,即以此View左上角为原点
mTouchStartX = event.x
mTouchStartY = event.y
}
MotionEvent.ACTION_MOVE -> {
if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop) {
updateViewPosition()
isMove = true
}
}
MotionEvent.ACTION_UP -> {
if (Math.abs(event.x - mTouchStartX) > mTouchSlop ||
Math.abs(event.y - mTouchStartY) > mTouchSlop || isMove
) {
updateViewPosition()
} else {
if (!isMove) {
if (PlayerFloatHelper.isCanClick) {
PlayerFloatHelper.startPlayingActivity(context)
}
}
}
isMove = false
mTouchStartY = 0f
mTouchStartX = mTouchStartY
}
}
true
}
llMeditationInfo?.setOnTouchListener { _, event ->
mCurrX = event.rawX
mCurrY = event.rawY - 25
when (event.action) {
MotionEvent.ACTION_DOWN -> {
//获取相对View的坐标,即以此View左上角为原点
mTouchStartX = event.x
mTouchStartY = event.y
}
MotionEvent.ACTION_MOVE -> {
if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop) {
updateViewPosition()
isMove = true
}
}
MotionEvent.ACTION_UP -> {
if (Math.abs(event.x - mTouchStartX) > mTouchSlop ||
Math.abs(event.y - mTouchStartY) > mTouchSlop || isMove
) {
updateViewPosition()
} else {
if (!isMove) {
if (PlayerFloatHelper.isCanClick) {
PlayerFloatHelper.startPlayingActivity(context)
}
}
}
isMove = false
mTouchStartY = 0f
mTouchStartX = mTouchStartY
}
}
true
}
playClose!!.setOnTouchListener { _, event ->
mCurrX = event.rawX
mCurrY = event.rawY - 25
when (event.action) {
MotionEvent.ACTION_DOWN -> {
//获取相对View的坐标,即以此View左上角为原点
mTouchStartX = event.x
mTouchStartY = event.y
}
MotionEvent.ACTION_MOVE -> {
if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop) {
updateViewPosition()
isMove = true
}
}
MotionEvent.ACTION_UP -> {
if (Math.abs(event.x - mTouchStartX) > mTouchSlop ||
Math.abs(event.y - mTouchStartY) > mTouchSlop || isMove
) {
updateViewPosition()
} else {
if (!isMove) {
for (listener in listeners) {
//数据重新设置回调
listener.onPauseClick()
}
this@MeditationFloatWindow.visibility = View.GONE
PlayerFloatHelper.removeView(mContext)
PlayerFloatHelper.playTempData.clear()
AudioPlayer.get().stopPlayer()
}
}
isMove = false
mTouchStartY = 0f
mTouchStartX = mTouchStartY
}
}
true
}
playState!!.setOnTouchListener { _, event ->
mCurrX = event.rawX
mCurrY = event.rawY - 25
when (event.action) {
MotionEvent.ACTION_DOWN -> {
//获取相对View的坐标,即以此View左上角为原点
mTouchStartX = event.x
mTouchStartY = event.y
}
MotionEvent.ACTION_MOVE -> {
if (Math.abs(event.x - mTouchStartX) > mTouchSlop || Math.abs(event.y - mTouchStartY) > mTouchSlop) {
updateViewPosition()
isMove = true
}
}
MotionEvent.ACTION_UP -> {
if (Math.abs(event.x - mTouchStartX) > mTouchSlop ||
Math.abs(event.y - mTouchStartY) > mTouchSlop || isMove
) {
updateViewPosition()
} else {
if (!isMove) {
if (AudioPlayer.get().isPlaying) {
playState!!.setImageResource(com.ydl.media.R.drawable.ico_yyfc_play)
AudioPlayer.get().playPause()
for (listener in listeners) {
//数据重新设置回调
listener.onPauseClick()
}
} else {
playState!!.setImageResource(com.ydl.media.R.drawable.ico_yyfc_pause)
AudioPlayer.get().playPause()
for (listener in listeners) {
//数据重新设置回调
listener.onStartClick()
}
}
}
}
isMove = false
mTouchStartY = 0f
mTouchStartX = mTouchStartY
}
}
true
}
if (mStateChangeListener == null) {
mStateChangeListener = object : OnPlayerEventListener {
override fun onComplete() {
myHandler?.sendEmptyMessage(UPDATE_VIEW_COMPLETE)
}
override fun onChange(music: Music) {
}
override fun onPlayerStart() {
}
override fun onPlayerPause() {
}
override fun onPublish(percent: Int, currentPosition: Long) {
this@MeditationFloatWindow.time = currentPosition.toInt()
myHandler?.sendEmptyMessage(UPDATE_PLAY_TIME)
}
override fun onBufferingUpdate(percent: Int) {
}
override fun onPrepared(duration: Long) {
this@MeditationFloatWindow.allTime = duration.toInt()
myHandler?.sendEmptyMessage(UPDATE_PLAY_TIME)
myHandler?.sendEmptyMessage(UPDATE_VIEW_STATE)
}
}
AudioPlayer.get().addOnPlayEventListener(mStateChangeListener!!)
}
}
private fun resetAudioView() {
if (!TextUtils.isEmpty(AudioPlayer.get().playMusic?.coverPath)) {
GlideApp.with(context.applicationContext)
.load(AudioPlayer.get().playMusic?.coverPath)
.transform(GlideRoundTransform(context, 4))
.error(com.ydl.media.R.drawable.ico_play_float_pic)
.into(playHead!!)
}
if (TextUtils.isEmpty(AudioPlayer.get().playMusic?.title)) {
if (PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_FM) {
titleView!!.text = "心灵电台"
}
if (PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_CONFIDE) {
titleView!!.text = "壹点倾诉,心灵寄语"
}
} else {
titleView!!.text = AudioPlayer.get().playMusic?.title
}
mRootLayout!!.visibility = View.VISIBLE
}
private fun getStringTime(time: Int): String {
if (time <= 0) return "00:00"
var min = time / 60000
var ss = (time - min * 60000) / 1000
var mm = "" + min
var SS = "" + ss
if (min < 10) {
mm = "0$mm"
}
if (ss < 10) {
SS = "0$ss"
}
return "$mm:$SS"
}
private fun updatePlayTime() {
}
override fun onTouchEvent(event: MotionEvent): Boolean {
//获取相对屏幕的坐标,即以屏幕左上角为原点
mCurrX = event.rawX
mCurrY = event.rawY - 25
Log.i("currP", "currX$mCurrX====currY$mCurrY")
when (event.action) {
MotionEvent.ACTION_DOWN -> {
//获取相对View的坐标,即以此View左上角为原点
mTouchStartX = event.x
mTouchStartY = event.y
}
MotionEvent.ACTION_MOVE -> updateViewPosition()
MotionEvent.ACTION_UP -> {
updateViewPosition()
mTouchStartY = 0f
mTouchStartX = mTouchStartY
}
}
return true
}
private fun updateViewPosition() {
//更新浮动窗口位置参数
wmParams.x = (mCurrX - mTouchStartX).toInt()
wmParams.y = (mCurrY - mTouchStartY).toInt()
wm!!.updateViewLayout(this, wmParams)
}
fun updatePlayState() {
if (AudioPlayer.get().isPlaying) {
playState!!.setImageResource(com.ydl.media.R.drawable.ico_yyfc_pause)
} else {
playState!!.setImageResource(com.ydl.media.R.drawable.ico_yyfc_play)
for (listener in listeners) {
listener.onPauseClick()
}
}
}
fun setPlayingState() {
playState!!.setImageResource(com.ydl.media.R.drawable.ico_yyfc_pause)
resetAudioView()
}
fun onDestroy() {
listeners.clear()
mStateChangeListener?.let { AudioPlayer.get().removeOnPlayEventListener(it) }
}
fun addFloatClickListener(floatClickListener: FloatViewPlayListener) {
listeners.add(floatClickListener)
}
fun removeFloatClickListener(floatClickListener: FloatViewPlayListener) {
listeners.remove(floatClickListener)
}
interface FloatViewPlayListener {
fun onPauseClick()
fun onStartClick()
fun onPlayFinish()
}
internal inner class MyHandler : Handler() {
override fun handleMessage(msg: Message) {
when (msg.what) {
UPDATE_VIEW_STATE -> updatePlayState()
UPDATE_VIEW_COMPLETE -> {
updatePlayState()
for (listener in listeners) {
//数据重新设置回调
listener.onPlayFinish()
}
}
UPDATE_PLAY_TIME -> {
updatePlayTime()
}
}
}
}
}
package com.yidianling.muse.helper
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.graphics.PixelFormat
import android.graphics.Point
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import androidx.core.view.ViewCompat
import com.alibaba.android.arouter.launcher.ARouter
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.view.PlayTypeEnum
import com.yidianling.common.tools.RxImageTool
class MeditationPlayWindowController {
companion object {
@SuppressLint("StaticFieldLeak")
private var mPlayerFloatView: MeditationFloatWindow? = null
//已添加悬浮窗页面全路径名
private var showingPageName: String? = null
private var wm: WindowManager? = null
var isCanClick = true
var playingType = PlayTypeEnum.PLAY_TYPE_NONE
var playTempData = hashMapOf<String, String>()
/**
* 如果有音频正在播放则显示
*/
fun showIfPlaying(context: Context) {
if (MediaPlayerManager.getInstance(context)?.isPlaying() == true) {
show(context)
mPlayerFloatView?.updatePlayState()
} else {
hide()
}
}
/**
* 显示悬浮控件
*/
fun show(
context: Context,
playTypeEnum: PlayTypeEnum = PlayTypeEnum.PLAY_TYPE_NONE,
playData: HashMap<String, String> = hashMapOf<String, String>()
) {
playingType = playTypeEnum
if (playData.size > 0) {
this.playTempData.putAll(playData)
}
if (mPlayerFloatView == null) {
mPlayerFloatView = MeditationFloatWindow(context)
mPlayerFloatView?.addFloatClickListener(object :
MeditationFloatWindow.FloatViewPlayListener {
override fun onPauseClick() {
}
override fun onStartClick() {
}
override fun onPlayFinish() {
}
})
}
if (showingPageName != context::class.qualifiedName) {
mPlayerFloatView?.resetWm(context)
addFloatToWm(context)
}
mPlayerFloatView?.resetView()
mPlayerFloatView?.visibility = View.VISIBLE
mPlayerFloatView?.setPlayingState()
}
fun hide() {
mPlayerFloatView?.visibility = View.GONE
}
fun addClickListener(listener: MeditationFloatWindow.FloatViewPlayListener) {
mPlayerFloatView?.addFloatClickListener(listener)
}
fun removeClickListener(listener: MeditationFloatWindow.FloatViewPlayListener) {
mPlayerFloatView?.removeFloatClickListener(listener)
}
fun isShow(context: Context): Boolean {
return !TextUtils.isEmpty(showingPageName) && showingPageName == context::class.qualifiedName && mPlayerFloatView?.visibility == View.VISIBLE
}
fun removeView(context: Context) {
if (TextUtils.isEmpty(showingPageName) || showingPageName != context::class.qualifiedName) {
return
}
mPlayerFloatView?.visibility = View.GONE
wm?.removeViewImmediate(mPlayerFloatView)
showingPageName = ""
wm = null
}
fun onDestroy() {
if (mPlayerFloatView != null) {
if (!TextUtils.isEmpty(showingPageName)) {
wm?.removeViewImmediate(mPlayerFloatView)
showingPageName = ""
}
mPlayerFloatView?.onDestroy()
mPlayerFloatView?.removeAllViews()
}
}
fun setPlayingState(context: Context) {
show(context)
mPlayerFloatView?.setPlayingState()
}
fun updatePlayState() {
mPlayerFloatView?.updatePlayState()
}
private fun addFloatToWm(context: Context) {
if (wm != null && !TextUtils.isEmpty(showingPageName)) {
if (ViewCompat.isAttachedToWindow(mPlayerFloatView!!)) {
// if (context is Activity && !(context.isFinishing)){
// wm?.removeViewImmediate(mPlayerFloatView)
// }
wm?.removeViewImmediate(mPlayerFloatView)
}
wm = null
}
//获取WindowManager
wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
//设置LayoutParams(全局变量)相关参数
val wmParams = mPlayerFloatView?.wmParams
wmParams?.type = WindowManager.LayoutParams.TYPE_APPLICATION //设置window type
wmParams?.format = PixelFormat.RGBA_8888 //设置图片格式,效果为背景透明
//设置Window flag
wmParams?.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
wmParams?.gravity = Gravity.LEFT or Gravity.TOP //调整悬浮窗口至左上角
//以屏幕左上角为原点,设置x、y初始值
val size = Point()
wm?.defaultDisplay?.getSize(size)
wmParams?.x = 0
wmParams?.y = size.y * 5 / 6
//设置悬浮窗口长宽数据
wmParams?.width = WindowManager.LayoutParams.MATCH_PARENT
wmParams?.height = RxImageTool.dp2px(56f)
//显示myFloatView图像
wm?.addView(mPlayerFloatView, wmParams)
showingPageName = context::class.qualifiedName!!
}
/**
* 打开播放中的页面详情
*/
fun startPlayingActivity(context: Context?, fullScreen: Int = 0) {
if (playingType == PlayTypeEnum.PLAY_TYPE_FM) {
//FM播放页
startFMPlayActivity(context)
} else if (playingType == PlayTypeEnum.PLAY_TYPE_COURSE) {
var url = AudioPlayer.get().playMusic?.path
//课程播放页
startCoursePlayActivity(context, 1, fullScreen, url, true)
}
}
fun startCoursePlayActivity(
context: Context?,
from: Int,
fullScreen: Int = 0,
coursePlayUrl: String? = "",
isFromFloatView: Boolean = false
) {
ARouter.getInstance()
.build("/course/play")
.withInt("course_id", playTempData["course_id"]?.toInt() ?: 0)
.withInt("course_type", 0)
.withString("coursePlayUrl", coursePlayUrl)
.withInt("from", from)
.withBoolean("isFromFloatView", isFromFloatView)
.withInt("fullScreen", fullScreen)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.navigation()
}
fun startFMPlayActivity(context: Context?) {
val bundle = Bundle()
bundle.putInt("id", playTempData["fmId"]?.toInt() ?: 0)
ARouter.getInstance().build("/fm/detail")
.withBundle("bundle", bundle)
.navigation()
}
/**
* 获取FM播放Id
*/
fun getFmId(): Int {
return playTempData["fmId"]?.toInt() ?: 0
}
}
}
\ No newline at end of file
package com.yidianling.home.http
import com.google.gson.Gson
import com.ydl.ydlcommon.data.http.BaseAPIResponse
import com.ydl.ydlcommon.data.http.BaseResponse
import com.ydl.ydlcommon.data.http.RxUtils
import com.ydl.ydlnet.YDLHttpUtils
import com.yidianling.muse.bean.MuseModuleBean
import com.yidianling.muse.bean.*
import com.yidianling.muse.http.MusePagerApi
import io.reactivex.Observable
import okhttp3.MediaType
import okhttp3.RequestBody
/**
* @author jiucheng
......@@ -37,4 +43,67 @@ class MuseHttp {
fun newMuseRequest(): Observable<BaseAPIResponse<MuseModuleBean>> {
return getMusePagerApi().getMuseData()
}
fun getPureMusicPlayDetail(
meditionType: Int,
meditationId: Long
): Observable<BaseAPIResponse<MeditationPlayModuleBean>> {
return getMusePagerApi().getPureMusicPlayDetail(
meditionType = meditionType,
meditationId = meditationId
)
}
fun getMeditationPlayDetail(
meditionType: Int,
mediaId: Long,
meditationId: Long
): Observable<BaseAPIResponse<MeditationPlayModuleBean>> {
return getMusePagerApi().getMeditationPlayDetail(
meditionType = meditionType,
mediaId = mediaId,
meditationId = meditationId
)
}
fun collectMeditation(
meditationId: Long,
mediaId: Long,
status: Int,
businessType: Int
): Observable<BaseAPIResponse<CollectResultModule>> {
val params = MeditationCollectRequestModule(
meditationId = meditationId,
mediaId = mediaId,
status = status,
businessType = businessType
)
var str = Gson().toJson(params)
val body = RequestBody.create(
MediaType.parse("application/json; charset=utf-8"),
str
) as RequestBody
return RxUtils.mapObservable(params).flatMap { getMusePagerApi().collectMeditation(body) }
}
fun postMeditationPlayRecord(
meditationId: Int,
isQuit: Int,
mediaId: Long,
playTime: Int, isComplete: Int
): Observable<BaseAPIResponse<MeditationPlayRecordResponseModule>> {
val params = MeditationPlayRecordRequestModule(
meditationId = meditationId,
isQuit = isQuit, mediaId = mediaId, playTime = playTime, isComplete = isComplete
)
var str = Gson().toJson(params)
val body = RequestBody.create(
MediaType.parse("application/json; charset=utf-8"),
str
) as RequestBody
return RxUtils.mapObservable(params)
.flatMap { getMusePagerApi().meditationPlayRecord(body) }
}
}
\ No newline at end of file
package com.yidianling.home.http
package com.yidianling.muse.http
import com.ydl.ydlcommon.base.config.YDL_DOMAIN
import com.ydl.ydlcommon.base.config.YDL_DOMAIN_JAVA
import com.ydl.ydlcommon.data.http.BaseAPIResponse
import com.yidianling.muse.bean.MuseModuleBean
import com.ydl.ydlcommon.data.http.BaseResponse
import com.yidianling.muse.bean.*
import io.reactivex.Observable
import retrofit2.http.GET
import retrofit2.http.Headers
import okhttp3.RequestBody
import retrofit2.http.*
/**
* @author jiucheng
......@@ -21,4 +22,44 @@ interface MusePagerApi {
@GET("meditation/meditation/list")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA)
fun getMuseData(): Observable<BaseAPIResponse<MuseModuleBean>>
/**
* 声音播放详情页
*/
@GET("cms/meditation/meditationPlayDetail")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA)
fun getPureMusicPlayDetail(
@Query("meditionType") meditionType: Int = 0,
@Query("meditationId") meditationId: Long
): Observable<BaseAPIResponse<MeditationPlayModuleBean>>
/**
* 冥想播放详情页
*/
@GET("cms/meditation/meditationPlayDetail")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA)
fun getMeditationPlayDetail(
@Query("meditionType") meditionType: Int = 1,
@Query("mediaId") mediaId: Long,
@Query("meditationId") meditationId: Long
): Observable<BaseAPIResponse<MeditationPlayModuleBean>>
/**
* 收藏和取消收藏
*/
@POST("cms/meditation/collect")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA,"Content-Type:application/json")
fun collectMeditation(@Body body: RequestBody): Observable<BaseAPIResponse<CollectResultModule>>
/**
* 冥想播放记录
*/
@POST("cms/meditation/playRecord")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA,"Content-Type:application/json")
fun meditationPlayRecord(@Body body: RequestBody
): Observable<BaseAPIResponse<MeditationPlayRecordResponseModule>>
}
\ No newline at end of file
package com.yidianling.muse.service
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.graphics.PixelFormat
import android.media.MediaPlayer
import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.util.DisplayMetrics
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.WindowManager
import android.widget.ImageView
import android.widget.TextView
import androidx.core.app.NotificationCompat
import com.bumptech.glide.Glide
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.yidianling.home.http.MuseHttp
import com.yidianling.muse.R
import com.yidianling.muse.activity.PlayMeditationActivity
import com.yidianling.muse.bean.MeditationPlayModuleBean
import com.yidianling.muse.constants.MuseBIConstants
import com.yidianling.muse.event.MeditationFloatEvent
import com.yidianling.muse.helper.FloatViewTouchListener
import com.yidianling.muse.helper.MediaPlayerManager
import com.yidianling.muse.utils.MediaPlayerTimeUtil
import de.greenrobot.event.EventBus
import io.feeeei.circleseekbar.CircleSeekBar
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_play_meditation.*
import kotlinx.android.synthetic.main.player_control_view.*
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt
class MeditationWindowService : Service() {
private lateinit var mWindowManager: WindowManager
private var floatRootView: View? = null
private var ivClose: ImageView? = null
private var ivCover: ImageView? = null
private var tvTitle: TextView? = null
private var ivProgress: CircleSeekBar? = null
private var ivPlayOrPause: ImageView? = null
private var mMediaPlayer: MediaPlayer? = null
private var mTimer = Timer()
private var mCurrentMeditation: MeditationPlayModuleBean.MeditationDetail? = null
private var mMeditations = mutableListOf<MeditationPlayModuleBean.MeditationDetail>()
private var windowIsShow = false
private var mDisposable: Disposable? = null
private var mObservable: Observable<Long>? = null
private var mObserver: Observer<Long>? = null
private var currentMediaId:Long? = null
inner class MeditationBinder : Binder() {
val service: MeditationWindowService
get() = this@MeditationWindowService
}
override fun onCreate() {
super.onCreate()
EventBus.getDefault().register(this)
}
private fun showWindow() {
mWindowManager = getSystemService(WINDOW_SERVICE) as WindowManager
val outMetrics = DisplayMetrics()
mWindowManager.defaultDisplay.getMetrics(outMetrics)
var layoutParams = WindowManager.LayoutParams().apply {
type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
WindowManager.LayoutParams.TYPE_PHONE
}
flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
format = PixelFormat.RGBA_8888
width = outMetrics.widthPixels - dp2px(32F)
height = WRAP_CONTENT
gravity = Gravity.LEFT or Gravity.TOP
x = outMetrics.widthPixels /2 - width / 2
y = outMetrics.heightPixels - dp2px(140F)
}
floatRootView =
LayoutInflater.from(this).inflate(R.layout.layout_meditation_play_float_view, null)
ivClose = floatRootView?.findViewById(R.id.iv_close)
ivCover = floatRootView?.findViewById(R.id.iv_cover)
tvTitle = floatRootView?.findViewById(R.id.tv_title)
ivProgress = floatRootView?.findViewById(R.id.progress_bar)
ivPlayOrPause = floatRootView?.findViewById(R.id.iv_play_status)
floatRootView?.setOnTouchListener(FloatViewTouchListener(layoutParams, mWindowManager))
mWindowManager.addView(floatRootView, layoutParams)
windowIsShow = true
}
fun onEventMainThread(event: Any) {
if (event is com.ydl.ydlcommon.event.MeditationFloatEvent){
if (event.show!=null && !event.show) {
if (event.stop == true){
try {
mMediaPlayer?.stop()
}catch (e:Exception){
}
hideFloatWindow()
}
hideFloatWindow()
}
}
if (event is MeditationFloatEvent){
if (event.time!=null){
if (event.time>0){
initRxTimeOff(event.time)
}else{
mDisposable?.dispose()
}
}else{
if (event.show!=null && !event.show) {
if (event.stop == true){
try {
mMediaPlayer?.stop()
}catch (e:Exception){
}
hideFloatWindow()
}
hideFloatWindow()
}
if (event.show!=null && event.show && event.meditation != null) {
if (!windowIsShow) {
showWindow()
}
updateFloatView(event.meditation)
}
}
}
}
private fun updateFloatView(meditation: MeditationPlayModuleBean.MeditationDetail) {
currentMediaId = meditation.mediaId
MediaPlayerManager.getInstance(this)?.setMediaId(currentMediaId)
mMediaPlayer = MediaPlayerManager.getInstance(this)?.getMediaPlayer()
tvTitle?.setOnClickListener {
//悬浮窗暂停点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLICK,"")
val intent = Intent(this, PlayMeditationActivity::class.java)
intent.putExtra("MEDIA_ID", meditation.mediaId)
intent.putExtra("MEDITATION_ID", meditation.meditationId)
intent.putExtra("MEDITATION_TYPE", meditation.meditationType)
intent.putExtra("MEDIA_COVER_URL", meditation.coverImageUrl)
intent.putExtra("MEDIA_URL", meditation.mediaUrl)
intent.flags = FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
ivCover?.setOnClickListener {
//悬浮窗暂停点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLICK,"")
val intent = Intent(this, PlayMeditationActivity::class.java)
intent.putExtra("MEDIA_ID", meditation.mediaId)
intent.putExtra("MEDITATION_ID", meditation.meditationId)
intent.putExtra("MEDITATION_TYPE", meditation.meditationType)
intent.putExtra("MEDIA_COVER_URL", meditation.coverImageUrl)
intent.putExtra("MEDIA_URL", meditation.mediaUrl)
intent.flags = FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
if (mMediaPlayer?.isPlaying == true) {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_play)
} else {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
}
ivProgress?.maxProcess = mMediaPlayer?.duration ?: 0
ivProgress?.curProcess = mMediaPlayer?.currentPosition ?: 0
Glide.with(floatRootView!!)
.load(meditation.coverImageUrl)
.into(ivCover!!)
tvTitle?.text = meditation.title
ivPlayOrPause?.setOnClickListener {
if (mMediaPlayer?.isPlaying == true) {
//悬浮窗暂停点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_PAUSE_CLICK,"")
MediaPlayerManager.getInstance(this)?.pause()
if (meditation.meditationId != null && meditation.mediaId != null) {
MuseHttp.getInstance().postMeditationPlayRecord(
meditationId = meditation.meditationId!!.toInt(),
isQuit = 1, mediaId = meditation.mediaId!!,
playTime = (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0,
isComplete = 0
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
}, {
object : ThrowableConsumer() {
override fun accept(msg: String) {
}
}
})
}
} else {
//悬浮窗播放点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_PLAY_CLICK,"")
MediaPlayerManager.getInstance(this)?.play()
}
if (mMediaPlayer?.isPlaying == true) {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_play)
} else {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
}
}
mTimer.schedule(object : TimerTask() {
override fun run() {
ivProgress?.curProcess = mMediaPlayer?.currentPosition ?: 0
}
}, 0, 50)
mMediaPlayer?.setOnCompletionListener {
val duration = meditation?.duration?.toInt()?:0
val currentDuration = (mMediaPlayer?.currentPosition?:0)/1000
if(meditation.mediaId!=null && meditation.meditationId!=null){
val playTime = (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0
if(duration == currentDuration){
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = meditation.meditationId.toInt(),
mediaId = meditation.mediaId,
isQuit = 0,
playTime = playTime,
isComplete = 1
)
}
}
if (mMediaPlayer?.isPlaying == true) {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_play)
} else {
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
}
}
ivClose?.setOnClickListener {
//悬浮窗关闭点击事件
ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLOSE_CLICK,"")
if(meditation.mediaId!=null && meditation.meditationId!=null){
val playTime = (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0
MediaPlayerTimeUtil.uploadPlayRecord(
meditationId = meditation.meditationId.toInt(),
mediaId = meditation.mediaId,
isQuit = 0,
playTime = playTime,
isComplete = 0
)
}
MediaPlayerManager.getInstance(this)?.stop()
hideFloatWindow()
}
}
private fun hideFloatWindow() {
if (floatRootView != null && floatRootView?.windowToken != null) {
if (mWindowManager != null) {
windowIsShow = false
mWindowManager.removeViewImmediate(floatRootView)
}
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel("壹点灵","play",NotificationManager.IMPORTANCE_HIGH)
manager.createNotificationChannel(channel)
val notification = NotificationCompat.Builder(this,"壹点灵").build()
startForeground(1,notification)
startForegroundService(intent)
}else{
startService(intent)
}
}
return super.onStartCommand(intent, flags, startId)
}
override fun startForegroundService(service: Intent?): ComponentName? {
return super.startForegroundService(service)
}
override fun onDestroy() {
super.onDestroy()
if (EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this)
}
mDisposable?.dispose()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
stopForeground(true)
}
}
override fun onBind(intent: Intent?): IBinder? {
return MeditationBinder()
}
private fun dp2px(dp: Float): Int {
val scale = resources.displayMetrics.density
return (dp * scale + 0.5f).toInt()
}
private fun initRxTimeOff(time: Long) {
mObservable = Observable.interval(0, 1, TimeUnit.SECONDS)
.take(time / 1000 + 1)
.map { t -> time - t * 1000 }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
mObserver = object : Observer<Long> {
override fun onSubscribe(d: Disposable) {
mDisposable = d
}
override fun onNext(t: Long) {
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
if (mMediaPlayer?.isPlaying == true) {
mMediaPlayer?.stop()
ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
}
hideFloatWindow()
}
}
if (mObserver != null && mObserver is Observer<Long>) {
mObservable?.subscribe(mObserver as Observer<Long>)
}
if (mDisposable?.isDisposed == true && mObserver != null && mObserver is Observer<Long>) {
mObservable?.subscribe(mObserver as Observer<Long>)
}
}
}
\ No newline at end of file
package com.yidianling.muse.utils
import android.content.Context
import android.util.DisplayMetrics
class DisplayUtil {
companion object{
fun dp2px(displayMetrics: DisplayMetrics,dpValue:Float):Int{
val scale = displayMetrics.density
return (dpValue*scale + 0.5F).toInt()
}
}
}
\ No newline at end of file
package com.yidianling.muse.utils
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.yidianling.home.http.MuseHttp
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
class MediaPlayerTimeUtil {
companion object{
fun calculateTime(time:Int):String?{
var minute = 0
var second = 0
if (time>60){
minute = time / 60
second = time % 60
return if (minute in 0..9){
if (second in 0..9){
"0$minute:0$second"
}else{
"0$minute:$second"
}
}else{
if (second in 0..9){
"$minute:0$second"
}else{
"$minute:$second"
}
}
}else if (time<60){
second = time
return if (second in 0..9){
"00:0$second"
}else{
"00:$second"
}
}
return null
}
fun formatTimeOff(finishTime:Long):String{
var totalTime = (finishTime / 1000).toInt() //秒
var minute = 0
var second = 0
if (60 <= totalTime) {
minute = totalTime / 60
totalTime -= 60 * minute
}
if (0 <= totalTime) {
second = totalTime
}
val sb = StringBuilder()
if (minute < 10) {
sb.append("0").append(minute).append(":")
} else {
sb.append(minute).append(":")
}
if (second < 10) {
sb.append("0").append(second)
} else {
sb.append(second)
}
return sb.toString()
}
fun uploadPlayRecord(meditationId:Int?,mediaId:Long?,
isQuit:Int,playTime:Int,isComplete:Int){
if (meditationId != null && mediaId != null) {
MuseHttp.getInstance().postMeditationPlayRecord(
meditationId = meditationId!!.toInt(),
isQuit = isQuit, mediaId = mediaId!!,
playTime = playTime,
isComplete = isComplete
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
}, {
object : ThrowableConsumer() {
override fun accept(msg: String) {
}
}
})
}
}
}
}
\ No newline at end of file
package com.yidianling.muse.utils
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.Settings
object MeditationFloatPermissionUtil {
const val REQUEST_FLOAT_CODE=1001
private fun commonROMPermissionCheck(context: Context?):Boolean {
var result = true
if (Build.VERSION.SDK_INT >= 23){
try {
val clazz:Class<*> = Settings::class.java
val canDrawOverlays = clazz.getDeclaredMethod("canDrawOverlays",Context::class.java)
result = canDrawOverlays.invoke(null, context) as Boolean
}catch (e:Exception){
}
}
return result
}
fun checkSuspendedWindowPermission(context: Activity,block:() -> Unit){
if(commonROMPermissionCheck(context)){
block
}else{
context.startActivityForResult(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION).apply {
data = Uri.parse("package:${context.packageName}")
}, REQUEST_FLOAT_CODE)
}
}
}
\ No newline at end of file
package com.yidianling.muse.utils
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.os.Environment
import android.provider.MediaStore
import android.view.View
import com.yidianling.common.tools.ToastUtil
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.*
import kotlin.properties.Delegates
class ShareMeditationUtil {
companion object {
fun saveImageToLocal(view: View){
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(Date())
val fileName = "IMG_$timeStamp"
val bitmap = saveViewBitmapToAlbum(view,fileName,true)
}
private fun saveViewBitmapToAlbum(view: View, name: String, isPrompt: Boolean):Bitmap?{
view.isDrawingCacheEnabled = false
view.isDrawingCacheEnabled = true
view.measure(view.measuredWidth,view.measuredHeight)
try {
val bitmap = view.drawingCache
return saveBitmapToAlbum(view.context,bitmap,name, isPrompt)
}catch (e:Exception){
}
return null
}
private fun saveBitmapToAlbum(context: Context, bitmap: Bitmap, name:String, isPrompt:Boolean):Bitmap?{
var fileName by Delegates.notNull<String>()
val galleryPath = Environment.getExternalStorageDirectory().toString()+File.separator +
Environment.DIRECTORY_DCIM + File.separator + "Camera" + File.separator
var file:File?=null
var outStream:FileOutputStream?=null
try {
file = File(galleryPath, "$name.png")
fileName = file.toString()
outStream = FileOutputStream(fileName)
bitmap.compress(Bitmap.CompressFormat.PNG,90,outStream)
}catch (e:Exception){
}finally {
try {
outStream?.close()
}catch (e:IOException){
}
}
MediaStore.Images.Media.insertImage(context.contentResolver,bitmap,fileName,null)
val intent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
val uri = Uri.fromFile(file)
intent.data = uri
context.sendBroadcast(intent)
if (isPrompt){
ToastUtil.toastShort(if (bitmap!=null) "已保存" else "保存失败")
}
return bitmap
}
}
}
\ No newline at end of file
package com.yidianling.muse.widget
import android.os.Bundle
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
class PureMusicListBottomDialog():BottomSheetDialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}
\ No newline at end of file
package com.yidianling.muse.widget
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.TextView
import androidx.fragment.app.DialogFragment
import com.yidianling.muse.R
import com.yidianling.muse.utils.DisplayUtil
class QuitMeditationDialog : DialogFragment() {
private var tvQuit: TextView? = null
private var tvCancel: TextView? = null
private var mListener:ClickListener?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.share_meditation_dialog)
}
override fun onStart() {
super.onStart()
val displayMetrics = DisplayMetrics()
activity?.windowManager?.defaultDisplay?.getMetrics(displayMetrics)
val window = dialog?.window
window?.setGravity(Gravity.CENTER)
window?.setLayout(DisplayUtil.dp2px(displayMetrics,300F), WRAP_CONTENT)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.layout_quit_meditation, container)
initView(view)
return view
}
private fun initView(view: View?) {
tvQuit = view?.findViewById(R.id.tv_sure_quit)
tvCancel = view?.findViewById(R.id.tv_cancel_quit)
tvQuit?.setOnClickListener {
mListener?.quit()
dismiss()
}
tvCancel?.setOnClickListener {
dismiss()
}
}
fun setListener(listener: ClickListener):QuitMeditationDialog{
mListener = listener
return this
}
interface ClickListener{
fun quit() {}
}
companion object {
const val TAG = "QuitMeditationDialog"
fun newInstance(): QuitMeditationDialog {
val args = Bundle()
val fragment = QuitMeditationDialog()
fragment.arguments = args
return fragment
}
}
}
\ No newline at end of file
package com.yidianling.muse.widget
import android.app.Activity
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.fragment.app.DialogFragment
import com.bumptech.glide.Glide
import com.umeng.socialize.bean.SHARE_MEDIA
import com.ydl.ydlcommon.actions.share.ShareUtils
import com.yidianling.muse.R
import com.yidianling.muse.utils.ShareMeditationUtil
import kotlinx.android.synthetic.main.layout_share_play_meditation.*
class ShareMeditationDialog : DialogFragment() {
private var ivSharePicture: ImageView? = null
private var tvShareContent: TextView? = null
private var llWeChat: LinearLayout? = null
private var llCircleOfFriends: LinearLayout? = null
private var llSave: LinearLayout? = null
private var llQQZone: LinearLayout? = null
private var llQQFriend: LinearLayout? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.share_meditation_dialog)
}
override fun onStart() {
super.onStart()
val displayMetrics = DisplayMetrics()
activity?.windowManager?.defaultDisplay?.getMetrics(displayMetrics)
val window = dialog?.window
window?.setLayout(MATCH_PARENT, MATCH_PARENT)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.layout_share_meditation_dialog, container)
initView(view)
return view
}
private fun initView(view: View?) {
val shareImageUrl = arguments?.getString(KEY_SHARE_IMAGE_URL)?:""
val shareTitle = arguments?.getString(KEY_SHARE_TITLE)?:""
val shareContent = arguments?.getString(KEY_SHARE_CONTENT)?:""
val shareUrl = arguments?.getString(KEY_SHARE_URL)?:""
ivSharePicture = view?.findViewById(R.id.iv_share_picture)
tvShareContent = view?.findViewById(R.id.tv_share_content)
if (view != null && ivSharePicture != null) {
Glide.with(view.context)
.load(shareImageUrl)
.into(ivSharePicture!!)
}
llWeChat = view?.findViewById(R.id.ll_wechat_friend)
llCircleOfFriends = view?.findViewById(R.id.ll_wechat_circle_of_friends)
llSave = view?.findViewById(R.id.ll_save_picture)
llQQZone = view?.findViewById(R.id.ll_qq_zone)
llQQFriend = view?.findViewById(R.id.ll_qq_friend)
llWeChat?.setOnClickListener {
ShareUtils.shareTo(
SHARE_MEDIA.WEIXIN,
activity as Activity,
shareTitle,
shareUrl,
shareContent,
shareImageUrl
)
dismiss()
}
llCircleOfFriends?.setOnClickListener {
ShareUtils.shareTo(
SHARE_MEDIA.WEIXIN_CIRCLE,
activity as Activity,
shareTitle,
shareUrl,
shareContent,
shareImageUrl
)
dismiss()
}
llSave?.setOnClickListener {
ShareMeditationUtil.saveImageToLocal(csl_layout_top)
dismiss()
}
llQQZone?.setOnClickListener {
ShareUtils.shareTo(
SHARE_MEDIA.QZONE,
activity as Activity,
shareTitle,
shareUrl,
shareContent,
shareImageUrl
)
dismiss()
}
llQQFriend?.setOnClickListener {
ShareUtils.shareTo(
SHARE_MEDIA.QQ,
activity as Activity,
shareTitle,
shareUrl,
shareContent,
shareImageUrl
)
dismiss()
}
view?.findViewById<TextView>(R.id.tv_cancel_share)?.setOnClickListener {
dismiss()
}
}
companion object {
const val TAG = "ShareMeditationDialog"
private const val KEY_SHARE_TITLE = "key_share_title"
private const val KEY_SHARE_URL = "key_share_url"
private const val KEY_SHARE_CONTENT = "key_share_content"
private const val KEY_SHARE_IMAGE_URL = "key_share_image_url"
fun newInstance(shareTitle:String,shareUrl:String,shareContent:String,shareImageUrl: String): ShareMeditationDialog {
val args = Bundle()
args.putString(KEY_SHARE_TITLE, shareTitle)
args.putString(KEY_SHARE_CONTENT, shareContent)
args.putString(KEY_SHARE_URL, shareUrl)
args.putString(KEY_SHARE_IMAGE_URL, shareImageUrl)
val fragment = ShareMeditationDialog()
fragment.arguments = args
return fragment
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:interpolator="@android:anim/decelerate_interpolator">
<translate
android:fromYDelta="100%"
android:toYDelta="0%" />
<alpha
android:fromAlpha="0"
android:toAlpha="1"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:interpolator="@android:anim/accelerate_interpolator">
<translate
android:fromYDelta="0%"
android:toYDelta="100%" />
<alpha
android:fromAlpha="1"
android:toAlpha="0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="8dp"/>
<stroke android:width="1dp" android:color="#FFFFFFFF"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="12dp" />
<solid android:color="#CC000000" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="18dp"/>
<stroke android:color="#FFE8E8E8" android:width="0.5dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="8dp"/>
<solid android:color="@color/white"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="12dp"/>
<solid android:color="#33E0E0E0"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFFFF"/>
<corners android:radius="8dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFFFF"/>
<corners android:radius="20dp"/>
</shape>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="19dp"
android:viewportWidth="18"
android:viewportHeight="19">
<path
android:pathData="M9,18.1384C4.05,18.1384 0,14.1837 0,9.3501C0,7.2629 0.7875,5.1757 2.25,3.5279C2.7,3.0885 3.375,2.9787 3.825,3.4181C4.275,3.8575 4.3875,4.5166 3.9375,4.956C2.8125,6.1644 2.25,7.7023 2.25,9.3501C2.25,12.9753 5.2875,15.9413 9,15.9413C12.7125,15.9413 15.75,12.9753 15.75,9.3501C15.75,7.7023 15.1875,6.1644 14.0625,4.956C13.6125,4.5166 13.725,3.8575 14.175,3.4181C14.625,2.9787 15.3,3.0885 15.75,3.5279C17.2125,5.1757 18,7.1531 18,9.3501C18,14.1837 13.95,18.1384 9,18.1384Z"
android:strokeAlpha="0.80471075"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillAlpha="0.80471075"/>
<path
android:pathData="M10.3477,8.5714C10.3477,9.2857 9.8477,10 9.0977,10C8.3477,10 7.8477,9.4286 7.8477,8.5714L7.8477,1.4286C7.8477,0.7143 8.3477,0 9.0977,0C9.7227,0 10.3477,0.5714 10.3477,1.4286C10.3477,3.6696 10.3477,5.3503 10.3477,6.4708C10.3477,6.9376 10.3477,7.6378 10.3477,8.5714Z"
android:strokeAlpha="0.80471075"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillAlpha="0.80471075"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="19dp"
android:viewportWidth="18"
android:viewportHeight="19">
<path
android:pathData="M9,18.138C4.05,18.138 0,14.184 0,9.35C0,7.263 0.788,5.176 2.25,3.528C2.7,3.089 3.375,2.979 3.825,3.418C4.275,3.857 4.387,4.517 3.938,4.956C2.813,6.164 2.25,7.702 2.25,9.35C2.25,12.975 5.287,15.941 9,15.941C12.712,15.941 15.75,12.975 15.75,9.35C15.75,7.702 15.188,6.164 14.063,4.956C13.613,4.517 13.725,3.857 14.175,3.418C14.625,2.979 15.3,3.089 15.75,3.528C17.212,5.176 18,7.153 18,9.35C18,14.184 13.95,18.138 9,18.138Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M10.348,8.571C10.348,9.286 9.848,10 9.098,10C8.348,10 7.848,9.429 7.848,8.571L7.848,1.429C7.848,0.714 8.348,0 9.098,0C9.723,0 10.348,0.571 10.348,1.429C10.348,3.67 10.348,5.35 10.348,6.471C10.348,6.938 10.348,7.638 10.348,8.571Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M24.084,4.5C20.8017,4.5 18.4505,7.4335 17.4372,8.985C16.4228,7.4335 14.0727,4.5 10.7905,4.5C6.0805,4.5 2.25,8.7097 2.25,13.8835C2.25,16.3028 3.9045,19.7712 5.9129,21.5863C8.6912,25.1267 16.5018,31.5 17.466,31.5C18.4473,31.5 26.0903,25.2506 28.9188,21.6288C30.9625,19.7818 32.625,16.3087 32.625,13.8835C32.625,8.7096 28.7938,4.5 24.084,4.5"
android:strokeWidth="1"
android:fillColor="#FF675B"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="8dp"
android:height="9dp"
android:viewportWidth="8"
android:viewportHeight="9">
<path
android:pathData="M6.64877,5.7528L1.82138,8.7257C1.46481,8.94528 0.99774,8.83422 0.77811,8.47766C0.7045,8.35811 0.66553,8.22046 0.66553,8.08006L0.66553,0.84302C0.66553,0.42426 1.005,0.08478 1.42377,0.08478C1.56418,0.08478 1.70181,0.12375 1.82138,0.19738L6.64877,3.17028C7.36191,3.60946 7.58401,4.54359 7.14481,5.25674C7.02051,5.4586 6.85062,5.62849 6.64877,5.7528L6.64877,5.7528Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="9dp"
android:height="9dp"
android:viewportWidth="9"
android:viewportHeight="9">
<path
android:pathData="M1.97559,0.16724C2.66594,0.16724 3.22559,0.72688 3.22559,1.41724L3.22559,6.91724C3.22559,7.60759 2.66594,8.16724 1.97559,8.16724C1.28523,8.16724 0.72559,7.60759 0.72559,6.91724L0.72559,1.41724C0.72559,0.72688 1.28523,0.16724 1.97559,0.16724Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M6.97559,0.16724C7.66594,0.16724 8.22559,0.72688 8.22559,1.41724L8.22559,6.91724C8.22559,7.60759 7.66594,8.16724 6.97559,8.16724C6.28523,8.16724 5.72559,7.60759 5.72559,6.91724L5.72559,1.41724C5.72559,0.72688 6.28523,0.16724 6.97559,0.16724Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#5DD180"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M23.131,12.621C23.78,12.895 24.4,13.26 24.973,13.713C25.207,13.897 25.433,14.096 25.65,14.312C26.156,14.816 26.576,15.373 26.917,15.962C27.003,16.11 27.085,16.261 27.16,16.413L23.131,20.427C23.171,20.185 23.131,12.621 23.131,12.621L23.131,12.621ZM19.107,12.053C19.404,12.018 19.705,12 20.012,12C20.727,12 21.421,12.097 22.08,12.273C22.246,12.319 22.41,12.368 22.571,12.423L22.571,18.099C22.428,17.901 17.03,12.578 17.03,12.578C17.684,12.316 18.381,12.135 19.107,12.053L19.107,12.053ZM13.725,15.035C13.911,14.803 14.109,14.576 14.327,14.36C14.832,13.857 15.391,13.437 15.984,13.097C16.132,13.012 16.283,12.932 16.437,12.856L20.465,16.87C20.222,16.831 12.629,16.871 12.629,16.871C12.905,16.223 13.27,15.605 13.725,15.035L13.725,15.035ZM12.054,20.891C12.019,20.596 12,20.294 12,19.99C12,19.277 12.097,18.587 12.274,17.929C12.32,17.764 12.369,17.6 12.424,17.44L18.121,17.44C17.922,17.583 12.582,22.96 12.582,22.96C12.316,22.31 12.136,21.615 12.054,20.891L12.054,20.891ZM15.022,26.248C14.788,26.064 14.561,25.865 14.345,25.65C13.839,25.146 13.417,24.589 13.077,23.998C12.992,23.851 12.91,23.701 12.835,23.547L16.862,19.533C16.823,19.776 16.864,27.34 16.864,27.34C16.214,27.066 15.596,26.702 15.022,26.248L15.022,26.248ZM20.892,27.947C20.596,27.981 20.294,28 19.988,28C19.272,28 18.58,27.903 17.92,27.726C17.755,27.682 17.591,27.632 17.429,27.577L17.429,21.901C17.572,22.1 22.97,27.42 22.969,27.42C22.315,27.684 21.618,27.864 20.892,27.947L20.892,27.947ZM26.236,24.995C26.05,25.228 25.85,25.455 25.635,25.67C25.129,26.175 24.569,26.594 23.978,26.933C23.829,27.019 23.679,27.099 23.525,27.175L19.496,23.162C19.74,23.2 27.332,23.161 27.332,23.161C27.056,23.807 26.69,24.425 26.236,24.995L26.236,24.995ZM27.725,22.075C27.679,22.239 27.63,22.403 27.575,22.564L21.879,22.564C22.078,22.42 27.418,17.043 27.418,17.043C27.683,17.694 27.863,18.388 27.946,19.112C27.981,19.408 28,19.709 28,20.013C28,20.727 27.902,21.416 27.725,22.075L27.725,22.075Z"
android:strokeWidth="1"
android:fillType="nonZero"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:startX="31.222"
android:startY="40.376"
android:endX="20.938"
android:endY="23.787"
android:type="linear">
<item android:offset="0" android:color="#FF49B7FC"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#6CAAFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M25.997,24.952C25.655,25.011 24.686,23.341 24.686,23.341C24.686,24.295 24.231,25.489 23.205,26.384C23.661,26.563 24.8,26.98 24.516,27.398C24.288,27.756 20.927,27.636 19.958,27.517C18.99,27.636 15.572,27.756 15.401,27.398C15.116,26.92 16.255,26.503 16.711,26.384C15.742,25.548 15.287,24.355 15.287,23.401C15.287,23.401 14.318,25.011 13.976,25.011C13.806,25.011 13.635,24.116 14.261,22.028C14.546,21.014 14.888,20.239 15.401,18.866C15.344,15.287 16.711,12.364 20.015,12.364C23.262,12.364 24.686,15.227 24.629,18.807C25.142,20.179 25.484,21.014 25.769,21.969C26.395,24.057 26.168,24.952 25.997,24.952L25.997,24.952Z"
android:strokeWidth="1"
android:fillType="evenOdd"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:startX="36.074"
android:startY="47.516"
android:endX="20.015"
android:endY="24.704"
android:type="linear">
<item android:offset="0" android:color="#FF459FFC"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#FFBE66"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M24.537,23.148L19.098,22.739L19.098,22.712L19.126,22.712C19.239,22.576 19.418,22.512 19.57,22.412C19.911,22.189 20.248,21.96 20.597,21.731C21.506,21.133 22.397,20.467 23.288,19.85C23.529,19.683 24.077,19.383 24.232,19.169C24.313,19.057 24.37,18.851 24.287,18.733C24.216,18.531 23.912,18.596 23.649,18.596L21.818,18.596C21.639,18.703 20.664,18.624 20.375,18.624L16.795,18.678C16.502,18.679 15.503,18.597 15.324,18.705C15.689,18.702 16.063,18.77 16.379,18.842C16.802,18.938 17.236,18.916 17.627,19.005L18.071,19.032C18.729,19.183 19.493,19.182 20.153,19.332C20.576,19.428 21.01,19.407 21.401,19.496C21.591,19.539 21.802,19.481 21.929,19.578L21.873,19.578C21.509,19.898 20.816,20.13 20.375,20.395C19.271,21.058 18.111,21.652 17.017,22.33C16.781,22.477 16.366,22.708 16.24,22.957C16.155,23.125 16.201,23.513 16.351,23.584L16.795,23.584L24.537,23.23L24.537,23.148C24.784,23.142 25.237,23.12 25.397,23.23L24.565,23.257L25.397,28L25.342,28C25.084,27.753 24.365,27.5 24.01,27.319C23.101,26.855 22.183,26.398 21.263,25.928C20.944,25.766 20.624,25.607 20.291,25.438C20.222,25.402 20.062,25.247 19.958,25.274C19.917,25.285 19.811,25.386 19.764,25.411C19.47,25.561 19.182,25.704 18.904,25.847C17.911,26.356 16.928,26.812 15.935,27.319C15.534,27.523 15.041,27.874 14.603,28L15.629,22.194C15.333,22.002 15.103,21.7 14.852,21.458C14.403,21.026 13.939,20.55 13.437,20.177L12.854,19.578C12.458,19.283 12.121,18.912 11.772,18.569C11.612,18.412 11.399,18.294 11.273,18.106C11.615,18.073 12.006,18.015 12.327,17.942C12.8,17.834 13.276,17.853 13.715,17.751C14.363,17.601 15.038,17.622 15.657,17.479C16.02,17.395 17.081,17.395 17.294,17.233C17.427,17.087 17.476,16.869 17.572,16.688C17.773,16.309 17.973,15.912 18.182,15.516C18.795,14.36 19.41,13.181 19.986,12C20.008,12.028 19.996,12.007 20.014,12.055C20.131,12.154 20.161,12.321 20.236,12.463C20.433,12.836 20.615,13.224 20.819,13.608L22.706,17.261C23.473,17.333 24.385,17.444 25.12,17.615C25.768,17.765 26.443,17.744 27.062,17.888C27.435,17.974 28.508,17.966 28.727,18.133C28.382,18.355 28.162,18.738 27.839,18.978C27.6,19.156 27.433,19.405 27.201,19.578C26.556,20.056 25.995,20.682 25.425,21.24C25.231,21.43 24.4,22.067 24.371,22.303C24.46,22.437 24.514,22.961 24.537,23.148Z"
android:strokeWidth="1"
android:fillType="evenOdd"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:startX="29.642"
android:startY="35.648"
android:endX="20"
android:endY="25.049"
android:type="linear">
<item android:offset="0" android:color="#FFFCA629"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#DDF2FF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M29,22.42L29,27.802C29,28.348 28.558,28.791 28.012,28.791L12.989,28.791C12.443,28.791 12,28.348 12,27.802L12,22.42C12,21.874 12.443,21.431 12.988,21.431C13.534,21.431 13.977,21.874 13.977,22.42L13.977,26.814L27.023,26.814L27.023,22.42C27.023,21.874 27.466,21.431 28.012,21.431C28.557,21.431 29,21.874 29,22.42Z"
android:strokeWidth="1"
android:fillColor="#1DA1F2"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M19.794,23.659C19.98,23.849 20.235,23.956 20.5,23.956C20.766,23.956 21.02,23.849 21.206,23.659L25.149,19.634C25.531,19.244 25.525,18.618 25.135,18.236C24.745,17.854 24.119,17.861 23.737,18.251L21.488,20.546L21.488,11.988C21.488,11.443 21.046,11 20.5,11C19.954,11 19.512,11.443 19.512,11.988L19.512,20.546L17.264,18.251C16.882,17.861 16.256,17.854 15.866,18.236C15.476,18.618 15.469,19.244 15.851,19.634L19.794,23.659Z"
android:strokeWidth="1"
android:fillColor="#1DA1F2"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#5AC689"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M24.55,17.442C27.724,17.442 30.545,19.658 30.545,22.379C30.545,23.909 29.49,25.273 28.076,26.297L28.076,26.297L28.606,28L26.668,26.976C25.965,27.141 25.254,27.314 24.55,27.314C21.188,27.314 18.547,25.106 18.547,22.379C18.547,19.658 21.188,17.442 24.55,17.442ZM17.39,12C20.936,12 24.04,14.077 24.662,16.879C24.431,16.856 24.199,16.841 23.968,16.841C20.544,16.841 17.837,19.304 17.838,22.337C17.838,22.838 17.917,23.33 18.061,23.792C17.838,23.814 17.613,23.822 17.39,23.822C16.496,23.822 15.77,23.645 14.868,23.476L14.868,23.476L12.345,24.699L13.064,22.606C11.26,21.389 10.182,19.82 10.182,17.911C10.182,14.601 13.431,12 17.39,12ZM22.603,20.171C22.252,20.171 21.901,20.51 21.901,20.848C21.901,21.188 22.252,21.527 22.603,21.527C23.135,21.527 23.487,21.188 23.487,20.848C23.487,20.51 23.135,20.171 22.603,20.171ZM26.489,20.171C26.138,20.171 25.787,20.51 25.787,20.848C25.787,21.188 26.138,21.527 26.489,21.527C27.012,21.527 27.372,21.188 27.372,20.848C27.372,20.51 27.02,20.171 26.489,20.171ZM20.088,14.955C19.552,14.955 19.011,15.301 19.003,15.825C19.003,16.348 19.545,16.694 20.088,16.694C20.63,16.694 20.989,16.348 20.989,15.825C20.989,15.302 20.63,14.955 20.088,14.955ZM15.043,14.955C14.501,14.955 13.958,15.301 13.958,15.824C13.958,16.348 14.5,16.694 15.043,16.694C15.587,16.694 15.946,16.34 15.946,15.824C15.946,15.301 15.587,14.955 15.043,14.955Z"
android:strokeWidth="1"
android:fillType="nonZero"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:startX="49.894"
android:startY="36.333"
android:endX="22.633"
android:endY="23.033"
android:type="linear">
<item android:offset="0" android:color="#FF43E07D"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="22dp"
android:height="28dp"
android:viewportWidth="22"
android:viewportHeight="28">
<path
android:pathData="M20.439,10.786L7.159,0.949C5.383,-0.366 2.878,0.007 1.564,1.782C1.053,2.471 0.778,3.306 0.778,4.163L0.778,23.837C0.778,26.046 2.569,27.837 4.778,27.837C5.635,27.837 6.47,27.561 7.159,27.051L20.439,17.214C22.214,15.899 22.587,13.394 21.272,11.619C21.037,11.302 20.756,11.021 20.439,10.786Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="28dp"
android:viewportWidth="20"
android:viewportHeight="28">
<path
android:pathData="M3,0L3,0A3,3 0,0 1,6 3L6,25A3,3 0,0 1,3 28L3,28A3,3 0,0 1,0 25L0,3A3,3 0,0 1,3 0z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M17,0L17,0A3,3 0,0 1,20 3L20,25A3,3 0,0 1,17 28L17,28A3,3 0,0 1,14 25L14,3A3,3 0,0 1,17 0z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M23.1364,5.625C27.2107,5.625 30.727,8.3997 31.7605,12.285C31.9603,13.0368 32.0625,13.8148 32.0625,14.6054C32.0625,16.3752 31.6893,17.5476 30.7891,19.0993C30.5904,19.4417 30.214,19.6576 29.8017,19.6657C29.3894,19.6738 29.0039,19.4729 28.7904,19.1386C28.5769,18.8043 28.5677,18.3874 28.7665,18.045C29.4926,16.7939 29.7543,15.9696 29.7543,14.6054C29.7543,13.9954 29.6752,13.3967 29.5222,12.8199C28.74,9.8796 26.1212,7.8123 23.1364,7.8123C21.4231,7.8123 19.7928,8.486 18.551,9.7102C18.3337,9.9242 18.0338,10.0453 17.7203,10.0455C17.4069,10.0458 17.1068,9.9252 16.8891,9.7115C15.6572,8.5022 13.9894,7.8123 12.3011,7.8123C8.6713,7.8123 5.6832,10.8445 5.6832,14.6054C5.6832,16.4508 6.2319,17.6726 7.6458,19.7373C8.7682,21.3884 10.7236,23.3539 13.1743,25.4268C13.8799,26.023 14.5895,26.5979 15.2833,27.1391L15.9441,27.6484L16.4644,28.0403L16.963,28.4071L17.0388,28.4621C17.2386,28.6083 17.4695,28.6833 17.7181,28.6833C17.9687,28.6833 17.7849,28.6676 18.4086,28.454C19.0322,28.2403 19.6488,28.6043 19.9351,28.8639C20.2112,29.1142 20.2112,29.8454 19.8146,30.1888C19.418,30.5322 18.478,30.8711 17.7188,30.87C17.0249,30.8714 16.3472,30.6712 15.7772,30.2963L15.5596,30.1432L15.0406,29.762L14.3501,29.2395C13.4273,28.5336 12.5229,27.8064 11.6377,27.0585C9.0446,24.865 6.9665,22.7764 5.7083,20.9247C4.0714,18.5362 3.375,16.9851 3.375,14.6054C3.375,9.6683 7.3596,5.625 12.3011,5.625C14.2235,5.625 16.1063,6.2668 17.639,7.4123L17.7161,7.4711L17.7999,7.4073C19.2679,6.3037 21.0379,5.6787 22.8937,5.6281L23.1364,5.625Z"
android:strokeWidth="0.6"
android:fillColor="#FFFFFF"
android:strokeColor="#FFFFFF"
android:fillType="nonZero"/>
<path
android:pathData="M28.5779,23.985C29.2159,23.9853 29.7402,24.5434 29.7665,25.2503C29.7927,25.9571 29.3116,26.5612 28.6758,26.6197L28.5779,26.6243L21.7771,26.6243C21.1391,26.6239 20.6148,26.0658 20.5885,25.359C20.5623,24.6521 21.0434,24.0481 21.6792,23.9895L21.7771,23.985L28.5779,23.985L28.5779,23.985Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M26.4888,21.6176L26.4934,21.7155L26.4934,28.5159C26.4931,29.1539 25.9349,29.6781 25.2281,29.7044C24.5212,29.7307 23.9172,29.2496 23.8586,28.6138L23.8541,28.5159L23.8541,21.7155C23.8541,21.0586 24.4453,20.5254 25.1737,20.5254C25.8604,20.5254 26.4323,21.0004 26.4888,21.6176Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="11dp"
android:viewportWidth="18"
android:viewportHeight="11">
<path
android:pathData="M1.4,1.6l7.2,7.2l7.2,-7.2"
android:strokeLineJoin="round"
android:strokeWidth="2.6"
android:fillColor="#00000000"
android:strokeColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeLineCap="round"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="26dp"
android:height="24dp"
android:viewportWidth="26"
android:viewportHeight="24">
<path
android:pathData="M3.357,12.23C3.427,11.742 3.966,9.639 4.255,8.878C5.659,5.185 9.282,2.78 13.234,2.779C15.074,2.779 16.804,3.293 18.27,4.21L17.385,4.21C16.624,4.21 16.001,4.836 16.001,5.6C16.001,6.364 16.624,6.99 17.385,6.99L21.536,6.99C22.297,6.99 22.919,6.364 22.919,5.6L22.919,1.431C22.919,0.668 22.297,0.043 21.536,0.043C20.775,0.043 20.152,0.668 20.152,1.433L20.152,2.114C18.107,0.733 15.698,-0.003 13.234,0C10.232,0 7.479,1.07 5.336,2.863L5.322,2.863C5.017,3.127 4.713,3.405 4.422,3.696C4.132,3.974 3.883,4.252 3.634,4.558C3.592,4.613 3.551,4.655 3.509,4.711C3.399,4.864 3.288,5.003 3.191,5.141C3.067,5.308 2.942,5.489 2.831,5.656C2.707,5.836 2.596,6.017 2.485,6.198C2.402,6.378 2.306,6.545 2.209,6.726C2.098,6.92 2.001,7.129 1.904,7.322C1.835,7.488 1.766,7.669 1.697,7.836C1.545,8.211 1.406,8.586 1.296,8.975C1.185,9.364 0.616,11.044 0.616,12.473C0.72,13.116 1.196,13.438 2.044,13.438C2.978,13.438 3.201,13.309 3.357,12.23ZM18.274,23.912C22.583,22.673 25.616,16.681 25.616,13.74C25.616,12.835 25.094,12.415 24.384,12.337C24.019,12.297 23.652,12.404 23.366,12.637C23.08,12.869 22.862,13.167 22.862,13.575C21.832,18.183 20.782,19.116 17.383,21.255C16.551,21.655 16.285,22.26 16.585,23.07C16.886,23.881 17.449,24.161 18.274,23.912Z"
android:strokeAlpha="0.9049247"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillAlpha="0.9049247"/>
<path
android:pathData="M2.754,21.406L2.754,20.038L4.122,20.038L4.122,18.652L2.754,18.652L2.754,17.284L1.368,17.284L1.368,18.652L0,18.652L0,20.038L1.368,20.038L1.368,21.406L2.754,21.406ZM8.217,22L8.217,15.592L6.741,15.592L5.373,16.78L5.373,18.355L6.741,17.167L6.741,22L8.217,22ZM12.096,22.054C12.456,22.054 12.759,21.997 13.005,21.883C13.251,21.769 13.443,21.643 13.581,21.505C13.701,21.385 13.799,21.267 13.874,21.149C13.949,21.032 14.009,20.906 14.054,20.771C14.099,20.636 14.13,20.491 14.148,20.335C14.166,20.179 14.175,20.005 14.175,19.813C14.175,19.663 14.169,19.514 14.157,19.368C14.145,19.221 14.118,19.075 14.076,18.931C14.034,18.787 13.974,18.647 13.896,18.513C13.818,18.378 13.713,18.244 13.581,18.112C13.449,17.98 13.28,17.872 13.073,17.788C12.866,17.704 12.621,17.662 12.339,17.662C12.141,17.662 11.964,17.692 11.808,17.752C11.652,17.812 11.541,17.866 11.475,17.914L11.475,17.914L11.475,16.924L14.04,16.924L14.04,15.592L10.134,15.592L10.134,19.363L11.493,19.363C11.511,19.321 11.532,19.273 11.556,19.219C11.58,19.165 11.615,19.115 11.66,19.07C11.705,19.025 11.762,18.986 11.831,18.954C11.9,18.92 11.988,18.904 12.096,18.904C12.276,18.904 12.422,18.967 12.533,19.093C12.644,19.219 12.699,19.459 12.699,19.813C12.699,20.185 12.636,20.434 12.51,20.56C12.402,20.668 12.264,20.722 12.096,20.722C11.904,20.722 11.762,20.662 11.669,20.542C11.576,20.422 11.517,20.257 11.493,20.047L11.493,20.047L10.017,20.047C10.035,20.281 10.076,20.524 10.139,20.776C10.202,21.028 10.347,21.268 10.575,21.496C10.713,21.634 10.911,21.761 11.169,21.878C11.427,21.996 11.736,22.054 12.096,22.054Z"
android:strokeAlpha="0.9049247"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillAlpha="0.9049247"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="19dp"
android:viewportWidth="18"
android:viewportHeight="19">
<path
android:pathData="M12.486,7.991L2.805,0.423C1.656,-0.475 0,0.364 0,1.845L0,16.979C0,18.46 1.656,19.299 2.805,18.401L12.486,10.833C13.401,10.118 13.401,8.706 12.486,7.991Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M17.086,17.546L17.086,7.522L17.086,2.509C17.086,1.912 17.263,0.667 16.576,0.199C15.813,-0.32 14.789,0.236 14.789,1.172L14.789,16.208C14.789,16.806 14.612,18.05 15.299,18.518C16.063,19.038 17.086,18.481 17.086,17.546L17.086,17.546Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="19dp"
android:viewportWidth="18"
android:viewportHeight="19">
<path
android:pathData="M4.621,7.991L14.301,0.423C15.45,-0.475 17.107,0.364 17.107,1.845L17.107,16.979C17.107,18.46 15.45,19.299 14.301,18.401L4.621,10.833C3.705,10.118 3.705,8.706 4.621,7.991Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M0.02,17.546L0.02,7.522L0.02,2.509C0.02,1.912 -0.156,0.667 0.531,0.199C1.294,-0.32 2.318,0.236 2.318,1.172L2.318,16.208C2.318,16.806 2.495,18.05 1.808,18.518C1.044,19.038 0.02,18.481 0.02,17.546L0.02,17.546Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25dp"
android:height="24dp"
android:viewportWidth="25"
android:viewportHeight="24">
<path
android:pathData="M22.259,12.23C22.189,11.742 21.65,9.639 21.361,8.878C19.958,5.185 16.334,2.78 12.382,2.779C10.542,2.779 8.812,3.293 7.346,4.21L8.231,4.21C8.992,4.21 9.615,4.836 9.615,5.6C9.615,6.364 8.992,6.99 8.231,6.99L4.08,6.99C3.32,6.99 2.697,6.364 2.697,5.6L2.697,1.431C2.697,0.668 3.32,0.043 4.08,0.043C4.841,0.043 5.464,0.668 5.464,1.433L5.464,2.114C7.509,0.733 9.918,-0.003 12.382,0C15.384,0 18.137,1.07 20.28,2.863L20.294,2.863C20.599,3.127 20.903,3.405 21.194,3.696C21.484,3.974 21.733,4.252 21.982,4.558C22.024,4.613 22.065,4.655 22.107,4.711C22.217,4.864 22.328,5.003 22.425,5.141C22.55,5.308 22.674,5.489 22.785,5.656C22.909,5.836 23.02,6.017 23.131,6.198C23.214,6.378 23.31,6.545 23.407,6.726C23.518,6.92 23.615,7.129 23.712,7.322C23.781,7.488 23.85,7.669 23.919,7.836C24.071,8.211 24.21,8.586 24.32,8.975C24.431,9.364 25,11.044 25,12.473C24.896,13.116 24.42,13.438 23.572,13.438C22.638,13.438 22.415,13.309 22.259,12.23ZM7.342,23.912C3.034,22.673 0,16.681 0,13.74C0,12.835 0.522,12.415 1.232,12.337C1.597,12.297 1.964,12.404 2.25,12.637C2.536,12.869 2.754,13.167 2.754,13.575C3.784,18.183 4.834,19.116 8.233,21.255C9.065,21.655 9.331,22.26 9.031,23.07C8.73,23.881 8.167,24.161 7.342,23.912Z"
android:strokeAlpha="0.9049247"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillAlpha="0.9049247"/>
<path
android:pathData="M14.393,21.038L14.393,19.652L11.441,19.652L11.441,21.038L14.393,21.038ZM18.488,23L18.488,16.592L17.012,16.592L15.644,17.78L15.644,19.355L17.012,18.167L17.012,23L18.488,23ZM22.367,23.054C22.727,23.054 23.03,22.997 23.276,22.883C23.522,22.769 23.714,22.643 23.852,22.505C23.972,22.385 24.069,22.267 24.145,22.149C24.219,22.032 24.279,21.906 24.325,21.771C24.369,21.636 24.401,21.491 24.419,21.335C24.437,21.179 24.446,21.005 24.446,20.813C24.446,20.663 24.44,20.514 24.428,20.368C24.416,20.221 24.389,20.075 24.347,19.931C24.305,19.787 24.245,19.647 24.167,19.513C24.089,19.378 23.984,19.244 23.852,19.112C23.72,18.98 23.55,18.872 23.344,18.788C23.137,18.704 22.892,18.662 22.61,18.662C22.412,18.662 22.235,18.692 22.079,18.752C21.923,18.812 21.812,18.866 21.746,18.914L21.746,18.914L21.746,17.924L24.311,17.924L24.311,16.592L20.405,16.592L20.405,20.363L21.764,20.363C21.782,20.321 21.803,20.273 21.827,20.219C21.851,20.165 21.885,20.115 21.931,20.07C21.976,20.025 22.033,19.986 22.101,19.953C22.17,19.92 22.259,19.904 22.367,19.904C22.547,19.904 22.693,19.967 22.804,20.093C22.915,20.219 22.97,20.459 22.97,20.813C22.97,21.185 22.907,21.434 22.781,21.56C22.673,21.668 22.535,21.722 22.367,21.722C22.175,21.722 22.033,21.662 21.939,21.542C21.847,21.422 21.788,21.257 21.764,21.047L21.764,21.047L20.288,21.047C20.306,21.281 20.347,21.524 20.41,21.776C20.472,22.028 20.618,22.268 20.846,22.496C20.984,22.634 21.182,22.761 21.44,22.878C21.698,22.996 22.007,23.054 22.367,23.054Z"
android:strokeAlpha="0.9049247"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillAlpha="0.9049247"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="21dp"
android:height="21dp"
android:viewportWidth="21"
android:viewportHeight="21">
<path
android:pathData="M18.715,10.584L18.715,10.153C19.364,10.153 19.889,10.679 19.889,11.328C19.889,16.842 15.514,21 10,21C4.485,21 0,16.514 0,11C0,5.486 4.2,1.029 9.715,1.029C10.363,1.029 10.889,1.554 10.889,2.203C10.889,2.851 10.363,3.377 9.715,3.377C5.496,3.377 2.348,6.781 2.348,11C2.348,15.219 5.781,18.652 10,18.652C14.219,18.652 17.541,15.547 17.541,11.328C17.541,10.679 18.067,10.153 18.715,10.153L18.715,10.584Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M15.575,0.631L18.736,1L18.736,1C20.094,1.156 20.908,1.418 21,3.141L21,6.516C21,7.132 20.472,7.632 19.821,7.632C19.17,7.632 18.642,7.132 18.642,6.516L18.642,4.617L11.65,10.672C11.429,10.881 11.129,10.999 10.816,10.999C10.503,10.999 10.203,10.881 9.982,10.672C9.761,10.462 9.637,10.179 9.637,9.883C9.637,9.587 9.761,9.303 9.982,9.094L17.153,3.141L15.187,2.788C14.61,2.684 14.226,2.132 14.33,1.555C14.33,1.554 14.33,1.554 14.33,1.554C14.436,0.966 14.981,0.562 15.575,0.631Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M20.9855,1.125C21.5204,1.125 21.9539,1.5431 21.9539,2.0588L21.9539,2.9946C21.9539,3.5103 21.5204,3.9284 20.9855,3.9284L20.0171,3.9284L20.0171,5.8C20.0171,5.8239 20.0048,5.8457 20.0027,5.8696C27.4495,6.6089 32.9901,12.8444 32.6062,20.0537C32.2224,27.263 26.0486,32.9185 18.5625,32.9185C11.0764,32.9185 4.9027,27.263 4.5188,20.0537C4.1349,12.8444 9.6755,6.6089 17.1223,5.8696C17.1223,5.8457 17.1079,5.8239 17.1079,5.8L17.1079,3.9304L16.1395,3.9304C15.8823,3.9309 15.6354,3.8328 15.4534,3.6576C15.2713,3.4824 15.169,3.2446 15.169,2.9966L15.169,2.0588C15.169,1.5431 15.6026,1.125 16.1374,1.125M18.7637,9.0562C14.87,9.0052 11.2493,10.9749 9.287,14.2115C7.3248,17.448 7.3248,21.4504 9.287,24.687C11.2493,27.9235 14.87,29.8932 18.7637,29.8423C24.6714,29.765 29.4184,25.1346 29.4184,19.4492C29.4184,13.7639 24.6714,9.1334 18.7637,9.0562ZM19.0467,12.3446C19.5815,12.3446 20.0151,12.7627 20.0151,13.2784L20.0151,18.8892L23.8948,18.8892C24.4305,18.8892 24.8632,19.3065 24.8632,19.8231L24.8632,20.7589C24.8632,21.2754 24.4305,21.6927 23.8948,21.6947L18.0762,21.6947C17.8194,21.6947 17.5731,21.5963 17.3915,21.4211C17.2099,21.246 17.1079,21.0085 17.1079,20.7608L17.1079,13.2765C17.1079,12.7607 17.5414,12.3426 18.0762,12.3426L19.0446,12.3426L19.0467,12.3446Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeAlpha="0.25"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"
android:fillAlpha="0.25"/>
<path
android:pathData="M25.716,12L27,13.284L21.284,19L27,24.716L25.716,26L20,20.284L14.284,26L13,24.716L18.715,19L13,13.284L14.284,12L20,17.715L25.716,12Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M6.1846,10.9495L25.5392,10.9495C25.8482,10.9495 26.0988,10.6636 26.0988,10.311L26.0988,8.5135C26.0988,8.162 25.8482,7.875 25.5392,7.875L6.1846,7.875C5.8756,7.875 5.625,8.1609 5.625,8.5135L5.625,10.311C5.625,10.6625 5.8756,10.9495 6.1846,10.9495M6.1851,20.1729L21.2294,20.1729C21.5394,20.1729 21.7895,19.887 21.7895,19.5345L21.7895,17.7369C21.7895,17.3844 21.5394,17.0985 21.2294,17.0985L6.1861,17.0985C5.8761,17.0985 5.626,17.3844 5.626,17.7369L5.626,19.5345C5.626,19.887 5.8761,20.1729 6.1861,20.1729M15.8367,26.3219L6.1889,26.3219C5.8773,26.3219 5.625,26.6519 5.625,27.0598L5.625,28.6585C5.625,29.0664 5.8773,29.3964 6.1889,29.3964L15.8367,29.3964C16.1483,29.3964 16.4007,29.0664 16.4007,28.6585L16.4007,27.0598C16.4007,26.6519 16.1483,26.3219 15.8367,26.3219M30.9979,12.6289C28.5308,12.8792 26.5515,14.9612 26.5139,17.5849L26.513,17.5849L26.513,21.9195C25.9483,21.6384 25.3283,21.493 24.7004,21.4944C22.4333,21.4944 20.6206,23.3329 20.6206,25.6318C20.6206,27.9307 22.4333,29.7692 24.7004,29.7692C26.9666,29.7692 28.8555,27.9307 28.7793,25.6318L28.7793,17.6612C28.7793,16.2641 29.7836,15.1241 31.1033,14.9312C31.3295,14.9 31.4987,14.703 31.5,14.4692L31.5,13.0927C31.4995,12.9608 31.4446,12.8354 31.3491,12.7471C31.2535,12.6588 31.126,12.6159 30.9979,12.6289"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="2dp"/>
<solid android:color="#33282E3F"/>
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="2dp"/>
<solid android:color="@color/white"/>
</shape>
</clip>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@android:id/background">
<shape>
<corners android:radius="2dp"/>
<stroke android:color="#66FFFFFF"
android:height="4dp"/>
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="2dp"/>
<solid android:color="#FFFFFF"/>
</shape>
</clip>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#FFFFFF"/>
<size android:width="10dp" android:height="10dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF" />
<corners
android:topLeftRadius="@dimen/platform_dp_20"
android:topRightRadius="@dimen/platform_dp_20" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#B3000000">
<ImageView
android:id="@+id/iv_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#33282E3F" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="30dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/csl_layout"
android:layout_width="104dp"
android:layout_height="36dp"
android:layout_marginStart="16dp"
android:layout_marginTop="5dp"
android:background="@drawable/bg_meditation_play_top"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:src="@drawable/icon_close_play_meditation"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="0.5dp"
android:layout_height="20dp"
android:background="#FFE8E8E8"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="9dp"
android:src="@drawable/icon_play_meditation_down_arrow"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/iv_share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="17dp"
android:padding="5dp"
android:src="@drawable/icon_play_meditation_share"
app:layout_constraintBottom_toBottomOf="@id/csl_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/csl_layout" />
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="150dp"
android:gravity="center"
android:textColor="@color/white"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/csl_layout"
tools:text="舒缓安神舒神舒缓安神舒缓安神舒缓安神舒缓安神" />
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="12dp"
android:gravity="center"
android:textColor="@color/white"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title"
tools:text="舒缓安神舒缓安神舒缓安神舒缓安神舒缓安神舒缓安神舒缓安神舒缓安神" />
<include
android:id="@+id/player_control_layout"
android:visibility="gone"
layout="@layout/player_control_view" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guide_line"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<LinearLayout
android:id="@+id/ll_pure_music_time_off"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
app:layout_constraintStart_toStartOf="@id/guide_line"
app:layout_constraintEnd_toEndOf="@id/guide_line"
app:layout_constraintTop_toTopOf="@id/iv_collect"
tools:visibility="visible"
android:visibility="gone">
<ImageView
android:id="@+id/iv_time_off_pure_music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_play_meditation_time_off" />
<TextView
android:id="@+id/tv_time_off_pure_music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:gravity="center"
tools:text="56:32"
android:textSize="12sp"
android:textColor="@color/white" />
</LinearLayout>
<ImageView
android:id="@+id/iv_collect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="50dp"
android:layout_marginBottom="48dp"
android:src="@drawable/icon_play_meditation_collect"
app:layout_constraintBottom_toTopOf="@id/seekbar_play_progress"
app:layout_constraintEnd_toStartOf="@id/guide_line" />
<ImageView
android:id="@+id/iv_pure_music_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginBottom="48dp"
android:src="@drawable/icon_pure_music_list"
app:layout_constraintBottom_toTopOf="@id/seekbar_play_progress"
app:layout_constraintStart_toEndOf="@id/guide_line"
tools:visibility="visible"
android:visibility="gone" />
<ImageView
android:id="@+id/iv_time_off"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:layout_marginBottom="48dp"
android:src="@drawable/icon_play_meditation_time_off"
app:layout_constraintBottom_toTopOf="@id/seekbar_play_progress"
app:layout_constraintStart_toEndOf="@id/guide_line"
tools:visibility="gone" />
<TextView
android:id="@+id/tv_time_off"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
tools:text="56:32"
android:textSize="12sp"
android:textColor="@color/white"
app:layout_constraintTop_toBottomOf="@id/iv_time_off"
app:layout_constraintStart_toStartOf="@id/iv_time_off"
app:layout_constraintEnd_toEndOf="@id/iv_time_off" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="match_parent"
android:background="#B3000000"
android:id="@+id/root_layout">
<ImageView
android:id="@+id/iv_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#33282E3F" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent">
<ImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_marginEnd="24dp"
android:padding="12dp"
android:src="@drawable/icon_play_meditation_time_off_close"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="90dp"
android:text="定时关闭"
android:textColor="@color/white"
android:textStyle="bold"
android:textSize="24sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_close" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<com.weigan.loopview.LoopView
android:id="@+id/wheel_hour"
android:layout_width="50dp"
android:layout_height="240dp"
app:awv_itemsVisibleCount="4"
app:awv_textsize="36"
app:awv_dividerTextColor="0x00FFFFFF"
app:awv_isLoop="false"
app:awv_outerTextColor="0x66FFFFFF"
app:awv_centerTextColor="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="小时"
android:textColor="@color/white"
android:textSize="18sp" />
<com.weigan.loopview.LoopView
android:id="@+id/wheel_minute"
android:layout_width="50dp"
android:layout_height="240dp"
android:layout_marginStart="60dp"
app:awv_itemsVisibleCount="4"
app:awv_textsize="36"
app:awv_dividerTextColor="0x00FFFFFF"
app:awv_isLoop="false"
app:awv_outerTextColor="0x66FFFFFF"
app:awv_centerTextColor="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="分钟"
android:textColor="@color/white"
android:textSize="18sp" />
</LinearLayout>
<TextView
android:id="@+id/tv_cancel_time_off"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginBottom="50dp"
android:layout_marginHorizontal="16dp"
android:background="@drawable/bg_cancel_play_meditation_time_off"
android:text="关闭定时"
android:textColor="@color/white"
android:textSize="16sp"
android:gravity="center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<TextView
android:id="@+id/tv_save_setting"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginBottom="28dp"
android:layout_marginHorizontal="16dp"
android:background="@drawable/bg_save_play_meditation_time_off"
android:text="保存设置"
android:textColor="#FF282E3F"
android:textSize="16sp"
android:gravity="center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/tv_cancel_time_off" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="150dp"
android:background="@drawable/shape_bg_solid_282e3f_r_top_20">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="-20dp"
app:cardCornerRadius="20dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/wv_choose_music"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#282E3F"
android:scrollbars="none" />
<LinearLayout
android:id="@+id/ll_close"
android:layout_width="match_parent"
android:gravity="center_horizontal"
android:layout_height="38dp">
<ImageView
android:layout_width="24dp"
android:layout_height="10dp"
android:src="@drawable/ic_close_choose_music"
android:layout_marginTop="12dp" />
</LinearLayout>
</FrameLayout>
</androidx.cardview.widget.CardView>
</FrameLayout>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:background="@drawable/bg_meditation_play_float"
android:layout_marginHorizontal="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/csl_root_layout"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="@drawable/bg_play_meditation_float_view">
<ImageView
android:id="@+id/iv_close"
android:layout_width="28dp"
android:layout_height="29dp"
android:paddingHorizontal="5dp"
android:paddingVertical="5dp"
android:layout_marginStart="15dp"
android:src="@drawable/icon_close_meditation_play_float_view"
app:layout_constraintEnd_toStartOf="@id/ll_meditation_info"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<LinearLayout
android:id="@+id/ll_meditation_info"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="20dp"
android:gravity="center_vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_close" >
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="8dp"
app:cardElevation="0dp">
<ImageView
android:id="@+id/iv_cover"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="centerCrop"
android:src="@drawable/platform_loading_logo" />
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/tv_title"
android:layout_width="165dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/white"
android:textSize="16sp"
tools:text="睡眠安抚睡眠安抚睡眠安抚睡眠安抚"/>
</LinearLayout>
<FrameLayout
android:id="@+id/fl_layout"
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_marginEnd="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<io.feeeei.circleseekbar.CircleSeekBar
android:id="@+id/progress_bar"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
app:wheel_unreached_color="#33FFFFFF"
app:wheel_reached_color="#FFFFFF"
app:wheel_unreached_width="2dp"
app:wheel_reached_width="2dp"/>
<ImageView
android:id="@+id/iv_play_status"
android:layout_width="20dp"
android:layout_height="20dp"
android:padding="5dp"
android:layout_gravity="center"
android:src="@drawable/icon_meditation_float_pause"/>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
\ No newline at end of file
<?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">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
\ No newline at end of file
<?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="wrap_content"
android:layout_marginHorizontal="38dp"
android:background="@drawable/bg_meditation_quit"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="28dp"
android:text="确定要结束练习吗?"
android:textColor="#FF242424"
android:textSize="16sp"
android:layout_gravity="center_horizontal"/>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#88D8D8D8"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="44dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_sure_quit"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:text="结束练习"
android:textColor="#FF666666"
android:textSize="18sp"/>
<View
android:layout_width="0.5dp"
android:layout_height="match_parent"
android:background="#88D8D8D8"/>
<TextView
android:id="@+id/tv_cancel_quit"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:text="再练一会"
android:textColor="#FF1DA1F2"
android:textSize="18sp"/>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?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:id="@+id/csl_root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#5D000000">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/csl_share_layout"
android:layout_width="match_parent"
android:layout_height="176dp"
android:layout_margin="20dp"
android:background="@drawable/bg_share_play_meditation_bottom"
android:paddingHorizontal="15dp"
android:paddingTop="28dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<LinearLayout
android:id="@+id/ll_wechat_friend"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_wechat_circle_of_friends"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/icon_meditation_share_wechat" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="微信好友"
android:textColor="#FF666666"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_wechat_circle_of_friends"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_save_picture"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/ll_wechat_friend"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/icon_meditation_share_friends" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="朋友圈"
android:textColor="#FF666666"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_save_picture"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:visibility="gone"
app:layout_constraintEnd_toStartOf="@id/ll_qq_zone"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/ll_wechat_circle_of_friends"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/icon_meditation_share_save" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="保存图片"
android:textColor="#FF666666"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_qq_zone"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_qq_friend"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/ll_save_picture"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/icon_meditation_share_qqzone" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="QQ空间"
android:textColor="#FF666666"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_qq_friend"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/ll_qq_zone"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/icon_meditation_share_qq" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="QQ好友"
android:textColor="#FF666666"
android:textSize="14sp" />
</LinearLayout>
<TextView
android:id="@+id/tv_cancel_share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="取消"
android:textColor="#FF242424"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/csl_layout_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_share_play_meditation_bottom"
android:paddingBottom="18dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/csl_share_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:id="@+id/iv_share_picture"
android:layout_width="match_parent"
android:layout_height="267dp"
android:layout_margin="16dp"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/muse_muse_icon_playing"
android:visibility="invisible"/>
<TextView
android:id="@+id/tv_share_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="18dp"
android:visibility="invisible"
tools:text='" 你一定要站在自己所热爱的世界里闪闪发光 "'
android:textColor="#FF282E3F"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_share_picture" />
<ImageView
android:id="@+id/iv_share_logo"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="16dp"
android:layout_marginTop="44dp"
android:scaleType="centerCrop"
android:src="@drawable/muse_muse_icon_playing"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_share_content" />
<TextView
android:id="@+id/tv_app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="壹点灵"
android:textColor="#FF282E3F"
android:textSize="18sp"
android:textStyle="bold"
android:visibility="invisible"
app:layout_constraintStart_toEndOf="@id/iv_share_logo"
app:layout_constraintTop_toTopOf="@id/iv_share_logo" />
<TextView
android:id="@+id/tv_app_slogan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="温暖而有力的爱着你"
android:textColor="#FF999999"
android:textSize="14sp"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@id/iv_share_logo"
app:layout_constraintStart_toEndOf="@id/iv_share_logo" />
<ImageView
android:id="@+id/iv_share_qr_code"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="16dp"
android:scaleType="centerCrop"
android:visibility="invisible"
android:src="@drawable/muse_muse_icon_playing"
app:layout_constraintBottom_toBottomOf="@id/iv_share_logo"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_share_logo" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="@layout/activity_play_meditation">
<ImageView
android:id="@+id/exo_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp"
android:src="@drawable/icon_pause_meditation"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/exo_prev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="50dp"
android:src="@drawable/icon_play_meditation_previous"
app:layout_constraintBottom_toBottomOf="@id/exo_play"
app:layout_constraintEnd_toStartOf="@id/exo_play"
app:layout_constraintTop_toTopOf="@id/exo_play" />
<ImageView
android:id="@+id/exo_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:src="@drawable/icon_play_meditation_next"
app:layout_constraintBottom_toBottomOf="@id/exo_play"
app:layout_constraintStart_toEndOf="@id/exo_play"
app:layout_constraintTop_toTopOf="@id/exo_play" />
<ImageView
android:id="@+id/exo_rew"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="40dp"
android:src="@drawable/icon_play_meditation_rewind"
app:layout_constraintBottom_toBottomOf="@id/exo_play"
app:layout_constraintEnd_toStartOf="@id/exo_prev"
app:layout_constraintTop_toTopOf="@id/exo_play" />
<ImageView
android:id="@+id/exo_ffwd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:src="@drawable/icon_play_meditation_fast_forward"
app:layout_constraintBottom_toBottomOf="@id/exo_play"
app:layout_constraintStart_toEndOf="@id/exo_next"
app:layout_constraintTop_toTopOf="@id/exo_play" />
<androidx.appcompat.widget.AppCompatSeekBar
android:id="@+id/seekbar_play_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="4dp"
android:maxHeight="4dp"
android:layout_marginHorizontal="64dp"
android:layout_marginBottom="50dp"
android:thumb="@drawable/play_meditation_thumb"
android:progressDrawable="@drawable/meditation_seekbar_bg"
android:thumbOffset="0dp"
android:paddingStart="0dp"
android:paddingEnd="0dp"
app:layout_constraintBottom_toTopOf="@id/exo_play"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/exo_position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:textColor="#B3FFFFFF"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@id/seekbar_play_progress"
app:layout_constraintEnd_toStartOf="@id/seekbar_play_progress"
app:layout_constraintTop_toTopOf="@id/seekbar_play_progress"
tools:text="03:46" />
<TextView
android:id="@+id/exo_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:textColor="#B3FFFFFF"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@id/seekbar_play_progress"
app:layout_constraintStart_toEndOf="@id/seekbar_play_progress"
app:layout_constraintTop_toTopOf="@id/seekbar_play_progress"
tools:text="13:46" />
</merge>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="muse_Transparent" parent="@style/Base.Theme.AppCompat">
<item name="colorPrimary">@color/transparent</item>
<item name="colorPrimaryDark">@color/transparent</item>
<style name="muse_Transparent" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="share_meditation_dialog" parent="Theme.Design.BottomSheetDialog">
<item name="android:windowIsFloating">true</item>
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
</style>
<style name="music_dialog_style" parent="@android:style/Theme.Dialog">
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
<!-- 弹框-底部弹出动画 -->
<style name="dialog_anim" mce_bogus="1" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/dialog_bottom_enter</item>
<item name="android:windowExitAnimation">@anim/dialog_bottom_exit</item>
</style>
<style name="un_full_screen_activity" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="windowNoTitle">true</item>
<item name="background">@color/transparent</item>
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:backgroundDimAmount">0.5</item>
</style>
</resources>
\ No newline at end of file
......@@ -116,6 +116,9 @@ class MineFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, View.
rootView.findViewById<View>(R.id.ll_my_test_log).setOnClickListener(this)
//客服
rootView.findViewById<View>(R.id.ll_service).setOnClickListener(this)
//冥想
rootView.findViewById<View>(R.id.ll_meditation).setOnClickListener(this)
init()
GlideApp.with(this).load("https://static.yidianling.com/banner/bottombanner@2x.png")
.into(iv_mine_logo)
......@@ -130,14 +133,10 @@ class MineFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, View.
.getGlobalInfo()?.info && null != PlatformRamImpl.getInstance()
.getGlobalInfo()?.info?.app_share
) {
share_title =
PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.title.toString()
share_context =
PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.descrip.toString()
share_head =
PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.cover_url.toString()
share_url =
PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.dl_url.toString()
share_title = PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.title.toString()
share_context = PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.descrip.toString()
share_head = PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.cover_url.toString()
share_url = PlatformRamImpl.getInstance().getGlobalInfo()?.info?.app_share?.dl_url.toString()
}
}
......@@ -492,6 +491,16 @@ class MineFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener, View.
} else if (id == R.id.jtv_test) { //debug下任意门入口
jtv_test?.postDelayed({ YdlBuryPointUtil.sendPv("PvEvent") }, 300)
jtv_test?.postDelayed({ YdlBuryPointUtil.sendClick("ClickEvent") }, 500)
} else if (id == R.id.ll_meditation) { //冥想
count(UserMyPageEvent.YDL_USER_MY_MIDDLE_TYPE_CLICK, "冥想")
mActivity?.let {
if (!startLoginByStatus(it, true)) {
return
}
val h5Params3 = H5Params(MH5_URL + "meditation/list?hideNavBar=1", null)
NewH5Activity.start(it, h5Params3)
}
}
}
......
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25dp"
android:height="25dp"
android:viewportWidth="25"
android:viewportHeight="25">
<path
android:pathData="M0,0.5h25v24h-25z"
android:strokeWidth="1"
android:fillColor="#D8D8D8"
android:fillAlpha="0"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M2,12.4617a11.5,11.4617 0,1 0,23 0a11.5,11.4617 0,1 0,-23 0z"
android:strokeWidth="1"
android:fillColor="#E8F5FD"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M0.8,12.4617a10.7,10.6617 0,1 0,21.4 0a10.7,10.6617 0,1 0,-21.4 0z"
android:strokeWidth="1.6"
android:fillColor="#00000000"
android:strokeColor="#1DA1F2"
android:fillType="evenOdd"/>
<path
android:pathData="M9.6,8.475a1.8,1.7917 0,1 0,3.6 0a1.8,1.7917 0,1 0,-3.6 0z"
android:strokeWidth="1.4"
android:fillColor="#00000000"
android:strokeColor="#FAA05A"
android:fillType="evenOdd"/>
<path
android:pathData="M18.6961,16.24C16.1493,16.729 14.6273,15.6357 14.13,12.96"
android:strokeWidth="1.4"
android:fillColor="#00000000"
android:strokeColor="#1DA1F2"
android:fillType="evenOdd"
android:strokeLineCap="round"/>
<path
android:pathData="M4.4101,16.4483C6.8394,16.7984 8.3027,15.6357 8.8,12.96"
android:strokeWidth="1.4"
android:fillColor="#00000000"
android:strokeColor="#1DA1F2"
android:fillType="evenOdd"
android:strokeLineCap="round"/>
<path
android:pathData="M9.47,11.465L13.45,11.465C14.3337,11.465 15.05,12.1813 15.05,13.065L15.05,17.445L15.05,17.445L7.87,17.445L7.87,13.065C7.87,12.1813 8.5863,11.465 9.47,11.465Z"
android:strokeWidth="1"
android:fillColor="#1DA1F2"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M14.1563,12.96L14.3563,12.96A0.7,0.7 0,0 1,15.0563 13.66L15.0563,18.24A0.7,0.7 0,0 1,14.3563 18.94L14.1563,18.94A0.7,0.7 0,0 1,13.4563 18.24L13.4563,13.66A0.7,0.7 0,0 1,14.1563 12.96z"
android:strokeWidth="1"
android:fillColor="#1DA1F2"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M8.57,12.96L8.77,12.96A0.7,0.7 0,0 1,9.47 13.66L9.47,18.24A0.7,0.7 0,0 1,8.77 18.94L8.57,18.94A0.7,0.7 0,0 1,7.87 18.24L7.87,13.66A0.7,0.7 0,0 1,8.57 12.96z"
android:strokeWidth="1"
android:fillColor="#1DA1F2"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M10.4563,12.96L12.4563,12.96C13.0086,12.96 13.4563,13.4077 13.4563,13.96L13.4563,19.9367L13.4563,19.9367L9.4563,19.9367L9.4563,13.96C9.4563,13.4077 9.9041,12.96 10.4563,12.96Z"
android:strokeWidth="1"
android:fillColor="#E8F5FD"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>
......@@ -460,10 +460,37 @@
</LinearLayout>
<!--meditation start-->
<LinearLayout
android:id="@+id/ll_meditation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:layout_width="25dp"
android:layout_height="25dp"
android:src="@drawable/user_mine_ic_my_meditation" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="冥想"
android:textColor="@color/platform_color_999999"
android:textSize="12sp" />
</LinearLayout>
<!--meditation end-->
<View
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2" />
android:layout_weight="1" />
</LinearLayout>
......
......@@ -13,8 +13,10 @@ import com.ydl.media.audio.manager.NotifyManager
import com.ydl.media.audio.model.Music
import com.ydl.media.audio.receiver.NoisyAudioStreamReceiver
import com.ydl.media.audio.utils.PlayProgressUtil
import com.ydl.ydlcommon.event.MeditationFloatEvent
import com.ydl.ydlcommon.utils.LogUtil
import com.yidianling.common.tools.ToastUtil
import de.greenrobot.event.EventBus
import tv.danmaku.ijk.media.player.IMediaPlayer
import tv.danmaku.ijk.media.player.IjkMediaPlayer
import java.io.IOException
......@@ -341,6 +343,10 @@ class AudioPlayer private constructor() {
listener.onPlayerStart()
}
}
val event = MeditationFloatEvent(show = false, stop = true, time = null)
EventBus.getDefault().post(event)
}
/**
......
......@@ -14,6 +14,10 @@ class ShareData : Serializable {
var cover: String? = null
var desc: String? = null
// just for Meditation
var type:String? = null
var isDarkMode = false
//分享到动态url
var url: String? = null
......
package com.ydl.ydlcommon.event
class MeditationEvent(
val mediaId: Int,
val meditationId: Long,
val meditationType: Int,
val businessType: Int,
val status: Int,
val buried: String,
val mediaUrl: String,
val mediaCoverUrl: String,
val title: String,
val desc: String
) {
override fun toString(): String {
return "MeditationEvent(mediaId=$mediaId, meditationId=$meditationId, meditationType=$meditationType, businessType=$businessType, status=$status, buried='$buried', mediaUrl='$mediaUrl', mediaCoverUrl='$mediaCoverUrl', title='$title', desc='$desc')"
}
}
\ No newline at end of file
package com.ydl.ydlcommon.event
class MeditationFloatEvent(
val show: Boolean,
val stop: Boolean? = null,
val time: Long? = null
// val meditation: MeditationPlayModuleBean.MeditationDetail? = null,
// val meditations: ArrayList<MeditationPlayModuleBean.MeditationDetail>? = null
)
\ No newline at end of file
......@@ -61,6 +61,8 @@ interface IYDLRouterConstant{
const val ROUTER_CHAT_CONSULT_ASSISTANT = ROUTER_BASE + "chat/ChatService"
//冥想过渡页面
const val ROUTER_MUSE_CENTER = ROUTER_BASE + "muse/MuseService"
//冥想播放页面
const val ROUTER_MUSE_PLAY = ROUTER_BASE + "muse/play"
/**
* 参数名称
*/
......
package com.ydl.event
/**
* h5页面内访问URL
*/
class ReloadUrlEvent {
var url: String? = null
constructor(url: String) {
this.url = url
}
}
\ No newline at end of file
package com.ydl.view
import android.app.Activity
import android.graphics.Color
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.DialogFragment
import com.umeng.socialize.bean.SHARE_MEDIA
import com.ydl.webview.R
import com.ydl.ydlcommon.actions.share.ShareUtils
class ShareMeditationDialog : DialogFragment() {
private var llRootLayout:ConstraintLayout?=null
private var llWeChat: LinearLayout? = null
private var llCircleOfFriends: LinearLayout? = null
private var llSave: LinearLayout? = null
private var llQQZone: LinearLayout? = null
private var llQQFriend: LinearLayout? = null
private var ivWeChat: ImageView? = null
private var ivCircleOfFriends: ImageView? = null
private var ivQQZone: ImageView? = null
private var ivQQFriend: ImageView? = null
private var tvWeChat: TextView? = null
private var tvCircleOfFriends: TextView? = null
private var tvQQZone: TextView? = null
private var tvQQFriend: TextView? = null
private var tvCancel: TextView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.share_meditation_dialog)
}
override fun onStart() {
super.onStart()
val displayMetrics = DisplayMetrics()
activity?.windowManager?.defaultDisplay?.getMetrics(displayMetrics)
val window = dialog?.window
window?.setLayout(MATCH_PARENT, MATCH_PARENT)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.layout_share_meditation_dialog, container)
initView(view)
return view
}
private fun initView(view: View?) {
val isDarkMode = arguments?.getBoolean(KEY_SHARE_DARK_MODE)
val shareUrl = arguments?.getString(KEY_SHARE_URL)
val shareTitle = arguments?.getString(KEY_SHARE_TITLE)
val shareContent = arguments?.getString(KEY_SHARE_CONTENT)
val shareCover = arguments?.getString(KEY_SHARE_COVER)
llRootLayout = view?.findViewById(R.id.csl_share_layout)
llWeChat = view?.findViewById(R.id.ll_wechat_friend)
llCircleOfFriends = view?.findViewById(R.id.ll_wechat_circle_of_friends)
llSave = view?.findViewById(R.id.ll_save_picture)
llQQZone = view?.findViewById(R.id.ll_qq_zone)
llQQFriend = view?.findViewById(R.id.ll_qq_friend)
ivWeChat = view?.findViewById(R.id.iv_wechat)
tvWeChat = view?.findViewById(R.id.tv_wechat)
ivCircleOfFriends = view?.findViewById(R.id.iv_circle)
tvCircleOfFriends = view?.findViewById(R.id.tv_circle)
ivQQZone = view?.findViewById(R.id.iv_qq_zone)
tvQQZone = view?.findViewById(R.id.tv_qq_zone)
ivQQFriend = view?.findViewById(R.id.iv_qq)
tvQQFriend = view?.findViewById(R.id.tv_qq)
tvCancel = view?.findViewById(R.id.tv_cancel_share)
updateUI(isDarkMode == true)
llWeChat?.setOnClickListener {
ShareUtils.shareTo(
SHARE_MEDIA.WEIXIN,
activity as Activity,
shareTitle!!,
shareUrl!!,
shareContent!!,
shareCover!!
)
dismiss()
}
llCircleOfFriends?.setOnClickListener {
ShareUtils.shareTo(
SHARE_MEDIA.WEIXIN_CIRCLE,
activity as Activity,
shareTitle!!,
shareUrl!!,
shareContent!!,
shareCover!!
)
dismiss()
}
llSave?.setOnClickListener {
dismiss()
}
llQQZone?.setOnClickListener {
ShareUtils.shareTo(
SHARE_MEDIA.QZONE,
activity as Activity,
shareTitle!!,
shareUrl!!,
shareContent!!,
shareCover!!
)
dismiss()
}
llQQFriend?.setOnClickListener {
ShareUtils.shareTo(
SHARE_MEDIA.QQ,
activity as Activity,
shareTitle!!,
shareUrl!!,
shareContent!!,
shareCover!!
)
dismiss()
}
tvCancel?.setOnClickListener {
dismiss()
}
}
private fun updateUI(isDarkMode: Boolean){
if (isDarkMode){
llRootLayout?.setBackgroundResource(R.drawable.bg_share_play_meditation_bottom_dark)
ivWeChat?.setImageResource(R.drawable.ic_icon_weixin)
ivCircleOfFriends?.setImageResource(R.drawable.ic_icon_friends)
ivQQZone?.setImageResource(R.drawable.ic_icon_qqzone)
ivQQFriend?.setImageResource(R.drawable.ic_icon_qq)
tvWeChat?.setTextColor(Color.parseColor("#FF84AACE"))
tvCircleOfFriends?.setTextColor(Color.parseColor("#FF84AACE"))
tvQQZone?.setTextColor(Color.parseColor("#FF84AACE"))
tvQQFriend?.setTextColor(Color.parseColor("#FF84AACE"))
tvCancel?.setTextColor(Color.parseColor("#FFFFFFFF"))
}else{
llRootLayout?.setBackgroundResource(R.drawable.bg_share_play_meditation_bottom)
ivWeChat?.setImageResource(R.drawable.icon_meditation_share_wechat)
ivCircleOfFriends?.setImageResource(R.drawable.icon_meditation_share_friends)
ivQQZone?.setImageResource(R.drawable.icon_meditation_share_qqzone)
ivQQFriend?.setImageResource(R.drawable.icon_meditation_share_qq)
tvWeChat?.setTextColor(Color.parseColor("#FF666666"))
tvCircleOfFriends?.setTextColor(Color.parseColor("#FF666666"))
tvQQZone?.setTextColor(Color.parseColor("#FF666666"))
tvQQFriend?.setTextColor(Color.parseColor("#FF666666"))
tvCancel?.setTextColor(Color.parseColor("#FF242424"))
}
}
companion object {
const val TAG = "ShareMeditationDialog"
private const val KEY_SHARE_DARK_MODE = "key_share_dark_mode"
private const val KEY_SHARE_URL = "key_share_url"
private const val KEY_SHARE_TITLE = "key_share_title"
private const val KEY_SHARE_CONTENT = "key_share_content"
private const val KEY_SHARE_COVER = "key_share_cover"
fun newInstance(isDarkMode: Boolean,shareUrl:String,shareTitle:String,
shareContent:String,shareCover:String): ShareMeditationDialog {
val args = Bundle()
args.putBoolean(KEY_SHARE_DARK_MODE, isDarkMode)
args.putString(KEY_SHARE_URL, shareUrl)
args.putString(KEY_SHARE_TITLE, shareTitle)
args.putString(KEY_SHARE_CONTENT, shareContent)
args.putString(KEY_SHARE_COVER, shareCover)
val fragment = ShareMeditationDialog()
fragment.arguments = args
return fragment
}
}
}
\ No newline at end of file
......@@ -145,6 +145,34 @@ class H5JsBean {
var merchantType:String=""
var day:String="" // 预约日期
// meditation start
// {"meditationId":21,"mediaId":15,"meditionType":1,"status":0,
// "coverImageUrl":"https://pic.ydlcdn.com/NsBRkaxNba.png",
// "title":"创建冥想-标题-20",
// "desc":"冥想测试数据基础入门1冥想测试数据基础入门1冥想测试数据基础入门1冥想测试数据基础入门1冥想测试数据基础入门1",
// "duration":250.9845}
var meditationId:Int?=null
var mediaId:Int?=null
var meditionType:Int?=null
var status = 0
var coverImageUrl:String?=null
var desc:String?=null
var mediaUrl:String?=null
var duration:Double?=null
var businessType:Int?=null
var share_url:String?=null
var cover:String?=null
var isDarkMode = false
var buried:String?=null
val color:String?=null
val alpha:String?=null
// meditation end
}
}
}
......@@ -9,6 +9,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
......@@ -34,13 +35,16 @@ import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;
import com.umeng.socialize.UMShareAPI;
import com.umeng.socialize.bean.SHARE_MEDIA;
import com.ydl.event.ReloadUrlEvent;
import com.ydl.utils.PopUtils;
import com.ydl.utils.ProxyCheckUtils;
import com.ydl.utils.WebUrlParamsUtils;
import com.ydl.view.ShareMeditationDialog;
import com.ydl.ydl_router.manager.YDLRouterManager;
import com.ydl.ydlcommon.base.BaseActivity;
import com.ydl.ydlcommon.base.BaseApp;
import com.ydl.ydlcommon.bean.StatusBarOptions;
import com.ydl.ydlcommon.event.MeditationEvent;
import com.ydl.ydlcommon.modular.ModularServiceManager;
import com.ydl.ydlcommon.ui.LogoLoadingView;
import com.ydl.ydlcommon.utils.ActivityManager;
......@@ -116,6 +120,10 @@ public class NewH5Activity extends BaseActivity implements PtrHandler {
protected String shareDesc;
private String cover;
private boolean isDarkMode = false;
private ShareMeditationDialog shareMeditationDialog;
protected PopupWindow popupWindow;
protected ValueCallback<Uri> uploadMessage;
......@@ -285,6 +293,7 @@ public class NewH5Activity extends BaseActivity implements PtrHandler {
R.anim.platform_activity_anim_out);
}
private void initTimeOutHandler() {
mTimeOutHandler = new Handler(msg -> {
if (wv_content.getProgress() < 100) {
......@@ -525,6 +534,20 @@ public class NewH5Activity extends BaseActivity implements PtrHandler {
public void openShareMenu(H5JsBean.H5JsCmd.Params params) {
if (params.getShare() != null) {
if (params.getShare().getType().equals("Meditation")){
shareUrl = params.getShare().getShare_url();
shareTitle = params.getShare().getTitle();
shareDesc = params.getShare().getDesc();
cover = params.getShare().getCover();
isDarkMode = params.getShare().isDarkMode();
if(shareMeditationDialog == null){
shareMeditationDialog = ShareMeditationDialog.Companion.newInstance(isDarkMode,
shareUrl,shareTitle,shareDesc,cover);
}
if (shareMeditationDialog!=null && !shareMeditationDialog.isAdded()){
shareMeditationDialog.show(getSupportFragmentManager(),"share_meditation");
}
}else{
purl = params.getShare().getUrl();
shareUrl = params.getShare().getShare_url();
shareTitle = params.getShare().getTitle();
......@@ -535,6 +558,7 @@ public class NewH5Activity extends BaseActivity implements PtrHandler {
share(base64DataStr, params);
}
}
}
private void initView() {
......@@ -1479,4 +1503,25 @@ public class NewH5Activity extends BaseActivity implements PtrHandler {
this.startActivity(WebModularServiceUtils.Companion.getDynamicService().publishArticleToTrend(NewH5Activity.this, url, cover, shareTitle));
}
public void switchSound(int mediaId, long meditationId, int meditationType, int businessType,
String buried, String mediaUrl, String mediaCoverUrl,
String title, String desc, int status){
MeditationEvent event = new MeditationEvent(
mediaId,meditationId,meditationType,businessType,
status,buried,mediaUrl,mediaCoverUrl,title,desc);
EventBus.getDefault().post(event);
}
public void setBG(String color,String alpha){
try {
store_house_ptr_frame.setBackgroundColor(Color.parseColor(color));
int a = Integer.valueOf(alpha);
store_house_ptr_frame.getBackground().setAlpha(a);
}catch (Exception ex){
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFFFF"/>
<corners android:radius="20dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FF2B5C8E"/>
<corners android:radius="20dp"/>
</shape>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#282E3F"
android:fillAlpha="0.29826814"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M23.1313,12.621C23.7797,12.8952 24.4004,13.2595 24.9725,13.7126C25.2067,13.8971 25.4335,14.0965 25.6498,14.3121C26.1557,14.8156 26.5758,15.3732 26.9174,15.9625C27.0029,16.1105 27.0848,16.2612 27.1599,16.4128L23.1313,20.4269C23.171,20.1853 23.1313,12.621 23.1313,12.621L23.1313,12.621ZM19.1074,12.0532C19.4038,12.0184 19.705,12 20.0115,12C20.727,12 21.421,12.0967 22.0804,12.2733C22.246,12.319 22.4103,12.3682 22.5713,12.4229L22.5713,18.0988C22.4275,17.901 17.0299,12.5784 17.0299,12.5784C17.6844,12.3162 18.3808,12.1353 19.1074,12.0531L19.1074,12.0532ZM13.7248,15.0349C13.9107,14.8029 14.1092,14.5764 14.3268,14.3604C14.8324,13.8569 15.3909,13.4371 15.9839,13.0973C16.1316,13.0121 16.2833,12.9321 16.4366,12.8557L20.4648,16.8695C20.2223,16.8308 12.629,16.871 12.629,16.871C12.9048,16.2234 13.27,15.6052 13.7249,15.0349L13.7248,15.0349ZM12.0542,20.8909C12.0194,20.5958 12,20.2943 12,19.9902C12,19.2768 12.0969,18.5869 12.2745,17.9294C12.3197,17.7641 12.3693,17.5995 12.4237,17.4401L18.1214,17.4401C17.9217,17.5829 12.5819,22.9605 12.5819,22.9605C12.3163,22.3096 12.1363,21.6155 12.0541,20.8909L12.0542,20.8909ZM15.0223,26.2485C14.7881,26.0636 14.5607,25.8652 14.3452,25.6501C13.8387,25.1457 13.4174,24.5888 13.0771,23.9983C12.9915,23.8506 12.91,23.7008 12.8346,23.547L16.8619,19.5332C16.8228,19.7757 16.8643,27.3403 16.8643,27.3403C16.2141,27.0658 15.5956,26.7021 15.0223,26.2485L15.0223,26.2485ZM20.892,27.9468C20.5959,27.9807 20.294,28 19.9885,28C19.2724,28 18.58,27.9033 17.9199,27.7257C17.7546,27.6816 17.5906,27.6315 17.4287,27.5771L17.4287,21.9006C17.5724,22.0996 22.9698,27.4204 22.9692,27.4204C22.3149,27.6838 21.6182,27.8641 20.892,27.9469L20.892,27.9468ZM26.2358,24.9953C26.0496,25.2285 25.8502,25.455 25.6351,25.6701C25.1285,26.1748 24.5694,26.5943 23.9779,26.9335C23.8287,27.0193 23.6785,27.0993 23.5249,27.1748L19.4964,23.1616C19.7395,23.2003 27.3316,23.1607 27.3316,23.1607C27.0562,23.8074 26.69,24.4247 26.2358,24.9953L26.2358,24.9953ZM27.7246,22.0746C27.6794,22.2395 27.6298,22.4035 27.5753,22.5636L21.8786,22.5636C22.0783,22.4204 27.4184,17.0429 27.4184,17.0429C27.6827,17.6944 27.8634,18.3881 27.9458,19.1124C27.9806,19.4078 28,19.7087 28,20.0134C27.9997,20.7268 27.9024,21.4161 27.7246,22.0746L27.7246,22.0746Z"
android:strokeWidth="1"
android:fillColor="#5DD180"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#282E3F"
android:fillAlpha="0.29826814"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M25.9967,24.9517C25.6549,25.0114 24.6864,23.3409 24.6864,23.3409C24.6864,24.2955 24.2307,25.4886 23.2052,26.3835C23.661,26.5625 24.8004,26.9801 24.5155,27.3977C24.2876,27.7557 20.9265,27.6364 19.9581,27.517C18.9896,27.6364 15.5715,27.7557 15.4006,27.3977C15.1158,26.9205 16.2551,26.5028 16.7109,26.3835C15.7424,25.5483 15.2867,24.3551 15.2867,23.4006C15.2867,23.4006 14.3182,25.0114 13.9764,25.0114C13.8055,25.0114 13.6346,24.1165 14.2612,22.0284C14.5461,21.0142 14.8879,20.2386 15.4006,18.8665C15.3436,15.2869 16.7109,12.3636 20.015,12.3636C23.2622,12.3636 24.6864,15.2273 24.6294,18.8068C25.1422,20.179 25.484,21.0142 25.7688,21.9687C26.3954,24.0568 26.1676,24.9517 25.9967,24.9517L25.9967,24.9517Z"
android:strokeWidth="1"
android:fillColor="#6CAAFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#282E3F"
android:fillAlpha="0.29826814"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M24.5371,23.1482L19.0981,22.7394L19.0981,22.7121L19.1259,22.7121C19.2388,22.5763 19.4178,22.5116 19.5699,22.4123C19.9106,22.1895 20.2481,21.96 20.5966,21.7308C21.5062,21.1327 22.397,20.4672 23.2883,19.8501C23.5294,19.6832 24.0773,19.3825 24.2318,19.1687C24.3126,19.0569 24.3701,18.8507 24.2873,18.7325C24.2161,18.5306 23.9116,18.5963 23.6491,18.5963L21.8176,18.5963C21.6395,18.7032 20.664,18.6235 20.3746,18.6235L16.7949,18.678C16.5021,18.6785 15.5033,18.5968 15.3242,18.7053C15.6888,18.7017 16.0633,18.7696 16.3787,18.8416C16.8017,18.938 17.2362,18.916 17.6274,19.0051L18.0714,19.0324C18.7288,19.1835 19.4932,19.1824 20.1526,19.3322C20.5758,19.4284 21.0101,19.4069 21.4014,19.4957C21.5908,19.5387 21.8017,19.4815 21.9286,19.5775L21.8731,19.5775C21.5086,19.8981 20.8158,20.1303 20.3746,20.3952C19.2713,21.0577 18.1107,21.6518 17.0169,22.3305C16.7813,22.4767 16.3661,22.7083 16.2399,22.9574C16.1552,23.1246 16.2005,23.5126 16.3509,23.5843L16.7949,23.5843L24.5371,23.23L24.5371,23.1482C24.7844,23.1418 25.2367,23.1198 25.3973,23.23L24.5648,23.2572L25.3973,28L25.3418,28C25.084,27.7533 24.3653,27.5 24.0098,27.3186C23.101,26.8547 22.1835,26.3978 21.2626,25.9284C20.9439,25.766 20.6241,25.6073 20.2914,25.4378C20.2216,25.4023 20.0625,25.247 19.9584,25.2743C19.9168,25.2852 19.8114,25.3864 19.7641,25.4106C19.47,25.5606 19.1818,25.7043 18.9039,25.8467C17.9109,26.3557 16.9276,26.8118 15.9347,27.3186C15.5339,27.5231 15.0414,27.8742 14.6027,28L15.6294,22.1942C15.3327,22.0022 15.1033,21.6995 14.8524,21.4583C14.4035,21.0264 13.9391,20.5497 13.4372,20.1772L12.8545,19.5775C12.458,19.2831 12.1213,18.9116 11.7722,18.569C11.6123,18.412 11.3995,18.2938 11.2727,18.1056C11.6153,18.0734 12.0057,18.0154 12.3272,17.9421C12.8,17.8342 13.2759,17.8531 13.7147,17.7513C14.3633,17.6008 15.0379,17.6222 15.6572,17.4787C16.0204,17.3946 17.0809,17.3955 17.2944,17.2334C17.4265,17.0873 17.4757,16.8693 17.5719,16.6882C17.7734,16.309 17.9727,15.912 18.1824,15.5162C18.7947,14.3601 19.4099,13.1813 19.9861,12C20.0085,12.0278 19.996,12.0075 20.0139,12.0545C20.1314,12.1535 20.1606,12.3212 20.2359,12.4634C20.4333,12.8361 20.6152,13.224 20.8186,13.6082L22.7056,17.2606C23.4734,17.3328 24.3847,17.4444 25.1198,17.615C25.7684,17.7655 26.443,17.7441 27.0623,17.8876C27.4347,17.9738 28.5076,17.966 28.7273,18.1329C28.3822,18.3555 28.1621,18.738 27.8393,18.9779C27.6,19.1556 27.4332,19.4051 27.201,19.5775C26.5564,20.0565 25.9953,20.6822 25.4251,21.2402C25.2308,21.4302 24.4001,22.0668 24.3706,22.3032C24.4598,22.4366 24.5136,22.9609 24.5371,23.1482Z"
android:strokeWidth="1"
android:fillColor="#FFBE66"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#282E3F"
android:fillAlpha="0.29826814"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M24.5505,17.4423C27.7242,17.4423 30.5455,19.6578 30.5455,22.3785C30.5455,23.9089 29.4899,25.2727 28.0759,26.2974L28.0759,26.2974L28.6063,28L26.6683,26.9757C25.9653,27.141 25.2539,27.314 24.5505,27.314C21.188,27.314 18.5475,25.1062 18.5475,22.3785C18.5475,19.6578 21.188,17.4423 24.5505,17.4423ZM17.3901,12C20.9355,12 24.0401,14.0773 24.6621,16.8794C24.4313,16.8565 24.1992,16.8409 23.968,16.8409C20.5439,16.8409 17.8373,19.3039 17.8377,22.3372C17.8377,22.8383 17.9174,23.3296 18.0613,23.7923C17.8377,23.8144 17.6133,23.8221 17.3901,23.8221C16.4958,23.8221 15.7695,23.6446 14.8676,23.4757L14.8676,23.4757L12.3454,24.6988L13.0637,22.606C11.2598,21.3894 10.1818,19.8198 10.1818,17.9107C10.1818,14.6013 13.4307,12 17.3901,12ZM22.6032,20.1708C22.2524,20.1708 21.9007,20.5103 21.9007,20.8482C21.9007,21.1881 22.2524,21.5269 22.6032,21.5269C23.1352,21.5269 23.4873,21.1881 23.4873,20.8482C23.4873,20.5103 23.1352,20.1708 22.6032,20.1708ZM26.4889,20.1708C26.1376,20.1708 25.7867,20.5103 25.7867,20.8482C25.7867,21.1881 26.1376,21.5269 26.4889,21.5269C27.0115,21.5269 27.3721,21.1881 27.3721,20.8482C27.3721,20.5103 27.02,20.1708 26.4889,20.1708ZM20.0879,14.9551C19.5525,14.9551 19.0107,15.3012 19.0027,15.8252C19.0027,16.348 19.5448,16.6945 20.0879,16.6945C20.6301,16.6945 20.9894,16.348 20.9894,15.8252C20.9894,15.3016 20.6305,14.9551 20.0879,14.9551ZM15.0432,14.9547C14.5006,14.9547 13.958,15.3008 13.958,15.8244C13.958,16.3476 14.5002,16.6937 15.0432,16.6937C15.5867,16.6937 15.9456,16.3402 15.946,15.8244C15.946,15.3012 15.5867,14.9547 15.0432,14.9547Z"
android:strokeWidth="1"
android:fillColor="#5AC689"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#5DD180"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M23.131,12.621C23.78,12.895 24.4,13.26 24.973,13.713C25.207,13.897 25.433,14.096 25.65,14.312C26.156,14.816 26.576,15.373 26.917,15.962C27.003,16.11 27.085,16.261 27.16,16.413L23.131,20.427C23.171,20.185 23.131,12.621 23.131,12.621L23.131,12.621ZM19.107,12.053C19.404,12.018 19.705,12 20.012,12C20.727,12 21.421,12.097 22.08,12.273C22.246,12.319 22.41,12.368 22.571,12.423L22.571,18.099C22.428,17.901 17.03,12.578 17.03,12.578C17.684,12.316 18.381,12.135 19.107,12.053L19.107,12.053ZM13.725,15.035C13.911,14.803 14.109,14.576 14.327,14.36C14.832,13.857 15.391,13.437 15.984,13.097C16.132,13.012 16.283,12.932 16.437,12.856L20.465,16.87C20.222,16.831 12.629,16.871 12.629,16.871C12.905,16.223 13.27,15.605 13.725,15.035L13.725,15.035ZM12.054,20.891C12.019,20.596 12,20.294 12,19.99C12,19.277 12.097,18.587 12.274,17.929C12.32,17.764 12.369,17.6 12.424,17.44L18.121,17.44C17.922,17.583 12.582,22.96 12.582,22.96C12.316,22.31 12.136,21.615 12.054,20.891L12.054,20.891ZM15.022,26.248C14.788,26.064 14.561,25.865 14.345,25.65C13.839,25.146 13.417,24.589 13.077,23.998C12.992,23.851 12.91,23.701 12.835,23.547L16.862,19.533C16.823,19.776 16.864,27.34 16.864,27.34C16.214,27.066 15.596,26.702 15.022,26.248L15.022,26.248ZM20.892,27.947C20.596,27.981 20.294,28 19.988,28C19.272,28 18.58,27.903 17.92,27.726C17.755,27.682 17.591,27.632 17.429,27.577L17.429,21.901C17.572,22.1 22.97,27.42 22.969,27.42C22.315,27.684 21.618,27.864 20.892,27.947L20.892,27.947ZM26.236,24.995C26.05,25.228 25.85,25.455 25.635,25.67C25.129,26.175 24.569,26.594 23.978,26.933C23.829,27.019 23.679,27.099 23.525,27.175L19.496,23.162C19.74,23.2 27.332,23.161 27.332,23.161C27.056,23.807 26.69,24.425 26.236,24.995L26.236,24.995ZM27.725,22.075C27.679,22.239 27.63,22.403 27.575,22.564L21.879,22.564C22.078,22.42 27.418,17.043 27.418,17.043C27.683,17.694 27.863,18.388 27.946,19.112C27.981,19.408 28,19.709 28,20.013C28,20.727 27.902,21.416 27.725,22.075L27.725,22.075Z"
android:strokeWidth="1"
android:fillType="nonZero"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:startX="31.222"
android:startY="40.376"
android:endX="20.938"
android:endY="23.787"
android:type="linear">
<item android:offset="0" android:color="#FF49B7FC"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#6CAAFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M25.997,24.952C25.655,25.011 24.686,23.341 24.686,23.341C24.686,24.295 24.231,25.489 23.205,26.384C23.661,26.563 24.8,26.98 24.516,27.398C24.288,27.756 20.927,27.636 19.958,27.517C18.99,27.636 15.572,27.756 15.401,27.398C15.116,26.92 16.255,26.503 16.711,26.384C15.742,25.548 15.287,24.355 15.287,23.401C15.287,23.401 14.318,25.011 13.976,25.011C13.806,25.011 13.635,24.116 14.261,22.028C14.546,21.014 14.888,20.239 15.401,18.866C15.344,15.287 16.711,12.364 20.015,12.364C23.262,12.364 24.686,15.227 24.629,18.807C25.142,20.179 25.484,21.014 25.769,21.969C26.395,24.057 26.168,24.952 25.997,24.952L25.997,24.952Z"
android:strokeWidth="1"
android:fillType="evenOdd"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:startX="36.074"
android:startY="47.516"
android:endX="20.015"
android:endY="24.704"
android:type="linear">
<item android:offset="0" android:color="#FF459FFC"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#FFBE66"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M24.537,23.148L19.098,22.739L19.098,22.712L19.126,22.712C19.239,22.576 19.418,22.512 19.57,22.412C19.911,22.189 20.248,21.96 20.597,21.731C21.506,21.133 22.397,20.467 23.288,19.85C23.529,19.683 24.077,19.383 24.232,19.169C24.313,19.057 24.37,18.851 24.287,18.733C24.216,18.531 23.912,18.596 23.649,18.596L21.818,18.596C21.639,18.703 20.664,18.624 20.375,18.624L16.795,18.678C16.502,18.679 15.503,18.597 15.324,18.705C15.689,18.702 16.063,18.77 16.379,18.842C16.802,18.938 17.236,18.916 17.627,19.005L18.071,19.032C18.729,19.183 19.493,19.182 20.153,19.332C20.576,19.428 21.01,19.407 21.401,19.496C21.591,19.539 21.802,19.481 21.929,19.578L21.873,19.578C21.509,19.898 20.816,20.13 20.375,20.395C19.271,21.058 18.111,21.652 17.017,22.33C16.781,22.477 16.366,22.708 16.24,22.957C16.155,23.125 16.201,23.513 16.351,23.584L16.795,23.584L24.537,23.23L24.537,23.148C24.784,23.142 25.237,23.12 25.397,23.23L24.565,23.257L25.397,28L25.342,28C25.084,27.753 24.365,27.5 24.01,27.319C23.101,26.855 22.183,26.398 21.263,25.928C20.944,25.766 20.624,25.607 20.291,25.438C20.222,25.402 20.062,25.247 19.958,25.274C19.917,25.285 19.811,25.386 19.764,25.411C19.47,25.561 19.182,25.704 18.904,25.847C17.911,26.356 16.928,26.812 15.935,27.319C15.534,27.523 15.041,27.874 14.603,28L15.629,22.194C15.333,22.002 15.103,21.7 14.852,21.458C14.403,21.026 13.939,20.55 13.437,20.177L12.854,19.578C12.458,19.283 12.121,18.912 11.772,18.569C11.612,18.412 11.399,18.294 11.273,18.106C11.615,18.073 12.006,18.015 12.327,17.942C12.8,17.834 13.276,17.853 13.715,17.751C14.363,17.601 15.038,17.622 15.657,17.479C16.02,17.395 17.081,17.395 17.294,17.233C17.427,17.087 17.476,16.869 17.572,16.688C17.773,16.309 17.973,15.912 18.182,15.516C18.795,14.36 19.41,13.181 19.986,12C20.008,12.028 19.996,12.007 20.014,12.055C20.131,12.154 20.161,12.321 20.236,12.463C20.433,12.836 20.615,13.224 20.819,13.608L22.706,17.261C23.473,17.333 24.385,17.444 25.12,17.615C25.768,17.765 26.443,17.744 27.062,17.888C27.435,17.974 28.508,17.966 28.727,18.133C28.382,18.355 28.162,18.738 27.839,18.978C27.6,19.156 27.433,19.405 27.201,19.578C26.556,20.056 25.995,20.682 25.425,21.24C25.231,21.43 24.4,22.067 24.371,22.303C24.46,22.437 24.514,22.961 24.537,23.148Z"
android:strokeWidth="1"
android:fillType="evenOdd"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:startX="29.642"
android:startY="35.648"
android:endX="20"
android:endY="25.049"
android:type="linear">
<item android:offset="0" android:color="#FFFCA629"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#DDF2FF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M29,22.42L29,27.802C29,28.348 28.558,28.791 28.012,28.791L12.989,28.791C12.443,28.791 12,28.348 12,27.802L12,22.42C12,21.874 12.443,21.431 12.988,21.431C13.534,21.431 13.977,21.874 13.977,22.42L13.977,26.814L27.023,26.814L27.023,22.42C27.023,21.874 27.466,21.431 28.012,21.431C28.557,21.431 29,21.874 29,22.42Z"
android:strokeWidth="1"
android:fillColor="#1DA1F2"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
<path
android:pathData="M19.794,23.659C19.98,23.849 20.235,23.956 20.5,23.956C20.766,23.956 21.02,23.849 21.206,23.659L25.149,19.634C25.531,19.244 25.525,18.618 25.135,18.236C24.745,17.854 24.119,17.861 23.737,18.251L21.488,20.546L21.488,11.988C21.488,11.443 21.046,11 20.5,11C19.954,11 19.512,11.443 19.512,11.988L19.512,20.546L17.264,18.251C16.882,17.861 16.256,17.854 15.866,18.236C15.476,18.618 15.469,19.244 15.851,19.634L19.794,23.659Z"
android:strokeWidth="1"
android:fillColor="#1DA1F2"
android:fillType="nonZero"
android:strokeColor="#00000000"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0"
android:strokeWidth="1"
android:fillColor="#5AC689"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
<path
android:pathData="M24.55,17.442C27.724,17.442 30.545,19.658 30.545,22.379C30.545,23.909 29.49,25.273 28.076,26.297L28.076,26.297L28.606,28L26.668,26.976C25.965,27.141 25.254,27.314 24.55,27.314C21.188,27.314 18.547,25.106 18.547,22.379C18.547,19.658 21.188,17.442 24.55,17.442ZM17.39,12C20.936,12 24.04,14.077 24.662,16.879C24.431,16.856 24.199,16.841 23.968,16.841C20.544,16.841 17.837,19.304 17.838,22.337C17.838,22.838 17.917,23.33 18.061,23.792C17.838,23.814 17.613,23.822 17.39,23.822C16.496,23.822 15.77,23.645 14.868,23.476L14.868,23.476L12.345,24.699L13.064,22.606C11.26,21.389 10.182,19.82 10.182,17.911C10.182,14.601 13.431,12 17.39,12ZM22.603,20.171C22.252,20.171 21.901,20.51 21.901,20.848C21.901,21.188 22.252,21.527 22.603,21.527C23.135,21.527 23.487,21.188 23.487,20.848C23.487,20.51 23.135,20.171 22.603,20.171ZM26.489,20.171C26.138,20.171 25.787,20.51 25.787,20.848C25.787,21.188 26.138,21.527 26.489,21.527C27.012,21.527 27.372,21.188 27.372,20.848C27.372,20.51 27.02,20.171 26.489,20.171ZM20.088,14.955C19.552,14.955 19.011,15.301 19.003,15.825C19.003,16.348 19.545,16.694 20.088,16.694C20.63,16.694 20.989,16.348 20.989,15.825C20.989,15.302 20.63,14.955 20.088,14.955ZM15.043,14.955C14.501,14.955 13.958,15.301 13.958,15.824C13.958,16.348 14.5,16.694 15.043,16.694C15.587,16.694 15.946,16.34 15.946,15.824C15.946,15.301 15.587,14.955 15.043,14.955Z"
android:strokeWidth="1"
android:fillType="nonZero"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:startX="49.894"
android:startY="36.333"
android:endX="22.633"
android:endY="23.033"
android:type="linear">
<item android:offset="0" android:color="#FF43E07D"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
</vector>
<?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:id="@+id/csl_root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#5D000000">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/csl_share_layout"
android:layout_width="match_parent"
android:layout_height="176dp"
android:layout_margin="20dp"
android:background="@drawable/bg_share_play_meditation_bottom"
android:paddingHorizontal="15dp"
android:paddingTop="28dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<LinearLayout
android:id="@+id/ll_wechat_friend"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_wechat_circle_of_friends"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_wechat"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/icon_meditation_share_wechat" />
<TextView
android:id="@+id/tv_wechat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="微信好友"
android:textColor="#FF666666"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_wechat_circle_of_friends"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_save_picture"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/ll_wechat_friend"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_circle"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/icon_meditation_share_friends" />
<TextView
android:id="@+id/tv_circle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="朋友圈"
android:textColor="#FF666666"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_save_picture"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:visibility="gone"
app:layout_constraintEnd_toStartOf="@id/ll_qq_zone"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/ll_wechat_circle_of_friends"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/icon_meditation_share_save" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="保存图片"
android:textColor="#FF666666"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_qq_zone"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_qq_friend"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/ll_save_picture"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_qq_zone"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/icon_meditation_share_qqzone" />
<TextView
android:id="@+id/tv_qq_zone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="QQ空间"
android:textColor="#FF666666"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_qq_friend"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/ll_qq_zone"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_qq"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/icon_meditation_share_qq" />
<TextView
android:id="@+id/tv_qq"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="QQ好友"
android:textColor="#FF666666"
android:textSize="14sp" />
</LinearLayout>
<TextView
android:id="@+id/tv_cancel_share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="取消"
android:textColor="#FF242424"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -3,7 +3,8 @@
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:layout_height="match_parent"
android:id="@+id/rl_root">
<com.ydl.ydlcommon.ui.LogoLoadingView
android:id="@+id/v_loading"
......@@ -51,6 +52,7 @@
android:id="@+id/wv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/platform_transparent"/>
</in.srain.cube.views.ptr.PtrFrameLayout>
</LinearLayout>
......
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="share_meditation_dialog" parent="Theme.Design.BottomSheetDialog">
<item name="android:windowIsFloating">true</item>
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowSoftInputMode">adjustResize</item>
</style>
</resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment