Commit 6e1fa956 by 万齐军

Merge branch 'feat/qj/confide_2.0' into 'd/v_confide_2.0'

confide 2.0

See merge request app_android_lib/YDL-Component!17
parents eb8a5a47 59882ebd
/*___Generated_by_IDEA___*/
package com.ydl.component;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}
\ No newline at end of file
/*___Generated_by_IDEA___*/
package com.ydl.component;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}
\ No newline at end of file
/*___Generated_by_IDEA___*/
package com.ydl.component;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}
\ No newline at end of file
...@@ -6,7 +6,6 @@ import android.graphics.Color ...@@ -6,7 +6,6 @@ import android.graphics.Color
import android.os.Build import android.os.Build
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SimpleItemAnimator import androidx.recyclerview.widget.SimpleItemAnimator
import com.alibaba.android.arouter.facade.annotation.Route import com.alibaba.android.arouter.facade.annotation.Route
...@@ -36,16 +35,12 @@ import com.ydl.webview.NewH5Activity ...@@ -36,16 +35,12 @@ import com.ydl.webview.NewH5Activity
import com.ydl.ydl_image.listener.YDLImageRecyclerOnScrollListener import com.ydl.ydl_image.listener.YDLImageRecyclerOnScrollListener
import com.ydl.ydlcommon.base.config.HttpConfig.Companion.H5_URL import com.ydl.ydlcommon.base.config.HttpConfig.Companion.H5_URL
import com.ydl.ydlcommon.base.config.HttpConfig.Companion.YDL_H5 import com.ydl.ydlcommon.base.config.HttpConfig.Companion.YDL_H5
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.ydl.ydlcommon.mvp.lce.BaseLceActivity import com.ydl.ydlcommon.mvp.lce.BaseLceActivity
import com.ydl.ydlcommon.utils.BuryPointUtils import com.ydl.ydlcommon.utils.BuryPointUtils
import com.ydl.ydlcommon.utils.LogUtil
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.ydl.ydlcommon.utils.remind.ToastHelper import com.ydl.ydlcommon.utils.remind.ToastHelper
import com.ydl.ydlcommon.view.DrawableRightTextView import com.ydl.ydlcommon.view.DrawableRightTextView
import com.ydl.ydlcommon.view.WrapContentLinearLayoutManager import com.ydl.ydlcommon.view.WrapContentLinearLayoutManager
import com.yidianling.common.tools.RxImageTool import com.yidianling.common.tools.RxImageTool
import com.yidianling.consultant.api.IConsultantService
import com.yidianling.im.api.service.IImService import com.yidianling.im.api.service.IImService
import kotlinx.android.synthetic.main.confide_home_activity.* import kotlinx.android.synthetic.main.confide_home_activity.*
import kotlinx.android.synthetic.main.confide_title_bar.* import kotlinx.android.synthetic.main.confide_title_bar.*
...@@ -140,6 +135,7 @@ class ConfideHomeActivity : BaseLceActivity<IConfideHomeContract.View,IConfideHo ...@@ -140,6 +135,7 @@ class ConfideHomeActivity : BaseLceActivity<IConfideHomeContract.View,IConfideHo
//重置页 //重置页
page = 1 page = 1
allFiltersBean!!.page = page allFiltersBean!!.page = page
clearCacheData()
mPresenter.confideHomeRequest(true) mPresenter.confideHomeRequest(true)
recommendList(page) recommendList(page)
} }
...@@ -329,9 +325,8 @@ class ConfideHomeActivity : BaseLceActivity<IConfideHomeContract.View,IConfideHo ...@@ -329,9 +325,8 @@ class ConfideHomeActivity : BaseLceActivity<IConfideHomeContract.View,IConfideHo
override fun confideHomeResponse(list: MutableList<ConfideHomeDataBean>) { override fun confideHomeResponse(list: MutableList<ConfideHomeDataBean>) {
initParam() initParam()
hideError() hideError()
updateCacheData(list) cacheList?.addAll(0, list)
updateAdapter() updateAdapter()
updateQuickConsultUrl()
setSuspendListener() setSuspendListener()
v_filterView.refreshView() v_filterView.refreshView()
} }
...@@ -350,18 +345,6 @@ class ConfideHomeActivity : BaseLceActivity<IConfideHomeContract.View,IConfideHo ...@@ -350,18 +345,6 @@ class ConfideHomeActivity : BaseLceActivity<IConfideHomeContract.View,IConfideHo
} }
/** /**
* 更新一键倾诉按钮url
*/
private fun updateQuickConsultUrl() {
//这边用try catch的原因是防止因为接口数据结构变化导致cacheList!![1].body!![1].linkUrl获取失败
quickConsultUrl = try {
cacheList!![1].body!![1].linkUrl
}catch (e: Exception) {
"https://h5.ydl.com/confideMatch"
}
}
/**
* 更新适配器数据 * 更新适配器数据
*/ */
private fun updateAdapter() { private fun updateAdapter() {
...@@ -391,34 +374,6 @@ class ConfideHomeActivity : BaseLceActivity<IConfideHomeContract.View,IConfideHo ...@@ -391,34 +374,6 @@ class ConfideHomeActivity : BaseLceActivity<IConfideHomeContract.View,IConfideHo
} }
/** /**
* 更新缓存数据
*/
private fun updateCacheData(list: List<ConfideHomeDataBean>) {
clearCacheData()
var soundBean: ConfideHomeDataBean? = null
for (index in 0 until list.size) {
//将听声寻人数据取出 最后加入
when {
//听声寻人
list[index].type == IConfideHomeConfig.TYPE_SOUND -> soundBean = list[index]
//为你推荐
list[index].type == IConfideHomeConfig.TYPE_RECOMMEND -> {
//如果为你推荐的数量大于等于10条 就认为有下一页
hasMore = null != list[index].body && list[index].body!!.size >= 10
list[index].recommendId = page
(cacheList as ArrayList).add(list[index])
}
//其他模块正常添加
else -> (cacheList as ArrayList).add(list[index])
}
}
//听声寻人 放在最后添加
if (null != soundBean) {
(cacheList as ArrayList).add(soundBean)
}
}
/**
* 根据筛选条件 更新为你推荐数据 * 根据筛选条件 更新为你推荐数据
*/ */
private fun updateCacheDataByRecommend(bean: ConfideHomeDataBean) { private fun updateCacheDataByRecommend(bean: ConfideHomeDataBean) {
......
...@@ -29,7 +29,7 @@ class VideoShowAdapter(private val data: List<ConfideHomeBodyBean>?, private val ...@@ -29,7 +29,7 @@ class VideoShowAdapter(private val data: List<ConfideHomeBodyBean>?, private val
override fun onBindViewHolder(holder: BindingViewHolder<ItemVideoShowBinding>, position: Int) { override fun onBindViewHolder(holder: BindingViewHolder<ItemVideoShowBinding>, position: Int) {
val itemVideoShowViewModel = dataList[position] val itemVideoShowViewModel = dataList[position]
holder.binding.item = itemVideoShowViewModel holder.binding.item = itemVideoShowViewModel
holder.itemView.setOnClickListener { /*event.videoShowClick(position, data)*/ } holder.itemView.setOnClickListener { event.videoShowClick(position, data) }
} }
override fun getItemCount() = dataList.size override fun getItemCount() = dataList.size
......
...@@ -87,10 +87,6 @@ interface IConfideHomeContract{ ...@@ -87,10 +87,6 @@ interface IConfideHomeContract{
interface Presenter : IPresenter<View> { interface Presenter : IPresenter<View> {
/** /**
* 加载本地缓存
*/
fun loadLocalData(context: Context)
/**
* 倾诉首页数据请求 * 倾诉首页数据请求
*/ */
fun confideHomeRequest(isRefresh:Boolean = true) fun confideHomeRequest(isRefresh:Boolean = true)
......
...@@ -4,12 +4,12 @@ import android.annotation.SuppressLint ...@@ -4,12 +4,12 @@ import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Color
import android.net.Uri import android.net.Uri
import android.opengl.Visibility
import android.os.Build
import android.text.TextUtils import android.text.TextUtils
import android.view.* import android.view.Gravity
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.alibaba.android.arouter.launcher.ARouter import com.alibaba.android.arouter.launcher.ARouter
...@@ -154,6 +154,7 @@ class ConfideHomeEventImpl(context: Context, var confideHomeView: IConfideHomeCo ...@@ -154,6 +154,7 @@ class ConfideHomeEventImpl(context: Context, var confideHomeView: IConfideHomeCo
override fun videoShowClick(index: Int, data: List<ConfideHomeBodyBean>?) { override fun videoShowClick(index: Int, data: List<ConfideHomeBodyBean>?) {
val dataJson = if (data != null) JSON.toJSONString(data) else null val dataJson = if (data != null) JSON.toJSONString(data) else null
pauseVoice()
ARouter.getInstance().build(ConfideRoute.R_VIDEO_SHOW).withInt("initPos", index) ARouter.getInstance().build(ConfideRoute.R_VIDEO_SHOW).withInt("initPos", index)
.withString("initData", dataJson).navigation() .withString("initData", dataJson).navigation()
} }
......
...@@ -38,4 +38,11 @@ interface ConfideHomeApi { ...@@ -38,4 +38,11 @@ interface ConfideHomeApi {
// 1=在线 3-通话中 2-离线 // 1=在线 3-通话中 2-离线
@GET("auth/listen/dialchangestatus") @GET("auth/listen/dialchangestatus")
fun getDialStatus(@Query("doctorId") doctorId: String): Observable<BaseAPIResponse<DialStatus>> fun getDialStatus(@Query("doctorId") doctorId: String): Observable<BaseAPIResponse<DialStatus>>
@GET
fun recommendDoctor(
@Url url: String,
@Query("page") page: Int,
@Query("businessSource") source: Int
): Observable<BaseAPIResponse<ConfideHomeDataBean>>
} }
\ No newline at end of file
package com.ydl.confide.home.presenter package com.ydl.confide.home.presenter
import android.content.Context
import android.text.TextUtils
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.ydl.confide.home.bean.ConfideHomeDataBean
import com.ydl.confide.home.contract.IConfideHomeContract import com.ydl.confide.home.contract.IConfideHomeContract
import com.ydl.confide.home.http.ConfideRecommendParam import com.ydl.confide.home.http.ConfideRecommendParam
import com.ydl.confide.home.model.ConfideHomeModelImpl import com.ydl.confide.home.model.ConfideHomeModelImpl
import com.ydl.confide.home.util.ConfideHomeUtils
import com.ydl.ydlcommon.data.http.RxUtils import com.ydl.ydlcommon.data.http.RxUtils
import com.ydl.ydlcommon.data.http.ThrowableConsumer import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.ydl.ydlcommon.mvp.base.BasePresenter import com.ydl.ydlcommon.mvp.base.BasePresenter
import com.ydl.ydlcommon.mvp.base.IView import com.ydl.ydlcommon.mvp.base.IView
import com.ydl.ydlcommon.utils.YDLAsyncUtils
import com.ydl.ydlcommon.utils.YDLCacheUtils
import com.yidianling.common.tools.RxNetTool import com.yidianling.common.tools.RxNetTool
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer import io.reactivex.functions.Consumer
...@@ -26,127 +18,77 @@ import io.reactivex.functions.Consumer ...@@ -26,127 +18,77 @@ import io.reactivex.functions.Consumer
* @Company 壹点灵 * @Company 壹点灵
* @date 2018/8/10 * @date 2018/8/10
*/ */
class ConfideHomePresenterImpl : BasePresenter<IConfideHomeContract.View,IConfideHomeContract.Model>(), IConfideHomeContract.Presenter{ class ConfideHomePresenterImpl : BasePresenter<IConfideHomeContract.View, IConfideHomeContract.Model>(),
IConfideHomeContract.Presenter {
override fun createModel(): IConfideHomeContract.Model { override fun createModel(): IConfideHomeContract.Model {
return ConfideHomeModelImpl() return ConfideHomeModelImpl()
} }
/** /**
* 加载本地缓存
*/
override fun loadLocalData(context: Context) {
YDLAsyncUtils.asyncAsResult(object : YDLAsyncUtils.AsyncObjecyerResult{
override fun doAsyncAction(): Any {
//读取缓存数据
var cacheData = YDLCacheUtils.getConfideHomeData()
if (cacheData.isEmpty()) {
cacheData = String(ConfideHomeUtils.getAssertsFile(context, "confide_home.json")!!)
}
return cacheData
}
override fun asyncResult(`object`: Any?) {
//如果没有缓存数据,显示加载框
if (`object` !is String || TextUtils.isEmpty(`object`)){
mView.showLoading()
}
if (`object` is String){
val gson = Gson()
val list = gson.fromJson<MutableList<ConfideHomeDataBean>>(`object`, object : TypeToken<MutableList<ConfideHomeDataBean>>() {
}.type)
if(null != list && !list.isEmpty()){
mView.confideHomeResponse(list)
}
}
confideHomeRequest(false)
}
})
}
/**
* 请求首页数据 * 请求首页数据
*/ */
override fun confideHomeRequest(isRefresh:Boolean) { override fun confideHomeRequest(isRefresh: Boolean) {
if (!RxNetTool.isConnected(mView.getContext())){ if (!RxNetTool.isConnected(mView.getContext())) {
mView.confideHomeRequestFail() mView.confideHomeRequestFail()
return return
} }
val disposable = mModel.confideHomeRequest() val disposable = mModel.confideHomeRequest()
.map { it } .map { it }
.filter { it != null } .filter { it != null }
.compose(RxUtils.applySchedulers(mView as IView)) .compose(RxUtils.applySchedulers(mView as IView))
.doFinally { mView.hideLoading() } .doFinally { mView.hideLoading() }
.subscribe(Consumer { .subscribe(Consumer {
mView.confideHomeResponse(it) mView.confideHomeResponse(it)
updateCache(it) }, object : ThrowableConsumer() {
}, object : ThrowableConsumer() { override fun accept(msg: String) {
override fun accept(msg: String) { mView.confideHomeRequestFail()
mView.confideHomeRequestFail() }
} })
})
}
/**
* 更新本地缓存
*/
private fun updateCache(list : MutableList<ConfideHomeDataBean>){
YDLAsyncUtils.async(object : YDLAsyncUtils.AsyncObjecyer{
override fun doAsyncAction() {
var gson = Gson()
var json = gson.toJson(list)
YDLCacheUtils.saveConfideHomeData(json)
}
})
} }
/** /**
* 为你推荐列表(筛选调用) * 为你推荐列表(筛选调用)
*/ */
override fun recommendList(param : ConfideRecommendParam) { override fun recommendList(param: ConfideRecommendParam) {
if (!RxNetTool.isConnected(mView.getContext())){ if (!RxNetTool.isConnected(mView.getContext())) {
mView.showError1("网络不给力") mView.showError1("网络不给力")
return return
} }
val disposable = mModel.recommendList(param) val disposable = mModel.recommendList(param)
.map { it } .map { it }
.filter { it != null } .filter { it != null }
.compose(RxUtils.applySchedulers(mView as IView)) .compose(RxUtils.applySchedulers(mView as IView))
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer { .subscribe(Consumer {
mView.recommendListResponse(it) mView.recommendListResponse(it)
}, object : ThrowableConsumer() { }, object : ThrowableConsumer() {
override fun accept(msg: String) { override fun accept(msg: String) {
mView.showError1(msg) mView.showError1(msg)
} }
}) })
} }
/** /**
* 为你推荐列表(翻页时调用) * 为你推荐列表(翻页时调用)
*/ */
override fun recommendListMore(param: ConfideRecommendParam) { override fun recommendListMore(param: ConfideRecommendParam) {
if (!RxNetTool.isConnected(mView.getContext())){ if (!RxNetTool.isConnected(mView.getContext())) {
mView.showError1("网络不给力") mView.showError1("网络不给力")
return return
} }
val disposable = mModel.recommendList(param) val disposable = mModel.recommendList(param)
.map { it } .map { it }
.filter { it != null } .filter { it != null }
.compose(RxUtils.applySchedulers(mView as IView)) .compose(RxUtils.applySchedulers(mView as IView))
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer { .subscribe(Consumer {
mView.recommendListMoreResponse(it) mView.recommendListMoreResponse(it)
}, object : ThrowableConsumer() { }, object : ThrowableConsumer() {
override fun accept(msg: String) { override fun accept(msg: String) {
mView.showError(msg) mView.showError(msg)
mView.showError1(msg) mView.showError1(msg)
} }
}) })
} }
} }
\ No newline at end of file
package com.ydl.confide.home.util package com.ydl.confide.home.util
import android.content.Context import android.content.Context
import androidx.core.content.ContextCompat
import androidx.appcompat.widget.AppCompatTextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.text.TextUtils import android.text.TextUtils
import android.view.View import android.view.View
import android.view.animation.AnimationUtils import android.view.animation.AnimationUtils
import android.view.animation.LinearInterpolator import android.view.animation.LinearInterpolator
import android.widget.ImageView import android.widget.ImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.ydl.confide.R import com.ydl.confide.R
import com.ydl.confide.home.adapter.ConfideHomeAdapter import com.ydl.confide.home.adapter.ConfideHomeAdapter
import com.ydl.confide.home.bean.ConfideHomeAllFiltersBean import com.ydl.confide.home.bean.ConfideHomeAllFiltersBean
...@@ -84,32 +84,12 @@ class ConfideHomeUtils { ...@@ -84,32 +84,12 @@ class ConfideHomeUtils {
* 数据重组 * 数据重组
*/ */
fun resetData(list: MutableList<ConfideHomeDataBean>, filterView: ConfideHomeFilterView, listScrollListener: ConfideHomeRecycleViewListener) { fun resetData(list: MutableList<ConfideHomeDataBean>, filterView: ConfideHomeFilterView, listScrollListener: ConfideHomeRecycleViewListener) {
val recommendList: MutableList<ConfideHomeDataBean> = ArrayList() for ((index, dataBean) in list.withIndex()) {
var soundDataBean: ConfideHomeDataBean? = null
for ((index, dataBean) in list.withIndex().reversed()) {
//给隐藏的为你推荐筛选view赋值 //给隐藏的为你推荐筛选view赋值
if (dataBean.type == IConfideHomeConfig.TYPE_RECOMMEND_FILTER) { if (dataBean.type == IConfideHomeConfig.TYPE_RECOMMEND_FILTER) {
listScrollListener.setFilterIndex(index) listScrollListener.setFilterIndex(index)
filterView.initData(dataBean) filterView.initData(dataBean)
} }
//拆分为你推荐数据
if (dataBean.type == IConfideHomeConfig.TYPE_RECOMMEND) {
//如果是为你推荐数据 则进行筛分
recommendList.addAll(getRecommendList(dataBean))
//移除当前 为你推荐数据
list.removeAt(index)
}
//移除听声寻人数据 放在最后
if (dataBean.type == IConfideHomeConfig.TYPE_SOUND) {
soundDataBean = ConfideHomeDataBean(dataBean.type, dataBean.body, dataBean.head, dataBean.footer, dataBean.recommendId)
list.removeAt(index)
}
}
//添加 拆分后的 为你推荐数据
list.addAll(recommendList)
//添加 听声寻人 数据
if (null != soundDataBean) {
list.add(soundDataBean)
} }
} }
......
...@@ -15,28 +15,44 @@ import com.ydl.confide.R ...@@ -15,28 +15,44 @@ import com.ydl.confide.R
import com.ydl.confide.api.ConfideRoute import com.ydl.confide.api.ConfideRoute
import com.ydl.confide.databinding.ActivityExpertIntroBinding import com.ydl.confide.databinding.ActivityExpertIntroBinding
import com.ydl.confide.home.bean.ConfideHomeBodyBean import com.ydl.confide.home.bean.ConfideHomeBodyBean
import com.ydl.confide.home.bean.ConfideHomeDataBean import com.ydl.confide.home.http.ConfideHomeApi
import com.ydl.confide.home.util.ConfideNetworkUtil
import com.ydl.confide.router.PhoneCallIn import com.ydl.confide.router.PhoneCallIn
import com.ydl.webview.H5Params import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity import com.ydl.webview.NewH5Activity
import com.ydl.ydlcommon.base.config.HttpConfig
import com.ydl.ydlcommon.base.config.HttpConfig.Companion.YDL_H5 import com.ydl.ydlcommon.base.config.HttpConfig.Companion.YDL_H5
import com.ydl.ydlcommon.utils.BuryPointUtils import com.ydl.ydlcommon.utils.BuryPointUtils
import com.ydl.ydlcommon.view.dialog.CommonDialog import com.ydl.ydlcommon.utils.LogUtil
import com.ydl.ydlnet.YDLHttpUtils
import com.yidianling.common.tools.ToastUtil
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
@Route(path = ConfideRoute.R_VIDEO_SHOW) @Route(path = ConfideRoute.R_VIDEO_SHOW)
class ExpertIntroActivity : AppCompatActivity() { class ExpertIntroActivity : AppCompatActivity() {
companion object {
private const val SOURCE_VIDEO = 10
}
private val tag = javaClass.simpleName
@Autowired @Autowired
@JvmField @JvmField
var initPos: Int = 0 var initPos: Int = 0
@Autowired @Autowired
@JvmField @JvmField
var initData:String?=null var initData: String? = null
private var lastSelectPos = 0 private var lastSelectPos = 0
private lateinit var binding: ActivityExpertIntroBinding private lateinit var binding: ActivityExpertIntroBinding
private lateinit var adapter: IntroAdapter private lateinit var adapter: IntroAdapter
private var page = 1
private var disposable: Disposable? = null
private val confideApi = YDLHttpUtils.obtainApi(ConfideHomeApi::class.java)
private val data = mutableListOf<VideoViewModel>() private val data = mutableListOf<VideoViewModel>()
...@@ -51,14 +67,14 @@ class ExpertIntroActivity : AppCompatActivity() { ...@@ -51,14 +67,14 @@ class ExpertIntroActivity : AppCompatActivity() {
decorView.systemUiVisibility = option decorView.systemUiVisibility = option
window.statusBarColor = Color.TRANSPARENT window.statusBarColor = Color.TRANSPARENT
} }
if(initData!=null){ if (initData != null) {
val beans = JSON.parseArray(initData, ConfideHomeBodyBean::class.java) val beans = JSON.parseArray(initData, ConfideHomeBodyBean::class.java)
val vms = beans.map { VideoViewModel().mapOf(it) } val vms = beans.map { VideoViewModel().mapOf(it) }
data.addAll(vms) data.addAll(vms)
} }
binding.ivBack.setOnClickListener { onBackPressed() } binding.ivBack.setOnClickListener { onBackPressed() }
binding.tvConfideRecord.setOnClickListener { binding.tvConfideRecord.setOnClickListener {
if (!PhoneCallIn.loginByOneKeyLogin(this,true)) { if (!PhoneCallIn.loginByOneKeyLogin(this, true)) {
return@setOnClickListener return@setOnClickListener
} }
BuryPointUtils.getInstance().createMap() BuryPointUtils.getInstance().createMap()
...@@ -84,11 +100,28 @@ class ExpertIntroActivity : AppCompatActivity() { ...@@ -84,11 +100,28 @@ class ExpertIntroActivity : AppCompatActivity() {
} }
private fun loadMore() { private fun loadMore() {
// data.add(VideoViewModel()) disposable = confideApi.recommendDoctor(HttpConfig.JAVA_BASE_URL + "auth/listen/nsearch?", page, SOURCE_VIDEO)
// data.add(VideoViewModel()) .subscribeOn(Schedulers.io())
// data.add(VideoViewModel()) .observeOn(AndroidSchedulers.mainThread())
// data.add(VideoViewModel()) .subscribe({ resp ->
// data.add(VideoViewModel()) if (resp.code == "200") {
// adapter.notifyItemRangeInserted(data.size - 5, 5) page++
val body = resp.data.body
val map = body?.map { VideoViewModel().mapOf(it) }
map?.let {
data.addAll(it)
adapter.notifyItemRangeInserted(data.size - it.size, it.size)
}
} else {
ToastUtil.toastShort(resp.msg)
}
}, { throwable ->
LogUtil.e(tag, throwable.message)
})
}
override fun onDestroy() {
super.onDestroy()
disposable?.dispose()
} }
} }
\ No newline at end of file
...@@ -3,7 +3,6 @@ package com.ydl.confide.intro ...@@ -3,7 +3,6 @@ package com.ydl.confide.intro
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.databinding.DataBindingUtil import androidx.databinding.DataBindingUtil
...@@ -49,8 +48,7 @@ internal class IntroAdapter( ...@@ -49,8 +48,7 @@ internal class IntroAdapter(
parent, parent,
false false
) )
val holder = ItemIntroHolder(binding) return ItemIntroHolder(binding)
return holder
} }
override fun onBindViewHolder(holder: ItemIntroHolder, position: Int) { override fun onBindViewHolder(holder: ItemIntroHolder, position: Int) {
...@@ -63,10 +61,13 @@ internal class IntroAdapter( ...@@ -63,10 +61,13 @@ internal class IntroAdapter(
override fun onViewAttachedToWindow(holder: ItemIntroHolder) { override fun onViewAttachedToWindow(holder: ItemIntroHolder) {
val adapterPosition = holder.adapterPosition val adapterPosition = holder.adapterPosition
val videoView = IjkVideoView(context) val videoView = IjkVideoView(context)
if (hasAgreePlayWithoutWiFi || ConfideNetworkUtil.isWifi(context)) { val playUrl = data[adapterPosition].playUrl
videoView.setVideoURI(Uri.parse("https://video.ydlcdn.com/2020/04/01/ac2e4bb4e3ac8e2f0eca41e2d49c8484.mp4")) if (!playUrl.isNullOrBlank()) {
} else { if (hasAgreePlayWithoutWiFi || ConfideNetworkUtil.isWifi(context)) {
data[adapterPosition].playUrl?.let { videoView.tag = it } videoView.setVideoURI(Uri.parse(playUrl))
} else {
videoView.tag = playUrl
}
} }
videoViews.put(adapterPosition, videoView) videoViews.put(adapterPosition, videoView)
holder.onAttach(videoView) holder.onAttach(videoView)
...@@ -81,8 +82,9 @@ internal class IntroAdapter( ...@@ -81,8 +82,9 @@ internal class IntroAdapter(
hasAgreePlayWithoutWiFi = true hasAgreePlayWithoutWiFi = true
for (entry in videoViews.entries) { for (entry in videoViews.entries) {
val value = entry.value val value = entry.value
(value.tag as? String)?.let { val playUrl = value.tag as? String
value.setVideoURI(Uri.parse(it)) if (!playUrl.isNullOrBlank()) {
value.setVideoURI(Uri.parse(playUrl))
if (curPos == entry.key) { if (curPos == entry.key) {
value.start() value.start()
} }
...@@ -140,6 +142,21 @@ internal class IntroAdapter( ...@@ -140,6 +142,21 @@ internal class IntroAdapter(
fun onSelect(position: Int) { fun onSelect(position: Int) {
curPos = position curPos = position
onLoadDialStatus(position)
if (!ConfideNetworkUtil.isWifi(context) && !hasAgreePlayWithoutWiFi) {
return
}
for (entry in videoViews.entries) {
if (entry.key == position) {
entry.value.seekTo(0)
entry.value.start()
} else {
entry.value.pause()
}
}
}
private fun onLoadDialStatus(position: Int) {
val confideApi = YDLHttpUtils.obtainApi(ConfideHomeApi::class.java) val confideApi = YDLHttpUtils.obtainApi(ConfideHomeApi::class.java)
val curUid = data[position].uid val curUid = data[position].uid
if (curUid != null) { if (curUid != null) {
...@@ -158,16 +175,6 @@ internal class IntroAdapter( ...@@ -158,16 +175,6 @@ internal class IntroAdapter(
} }
}, { throwable -> throwable.printStackTrace() }) }, { throwable -> throwable.printStackTrace() })
} }
if (!ConfideNetworkUtil.isWifi(context) && !hasAgreePlayWithoutWiFi) {
return
}
for (entry in videoViews.entries) {
if (entry.key == position) {
entry.value.seekTo(0)
entry.value.start()
} else {
entry.value.pause()
}
}
} }
} }
\ No newline at end of file
...@@ -12,6 +12,7 @@ import com.alibaba.android.arouter.launcher.ARouter ...@@ -12,6 +12,7 @@ import com.alibaba.android.arouter.launcher.ARouter
import com.dou361.ijkplayer.widget.IjkVideoView import com.dou361.ijkplayer.widget.IjkVideoView
import com.ydl.confide.databinding.ItemExpertIntroBinding import com.ydl.confide.databinding.ItemExpertIntroBinding
import com.ydl.confide.home.bean.ConfideHomeBodyBean import com.ydl.confide.home.bean.ConfideHomeBodyBean
import com.ydl.ydlcommon.utils.LogUtil
import com.ydl.ydlcommon.view.dialog.YDLShareDialog import com.ydl.ydlcommon.view.dialog.YDLShareDialog
import com.yidianling.im.api.service.IImService import com.yidianling.im.api.service.IImService
import io.reactivex.Observable import io.reactivex.Observable
...@@ -29,6 +30,8 @@ internal class ItemIntroHolder(binding: ItemExpertIntroBinding) : ...@@ -29,6 +30,8 @@ internal class ItemIntroHolder(binding: ItemExpertIntroBinding) :
private var disposable: Disposable? = null private var disposable: Disposable? = null
private var video: IjkVideoView? = null private var video: IjkVideoView? = null
private var vm: VideoViewModel? = null
@Volatile @Volatile
private var isTouch = false private var isTouch = false
...@@ -38,6 +41,7 @@ internal class ItemIntroHolder(binding: ItemExpertIntroBinding) : ...@@ -38,6 +41,7 @@ internal class ItemIntroHolder(binding: ItemExpertIntroBinding) :
} }
fun onBind(item: VideoViewModel) { fun onBind(item: VideoViewModel) {
vm = item
binding.layoutCall.setOnClickListener { } binding.layoutCall.setOnClickListener { }
binding.btnChat.setOnClickListener { binding.btnChat.setOnClickListener {
val aty = it.context as? Activity val aty = it.context as? Activity
...@@ -55,12 +59,22 @@ internal class ItemIntroHolder(binding: ItemExpertIntroBinding) : ...@@ -55,12 +59,22 @@ internal class ItemIntroHolder(binding: ItemExpertIntroBinding) :
} }
} }
binding.videoView.setOnClickListener { binding.videoView.setOnClickListener {
video?.pause() if (video?.canPause() == true) {
binding.ivPlay.visibility = View.VISIBLE video?.pause()
if (item.isVideo) {
binding.ivPlay.visibility = View.VISIBLE
} else {
binding.voicePlay.stop()
}
}
} }
binding.ivPlay.setOnClickListener { binding.ivPlay.setOnClickListener {
video?.start() video?.start()
binding.ivPlay.visibility = View.GONE if (item.isVideo) {
binding.ivPlay.visibility = View.GONE
} else {
binding.voicePlay.start()
}
} }
binding.seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { binding.seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
...@@ -80,6 +94,7 @@ internal class ItemIntroHolder(binding: ItemExpertIntroBinding) : ...@@ -80,6 +94,7 @@ internal class ItemIntroHolder(binding: ItemExpertIntroBinding) :
} }
} }
}) })
binding.voicePlay.visibility = if (item.isVideo) View.GONE else View.VISIBLE
} }
fun onAttach(videoView: IjkVideoView) { fun onAttach(videoView: IjkVideoView) {
...@@ -95,22 +110,36 @@ internal class ItemIntroHolder(binding: ItemExpertIntroBinding) : ...@@ -95,22 +110,36 @@ internal class ItemIntroHolder(binding: ItemExpertIntroBinding) :
} }
} }
video?.setOnInfoListener { mp, what, extra -> video?.setOnInfoListener { mp, what, extra ->
Log.d(TAG, "${what},${extra}") Log.d(TAG, "OnInfo:${what},${extra}")
return@setOnInfoListener false return@setOnInfoListener true
}
video?.setOnCompletionListener {
video?.seekTo(0)
video?.start()
}
video?.setOnErrorListener { player, what, extra ->
LogUtil.e(TAG, "onError:$what,$extra")
return@setOnErrorListener true
} }
video?.setOnCompletionListener { stopTiming() }
startTiming() startTiming()
if (binding.voicePlay.visibility == View.VISIBLE) {
binding.voicePlay.start()
}
} }
private fun startTiming() { private fun startTiming() {
disposable = Observable.interval(300, TimeUnit.MILLISECONDS) disposable = Observable.interval(3, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.computation()) .subscribeOn(Schedulers.computation())
.filter { !isTouch }
.subscribe { .subscribe {
val pos = (video?.mMediaPlayer as IjkMediaPlayer?)?.currentPosition ?: 0 val pos = (video?.mMediaPlayer as IjkMediaPlayer?)?.currentPosition ?: 0
if (pos > 0) { if (pos > 0) {
binding.seekbar.progress = pos.toInt()// video.bufferPercentage if (vm?.isVideo == true) {
binding.ivCover.visibility = View.GONE
}
if (!isTouch) {
binding.seekbar.progress = pos.toInt()// video.bufferPercentage
}
} }
} }
} }
...@@ -127,9 +156,9 @@ class VideoViewModel { ...@@ -127,9 +156,9 @@ class VideoViewModel {
val lineStatus = ObservableInt() val lineStatus = ObservableInt()
val intro = ObservableField<String>("") val intro = ObservableField<String>("")
val tag = ObservableField<String>("") val tag = ObservableField<String>("")
var playUrl: String? = null//"https://video.ydlcdn.com/2020/04/01/ac2e4bb4e3ac8e2f0eca41e2d49c8484.mp4" var playUrl: String? = null
var coverUrl = ObservableField<String>("") var coverUrl = ObservableField<String>("")
var isVideo = true var isVideo = false
var uid: String? = null var uid: String? = null
var linkUrl: String? = null var linkUrl: String? = null
} }
...@@ -141,7 +170,9 @@ internal fun VideoViewModel.mapOf(bean: ConfideHomeBodyBean): VideoViewModel { ...@@ -141,7 +170,9 @@ internal fun VideoViewModel.mapOf(bean: ConfideHomeBodyBean): VideoViewModel {
intro.set(bean.confideContent) intro.set(bean.confideContent)
val sb = StringBuilder() val sb = StringBuilder()
bean.confidedTag?.forEach { sb.append(it).append(" | ") } bean.confidedTag?.forEach { sb.append(it).append(" | ") }
sb.setLength(sb.length - 1) if (sb.isNotEmpty()) {
sb.setLength(sb.length - 3)
}
tag.set(sb.toString()) tag.set(sb.toString())
if (bean.videoUrl != null) { if (bean.videoUrl != null) {
playUrl = bean.videoUrl playUrl = bean.videoUrl
......
...@@ -7,14 +7,14 @@ ...@@ -7,14 +7,14 @@
<shape> <shape>
<corners android:radius="4dp" /> <corners android:radius="4dp" />
<solid android:color="#59FFFFFF" /> <solid android:color="#59FFFFFF" />
<stroke android:width="1dp" /> <stroke android:width="1dp" android:color="@color/transparent"/>
</shape> </shape>
</item> </item>
<item> <item>
<shape> <shape>
<corners android:radius="4dp" /> <corners android:radius="4dp" />
<solid android:color="#59FFFFFF" /> <solid android:color="#59FFFFFF" />
<stroke android:width="2dp" /> <stroke android:width="3dp" android:color="@color/transparent"/>
</shape> </shape>
</item> </item>
</selector> </selector>
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
<shape> <shape>
<corners android:radius="4dp" /> <corners android:radius="4dp" />
<solid android:color="@color/white" /> <solid android:color="@color/white" />
<stroke android:width="1dp" /> <stroke android:width="1dp" android:color="@color/transparent"/>
</shape> </shape>
</clip> </clip>
</item> </item>
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
<shape> <shape>
<corners android:radius="4dp" /> <corners android:radius="4dp" />
<solid android:color="@color/white" /> <solid android:color="@color/white" />
<stroke android:width="2dp" /> <stroke android:width="3dp" android:color="@color/transparent"/>
</shape> </shape>
</clip> </clip>
</item> </item>
......
...@@ -27,6 +27,16 @@ ...@@ -27,6 +27,16 @@
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<ImageView <ImageView
android:id="@+id/ivCover"
android:layout_width="0dp"
android:layout_height="0dp"
app:imageUrl="@{item.coverUrl}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/ivPlay" android:id="@+id/ivPlay"
android:layout_width="76dp" android:layout_width="76dp"
android:layout_height="76dp" android:layout_height="76dp"
...@@ -37,6 +47,18 @@ ...@@ -37,6 +47,18 @@
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<com.yidianling.common.view.ui.VoicePlayingIcon
android:id="@+id/voicePlay"
android:layout_width="76dp"
android:layout_height="76dp"
android:padding="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shape="@{1}"
app:shapeBg="@{0x99000000}" />
<View <View
android:id="@+id/vDisableClick" android:id="@+id/vDisableClick"
android:layout_width="0dp" android:layout_width="0dp"
...@@ -117,14 +139,16 @@ ...@@ -117,14 +139,16 @@
<TextView <TextView
android:id="@+id/tvIntro" android:id="@+id/tvIntro"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginRight="40dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:text="@{item.intro}" android:text="@{item.intro}"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="15sp" android:textSize="15sp"
app:layout_constraintBottom_toTopOf="@+id/tvTag" app:layout_constraintBottom_toTopOf="@+id/tvTag"
app:layout_constraintLeft_toLeftOf="@+id/tvTag" app:layout_constraintLeft_toLeftOf="@+id/tvTag"
app:layout_constraintRight_toLeftOf="@+id/btnShare"
tools:text="tag|tag|tag" /> tools:text="tag|tag|tag" />
<TextView <TextView
...@@ -143,8 +167,9 @@ ...@@ -143,8 +167,9 @@
android:id="@+id/tvConfideCount" android:id="@+id/tvConfideCount"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@color/white" android:layout_marginLeft="8dp"
android:text="@{item.count}" android:text="@{item.count}"
android:textColor="@color/white"
android:textSize="13sp" android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="@+id/tvName" app:layout_constraintBottom_toBottomOf="@+id/tvName"
app:layout_constraintLeft_toRightOf="@+id/tvName" app:layout_constraintLeft_toRightOf="@+id/tvName"
...@@ -196,13 +221,18 @@ ...@@ -196,13 +221,18 @@
app:layout_constraintRight_toRightOf="parent" /> app:layout_constraintRight_toRightOf="parent" />
<ImageView <ImageView
android:layout_width="46dp" android:layout_width="48dp"
android:layout_height="46dp" android:layout_height="48dp"
android:layout_marginRight="10dp" android:layout_marginRight="10dp"
android:layout_marginBottom="20dp" android:layout_marginBottom="20dp"
android:padding="1dp"
app:circle="@{true}" app:circle="@{true}"
app:imageUrl="@{item.avatar}" app:imageUrl="@{item.avatar}"
app:layout_constraintBottom_toTopOf="@+id/btnChat" app:layout_constraintBottom_toTopOf="@+id/btnChat"
app:layout_constraintRight_toRightOf="parent" /> app:layout_constraintRight_toRightOf="parent"
app:shape="@{1}"
app:shapeBg="@{0x00FFFFFF}"
app:shapeStrokeColor="@{0xFFFFFFFF}"
app:shapeStrokeWidth="@{1}" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout> </layout>
/*___Generated_by_IDEA___*/
package com.ydl.ydlcommon;
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
public final class BuildConfig {
public final static boolean DEBUG = Boolean.parseBoolean(null);
}
\ No newline at end of file
/*___Generated_by_IDEA___*/
package com.ydl.ydlcommon;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}
\ No newline at end of file
/*___Generated_by_IDEA___*/
package com.ydl.ydlcommon;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}
\ No newline at end of file
...@@ -66,6 +66,7 @@ dependencies { ...@@ -66,6 +66,7 @@ dependencies {
api(rootProject.ext.dependencies["support-v4"]) api(rootProject.ext.dependencies["support-v4"])
api(rootProject.ext.dependencies["appcompat-v7"]) api(rootProject.ext.dependencies["appcompat-v7"])
api(rootProject.ext.dependencies["design"]) api(rootProject.ext.dependencies["design"])
implementation(rootProject.ext.dependencies["annotations"])
implementation(rootProject.ext.dependencies["arouter"]) implementation(rootProject.ext.dependencies["arouter"])
kapt(rootProject.ext.dependencies["arouter-compiler"]) kapt(rootProject.ext.dependencies["arouter-compiler"])
compileOnly(rootProject.ext.dependencies["systembartint"]) compileOnly(rootProject.ext.dependencies["systembartint"])
......
package com.yidianling.common.view.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.yidianling.common.R;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class VoicePlayingIcon extends View {
//画笔
private Paint paint;
//跳动指针的集合
private List<Pointer> pointers;
//跳动指针的数量
private int pointerNum;
//逻辑坐标 原点
private float basePointX;
private float basePointY;
//指针间的间隙 默认5dp
private float pointerPadding;
//每个指针的宽度 默认3dp
private float pointerWidth;
//指针的颜色
private int pointerColor = Color.RED;
//控制开始/停止
private boolean isPlaying = false;
//子线程
private Thread myThread;
//指针波动速率
private int pointerSpeed;
private Random random;
private RectF rectF;
private float radius;
public VoicePlayingIcon(Context context) {
super(context);
init();
}
public VoicePlayingIcon(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
//取出自定义属性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.VoicePlayingIcon);
pointerColor = ta.getColor(R.styleable.VoicePlayingIcon_pointer_color, Color.WHITE);
pointerNum = ta.getInt(R.styleable.VoicePlayingIcon_pointer_num, 3);//指针的数量,默认为4
pointerWidth = dp2px(getContext(),
ta.getFloat(R.styleable.VoicePlayingIcon_pointer_width, 6f));//指针的宽度,默认5dp
pointerSpeed = ta.getInt(R.styleable.VoicePlayingIcon_pointer_speed, 40);
ta.recycle();
init();
}
public VoicePlayingIcon(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.VoicePlayingIcon);
pointerColor = ta.getColor(R.styleable.VoicePlayingIcon_pointer_color, Color.RED);
pointerNum = ta.getInt(R.styleable.VoicePlayingIcon_pointer_num, 3);
pointerWidth = dp2px(getContext(), ta.getFloat(R.styleable.VoicePlayingIcon_pointer_width, 6f));
pointerSpeed = ta.getInt(R.styleable.VoicePlayingIcon_pointer_speed, 40);
ta.recycle();
init();
}
/**
* 初始化画笔与指针的集合
*/
private void init() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(pointerColor);
radius = pointerWidth / 2;
pointers = new ArrayList<>();
for (int i = 0; i < pointerNum; i++) {
pointers.add(new Pointer());
}
random = new Random();
rectF = new RectF();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//获取逻辑原点的,也就是画布左下角的坐标。这里减去了paddingBottom的距离
basePointY = getHeight() - getPaddingBottom();
for (int i = 0; i < pointerNum; i++) {
//创建指针对象,利用0~1的随机数 乘以 可绘制区域的高度。作为每个指针的初始高度。
Pointer pointer = pointers.get(i);
if (pointer != null) {
pointer.height = (float) (0.1 * (random.nextInt(10) + 1) * (getHeight() - getPaddingBottom() - getPaddingTop()));
}
}
//计算每个指针之间的间隔 总宽度 - 左右两边的padding - 所有指针占去的宽度 然后再除以间隔的数量
pointerPadding = (getWidth() - getPaddingLeft() - getPaddingRight() - pointerWidth * pointerNum) / (pointerNum - 1);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//将x坐标移动到逻辑原点,也就是左下角
basePointX = 0f + getPaddingLeft();
//循环绘制每一个指针。
for (int i = 0; i < pointers.size(); i++) {
//绘制指针,也就是绘制矩形
rectF.set(basePointX,
basePointY - pointers.get(i).height,
basePointX + pointerWidth,
basePointY);
canvas.drawRoundRect(rectF, radius, radius, paint);
basePointX += (pointerPadding + pointerWidth);
}
}
/**
* 开始播放
*/
public void start() {
if (!isPlaying) {
if (myThread == null) {//开启子线程
myThread = new Thread(new MyRunnable());
myThread.start();
}
isPlaying = true;//控制子线程中的循环
}
}
/**
* 停止子线程,并刷新画布
*/
public void stop() {
isPlaying = false;
invalidate();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (myThread != null) {
myThread.interrupt();
myThread = null;
}
}
/**
* 子线程,循环改变每个指针的高度
*/
public class MyRunnable implements Runnable {
@Override
public void run() {
for (float i = 0; i < Integer.MAX_VALUE; ) {//创建一个死循环,每循环一次i+0.1
try {
for (int j = 0; j < pointers.size(); j++) { //循环改变每个指针高度
float rate = (float) Math.abs(Math.sin(i + j));//利用正弦有规律的获取0~1的数。
pointers.get(j).height = (basePointY - getPaddingTop()) * rate; //rate 乘以 可绘制高度,来改变每个指针的高度
}
Thread.sleep(pointerSpeed);//休眠一下下,可自行调节
if (isPlaying) { //控制开始/暂停
postInvalidate();
i += 0.1;
}
} catch (InterruptedException e) {
//ignore
break;
}
}
}
}
/**
* 指针对象
*/
private static class Pointer {
private float height;
}
static int dp2px(Context context, float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}
...@@ -318,4 +318,11 @@ ...@@ -318,4 +318,11 @@
<attr name="ratingTitleVisible" format="boolean"/> <attr name="ratingTitleVisible" format="boolean"/>
<attr name="ratingCenterColor" format="color"/> <attr name="ratingCenterColor" format="color"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="VoicePlayingIcon">
<attr name="pointer_color" format="color" />
<attr name="pointer_num" format="integer" />
<attr name="pointer_width" format="float" />
<attr name="pointer_speed" format="integer" />
</declare-styleable>
</resources> </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