Commit 439fb8b9 by 徐健

Merge

parents 532811f2 4d43b18f
......@@ -80,6 +80,17 @@ android {
keyPassword "123456"
}
}
dexOptions {
//使用增量模式构建
// incremental true//最大堆内存
javaMaxHeapSize "4g"//是否支持大工程模式
jumboMode = true//预编译
preDexLibraries = true//线程数
threadCount = 8
//禁止打了运行时注解的类全部打到主dex中
keepRuntimeAnnotatedClasses = false
// additionalParameters = ["--minimal-main-dex"]
}
//多维度
//flavorDimensions "APP", "SERVER"
......
......@@ -9,6 +9,7 @@ import com.ydl.devicesidlib.DeviceIDHelper;
import com.ydl.media.audio.PlayService;
import com.ydl.ydlcommon.base.delegate.IAppLifecycles;
import com.ydl.ydlcommon.utils.YdlBuryPointUtil;
import com.yidianling.course.lifeCallback.CoursePlayLifecycle;
import org.jetbrains.annotations.NotNull;
......@@ -37,6 +38,8 @@ public class DemoAppLifecycles implements IAppLifecycles {
Intent intent = new Intent(application, PlayService.class);
application.startService(intent);
application.registerActivityLifecycleCallbacks(new CoursePlayLifecycle());
}
@Override
......
......@@ -27,7 +27,7 @@ public final class DemoGlobalConfig implements IConfigModule {
public void applyOptions(@NotNull Context context, @NotNull GlobalConfig.Builder builder) {
builder.setFrom( "ydl".equals(BuildConfig.FLAVOR) ?YDLConstants.FROM_YDL :YDLConstants.FROM_XLZX)
.addUrl("github", APP_DOMAIN)
.setEnv(YDLConstants.ENV_TEST)
.setEnv(YDLConstants.ENV_PROD)
.setDebug(BuildConfig.DEBUG);
}
}
......@@ -20,7 +20,9 @@ import com.ydl.media.audio.model.Music;
import com.ydl.media.audio.utils.CoverImageUtils;
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.user.LoginUtils;
import java.util.HashMap;
import java.util.Locale;
......@@ -297,6 +299,6 @@ public class PlayFragment extends Fragment implements View.OnClickListener,
@Override
public void onComplete() {
LogUtil.e("onComplete");
}
}
ext {
kotlin_version = "1.3.21"
dev_mode = true
dev_mode = false
ydl_app = [
appName : "心理咨询壹点灵",
......@@ -28,10 +28,10 @@ ext {
version = [
androidSupportSdkVersion: "28.0.0",
retrofitSdkVersion : "2.3.0",
retrofitSdkVersion : "2.6.0",
dagger2SdkVersion : "2.23.2",
glideSdkVersion : "4.3.1",
butterknifeSdkVersion : "9.0.0",
butterknifeSdkVersion : "8.8.1",
rxlifecycleSdkVersion : "1.0",
rxlifecycle2SdkVersion : "2.2.2",
espressoSdkVersion : "3.0.1",
......@@ -42,13 +42,14 @@ ext {
ydlPublishVersion = [
// -------------- 业务模块 --------------
//第三步 若干
"m-confide" : "0.0.16",
"m-consultant" : "0.0.24",
"m-course" : "0.0.9",
"m-fm" : "0.0.12",
"m-muse" : "0.0.8",
"m-tests" : "0.0.5",
"m-user" : "0.0.26",
"m-confide" : "0.0.18",
"m-consultant" : "0.0.26",
"m-course" : "0.0.16",
"m-fm" : "0.0.14",
"m-muse" : "0.0.11",
"m-tests" : "0.0.9",
"m-user" : "0.0.30",
//-------------- 业务模块 API 层 --------------
"m-audioim-api" : "0.0.1",
"m-confide-api" : "0.0.1",
......@@ -57,18 +58,20 @@ ext {
"m-fm-api" : "0.0.2",
"m-muse-api" : "0.0.1",
"m-tests-api" : "0.0.1",
"m-user-api" : "0.0.5",
"m-user-api" : "0.0.7",
//-------------- 功能组件 --------------
//第一步
"ydl-platform" : "0.0.21",
"ydl-platform" : "0.0.24",
//第二步 若干
"ydl-webview" : "0.0.21",
"ydl-media" : "0.0.10",
"ydl-pay" : "0.0.7",
"m-audioim" : "0.0.13",
"ydl-webview" : "0.0.24",
"ydl-media" : "0.0.12",
"ydl-pay" : "0.0.9",
"m-audioim" : "0.0.15",
//以下 几乎不会动
"router" : "0.0.1",
"ydl-net" : "0.0.1",
"ydl-net" : "0.0.2",
"ydl-utils" : "0.0.2",
"ydl-flutter-base": "0.0.3",
]
......@@ -77,8 +80,8 @@ ext {
// -------------- 业务模块 --------------
//第三步 若干
"m-confide" : "0.0.15",
"m-consultant" : "0.0.22",
"m-course" : "0.0.8",
"m-consultant" : "0.0.26",
"m-course" : "0.0.16",
"m-fm" : "0.0.11",
"m-muse" : "0.0.7",
"m-tests" : "0.0.4",
......@@ -91,18 +94,20 @@ ext {
"m-fm-api" : "0.0.2",
"m-muse-api" : "0.0.1",
"m-tests-api" : "0.0.1",
"m-user-api" : "0.0.5",
"m-user-api" : "0.0.7",
//-------------- 功能组件 --------------
//第一步
"ydl-platform" : "0.0.21",
"ydl-platform" : "0.0.24",
//第二步 若干
"ydl-webview" : "0.0.21",
"ydl-media" : "0.0.10",
"ydl-pay" : "0.0.7",
"m-audioim" : "0.0.13",
"ydl-webview" : "0.0.24",
"ydl-media" : "0.0.12",
"ydl-pay" : "0.0.9",
"m-audioim" : "0.0.15",
//以下 几乎不会动
"router" : "0.0.1",
"ydl-net" : "0.0.1",
"ydl-net" : "0.0.2",
"ydl-utils" : "0.0.2",
"ydl-flutter-base": "0.0.3",
]
......@@ -125,7 +130,7 @@ ext {
"retrofit-converter-scalars" : "com.squareup.retrofit2:converter-scalars:${version["retrofitSdkVersion"]}",
"okhttp3" : "com.squareup.okhttp3:okhttp:3.12.3",
"okhttp4" : "com.squareup.okhttp3:okhttp:4.0.0",
"okhttp3-logging" : "com.squareup.okhttp3:logging-interceptor:3.8.0",
"okhttp3-logging" : "com.squareup.okhttp3:logging-interceptor:3.12.2",
"okhttp-urlconnection" : "com.squareup.okhttp:okhttp-urlconnection:2.0.0",
"glide" : "com.github.bumptech.glide:glide:${version["glideSdkVersion"]}",
"glide-compiler" : "com.github.bumptech.glide:compiler:${version["glideSdkVersion"]}",
......@@ -158,7 +163,7 @@ ext {
"rxerrorhandler" : "me.jessyan:rxerrorhandler:1.0.1",
//rx2
"rxandroid2" : "io.reactivex.rxjava2:rxandroid:2.0.1",
"rxandroid2" : "io.reactivex.rxjava2:rxandroid:2.1.1",
"rxjava2" : "io.reactivex.rxjava2:rxjava:2.2.10",
"rxlifecycle2" : "com.trello.rxlifecycle2:rxlifecycle:${version["rxlifecycle2SdkVersion"]}",
"rxlifecycle2-android" : "com.trello.rxlifecycle2:rxlifecycle-android:${version["rxlifecycle2SdkVersion"]}",
......@@ -176,7 +181,6 @@ ext {
"androideventbus" : "org.simple:androideventbus:1.0.5.1",
"otto" : "com.squareup:otto:1.3.8",
"gson" : "com.google.code.gson:gson:2.8.5",
"multidex" : "com.android.support:multidex:1.0.3",
"javax.annotation" : "javax.annotation:jsr250-api:1.0",
"arouter" : "com.alibaba:arouter-api:1.4.1",
"progressmanager" : "me.jessyan:progressmanager:1.5.0",
......@@ -236,14 +240,13 @@ ext {
"imagepicker" : "com.ydl:imagepicker:1.0.6",
"protector" : "com.ydl:protector:1.0.1-SNAPSHOT@aar",
"ydl-hnet" : "com.ydl:h-net:0.0.8",
"ydl-utils" : "com.ydl:ydl-utils:0.0.2",
"ydl-net" : "com.ydl:ydl-net:0.0.1",
"ydl-user-router" : "com.ydl:router:1.0.0-SNAPSHOT@aar",
"ydl-device" : "com.ydl:device-id:0.0.7@aar",
"ydl-net" : "com.ydl:ydl-net:${ydlCompileVersion["ydl-net"]}",
"ydl-utils" : "com.ydl:ydl-utils:${ydlCompileVersion["ydl-utils"]}",
//flutter功能组件升级===>发布ydl-flutter-base组件===>引用flutter相关的业务模块
"ydl-flutter" : "com.ydl:ydl-flutter:0.0.7@aar",
"ydl-flutter-base" : "com.ydl:ydl-flutter-base:${ydlCompileVersion["ydl-flutter-base"]}@aar",
//flutter功能组件升级===>发布ydl-flutter组件===>引用flutter相关的业务模块
"ydl-flutter" : "com.ydl:ydl-flutter:0.0.13@aar",
//基础组件 <<--- 先发这个,发完改这里的版本号
"ydl-platform" : "com.ydl:ydl-platform:${ydlCompileVersion["ydl-platform"]}@aar",
......
package com.yidianling.consultant
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.content.Context
import android.graphics.Typeface
import android.os.Build
import android.os.Bundle
import android.support.v4.content.ContextCompat
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.text.TextUtils
import android.view.*
import android.view.inputmethod.InputMethodManager
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.alibaba.android.arouter.launcher.ARouter
import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity
import com.ydl.ydl_image.config.SimpleImageOpConfiger
import com.ydl.ydl_image.listener.YDLImageRecyclerOnScrollListener
import com.ydl.ydl_image.manager.YDLImageCacheManager
import com.ydl.ydl_router.manager.YDLRouterParams
import com.ydl.ydlcommon.base.BaseMvpFragment
import com.ydl.ydlcommon.base.config.HttpConfig
import com.ydl.ydlcommon.router.IYDLRouterConstant
import com.ydl.ydlcommon.ui.LogoLoadingView
import com.ydl.ydlcommon.utils.BuryPointUtils
import com.ydl.ydlcommon.utils.StatusBarUtils
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.ydl.ydlcommon.utils.remind.ToastHelper
import com.ydl.ydlcommon.view.banner.GlideImageLoader
import com.ydl.ydlcommon.view.listener.EndlessRecyclerViewScrollListener
import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.common.tools.RxImageTool
import com.yidianling.common.tools.ToastUtil
import com.yidianling.consultant.adapter.ExpertSearchAdapter
import com.yidianling.consultant.constants.ConsultBIConstants
import com.yidianling.consultant.listener.OnCategoriesSelectedListener
import com.yidianling.consultant.listener.OnFilterConfirmListener
import com.yidianling.consultant.listener.OnSortItemSelectedListener
import com.yidianling.consultant.model.bean.*
import com.yidianling.consultant.modular.singlton.ConsultAssistantDialogUtils
import com.yidianling.consultant.modular.utils.TempH5RouteUtils
import com.yidianling.consultant.router.ConsultantIn
import com.yidianling.consultant.ui.view.AreaPopupWindow
import com.yidianling.consultant.ui.view.CategoryPopupWindow
import com.yidianling.consultant.ui.view.FilterPopupWindow
import com.yidianling.consultant.ui.view.SortPopupWindow
import kotlinx.android.synthetic.main.consultant_activity_expert_search_list.*
import kotlinx.android.synthetic.main.consultant_activity_expert_search_list.view.*
import kotlinx.android.synthetic.main.consultant_item_filter_online.view.*
import kotlinx.android.synthetic.main.consultant_layout_search_content.*
import kotlinx.android.synthetic.main.consultant_layout_search_content.view.*
import kotlinx.android.synthetic.main.consultant_layout_search_head_bg.*
import kotlinx.android.synthetic.main.consultant_layout_search_head_bg.view.*
import kotlinx.android.synthetic.main.consultant_layout_search_toolbar.*
import kotlinx.android.synthetic.main.consultant_layout_search_toolbar.view.*
import org.json.JSONObject
import java.util.concurrent.Executors
class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPresenter>(), View.OnClickListener, IExpertSearchView,
OnCategoriesSelectedListener, OnSortItemSelectedListener, OnFilterConfirmListener {
override fun layoutResId(): Int {
return R.layout.consultant_activity_expert_search_list
}
override fun initDataAndEvent() {
var statusBarHeight = StatusBarUtils.getStatusBarHeight(context);
rootView.setPadding(0,statusBarHeight,0,0)
btn_back?.visibility = View.INVISIBLE
initViews()
initData()
}
override fun initDataAndEventLazy() {
}
override fun showImage(url: String?, imgView: ImageView) {
YDLImageCacheManager.showImage(activity, url, imgView)
}
override fun showImage(url: String?, imgView: ImageView, ops: SimpleImageOpConfiger) {
YDLImageCacheManager.showImage(activity, url, imgView, ops)
}
override fun showImage(url: String?, imgView: ImageView, width: Int, heigh: Int, ops: SimpleImageOpConfiger) {
YDLImageCacheManager.showImage(activity, url, imgView, width, heigh, ops)
}
//
// override fun getStatusViewOptions(): StatusBarOptions {
// return StatusBarOptions(true,true)
// }
companion object {
const val EXTRA_CATEGORY = "category"
const val EXTRA_CATEGORY_NAME = "category_name"
const val EXTRA_SHOW_TYPE = "showType"
const val EXTRA_FROM_PAGE = "fromPage"
const val HOT_SEARCH_DOCTOR_NAME = "hot_search_doctor_name"
private const val EXTRA_IS_SHOW_HOT = "isInitShowHot"
private const val EXTRA_SEARCH_WORD = "searchWord"
private const val EXTRA_IS_FROM_SPLASH = "isFromSplash"
private const val FILTER_STATUS_NORMAL = 0 //默认筛选状态
private const val FILTER_STATUS_FILTERED = 1 //非默认筛选状态
private const val FILTER_STATUS_OPEN = 2 //筛选窗打开状态
const val FROM_HOME_SREARCH = 0
const val FROM_FIND_EXPERT = 1
const val FROM_ONLINE_EXPERT = 2
const val PAGE_SIZE = 15
}
private val allFilter = AllFilter() //当前筛选
private val tempFilter = AllFilter() //临时筛选,未确认状态
private var curPage = 1
private val doctorList = ArrayList<DoctorServiceItem>()
private val serviceList = ArrayList<DoctorServiceItem>()
private var hasMore = true
private var initCategory: Int = 0
private var initShowType: Int = 0
private lateinit var doctorAdapter: ExpertSearchAdapter
private lateinit var onScrollListener: EndlessRecyclerViewScrollListener
private var headData: HeadData? = null //筛选数据
private val props1 = JSONObject() //筛选标题埋点参数
private var fromPageType: Int = 0 //从哪个页面跳转过来的
private val fromPages = arrayOf("首页搜索", "找专家", "在线专家")
private var isRecommend = false //埋点数据
private var keyWord: String? = null //埋点数据
private var isDoSearch: Boolean = false //埋点判断是否通过搜索进入埋点的
private val bannerList = ArrayList<String>()
private var hasSelectedArea = false //是否选择过地区
private var hasSelectedSort = false //是否选择过排序
override fun createPresenter(): ExpertSearchPresenter = ExpertSearchPresenter()
private fun initViews() {
srlContainer.isEnabled = false
tvSubject.setOnClickListener(this)
tvArea.setOnClickListener(this)
tvSort.setOnClickListener(this)
tvFilter.setOnClickListener(this)
btn_call.setOnClickListener(this)
tv_guide.setOnClickListener(this)
rl_search.setOnClickListener(this)
initNetLossView()
// etSearch.setOnEditorActionListener { _, actionId, _ ->
// if (actionId == EditorInfo.IME_ACTION_SEARCH) {
// doSearch()
// }
// true
// }
// etSearch.setOnClickListener { appbar_layout.setExpanded(false) }
// etSearch.setOnFocusChangeListener { view, b -> if (b) appbar_layout.setExpanded(false) }
// btn_back.setOnClickListener {
// onBackPressed()
// }
doctorAdapter = ExpertSearchAdapter(context, this, doctorList)
rvExperts.adapter = doctorAdapter
val layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
rvExperts.layoutManager = layoutManager
onScrollListener = object : EndlessRecyclerViewScrollListener(layoutManager) {
private var isBtnShow: Boolean = false
private var sIsScrolling = false
override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
hideSoftInput()
if (newState == RecyclerView.SCROLL_STATE_DRAGGING || newState == RecyclerView.SCROLL_STATE_SETTLING) {
sIsScrolling = true
} else if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (sIsScrolling) {
}
sIsScrolling = false;
}
}
override fun onScrollTop() {
var alpha = PropertyValuesHolder.ofFloat("alpha", 1f, 0f)
var scaleX = PropertyValuesHolder.ofFloat("scaleX", 1f, 0f)
var scaleY = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f)
var animator = ObjectAnimator.ofPropertyValuesHolder(image_scroll_top, alpha, scaleX, scaleY).setDuration(200)
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
image_scroll_top.visibility = View.GONE
isBtnShow = false
}
})
animator.start()
}
override fun onScrollDown() {
if (isBtnShow) {
return
}
var alpha = PropertyValuesHolder.ofFloat("alpha", 0f, 1f)
var scaleX = PropertyValuesHolder.ofFloat("scaleX", 0f, 1f)
var scaleY = PropertyValuesHolder.ofFloat("scaleY", 0f, 1f)
var animator = ObjectAnimator.ofPropertyValuesHolder(image_scroll_top, alpha, scaleX, scaleY).setDuration(200)
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
image_scroll_top.visibility = View.VISIBLE
isBtnShow = true
}
})
animator.start()
}
override fun onScrollUp() {
if (!isBtnShow) {
return
}
var alpha = PropertyValuesHolder.ofFloat("alpha", 1f, 0f)
var scaleX = PropertyValuesHolder.ofFloat("scaleX", 1f, 0f)
var scaleY = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f)
var animator = ObjectAnimator.ofPropertyValuesHolder(image_scroll_top, alpha, scaleX, scaleY).setDuration(200)
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
image_scroll_top.visibility = View.GONE
isBtnShow = false
}
})
animator.start()
}
override fun onLoadMore(page: Int, totalItemsCount: Int, view: RecyclerView?) {
if (hasMore) {
curPage++
getPresenter().fetchListData(allFilter, curPage)
}
}
}
// rvExperts.addItemDecoration(ExpertItemDecoration(this))
rvExperts.addOnScrollListener(onScrollListener)
rvExperts.addOnScrollListener(YDLImageRecyclerOnScrollListener(activity))
// etSearch.addTextChangedListener(object : TextWatcher {
// override fun afterTextChanged(s: Editable?) {}
//
// override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
//
// override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
//
// }
//
// })
image_scroll_top.setOnClickListener(this)
// initStatus()
ConsultAssistantDialogUtils.INSTANCE.fitRequest(activity, "doctor_list")
}
private fun initNetLossView() {
v_loading.setListener(object : LogoLoadingView.LogoLoadingListener {
override fun onDataResetClick() {
rvExperts.visibility = View.GONE
v_loading.visibility = View.VISIBLE
ll_network_error.visibility = View.GONE
v_loading.setViewType(LogoLoadingView.TYPE_LOADING, null)
refresh(false)
}
override fun onBackClick() {
// finish()
}
})
}
override fun localData() {
}
override fun updateCache(showType: Int, searchBean: ExpertSearchBean) {
}
private fun initData() {
allFilter.showType.key = initShowType
val cat = CateItem()
cat.cateId = initCategory
allFilter.categories.clear()
allFilter.categories.add(cat)
getPresenter().fetchListHead()
//加载本地缓存数据
getPresenter().localData(initShowType)
//加载banner
getPresenter().fetchBannerList()
refresh(false)
v_loading.visibility = View.VISIBLE
v_loading.setViewType(LogoLoadingView.TYPE_LOADING, null)
if (fromPageType != -1) {
doctorAdapter.setEntrance(fromPages[fromPageType])
}
}
override fun onBannerListFetched(data: MutableList<ExpertBannerBean>?) {
if (null == data) {
if (bannerList.isEmpty()) {
bannerList.add("https://h2.yidianling.com/ct/list")
}
}
if (null != data && data.isNotEmpty()) {
bannerList.clear()
for (item in data) {
bannerList.add(item.image!!)
}
}
banner_search.setOnBannerListener {
if (null == data || data.isEmpty()) {
TempH5RouteUtils.tempH5Route(
IYDLRouterConstant.ROUTER_H5_H5,
YDLRouterParams().putExtra(IYDLRouterConstant.EXTRA_URL, "https://h2.yidianling.com/ct/list"), "")
} else {
if (it < data.size) {
TempH5RouteUtils.tempH5Route(data[it].linkUrl)
}
}
}
banner_search.setImageLoader(GlideImageLoader(R.drawable.consultant_expert_banner_default)).setImages(bannerList).start()
banner_search.setIndicatorBottomPadding(20)
}
/**
* 初始化状态栏位置
*/
private fun initStatus() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4以下不支持状态栏变色
StatusBarUtils.setTransparentForImageView(activity, null)
val statusBarHeight = StatusBarUtils.getStatusBarHeight(context)
val lp1 =title_layout.layoutParams as LinearLayout.LayoutParams
lp1.height = (RxImageTool.dp2px(48f) + statusBarHeight)
title_layout.setPadding(0, statusBarHeight, 0, 0)
}
}
//筛选数据获取后回调
override fun onHeadFetched(headData: HeadData?) {
//头部数据获取到后初始化筛选数据
this.headData = headData
if (initCategory != 0) {
if (headData?.cates != null) {
for (cate in headData.cates) {
if (cate.cateId == initCategory) {
allFilter.categories.clear()
allFilter.categories.add(cate)
if (allFilter.categories.size == 1 && !"全部".equals(allFilter.categories[0].cateName)) {
//显示选中标题
tvSubject.text = allFilter.categories[0].cateName
} else {
//显示主标题
tvSubject.text = "主题"
}
updateFilterTextViewStatus(tvSubject, FILTER_STATUS_FILTERED)
break
}
}
}
initCategory = 0
} else {
allFilter.categories.clear()
allFilter.categories.add(headData?.cates?.get(0) ?: CateItem())
}
allFilter.reorder = headData?.reorder?.get(0) ?: ReorderItem()
allFilter.showType = headData?.filters?.showType?.get(initShowType) ?: ShowTypeItem()
if (headData?.highlighter?.size ?: 0 > 0) {
//设置热门搜索
initHotViews(lin_filter2, headData!!.highlighter)
}
}
/**
* 热门
*/
private fun initHotViews(view: LinearLayout, hotData: List<HighlighterItem>) {
if (view.childCount > 0) {
return
}
val popWidth = RxDeviceTool.getScreenWidth(context)
val mWidth = (popWidth - RxImageTool.dp2px(10f)) / hotData.size
for ((index, hot) in hotData!!.withIndex()) {
val tv = View.inflate(context, R.layout.consultant_item_filter_online, null) as TextView
val textView = tv.tvFree
val params = LinearLayout.LayoutParams(0, RxImageTool.dp2px(22f))
params.weight = 1f
params.setMargins(0, 0, RxImageTool.dp2px(10f), 0)
textView.layoutParams = params
textView.text = hot.value
textView.setOnClickListener {
if (textView.isSelected) {
dealHotSelect(hot, false)
textView!!.isSelected = false
textView.paint.isFakeBoldText = false
} else {
dealHotSelect(hot, true)
textView.isSelected = true
textView.paint.isFakeBoldText = true
}
filterLabelSet()
//开始筛选数据
refresh()
}
view.addView(textView)
}
}
/**
* 处理热门搜索的选中逻辑
* * 1:主题
* 2:省
* 3:排序
* 4:咨询方式
* 5:年龄选择
* 6:其他选择
* 7:资质选择
* 8.市
*
* @param isAdd 是否是添加
*/
private fun dealHotSelect(hotData: HighlighterItem, isAdd: Boolean) {
when (hotData.type) {
"1" -> {
if (headData?.cates!!.size > 0) {
for (bean in headData?.cates!!) {
if (TextUtils.equals(hotData.id, bean.cateId.toString())) {
if (isAdd) {
if (allFilter.categories.size == 1 && allFilter.categories[0].cateId == 0) {
allFilter.categories.clear()
}
allFilter.categories.add(bean)
updateFilterTextViewStatus(tvSubject, FILTER_STATUS_FILTERED)
} else {
allFilter.categories.remove(bean)
if (allFilter.categories.size == 0) {
allFilter.categories.add(headData?.cates?.get(0) ?: CateItem())
updateFilterTextViewStatus(tvSubject, FILTER_STATUS_NORMAL)
}
}
}
}
if (allFilter.categories.size == 1 && "全部" != allFilter.categories[0].cateName) {
//显示选中标题
tvSubject.text = allFilter.categories[0].cateName
} else {
//显示主标题
tvSubject.text = "主题"
}
}
}
"2" -> {//省
if (headData?.region!!.size > 0) {
var bean = RegionItem()
if (isAdd) {
//热门中如果选择过地区、要把其他已选中的置位未选中
if (hasSelectedArea) {
for ((index, bean) in headData!!.highlighter.withIndex()) {
if (bean.type == "2" || bean.type == "8") {
var textview =lin_filter2.getChildAt(index) as TextView
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
}
}
bean.key = hotData.id
bean.value = hotData.value
for (headBean in headData!!.region) {
if (TextUtils.equals(headBean.key, bean.key)) {
bean.sub = headBean.sub
break
}
}
allFilter.region = bean
if (allFilter.region.value?.length ?: 0 > 4) {
tvArea.text = allFilter.region.value?.substring(0, 3) + "..."
} else {
tvArea.text = allFilter.region.value
}
updateFilterTextViewStatus(tvArea, FILTER_STATUS_FILTERED)
hasSelectedArea = true
} else {
allFilter.region = RegionItem()
tvArea.text = "地区"
updateFilterTextViewStatus(tvArea, FILTER_STATUS_NORMAL)
hasSelectedArea = false
}
allFilter.sub = SubItem("不限", null)
}
}
"3" -> {
//排序
if (headData?.reorder!!.size > 0) {
for (bean in headData?.reorder!!) {
if (TextUtils.equals(hotData.id, bean.key.toString())) {
if (isAdd) {
if (hasSelectedSort) {
for ((index, bean) in headData!!.highlighter.withIndex()) {
if (bean.type == "3") {
var textview =lin_filter2.getChildAt(index) as TextView
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
}
}
allFilter.reorder = bean
updateFilterTextViewStatus(tvSort, FILTER_STATUS_FILTERED)
hasSelectedSort = true
} else {
allFilter.reorder = headData?.reorder?.get(0) ?: ReorderItem()
updateFilterTextViewStatus(tvSort, FILTER_STATUS_NORMAL)
hasSelectedSort = false
}
}
}
when {
allFilter.reorder.value.equals("综合排序") ->tvSort.text = "排序"
allFilter.reorder.value?.length ?: 0 > 4 ->tvSort.text = allFilter.reorder.value?.substring(0, 3) + "..."
else ->tvSort.text = allFilter.reorder.value
}
}
}
"4" -> {
//咨询方式
if (headData?.filters?.enquiry!!.isNotEmpty()) {
for (bean in headData?.filters?.enquiry!!) {
if (TextUtils.equals(hotData.id, bean.key.toString())) {
if (isAdd) {
allFilter.enquiries.add(bean)
} else {
allFilter.enquiries.remove(bean)
}
}
}
}
if (allFilter.others.size + allFilter.enquiries.size + allFilter.ages.size + allFilter.title.size > 0) {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_NORMAL)
}
filterLabelSet()
}
"5" -> {
//年龄选择
if (headData?.filters?.age!!.isNotEmpty()) {
for (bean in headData?.filters?.age!!) {
if (TextUtils.equals(hotData.id, bean.key.toString())) {
if (isAdd) {
allFilter.ages.add(bean)
} else {
allFilter.ages.remove(bean)
}
}
}
}
if (allFilter.others.size + allFilter.enquiries.size + allFilter.ages.size + allFilter.title.size > 0) {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_NORMAL)
}
filterLabelSet()
}
"6" -> {
//其他选择
if (headData?.filters?.other!!.isNotEmpty()) {
for (bean in headData?.filters?.other!!) {
if (TextUtils.equals(hotData.id, bean.key.toString())) {
if (isAdd) {
allFilter.others.add(bean)
} else {
allFilter.others.remove(bean)
}
}
}
}
if (allFilter.others.size + allFilter.enquiries.size + allFilter.ages.size + allFilter.title.size > 0) {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_NORMAL)
}
filterLabelSet()
}
"7" -> {
//资质选择
if (headData?.filters?.title!!.isNotEmpty()) {
for (bean in headData?.filters?.title!!) {
if (TextUtils.equals(hotData.id, bean.key.toString())) {
if (isAdd) {
allFilter.title.add(bean)
} else {
allFilter.title.remove(bean)
}
}
}
}
if (allFilter.others.size + allFilter.enquiries.size + allFilter.ages.size + allFilter.title.size > 0) {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_NORMAL)
}
filterLabelSet()
}
"8" -> {
//市
if (headData?.region!!.size > 0) {
var bean = SubItem()
if (isAdd) {
//热门中如果选择过地区、要把其他已选中的置位未选中
if (hasSelectedArea) {
for ((index, bean) in headData!!.highlighter.withIndex()) {
if (bean.type == "2" || bean.type == "8") {
var textview =lin_filter2.getChildAt(index) as TextView
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
}
}
bean.key = hotData.id
bean.value = hotData.value
for (headBean in headData!!.region) {
if (TextUtils.equals(headBean.key!!.substring(0, 2), bean.key!!.substring(0, 2))) {
allFilter.region = headBean
break
}
}
allFilter.sub = bean
if (allFilter.sub.value?.length ?: 0 > 4) {
tvArea.text = allFilter.sub.value?.substring(0, 3) + "..."
} else {
tvArea.text = allFilter.sub.value
}
updateFilterTextViewStatus(tvArea, FILTER_STATUS_FILTERED)
hasSelectedArea = true
} else {
allFilter.region = RegionItem()
allFilter.sub = SubItem("不限", null)
tvArea.text = "地区"
updateFilterTextViewStatus(tvArea, FILTER_STATUS_NORMAL)
hasSelectedArea = false
}
}
}
}
}
//用于侧滑筛选过来更新快捷筛选选中状态
private fun updateOtherViews(otherdata: List<OtherItem>) {
if (lin_filter2.childCount > 0) {
//清空选中
for (i in 0.until(lin_filter2.childCount)) {
val textView =lin_filter2.getChildAt(i) as TextView
textView.isSelected = false
textView.paint.isFakeBoldText = false
}
//重置选中状态
for ((index, other) in otherdata.withIndex()) {
for (i in 0 until lin_filter2.childCount) {
val textView =lin_filter2.getChildAt(i) as TextView
if (textView.text == other.value) {
textView.isSelected = true
textView.paint.isFakeBoldText = true
}
}
}
}
}
//服务列表数据获取到后的回调
override fun onServiceListFetched(data: MutableList<DoctorServiceItem>, page: Int, totalPage: Int) {
LogUtil.d("onServiceListFetched")
// if (rvExperts.adapter != serviceAdapter) {
// rvExperts.adapter = serviceAdapter
// }
if (page == 1) {
if (fromPageType != -1 && isDoSearch) {
LogUtil.d("keyword: " + keyWord + " isRecommend: " + isRecommend + " hasResult: " + (data.size > 0 && data != null ?: false) + " location: " + fromPages[fromPageType])
}
serviceList.clear()
hasMore = true
// serviceAdapter.hasMore = true
}
if (fromPageType == -1) {
bury(keyWord ?: "", data.size > 0, isRecommend, "首页分类")
} else {
bury(keyWord ?: "", data.size > 0, isRecommend, fromPages[fromPageType])
}
if (page >= totalPage) {
hasMore = false
// serviceAdapter.hasMore = false
}
serviceList.addAll(data)
// serviceAdapter.notifyDataSetChanged()
isRecommend = false
isDoSearch = false
v_loading.visibility = View.GONE
ll_network_error.visibility = View.GONE
rvExperts.visibility = View.VISIBLE
srlContainer.isRefreshing = false
}
//专家列表数据获取到后的回调
override fun onDoctorListFetched(data: MutableList<DoctorServiceItem>, page: Int, totalPage: Int) {
LogUtil.d("onDoctorListFetched")
if (rvExperts.adapter != doctorAdapter) {
rvExperts.adapter = doctorAdapter
}
LogUtil.d("data size " + data.size)
if (page == 1) {
if (fromPageType != -1 && isDoSearch) {
LogUtil.d("keyword: " + keyWord + " isRecommend: " + isRecommend + " hasResult: " + (data.size > 0 && data != null ?: false) + " location: " + fromPages[fromPageType])
}
doctorList.clear()
doctorAdapter.hasMore = true
hasMore = true
}
if (fromPageType == -1) {
bury(keyWord ?: "", data != null && data.size > 0, isRecommend, "首页分类")
} else {
bury(keyWord ?: "", data != null && data.size > 0, isRecommend, fromPages[fromPageType])
}
if (page >= totalPage) {
hasMore = false
doctorAdapter.hasMore = false
}
doctorList.addAll(data)
doctorAdapter.notifyDataSetChanged()
isDoSearch = false
isRecommend = false
v_loading.visibility = View.GONE
ll_network_error.visibility = View.GONE
rvExperts.visibility = View.VISIBLE
srlContainer.isRefreshing = false
}
override fun fetchListFailed(msg: String?) {
isDoSearch = false
isRecommend = false
if (curPage == 1) {
v_loading.setViewType(LogoLoadingView.TYPE_NET_LOSS, getString(R.string.consultant_reload_hint))
v_loading.visibility = View.VISIBLE
ll_network_error.visibility = View.GONE
} else {
ToastHelper.show("网络不给力")
}
srlContainer.isRefreshing = false
}
override fun fetchListEmpty(msg: String?) {
isDoSearch = false
isRecommend = false
tv_reload.visibility = View.GONE
tv_reload_hint.text = msg
ll_network_error.visibility = View.VISIBLE
iv_exception.setImageResource(R.drawable.platform_ico_img_zixun_empty)
rvExperts.visibility = View.GONE
srlContainer.isRefreshing = false
}
override fun fetchFailed(msg: String?) {
isDoSearch = false
isRecommend = false
if (msg != null) {
ToastUtil.toastShort(msg)
}
v_loading.setViewType(LogoLoadingView.TYPE_NET_LOSS, getString(R.string.consultant_reload_hint))
v_loading.visibility = View.VISIBLE
ll_network_error.visibility = View.GONE
rvExperts.visibility = View.GONE
appbar_layout.setExpanded(false)
}
override fun showRefreshLayout() {
srlContainer.isRefreshing = true
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.image_scroll_top -> {
scrollToTop()
}
R.id.tvSubject -> {
props1.put("filtrate_first", "主题")
hideSoftInput()
appbar_layout.setExpanded(false)
appbar_layout.postDelayed({
showSubjectPopupWindow()
}, 300);
}
R.id.tvArea -> {
props1.put("filtrate_first", "地区")
hideSoftInput()
appbar_layout.setExpanded(false)
appbar_layout.postDelayed({
showAreaPopupWindow()
}, 300);
}
R.id.tvSort -> {
props1.put("filtrate_first", "排序")
hideSoftInput()
appbar_layout.setExpanded(false)
appbar_layout.postDelayed({
showSortPopupWindow()
}, 300);
}
R.id.tvFilter -> {
props1.put("filtrate_first", "筛选")
hideSoftInput()
appbar_layout.setExpanded(false)
appbar_layout.postDelayed({
showFilterPopupWindow()
}, 300);
}
R.id.tv_guide -> {
ActionCountUtils.count(ConsultBIConstants.ConsultEvent.APP_CONSULT_LIST_CONSULT_GUIDE_CLICK)
val h5param = H5Params(HttpConfig.H5_URL+ "help/consultation/", "咨询指南")
h5param.isShowMenu = true
NewH5Activity.start(context, h5param)
}
R.id.btn_call -> {
ActionCountUtils.count(ConsultBIConstants.ConsultEvent.APP_CONSULT_LIST_ONLINE_CUSTOMER_CLICK)
ConsultantIn.startP2PXiaoYi(context)
}
R.id.rl_search -> {
ARouter.getInstance()
.build("/consult/hot_search")
.withString(HOT_SEARCH_DOCTOR_NAME,tv_search_content.text.toString())
.navigation()
}
}
}
private fun scrollToTop() {
if ((rvExperts.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() > 10) {
rvExperts.scrollToPosition(10)
rvExperts.smoothScrollToPosition(0)
} else {
rvExperts.smoothScrollToPosition(0)
}
}
//显示筛选弹窗
private fun showFilterPopupWindow() {
// tempFilter.searchWord = etSearch.text.toString()
tempFilter.categories.clear()
tempFilter.categories.addAll(allFilter.categories)
tempFilter.reorder = allFilter.reorder
tempFilter.region = allFilter.region
tempFilter.sub = allFilter.sub
tempFilter.showType = allFilter.showType
tempFilter.ages.clear()
tempFilter.ages.addAll(allFilter.ages)
tempFilter.enquiries.clear()
tempFilter.enquiries.addAll(allFilter.enquiries)
tempFilter.others.clear()
tempFilter.others.addAll(allFilter.others)
tempFilter.priceRanges = allFilter.priceRanges
tempFilter.priceRangesView = allFilter.priceRangesView
if (headData?.filters != null) {
val filterPopupWindow = FilterPopupWindow(context, headData?.filters!!, tempFilter)
filterPopupWindow.setOnDismissListener {
// viewDim.visibility = View.INVISIBLE
viewDim_filter.visibility = View.GONE
if (allFilter.others.size + allFilter.enquiries.size + allFilter.ages.size + allFilter.title.size > 0 || !TextUtils.isEmpty(allFilter.priceRanges?.minPrice) || !TextUtils.isEmpty(allFilter.priceRanges?.maxPrice)) {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_NORMAL)
}
ConsultAssistantDialogUtils.INSTANCE.fitRequest(activity, "doctor_list")
}
filterPopupWindow.isClippingEnabled = false
filterPopupWindow.showAtLocation(viewSep2.rootView, Gravity.TOP + Gravity.RIGHT, 0, 0)
ConsultAssistantDialogUtils.INSTANCE.hide()
filterPopupWindow.onFilterConfirmListener = this
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_OPEN)
// viewDim.visibility = View.VISIBLE
viewDim_filter.visibility = View.VISIBLE
} else {
ToastUtil.toastShort("数据初始化失败,请重试")
getPresenter().fetchListHead()
}
}
//筛选确认回调
override fun onFilterConfirmed() {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_OPEN)
LogUtil.d("filter: " + tempFilter.showType.value + "," + tempFilter.enquiries.map { it.value }.joinToString(",") + "," + tempFilter.ages.map { it.value }.joinToString(",") + "," + tempFilter.others.map { it.value }.joinToString(","))
props1.put("filtrate_second", tempFilter.showType.value + "," + tempFilter.enquiries.map { it.value }.joinToString(",") + "," + tempFilter.ages.map { it.value }.joinToString(",") + "," + tempFilter.others.map { it.value }.joinToString(","))
BuryPointUtils.buryPoint("Filtrate", props1)
allFilter.showType = tempFilter.showType
allFilter.enquiries.clear()
allFilter.enquiries.addAll(tempFilter.enquiries)
allFilter.ages.clear()
allFilter.ages.addAll(tempFilter.ages)
allFilter.others.clear()
allFilter.others.addAll(tempFilter.others)
allFilter.title.clear()
allFilter.title.addAll(tempFilter.title)
allFilter.priceRanges = tempFilter.priceRanges
allFilter.priceRangesView = tempFilter.priceRangesView
//判断主题选中,判断热门筛选中是否也有该主题
Executors.newCachedThreadPool().execute {
if (headData!!.highlighter.size > 0) {
for (index in 0.until(headData!!.highlighter.size)) {
if (headData!!.highlighter[index].type == "4") {
var textview =lin_filter2.getChildAt(index) as TextView
activity.runOnUiThread {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
for (bean in allFilter.enquiries) {
if (TextUtils.equals(bean.key.toString(), headData!!.highlighter[index].id)) {
activity.runOnUiThread {
textview.isSelected = true
textview.paint.isFakeBoldText = true
}
break
}
}
}
if (headData!!.highlighter[index].type == "5") {
var textview =lin_filter2.getChildAt(index) as TextView
activity.runOnUiThread {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
for (bean in allFilter.ages) {
if (TextUtils.equals(bean.value.toString(), headData!!.highlighter[index].id)) {
activity.runOnUiThread {
textview.isSelected = true
textview.paint.isFakeBoldText = true
}
break
}
}
}
if (headData!!.highlighter[index].type == "6") {
var textview =lin_filter2.getChildAt(index) as TextView
activity.runOnUiThread {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
for (bean in allFilter.others) {
if (TextUtils.equals(bean.key.toString(), headData!!.highlighter[index].id)) {
activity.runOnUiThread {
textview.isSelected = true
textview.paint.isFakeBoldText = true
}
break
}
}
}
if (headData!!.highlighter[index].type == "7") {
var textview =lin_filter2.getChildAt(index) as TextView
activity.runOnUiThread {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
for (bean in allFilter.title) {
if (TextUtils.equals(bean.key.toString(), headData!!.highlighter[index].id)) {
activity.runOnUiThread {
textview.isSelected = true
textview.paint.isFakeBoldText = true
}
break
}
}
}
}
}
}
filterLabelSet()
//刷新快捷按钮选中状态
updateOtherViews(allFilter.others)
refresh()
}
//筛选标题显示处理
private fun filterLabelSet() {
if ((allFilter.others.size + allFilter.ages.size + allFilter.enquiries.size + allFilter.title.size) == 1) {
var text: String? = ""
if (allFilter.others.size == 1) {
text = allFilter.others[0].value
} else if (allFilter.ages.size == 1) {
text = allFilter.ages[0].value
} else if (allFilter.enquiries.size == 1) {
text = allFilter.enquiries[0].value
} else if (allFilter.title.size == 1) {
text = allFilter.title[0].value
} else {
text = "筛选"
}
if (text?.length ?: 0 > 4) {
tvFilter.text = text?.substring(0, 3) + "..."
} else {
tvFilter.text = text
}
} else {
tvFilter.text = "筛选"
}
}
private var sortPopup: SortPopupWindow? = null
//显示排序弹窗
private fun showSortPopupWindow() {
if (headData?.reorder != null) {
sortPopup = SortPopupWindow(activity, headData?.reorder!!, allFilter.reorder, this)
sortPopup!!.setOnDismissListener {
viewDim.visibility = View.INVISIBLE
if (allFilter.reorder != headData!!.reorder[0]) {
updateFilterTextViewStatus(tvSort, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvSort, FILTER_STATUS_NORMAL)
}
}
if (sortPopup!!.selectedSort != allFilter.reorder) {
sortPopup!!.selectedSort = allFilter.reorder
sortPopup!!.notifyDataSetChanged()
}
sortPopup!!.showAsDropDown(viewSep2)
updateFilterTextViewStatus(tvSort, FILTER_STATUS_OPEN)
viewDim.visibility = View.VISIBLE
} else {
ToastUtil.toastShort("数据初始化失败,请重试")
getPresenter().fetchListHead()
}
}
//排序选择回调
override fun onSortItemSelected(sortItem: ReorderItem) {
ActionCountUtils.count(ConsultBIConstants.ConsultEvent.APP_CONSULT_LIST_SORT_CLICK, sortItem.value
?: "")
if (sortItem.value.equals("综合排序")) {
tvSort.text = "排序"
} else if (sortItem.value?.length ?: 0 > 4) {
tvSort.text = sortItem.value?.substring(0, 3) + "..."
} else {
tvSort.text = sortItem.value
}
//判断排序选中,判断热门筛选中是否也有该排序
if (headData!!.highlighter.size > 0) {
for (index in 0.until(headData!!.highlighter.size)) {
if (headData!!.highlighter[index].type == "3") {
var textview =lin_filter2.getChildAt(index) as TextView
if (TextUtils.equals(sortItem.value, headData!!.highlighter[index].value)) {
textview.isSelected = true
textview.paint.isFakeBoldText = true
hasSelectedSort = true
} else {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
}
}
}
updateFilterTextViewStatus(tvSort, FILTER_STATUS_OPEN)
LogUtil.d("sortItem key: " + sortItem.key + " sortItem value: " + sortItem.value)
props1.put("filtrate_second", sortItem.value)
BuryPointUtils.buryPoint("Filtrate", props1)
allFilter.reorder = sortItem
sortPopup?.dismiss()
refresh()
}
//显示地区弹窗
private fun showAreaPopupWindow() {
if (headData?.region != null) {
val regionPopupWindow = AreaPopupWindow(activity, headData?.region
?: ArrayList(), allFilter.region, allFilter.sub)
regionPopupWindow.showAsDropDown(viewSep2)
viewDim.visibility = View.VISIBLE
updateFilterTextViewStatus(tvArea, FILTER_STATUS_OPEN)
regionPopupWindow.setOnDismissListener {
viewDim.visibility = View.INVISIBLE
if (tvArea.text != "地区") {
updateFilterTextViewStatus(tvArea, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvArea, FILTER_STATUS_NORMAL)
}
}
regionPopupWindow.onRegionSelectedListener = object : AreaPopupWindow.OnRegionSelectedListener {
override fun onRegionSelected(region: RegionItem, sub: SubItem) {
updateFilterTextViewStatus(tvArea, FILTER_STATUS_OPEN)
allFilter.region = region
allFilter.sub = sub
if (region.key == null && sub.key == null) {
// LogUtil.d("onRegionSelected: " + region.value)
// props1.put("filtrate_second", region.value)
// BuryPointUtils.buryPoint("Filtrate", props1)
tvArea.text = "地区"
} else if (region.key != null && sub.key == null) {
// LogUtil.d("onRegionSelected: " + region.value)
// props1.put("filtrate_second", region.value)
// BuryPointUtils.buryPoint("Filtrate", props1)
if (region.value?.length ?: 0 > 4) {
tvArea.text = region.value?.substring(0, 3) + "..."
} else {
tvArea.text = region.value
}
} else {
// LogUtil.d("onRegionSelected: " + sub.value)
// props1.put("filtrate_second", sub.value)
// BuryPointUtils.buryPoint("Filtrate", props1)
if (sub.value?.length ?: 0 > 4) {
tvArea.text = sub.value?.substring(0, 3) + "..."
} else {
tvArea.text = sub.value
}
}
ActionCountUtils.count(ConsultBIConstants.ConsultEvent.APP_CONSULT_LIST_AREA_CLICK, region.value + "|" + sub.value)
//更新热门搜索显示状态
if (headData!!.highlighter.size > 0) {
for ((index, hot) in headData!!.highlighter!!.withIndex()) {
if (hot.type == "2" || hot.type == "8") {
var textview =lin_filter2.getChildAt(index) as TextView
//有选择城市
if (!TextUtils.isEmpty(sub.key)) {
if (TextUtils.equals(sub.key, hot.id)) {
textview.isSelected = true
textview.paint.isFakeBoldText = true
hasSelectedArea = true
} else {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
} else {
if (TextUtils.equals(region.key, hot.id)) {
textview.isSelected = true
textview.paint.isFakeBoldText = true
hasSelectedArea = true
} else {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
}
}
}
}
regionPopupWindow.dismiss()
refresh()
}
}
} else {
ToastUtil.toastShort("数据初始化失败,请重试")
getPresenter().fetchListHead()
}
}
private var categoryPopup: CategoryPopupWindow? = null
//显示主题弹窗
private fun showSubjectPopupWindow() {
tempFilter.categories.clear()
tempFilter.categories.addAll(allFilter.categories)
val categories = headData?.cates
if (categories != null) {
categoryPopup = CategoryPopupWindow(activity, categories, tempFilter.categories)
categoryPopup!!.setOnDismissListener {
viewDim.visibility = View.INVISIBLE
if (allFilter.categories.size > 1 || (allFilter.categories.size == 1 && allFilter.categories[0] != headData!!.cates[0])) {
updateFilterTextViewStatus(tvSubject, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvSubject, FILTER_STATUS_NORMAL)
}
}
categoryPopup!!.onSubjectsSelectedListener = this
categoryPopup!!.showAsDropDown(viewSep2)
updateFilterTextViewStatus(tvSubject, FILTER_STATUS_OPEN)
viewDim.visibility = View.VISIBLE
} else {
ToastUtil.toastShort("数据初始化失败,请重试")
getPresenter().fetchListHead()
}
}
/**
* 主题选择确认回调
*
* 新增逻辑:当主题选择后,需要判断热门筛选中是否也有该主题,如果有,也需要同步更新选中状态
*/
override fun onCategoriesSelected(categories: ArrayList<CateItem>) {
ActionCountUtils.count(ConsultBIConstants.ConsultEvent.APP_CONSULT_LIST_THEME_CLICK, categories.map { it.cateName }.joinToString("|"))
if (categories.size == 1 && "全部" != categories[0].cateName) {
//显示选中标题
tvSubject.text = categories[0].cateName
} else {
//显示主标题
tvSubject.text = "主题"
}
//判断主题选中,判断热门筛选中是否也有该主题
Executors.newCachedThreadPool().execute {
if (headData!!.highlighter.size > 0) {
for (index in 0.until(headData!!.highlighter.size)) {
if (headData!!.highlighter[index].type == "1") {
var textview =lin_filter2.getChildAt(index) as TextView
activity.runOnUiThread {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
for (bean in categories) {
if (TextUtils.equals(bean.cateName, headData!!.highlighter[index].value)) {
activity.runOnUiThread {
textview.isSelected = true
textview.paint.isFakeBoldText = true
}
break
}
}
}
}
}
}
updateFilterTextViewStatus(tvSubject, FILTER_STATUS_OPEN)
// LogUtil.d("theme callback: " + categories.map { it.cateName }.joinToString(","))
// props1.put("filtrate_second", categories.map { it.cateName }.joinToString(","))
// BuryPointUtils.buryPoint("Filtrate", props1)
allFilter.categories.clear()
allFilter.categories.addAll(categories)
refresh()
if (categories.size == 1) {
doctorAdapter?.cateId = "${categories[0].cateId}"
} else {
doctorAdapter?.cateId = ""
}
}
//刷新列表
private fun refresh(isShowRefresh: Boolean? = true) {
srlContainer.isRefreshing = isShowRefresh!!
val key =tv_search_content.text.toString()
if (!TextUtils.isEmpty(key.trim())) {
allFilter.searchWord = key.trim()
} else {
allFilter.searchWord = null
}
curPage = 1
onScrollListener.resetState()
getPresenter().fetchListData(allFilter, curPage)
rvExperts.scrollToPosition(0)
}
//执行搜索
private fun doSearch() {
image_scroll_top.visibility = View.GONE
hideSoftInput();
// keyWord = etSearch.text.toString()
// if (TextUtils.isEmpty(keyWord?.trim())) {
// ToastUtil.toastShort(this, "请输入搜索内容")
// return
// }
ActionCountUtils.count(ConsultBIConstants.UserMainEvent.YDL_USER_SEARCH_CLICK, keyWord ?: "")
isDoSearch = true
resetFilter()
refresh()
}
//重置所有筛选
private fun resetFilter() {
allFilter.categories.clear()
allFilter.categories.add(headData?.cates?.get(0) ?: CateItem())
allFilter.reorder = headData?.reorder?.get(0) ?: ReorderItem()
allFilter.region = RegionItem()
allFilter.sub = SubItem()
allFilter.enquiries.clear()
allFilter.ages.clear()
allFilter.others.clear()
updateFilterTextViewStatus(tvSubject, FILTER_STATUS_NORMAL)
updateFilterTextViewStatus(tvArea, FILTER_STATUS_NORMAL)
updateFilterTextViewStatus(tvSort, FILTER_STATUS_NORMAL)
if (headData != null) {
if (allFilter.showType != headData!!.filters.showType[1]) {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_NORMAL)
}
}
}
//设置筛选点击按钮状态
private fun updateFilterTextViewStatus(tv: TextView, status: Int) {
when (status) {
FILTER_STATUS_NORMAL -> {
tv.typeface = Typeface.defaultFromStyle(Typeface.NORMAL)
tv.setTextColor(ContextCompat.getColor(context, R.color.platform_colorTextDefault))
tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.platform_ic_arrow_drop_down_grey_500_18dp, 0)
}
FILTER_STATUS_FILTERED -> {
tv.typeface = Typeface.DEFAULT_BOLD
tv.setTextColor(ContextCompat.getColor(context, R.color.consultant_main_theme))
tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.platform_ic_arrow_drop_down_grey_500_18dp, 0)
}
FILTER_STATUS_OPEN -> {
tv.typeface = Typeface.DEFAULT_BOLD
tv.setTextColor(ContextCompat.getColor(context, R.color.platform_colorTextDefault))
tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.consultant_ic_arrow_drop_down, 0)
}
}
}
private fun hideSoftInput() {
val view = activity.currentFocus
if (view != null) {
val imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
}
}
/**
* 事件埋点
*/
fun bury(keyworks: String, isResult: Boolean, isRecommend: Boolean, location: String) {
BuryPointUtils.getInstance().createMap()
.put("keyWord", keyworks)
.put("hasResult", isResult)
.put("isRecommend", isRecommend)
.put("location", location)
.burryPoint("search")
}
override fun onResume() {
super.onResume()
ActionCountUtils.count(ConsultBIConstants.ConsultEvent.APP_CONSULT_LIST_PAGE_VISIT)
}
override fun onDestroy() {
super.onDestroy()
ConsultAssistantDialogUtils.INSTANCE.resetStatus()
}
}
......@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.text.TextUtils
import com.google.gson.Gson
import com.ydl.ydlcommon.base.BaseApp
import com.ydl.ydlcommon.base.lifecycle.IActivityLifecycleable
import com.ydl.ydlcommon.data.http.RxUtils
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.ydl.ydlcommon.mvp.base.SimplePresenter
......@@ -22,7 +23,6 @@ import io.reactivex.schedulers.Schedulers
/**
* 专家搜索页Presenter
* Created by zqk on 17-9-19.
*/
class ExpertSearchPresenter : SimplePresenter<IExpertSearchView>() {
......@@ -43,10 +43,12 @@ class ExpertSearchPresenter : SimplePresenter<IExpertSearchView>() {
}
@SuppressLint("CheckResult")
fun fetchBannerList() {
ExpertSearchDataManager.getHttp().getBannerList()
.subscribeOn(Schedulers.io())
.compose(RxLifecycleUtils.bindToLifecycle(mView!!)).compose(RxUtils.resultJavaData())
.compose(RxLifecycleUtils.bindToLifecycle(mView!!))
.compose(RxUtils.resultJavaData())
.map { it }
.filter { it != null }
.observeOn(AndroidSchedulers.mainThread())
......@@ -121,6 +123,7 @@ class ExpertSearchPresenter : SimplePresenter<IExpertSearchView>() {
}
}
@SuppressLint("CheckResult")
fun fetchListData(allFilter: AllFilter, page: Int) {
var showType = 0
......@@ -164,7 +167,8 @@ class ExpertSearchPresenter : SimplePresenter<IExpertSearchView>() {
}
sb.append("&page=").append(page)
ExpertSearchDataManager.getHttp().searchDoctor(sb.toString())
.compose(RxLifecycleUtils.bindToLifecycle(mView!!)).compose(RxUtils.resultJavaData())
.compose(RxLifecycleUtils.bindToLifecycle(mView!!))
.compose(RxUtils.resultJavaData())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer {
......
......@@ -55,23 +55,17 @@ android {
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
kapt 'com.alibaba:arouter-compiler:1.2.2'
implementation 'com.jakewharton:butterknife:8.8.1'
// api 'com.dou361.ijkplayer-armv5:jjdxm-ijkplayer-armv5:1.0.0'
// api 'com.dou361.ijkplayer-arm64:jjdxm-ijkplayer-arm64:1.0.0'
// api 'com.dou361.ijkplayer-x86:jjdxm-ijkplayer-x86:1.0.0'
// api 'com.dou361.ijkplayer-x86_64:jjdxm-ijkplayer-x86_64:1.0.0'
// api('com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.6') {
// exclude group: 'com.android.support', module: 'appcompat-v7'
// }
api 'com.github.princekin-f:EasyFloat:1.1.2'
api rootProject.ext.dependencies["ydl-user-router"]
api rootProject.ext.dependencies["butterknife"]
if (rootProject.ext.dev_mode){
//开发时使用
implementation modularPublication('com.ydl:m-user-api')
......@@ -79,7 +73,7 @@ dependencies {
api project(":ydl-platform")
api project(":ydl-media")
api project(":ydl-pay")
api project(":ydl-flutter-base")
} else {
//发布时使用
compileOnly rootProject.ext.dependencies["ydl-m-user-api"]
......@@ -88,11 +82,10 @@ dependencies {
transitive = true
}
api rootProject.ext.dependencies["ydl-pay"]
api (rootProject.ext.dependencies["ydl-flutter-base"]){
transitive = true
}
api(rootProject.ext.dependencies["ydl-platform"]) {
transitive = true
}
}
api rootProject.ext.dependencies["ydl-flutter"]
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.yidianling.course">
<uses-sdk tools:overrideLibrary="com.lzf.easyfloat"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application>
<!--课程首页-->
<activity
......@@ -42,6 +48,7 @@
android:name=".course_special_list.activity.CourseSpecialListActivity"
android:screenOrientation="portrait" />
<service android:name="com.lzf.easyfloat.service.FloatService" />
</application>
</manifest>
package com.yidianling.course;
import android.support.v4.app.Fragment;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.ydl.ydlcommon.base.BaseActivity;
......@@ -11,7 +10,6 @@ import com.ydl.ydlcommon.base.BaseActivity;
@Route(path = "/course/home")
public class CourseActivity extends BaseActivity {
@Override
protected int layoutResId() {
return R.layout.activity_course;
......
......@@ -2,11 +2,13 @@ package com.yidianling.course
import CoursePlugin
import android.annotation.SuppressLint
import android.os.Bundle
import android.os.Handler
import android.text.TextUtils
import android.view.View
import com.alibaba.android.arouter.launcher.ARouter
import com.example.fm_plugin.base.BaseFlutterFragment
import com.google.gson.Gson
import com.ydl.ydl_flutter.flutter.base.BaseFlutterFragment
import com.ydl.ydl_router.manager.YDLRouterManager
import com.ydl.ydlcommon.data.http.BaseResponse
import com.ydl.ydlcommon.data.http.RxUtils
......@@ -40,10 +42,12 @@ class FlutterCourseHomeFragment : BaseFlutterFragment() {
private var hasRequestCoupon = false
private var dialog: CourseCouponDialog? = null
override fun initChannelPlugin(flutterView: FlutterView) {
CoursePlugin.register(this, flutterView)
CourseSendPlugin.initContext(this, flutterView)
}
override fun initialRoute(): String {
......
package com.yidianling.course.coursePlay
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
......@@ -19,12 +20,13 @@ import com.alibaba.android.arouter.facade.annotation.Route
import com.bumptech.glide.Glide
import com.dou361.ijkplayer.widget.PlayStateParams
import com.dou361.ijkplayer.widget.PlayerView
import com.lzf.easyfloat.enums.ShowPattern
import com.lzf.easyfloat.permission.PermissionUtils
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.audio.utils.PlayProgressUtil
import com.ydl.media.view.PlayTypeEnum
import com.ydl.media.view.PlayerFloatHelper
import com.ydl.ydl_image.module.GlideApp
import com.yidianling.ydl_pay.CommonPayDialog
import com.ydl.ydl_router.manager.YDLRouterManager
import com.ydl.ydlcommon.adapter.CommonRecyclerAdapter
import com.ydl.ydlcommon.base.BaseActivity
......@@ -48,6 +50,8 @@ import com.yidianling.course.bean.CourseMediaBean
import com.yidianling.course.bean.CourseMediaDetailBean
import com.yidianling.course.coursePlay.presenter.CoursePlayPresenter
import com.yidianling.course.router.CourseIn
import com.yidianling.course.widget.VideoFloatHelper
import com.yidianling.ydl_pay.CommonPayDialog
import kotlinx.android.synthetic.main.activity_course_play.*
import org.json.JSONException
import org.json.JSONObject
......@@ -148,9 +152,15 @@ class CoursePlayActivity : BaseActivity() {
recy_list?.isNestedScrollingEnabled = false
recy_list?.layoutManager = LinearLayoutManager(this, OrientationHelper.VERTICAL, false)
adapter = CommonRecyclerAdapter<CourseMediaBean>(recy_list, R.layout.item_course_playlist_item)
.setBindDataCallback(object : CommonRecyclerAdapter.BindDataCallback<CourseMediaBean> {
override fun bindDatabindData(holder: BaseViewHolder, bean: CourseMediaBean, position: Int) {
adapter =
CommonRecyclerAdapter<CourseMediaBean>(recy_list, R.layout.item_course_playlist_item)
.setBindDataCallback(object :
CommonRecyclerAdapter.BindDataCallback<CourseMediaBean> {
override fun bindDatabindData(
holder: BaseViewHolder,
bean: CourseMediaBean,
position: Int
) {
var gifView: ImageView = holder.getView(R.id.gifView)
var playView: ImageView = holder.getView(R.id.ic_play_view)
var bodyView: LinearLayout = holder.getView(R.id.lin_body)
......@@ -160,9 +170,11 @@ class CoursePlayActivity : BaseActivity() {
playView.visibility = View.GONE
bodyView.setBackgroundColor(this@CoursePlayActivity.resources.getColor(R.color.course_color_F8FCFF))
if (isShowAnim) {
Glide.with(this@CoursePlayActivity).asGif().load(R.drawable.course_music).into(gifView)
Glide.with(this@CoursePlayActivity).asGif()
.load(R.drawable.course_music).into(gifView)
} else {
Glide.with(this@CoursePlayActivity).asBitmap().load(R.drawable.course_music).into(gifView)
Glide.with(this@CoursePlayActivity).asBitmap()
.load(R.drawable.course_music).into(gifView)
}
holder.setTextColor(
R.id.text_title,
......@@ -173,13 +185,16 @@ class CoursePlayActivity : BaseActivity() {
playView.visibility = View.VISIBLE
bodyView.setBackgroundColor(this@CoursePlayActivity.resources.getColor(R.color.white))
if (courPlayBean?.courseExtra?.isBuy!!) {
GlideApp.with(this@CoursePlayActivity).load(R.drawable.course_ico_kcml_play).into(playView)
GlideApp.with(this@CoursePlayActivity)
.load(R.drawable.course_ico_kcml_play).into(playView)
} else {
if (bean.isDemo) {
GlideApp.with(this@CoursePlayActivity).load(R.drawable.course_ico_kcml_play)
GlideApp.with(this@CoursePlayActivity)
.load(R.drawable.course_ico_kcml_play)
.into(playView)
} else {
GlideApp.with(this@CoursePlayActivity).load(R.drawable.course_ico_kcml_lock)
GlideApp.with(this@CoursePlayActivity)
.load(R.drawable.course_ico_kcml_lock)
.into(playView)
}
}
......@@ -220,7 +235,11 @@ class CoursePlayActivity : BaseActivity() {
.show()
return@setOnClickListener
}
PlayProgressUtil.saveProgress(this@CoursePlayActivity, playList[index].url, 0)
PlayProgressUtil.saveProgress(
this@CoursePlayActivity,
playList[index].url,
0
)
if (play_type == 1) {
//暂停状态 开始播放
......@@ -228,10 +247,14 @@ class CoursePlayActivity : BaseActivity() {
}
if (play_type == 0) {
if (RxNetTool.isWifi(this@CoursePlayActivity)) {
(play_view as CoursePlayItemViewAudio).playView!!.play(position)
(play_view as CoursePlayItemViewAudio).playView!!.play(
position
)
} else {
if ((play_view as CoursePlayItemViewAudio).hasEnsureNetStatus) {
(play_view as CoursePlayItemViewAudio).playView!!.play(position)
(play_view as CoursePlayItemViewAudio).playView!!.play(
position
)
} else {
(play_view as CoursePlayItemViewAudio).setData(
position,
......@@ -331,7 +354,13 @@ class CoursePlayActivity : BaseActivity() {
//获取状态栏高度
var statusBarheight: Int = ScreenUtil.getStatusBarHeight(mContext)
//设置边距
setMargins(title_bar_layout, RxImageTool.dp2px(15f), statusBarheight, RxImageTool.dp2px(15f), 0)
setMargins(
title_bar_layout,
RxImageTool.dp2px(15f),
statusBarheight,
RxImageTool.dp2px(15f),
0
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.statusBarColor = Color.TRANSPARENT
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
......@@ -412,9 +441,7 @@ class CoursePlayActivity : BaseActivity() {
}
if (play_type == 0) {
handler.postDelayed({
play_view?.setData(index, playList, bean.courseExtra, from)
}, 500)
} else {
play_view?.setData(index, playList, bean.courseExtra, from)
}
......@@ -469,12 +496,6 @@ class CoursePlayActivity : BaseActivity() {
}
}
fun showPlayAnim(isShowAnim: Boolean) {
this.isShowAnim = isShowAnim
if (adapter != null) {
adapter?.notifyDataSetChanged()
}
}
fun showLoadingDialog() {
......@@ -525,7 +546,15 @@ class CoursePlayActivity : BaseActivity() {
ToastUtil.toastShort("缺少参数")
return
}
val dialog = YDLShareDialog.style1(this, share.title, share.share_url, share.desc, share.cover, "", "")
val dialog = YDLShareDialog.style1(
this,
share.title,
share.share_url,
share.desc,
share.cover,
"",
""
)
dialog.setCallBack(object : YDLShareDialog.ICallBack {
override fun callBack(type: Int) {
if (1 == type) {
......@@ -602,14 +631,19 @@ class CoursePlayActivity : BaseActivity() {
fun showVideoFloatView(): Boolean {
if (play_type == 0) {
// if (YDLMusicHelper.isCoursePlaying()) {
// YDLMusicHelper.cover = courPlayBean?.courseExtra?.pic
// YDLMusicHelper.name = courPlayBean?.courseExtra?.doctorName
// }
if (AudioPlayer.get().isPlaying && PlayerFloatHelper.playingType == PlayTypeEnum.PLAY_TYPE_COURSE) {
AudioPlayer.get().playMusic?.coverPath=courPlayBean?.courseExtra?.pic
AudioPlayer.get().playMusic?.artist=courPlayBean?.courseExtra?.doctorName
AudioPlayer.get().playMusic?.coverPath = courPlayBean?.courseExtra?.pic
AudioPlayer.get().playMusic?.artist = courPlayBean?.courseExtra?.doctorName
val hashMap = HashMap<String, String>()
hashMap["course_id"] = course_id.toString()
PlayerFloatHelper.playTempData.putAll(hashMap)
// PlayerFloatHelper.show(
// this,
// playTypeEnum = PlayTypeEnum.PLAY_TYPE_COURSE,
// playData = hashMap
// )
}
......@@ -630,13 +664,43 @@ class CoursePlayActivity : BaseActivity() {
// YDLMusicHelper.courseVideoUlr = (play_view as CoursePlayItemViewVideo).videoUrl
// YDLMusicHelper.course_id = courPlayBean?.courseExtra?.id!!.toInt()
PlayerFloatHelper.show(this)
VideoFloatHelper.setVideoInfo(
course_id.toString(),
(play_view as CoursePlayItemViewVideo).videoUrl!!,
true
)
VideoFloatHelper.defaultShowPattern = ShowPattern.FOREGROUND
checkPermission()
}
}
}
return true
}
/**
* 检测浮窗权限是否开启,若没有给与申请提示框(非必须,申请依旧是EasyFloat内部内保进行)
*/
private fun checkPermission() {
if (PermissionUtils.checkPermission(this)) {
VideoFloatHelper.showVideoFloat(this)
} else {
AlertDialog.Builder(this)
.setMessage("使用浮窗功能,需要您授权悬浮窗权限。")
.setPositiveButton("去开启") { _, _ ->
VideoFloatHelper.showVideoFloat(this)
}
.setNegativeButton("取消") { _, _ ->
ToastUtil.toastLong(
this,
"App正常工作需要内部存储使用权限,请开启"
)
}
.show()
}
}
override fun onDestroy() {
videoView?.onDestroy()
play_view?.onDestroy()
......
......@@ -102,7 +102,12 @@ class CoursePlayItemViewAudio : RelativeLayout, PlayViewInterface {
/**
* 设置显示数据
*/
override fun setData(index: Int, list: ArrayList<CourseMediaBean>, courseExtra: CourseExtraBean, from: Int) {
override fun setData(
index: Int,
list: ArrayList<CourseMediaBean>,
courseExtra: CourseExtraBean,
from: Int
) {
if (list.isEmpty()) return
playList.clear()
......@@ -110,8 +115,6 @@ class CoursePlayItemViewAudio : RelativeLayout, PlayViewInterface {
this.courseExtra = courseExtra
currentIndex = index
// YDLMusicHelper.course_id = courseExtra.id.toInt()
if (courseExtra.isBuy) {
playView?.setAutoNext(true)
} else {
......
......@@ -208,9 +208,12 @@ class CourseSearchActivity : BaseActivity(), CourseSearchAdapter.OnItemClick, IC
hideUnusualPage()
if (type) {
courseList.clear()
}
courseList.addAll(it.data.list)
courseSearchAdapterWrapper!!.notifyDataSetChanged()
} else {
courseList.addAll(it.data.list)
courseSearchAdapterWrapper!!.insertData()
}
} else {
if (!type) {
courseSearchAdapterWrapper!!.noMoreData()
......
package com.yidianling.course.courseSearch.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.course.courseSearch.CourseSearchBean
import io.reactivex.Observable
......@@ -16,5 +18,6 @@ interface CourseSearchListApi{
//专家课程搜索列表
@GET("auth/course/getList")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA)
fun courseSearchList(@Query("page")page: Int, @Query("keyWord")keyWord: String): Observable<BaseAPIResponse<CourseSearchBean>>
}
\ No newline at end of file
import android.app.AlertDialog
import android.content.Intent
import android.net.Uri
import android.os.Handler
import android.text.TextUtils
import com.example.fm_plugin.base.BaseFlutterFragment
import com.lzf.easyfloat.permission.PermissionUtils
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.audio.model.Music
import com.ydl.media.view.PlayTypeEnum
......@@ -9,20 +12,20 @@ import com.ydl.media.view.PlayerFloatHelper
import com.ydl.media.view.PlayerFloatView
import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity
import com.ydl.ydl_flutter.flutter.base.BaseFlutterFragment
import com.ydl.ydl_router.manager.YDLRouterManager
import com.ydl.ydlcommon.base.BaseApp
import com.ydl.ydlcommon.data.PlatformDataManager
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.course.BuildConfig
import com.yidianling.common.tools.ToastUtil
import com.yidianling.course.CourseConstants
import com.yidianling.course.bean.ScrollStatusChangeEvent
import com.yidianling.course.courseNew.mine.MyCourseActivity
import com.yidianling.course.course_special_list.activity.CourseSpecialListActivity
import com.yidianling.course.flutterPlugin.CourseSendPlugin
import com.yidianling.course.router.CourseIn
import com.yidianling.course.widget.VideoFloatHelper
import de.greenrobot.event.EventBus
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
......@@ -66,7 +69,7 @@ class CoursePlugin : MethodChannel.MethodCallHandler {
val loginBean = ModularServiceManager.getPlatformUserService()?.getUser()
val mMap = mutableMapOf<String, Any>()
var uid = loginBean?.userId ?: ""
mMap["isDevelopment"] = BuildConfig.DEBUG
mMap["isDevelopment"] = false
mMap["uid"] = if (TextUtils.isEmpty(uid)) "0" else uid
mMap["accessToken"] = loginBean?.token ?: ""
?: ""
......@@ -92,11 +95,21 @@ class CoursePlugin : MethodChannel.MethodCallHandler {
return
}
when {
jumpUrl!!.contains("user/login") -> mFragment!!.startActivity(
CourseIn.loginWayIntent(
mFragment!!.activity!!
)
jumpUrl!!.contains("user/login") -> {
//TODO flutter 登录状态判断需要更改
val loginBean =
ModularServiceManager.getPlatformUserService()?.getUser()
if (loginBean == null || TextUtils.isEmpty(loginBean.userId) || TextUtils.equals(
loginBean.userId,
"0"
)
) {
mFragment!!.startActivity(CourseIn.loginWayIntent(mFragment!!.activity!!))
} else {
MyCourseActivity.start(mFragment!!.activity)
}
}
jumpUrl.contains("course/myCourse") -> MyCourseActivity.start(mFragment!!.activity)
jumpUrl.contains("course/specialList") -> //跳转专题列表页
mFragment!!.activity!!.startActivity(
......@@ -177,20 +190,29 @@ class CoursePlugin : MethodChannel.MethodCallHandler {
if (demoType == 1) {
music.path = url
val hashMap = HashMap<String, String>()
hashMap["course_id"] = fileInfo["courseId"].toString()
AudioPlayer.get().singlePlay(music)
PlayerFloatHelper.show(
mFragment!!.activity,
playTypeEnum = PlayTypeEnum.PLAY_TYPE_COURSE
playTypeEnum = PlayTypeEnum.PLAY_TYPE_COURSE,
playData = hashMap
)
VideoFloatHelper.dismissFloat(mFragment!!.activity)
}
if (demoType == 2) {
//todo 视屏播放
// YDLMusicHelper.playType = 1
// YDLMusicHelper.courseVideoUlr = url
//
// PlayerFloatHelper.show(mFragment!!.activity)
VideoFloatHelper.setVideoInfo(
fileInfo["courseId"].toString(),
fileInfo["url"].toString(),
false
)
checkPermission()
if (PlayerFloatHelper.isShow(mFragment!!.activity!!)) {
PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(mFragment!!.activity!!)
AudioPlayer.get().stopPlayer()
}
}
Handler().postDelayed({ CourseSendPlugin.sendMsg(true) }, 300)
......@@ -215,4 +237,28 @@ class CoursePlugin : MethodChannel.MethodCallHandler {
}
})
}
/**
* 检测浮窗权限是否开启,若没有给与申请提示框(非必须,申请依旧是EasyFloat内部内保进行)
*/
private fun checkPermission() {
if (PermissionUtils.checkPermission(mFragment!!.activity)) {
VideoFloatHelper.showVideoFloat(mFragment!!.activity)
} else {
AlertDialog.Builder(mFragment!!.activity)
.setMessage("使用浮窗功能,需要您授权悬浮窗权限。")
.setPositiveButton("去开启") { _, _ ->
VideoFloatHelper.showVideoFloat(mFragment!!.activity)
}
.setNegativeButton("取消") { _, _ ->
ToastUtil.toastLong(
mFragment!!.activity,
"App正常工作需要内部存储使用权限,请开启"
)
}
.show()
}
}
}
\ No newline at end of file
package com.yidianling.course.flutterPlugin
import com.ydl.ydl_flutter.flutter.io.flutter.facade.FlutterFragment
import android.util.Log
import com.example.fm_plugin.base.FlutterFragment
import io.flutter.plugin.common.EventChannel
import io.flutter.view.FlutterView
......@@ -45,4 +46,5 @@ object CourseSendPlugin {
fun sendLoginSuccess(){
eventSink!!.success("loginSuccess")
}
}
\ No newline at end of file
package com.yidianling.course.lifeCallback
import android.app.Activity
import android.app.Application
import android.os.Bundle
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.view.PlayTypeEnum
import com.ydl.media.view.PlayerFloatHelper
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/11/19
*/
class CoursePlayLifecycle : Application.ActivityLifecycleCallbacks {
override fun onActivityPaused(activity: Activity?) {
}
override fun onActivityResumed(activity: Activity?) {
if (!PlayerFloatHelper.isCanClick) {
PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(activity!!)
AudioPlayer.get().stopPlayer()
} else {
PlayerFloatHelper.showIfPlaying(activity!!)
PlayerFloatHelper.playingType = PlayTypeEnum.PLAY_TYPE_COURSE
}
}
override fun onActivityStarted(activity: Activity?) {
}
override fun onActivityDestroyed(activity: Activity?) {
}
override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {
}
override fun onActivityStopped(activity: Activity?) {
}
override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {
}
}
\ No newline at end of file
package com.yidianling.course.uitls
import android.content.Context
import android.text.TextUtils
/**
* 工具类
* Created by hgw on 2018/3/31.
*/
object VideoProgressUtil {
/**
* 保存播放进度
*/
fun saveProgress(context: Context?, url: String?, progress: Int) {
if (TextUtils.isEmpty(url)) return
val shared = context?.getSharedPreferences("COURSE_VIDEO_PROGRESS", Context.MODE_PRIVATE)
val edit = shared?.edit()
edit?.putInt(url, progress)
edit?.apply()
}
/**
* 获取进度
*/
fun getProgress(context: Context?, url: String?): Int {
if (TextUtils.isEmpty(url)) return 0
val shared = context?.getSharedPreferences("COURSE_VIDEO_PROGRESS", Context.MODE_PRIVATE)
return shared?.getInt(url, 0) ?: 0
}
}
\ No newline at end of file
package com.yidianling.course.widget
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.content.Context
import android.graphics.Paint
import android.support.constraint.ConstraintLayout
......@@ -8,6 +10,7 @@ import android.text.TextUtils
import android.util.AttributeSet
import android.view.View
import com.alibaba.android.arouter.launcher.ARouter
import com.lzf.easyfloat.permission.PermissionUtils
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.audio.model.Music
import com.ydl.media.view.PlayTypeEnum
......@@ -19,6 +22,7 @@ import com.ydl.ydl_image.module.GlideApp
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.ydl.ydlcommon.utils.actionutil.BIConstants
import com.yidianling.common.tools.RxImageTool
import com.yidianling.common.tools.ToastUtil
import com.yidianling.course.CourseConstants
import com.yidianling.course.R
import com.yidianling.course.bean.Course
......@@ -228,14 +232,30 @@ class CourseItemNewView : ConstraintLayout {
PlayerFloatHelper.playingType=PlayTypeEnum.PLAY_TYPE_COURSE
music.path=course.demoFile
val hashMap = HashMap<String, String>()
hashMap["course_id"] =course.id.toString()
AudioPlayer.get().singlePlay(music)
PlayerFloatHelper.show(
mContext,
playTypeEnum = PlayTypeEnum.PLAY_TYPE_COURSE,
playData = hashMap
)
VideoFloatHelper.dismissFloat(mContext as Activity)
}
if (course.demoType == 2) {
//todo 视屏播放
// YDLMusicHelper.playType = 1
// YDLMusicHelper.courseVideoUlr = course.demoFile
//
// PlayerFloatHelper.show(mContext)
VideoFloatHelper.setVideoInfo(
course.id.toString(),
course.demoFile,
false
)
checkPermission()
if (PlayerFloatHelper.isShow(mContext)) {
PlayerFloatHelper.hide()
PlayerFloatHelper.removeView(mContext)
AudioPlayer.get().stopPlayer()
}
}
......@@ -269,4 +289,27 @@ class CourseItemNewView : ConstraintLayout {
fun hideListenerButton() {
tv_view_course.visibility = View.GONE
}
/**
* 检测浮窗权限是否开启,若没有给与申请提示框(非必须,申请依旧是EasyFloat内部内保进行)
*/
private fun checkPermission() {
if (PermissionUtils.checkPermission(mContext)) {
VideoFloatHelper.showVideoFloat(mContext as Activity)
} else {
AlertDialog.Builder(mContext)
.setMessage("使用浮窗功能,需要您授权悬浮窗权限。")
.setPositiveButton("去开启") { _, _ ->
VideoFloatHelper.showVideoFloat(mContext as Activity)
}
.setNegativeButton("取消") { _, _ ->
ToastUtil.toastLong(
mContext,
"App正常工作需要内部存储使用权限,请开启"
)
}
.show()
}
}
}
\ No newline at end of file
package com.yidianling.course.widget
import android.annotation.SuppressLint
import android.app.Activity
import android.os.Handler
import android.view.View
......@@ -36,8 +37,8 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
fun init() {
if (mContext == null) return
View.inflate(context, R.layout.course_play_music_view, this)
AudioPlayer.get().addOnPlayEventListener(this)
play_icon.setOnClickListener {
AudioPlayer.get().playPause()
......@@ -48,8 +49,6 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
}
}
AudioPlayer.get().addOnPlayEventListener(this)
pro_progress.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
if (p2) {
......@@ -114,9 +113,9 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
}
fun play(index: Int) {
updateButton()
PlayerFloatHelper.playingType=PlayTypeEnum.PLAY_TYPE_COURSE
PlayerFloatHelper.playingType = PlayTypeEnum.PLAY_TYPE_COURSE
AudioPlayer.get().play(index)
updateButton()
}
fun setImageBackground(url: String?) {
......@@ -127,14 +126,23 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
* 设置自动播放下一曲
*/
fun setAutoNext(auto: Boolean) {
if(!auto){
AudioPlayer.get().playMode=PlayModeEnum.SINGLE
if (!auto) {
AudioPlayer.get().playMode = PlayModeEnum.SINGLE
} else {
AudioPlayer.get().playMode = PlayModeEnum.LIST_LOOP
}
}
@SuppressLint("SetTextI18n")
override fun onChange(music: Music) {
if (mContext != null) {
Glide.with(mContext).asGif().load(R.drawable.course_loading5).into(img_gif)
}
play_icon.setImageResource(R.drawable.course_ico_course_play)
pro_progress.progress = 0
text_start_time.text = "00:00"
}
override fun onPlayerStart() {
......@@ -142,21 +150,18 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
}
override fun onPlayerPause() {
if (AudioPlayer.get().isPlaying){
if (AudioPlayer.get().isPlaying) {
setGifVisibity(true)
}else{
} else {
setGifVisibity(false)
}
}
override fun onPublish(percent: Int, currentPosition: Long) {
mHandler?.postDelayed({
//拖动seekbar时不进行以下操作
if (!seekBarIsDown) {
pro_progress.progress = progress
text_start_time.text = getStringTime(progress)
pro_progress.progress = currentPosition.toInt()
text_start_time.text = getStringTime(currentPosition.toInt())
}
}, 0)
}
override fun onBufferingUpdate(percent: Int) {
......@@ -170,7 +175,7 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
mHandler?.postDelayed({
pro_progress.max = duration.toInt()
text_end_time.text = getStringTime(pro_progress.max)
var index=AudioPlayer.get().getMusicList()?.indexOf(AudioPlayer.get().playMusic)?:0
var index = AudioPlayer.get().getMusicList()?.indexOf(AudioPlayer.get().playMusic) ?: 0
listener?.onPrepared(
AudioPlayer.get().playMusic, index
)
......@@ -186,11 +191,12 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
private fun showBufferLoading(show: Boolean) {
mHandler?.postDelayed({
if (show) {
if (!AudioPlayer.get().isPlaying) {
if (mContext != null) {
Glide.with(mContext).asGif().load(R.drawable.course_loading5).into(img_gif)
}
play_icon.setImageResource(R.drawable.course_ico_course_play)
}
} else {
if (mContext != null) {
Glide.with(mContext).asGif().load(R.drawable.course_audio_play).into(img_gif)
......@@ -202,17 +208,14 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
//显示或隐藏播放动画
private fun setGifVisibity(show: Boolean) {
if (context == null) return
if (mContext == null) return
mHandler?.postDelayed({
if (show) {
if (mContext != null) {
Glide.with(mContext).asGif().load(R.drawable.course_audio_play).into(img_gif)
}
play_icon.setImageResource(R.drawable.course_ico_course_pause)
} else {
if (mContext != null) {
Glide.with(mContext).asBitmap().load(R.drawable.course_ico_course_bg_pause).into(img_gif)
}
Glide.with(mContext).asBitmap().load(R.drawable.course_ico_course_bg_pause)
.into(img_gif)
play_icon.setImageResource(R.drawable.course_ico_course_play)
}
}, 0)
......@@ -225,7 +228,7 @@ class HPlayView : RelativeLayout, OnPlayerEventListener {
if (AudioPlayer.get().isPlaying) {
setGifVisibity(true)
}
}, 0)
}, 300)
}
......
package com.yidianling.course.widget
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.view.View
import android.widget.ImageView
import com.alibaba.android.arouter.launcher.ARouter
import com.dou361.ijkplayer.widget.PlayStateParams
import com.dou361.ijkplayer.widget.PlayerView
import com.lzf.easyfloat.EasyFloat
import com.lzf.easyfloat.enums.ShowPattern
import com.lzf.easyfloat.interfaces.OnInvokeView
import com.ydl.media.audio.utils.PlayProgressUtil
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.common.tools.RxImageTool
import com.yidianling.course.R
import com.yidianling.course.coursePlay.CoursePlayActivity
import com.yidianling.course.flutterPlugin.CourseSendPlugin
import com.yidianling.course.uitls.VideoProgressUtil
import java.util.*
/**
* @author jiucheng
* @描述:视频悬浮窗
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2019/11/19
*/
object VideoFloatHelper {
private const val courseTag = "course_video_play"
var courseVideoUrl = ""
var courseId = ""
var isCanClick = true
var isCurrentVideoPlaying = true
//视频播放器view
@SuppressLint("StaticFieldLeak")
private var videoView: PlayerView? = null
private var timer: Timer? = null
var defaultShowPattern = ShowPattern.CURRENT_ACTIVITY
fun setVideoInfo(
courseId: String,
courseVideoUrl: String,
isCanClick: Boolean
): VideoFloatHelper {
this.courseId = courseId
this.courseVideoUrl = courseVideoUrl
this.isCanClick = isCanClick
return this
}
fun showVideoFloat(activity: Activity) {
val x = RxDeviceTool.getScreenWidth(activity) - RxImageTool.dp2px(220f)
val y = RxDeviceTool.getScreenHeight(activity) * 3 / 4
EasyFloat.with(activity)
.setTag(courseTag)
.setShowPattern(defaultShowPattern)
.setLocation(x, y)
.setAppFloatAnimator(null)
.setFilter(CoursePlayActivity::class.java)
.setLayout(R.layout.course_float_video_view, OnInvokeView {
it.findViewById<ImageView>(R.id.iv_video_close).setOnClickListener {
dismissFloat(activity)
}
val videoFullScreen = it.findViewById<ImageView>(R.id.iv_video_full_screen)
if (isCanClick) {
videoFullScreen.visibility = View.VISIBLE
} else {
videoFullScreen.visibility = View.INVISIBLE
}
videoFullScreen.setOnClickListener {
if (isCanClick) {
startCoursePlayActivity(activity, 1, 1, courseVideoUrl, true)
}
}
val videoLayout = it.findViewById<ImageView>(R.id.app_video_box)
try {
initVideoPlayer(activity, videoLayout)
} catch (e: Exception) {
e.printStackTrace()
}
})
.show()
}
private fun initVideoPlayer(activity: Activity, view: View) {
val url = courseVideoUrl.replace("https", "http")
val hisTime = PlayProgressUtil.getProgress(activity, url)
videoView = PlayerView(activity, view)
.setScaleType(PlayStateParams.fitparent)
.hideAllUI()
.setNetWorkTypeTie(false)
.setAutoReConnect(true, 3)
.forbidTouch(true)
.setOnInfoListener { _, what, _ ->
if (what == PlayStateParams.STATE_COMPLETED) {
isCurrentVideoPlaying = false
PlayProgressUtil.saveProgress(activity, url, 0)
} else {
isCurrentVideoPlaying = true
}
true
}
.setPlaySource(url)
.startPlay()
.seekTo(hisTime)
view.setOnClickListener {
if (isCanClick) {
startCoursePlayActivity(activity, 1, 0, courseVideoUrl, true)
}
}
startTimer(url, activity)
}
private fun startTimer(url: String, activity: Activity) {
if (timer == null) {
timer = Timer()
}
timer?.schedule(object : TimerTask() {
override fun run() {
if (isCurrentVideoPlaying) {
var time = videoView?.currentPosition ?: 0
if (time < 3000) return
PlayProgressUtil.saveProgress(activity, url, time)
}
}
}, 1000, 1000)
}
private fun startCoursePlayActivity(
context: Context?,
from: Int,
fullScreen: Int,
coursePlayUrl: String,
isFromFloatView: Boolean
) {
ARouter.getInstance()
.build("/course/play")
.withInt("course_id", courseId.toInt())
.withInt("course_type", 1)
.withString("coursePlayUrl", coursePlayUrl)
.withInt("from", from)
.withBoolean("isFromFloatView", isFromFloatView)
.withInt("fullScreen", fullScreen)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.navigation()
}
fun dismissFloat(activity: Activity) {
CourseSendPlugin.sendMsg(false)
EasyFloat.dismissAppFloat(activity, courseTag)
if (videoView != null) {
videoView!!.stopPlay()
videoView = null
}
if (timer != null) {
timer!!.cancel()
}
timer = null
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rl_video_layout"
android:layout_width="200dp"
android:layout_height="124dp"
android:background="@drawable/play_float_background"
android:visibility="visible">
<include
layout="@layout/course_videoplay_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/iv_video_close"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:padding="8dp"
android:scaleType="centerCrop"
android:src="@drawable/ico_play_float_pause"
android:visibility="visible" />
<ImageView
android:id="@+id/iv_video_full_screen"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:padding="8dp"
android:scaleType="centerCrop"
android:src="@drawable/course_ico_play_float_full"
android:visibility="visible" />
</RelativeLayout>
\ No newline at end of file
......@@ -66,15 +66,13 @@ dependencies {
//开发时使用
api project(":ydl-platform")
implementation project(':ydl-media')
api project(":ydl-flutter-base")
} else {
//发布时使用
api rootProject.ext.dependencies["ydl-media"]
api (rootProject.ext.dependencies["ydl-flutter-base"]){
transitive = true
}
api (rootProject.ext.dependencies["ydl-platform"]) {
transitive = true
}
}
api rootProject.ext.dependencies["ydl-flutter"]
}
package com.yidianling.muse.activity
import com.alibaba.android.arouter.facade.annotation.Route
import com.example.fm_plugin.base.BaseFlutterActivity
import com.ydl.media.audio.AudioPlayer
import com.ydl.ydl_flutter.flutter.base.BaseFlutterActivity
import com.ydl.ydlcommon.router.IYDLRouterConstant
import com.yidianling.muse.handler.MusePlugin
import org.json.JSONObject
......
......@@ -132,7 +132,7 @@ class TestSearchActivity : BaseMvpActivity<TestSearchView, TestSearchPresenter>(
}
rv_hot_list.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
if (!isFirstLoad) {
if (!isFirstLoad && dx!=0 && dx!=0) {
hideSoftInput()
}
}
......
......@@ -24,7 +24,7 @@ modular {
groupId = "com.ydl"
artifactId = "m-user-api"
//开发时注释掉版本号,发布api时打开
version = rootProject.ext.ydlPublishVersion[childProject.getName()+"-api"]
//version = rootProject.ext.ydlPublishVersion[childProject.getName()+"-api"]
// API 层打包时需要引入的依赖
apiDependencies {
implementation "com.google.code.gson:gson:2.8.2"
......
......@@ -32,7 +32,7 @@ object LoginUtils {
//设置异常用户ID
CrashReport.setUserId(userInfo?.uid)
//登录IM聊天
// loginIm(userInfo)
loginIm(userInfo)
//设置极光注册id
LoginHelper.setChannelId()
val loginEvent = UserLoginEvent("login", userInfo?.uid!!)
......
......@@ -61,12 +61,7 @@ object UserHelper {
fun getUserInfoStr(): String? {
if (userTemp != null) return gson.toJson(userTemp)
try {
return SharedPreferencesEditor.getFileString(user_info_name_sp, user_info_key_sp)
} catch (e: Exception) {
userTemp = UserResponseBean()
}
return gson.toJson(userTemp)
}
fun updateUserinfo(userInfo: UserResponseBean.UserInfo?) {
......@@ -136,11 +131,6 @@ object UserHelper {
fun getUserSettingStr(): String? {
if (userSetting != null) return gson.toJson(userSetting)
try {
return SharedPreferencesEditor.getFileString(user_setting_name_sp, user_setting_key_sp)
} catch (e: Exception) {
userSetting = UserSettingBean()
}
return gson.toJson(userSetting)
}
}
\ No newline at end of file
......@@ -27,16 +27,26 @@ import com.yidianling.user.ui.login.RegisterAndLoginActivity
class UserRouterImp : IUserRouter {
val gson: Gson = Gson()
override fun getUserSetting(): UserSetting {
return gson.fromJson(UserHelper.getUserSettingStr(), UserSetting::class.java)
override fun getUserSetting(): UserSetting? {
var infoStr = UserHelper.getUserSettingStr()
if (TextUtils.isEmpty(infoStr)){
return null
}
return gson.fromJson(infoStr, UserSetting::class.java)
}
override fun updateUserInfoSp(userInfo: UserResponse.UserInfo?) {
val info:UserResponseBean.UserInfo = gson.fromJson(gson.toJson(userInfo), UserResponseBean.UserInfo::class.java)
if (userInfo==null){
return
}
val info:UserResponseBean.UserInfo = gson.fromJson( gson.toJson(userInfo), UserResponseBean.UserInfo::class.java)
UserHelper.updateUserinfo(info)
}
override fun updateUserSetingSp(userSetting: UserSetting?) {
if (userSetting==null){
return
}
val info:UserSettingBean= gson.fromJson(gson.toJson(userSetting), UserSettingBean::class.java)
UserHelper.updateUserSetting(info)
}
......@@ -50,8 +60,12 @@ class UserRouterImp : IUserRouter {
UserHelper.setUserinfo(info)
}
override fun getUserResponse(): UserResponse {
return gson.fromJson(UserHelper.getUserInfoStr(), UserResponse::class.java)
override fun getUserResponse(): UserResponse? {
var infoStr = UserHelper.getUserInfoStr()
if (TextUtils.isEmpty(infoStr)){
return null
}
return gson.fromJson(infoStr,UserResponse::class.java)
}
override fun isLogin(): Boolean {
......
include ':app', ':ydl-flutter-base',":router", ':ydl-net', ':ydl-utils', ':ydl-platform', ':ydl-webview',
include ':app',":router", ':ydl-net', ':ydl-utils', ':ydl-platform', ':ydl-webview',
':m-confide', ':m-audioim',':ydl-media',":m-user", ':m-consultant', ':m-muse',
':m-fm', ':m-tests',":m-course", ':ydl-pay'
......
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply from: "../maven_push.gradle"
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 17
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
flavorDimensions "versionCode"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0'
api rootProject.ext.dependencies["ydl-flutter"]
}
IS_PUBLISH=true
VERSION_NAME=0.0.3
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ydl.ydl_flutter" />
package com.ydl.ydl_flutter.flutter.base
import android.content.Context
import android.content.Intent
import android.graphics.PixelFormat
import android.os.Bundle
import android.util.AttributeSet
import android.view.WindowManager
import io.flutter.app.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.view.FlutterView
import org.json.JSONObject
/**
* flutter 页面基类
* Created by xj on 2019/9/30.
*/
abstract class BaseFlutterActivity : FlutterActivity() {
companion object {
const val ROUTE_PAGE = "route" //路由
/**
* 路由传递过来的参数
*/
const val ROUTER_PARAMS = "routerParam"
}
override fun createFlutterView(context: Context?): FlutterView {
val matchParent = WindowManager.LayoutParams(-1, -1)
val nativeView = this.createFlutterNativeView()
val flutterView = FlutterView(this, null as AttributeSet?, nativeView)
flutterView.layoutParams = matchParent
this.setContentView(flutterView)
//这个action必加,不然无法在flutter端获取route参数值
intent.action = Intent.ACTION_RUN
/**
* 在这边初始化route
*/
intent.putExtra(ROUTE_PAGE, initialRoute())
//渲染优化(优化一丢丢几乎看不出来)
flutterView.setZOrderOnTop(true)
flutterView.holder.setFormat(PixelFormat.TRANSLUCENT)
return flutterView
}
public override fun onCreate( savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
/**
* 获取统一路由传递过来的参数并初始化交互通道
*/
val json = intent.getStringExtra(ROUTER_PARAMS)
initChannelPlugin(JSONObject(json))
}
/**
* 路由,例 "/native/muse/home"
*/
abstract fun initialRoute(): String
/**
* 初始化flutter channel插件
*/
abstract fun initChannelPlugin(jsonObject: JSONObject)
}
\ No newline at end of file
package com.ydl.ydl_flutter.flutter.base
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import com.ydl.ydl_flutter.flutter.io.flutter.facade.Flutter
import com.ydl.ydl_flutter.flutter.io.flutter.facade.FlutterFragment
import io.flutter.view.FlutterView
/**
* flutter fragment 基类
* Created by xj on 2019/9/30.
*/
abstract class BaseFlutterFragment : FlutterFragment() {
private var mFlutterView: FlutterView? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): FlutterView {
mFlutterView= Flutter.createView(
activity!!,
lifecycle,
initialRoute())
initChannelPlugin(mFlutterView!!)
return mFlutterView!!
}
/**
* 路由,例 "quick_reply"
*/
abstract fun initialRoute(): String
/**
* 初始化flutter channel插件
*/
abstract fun initChannelPlugin(flutterView: FlutterView)
}
package com.ydl.ydl_flutter.flutter.io.flutter.facade;
import android.app.Activity;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleObserver;
import android.arch.lifecycle.OnLifecycleEvent;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.StringCodec;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.view.FlutterMain;
import io.flutter.view.FlutterNativeView;
import io.flutter.view.FlutterRunArguments;
import io.flutter.view.FlutterView;
/**
* Main entry point for using Flutter in Android applications.
*
* <p><strong>Warning:</strong> This file is auto-generated by Flutter tooling.
* DO NOT EDIT.</p>
*/
public final class Flutter {
private Flutter() {
// to prevent instantiation
}
/**
* Initiates the Dart VM. Calling this method at an early point may help decreasing time to first
* frame for a subsequently created {@link FlutterView}.
*
* @param applicationContext the application's {@link Context}
*/
public static void startInitialization(@NonNull Context applicationContext) {
FlutterMain.startInitialization(applicationContext);
}
/**
* Creates a {@link FlutterFragment} managing a {@link FlutterView}. The optional
* initial route string will be made available to the Dart code
* (via {@code window.defaultRouteName}) and may be used to determine which widget
* should be displayed in the view. The default initialRoute is "/".
*
* @param initialRoute an initial route {@link String}, or null
* @return a {@link FlutterFragment}
*/
@NonNull
public static FlutterFragment createFragment(String initialRoute) {
final FlutterFragment fragment = new FlutterFragment();
final Bundle args = new Bundle();
args.putString(FlutterFragment.ARG_ROUTE, initialRoute);
fragment.setArguments(args);
return fragment;
}
/**
* Creates a {@link FlutterView} linked to the specified {@link Activity} and {@link Lifecycle}.
* The optional initial route string will be made available to the Dart code (via
* {@code window.defaultRouteName}) and may be used to determine which widget should be displayed
* in the view. The default initialRoute is "/".
*
* @param activity an {@link Activity}
* @param lifecycle a {@link Lifecycle}
* @param initialRoute an initial route {@link String}, or null
* @return a {@link FlutterView}
*/
@NonNull
public static FlutterView createView(@NonNull final Activity activity, @NonNull final Lifecycle lifecycle, final String initialRoute) {
FlutterMain.startInitialization(activity.getApplicationContext());
FlutterMain.ensureInitializationComplete(activity.getApplicationContext(), null);
final FlutterNativeView nativeView = new FlutterNativeView(activity);
final FlutterView flutterView = new FlutterView(activity, null, nativeView) {
private final BasicMessageChannel<String> lifecycleMessages = new BasicMessageChannel<>(this, "flutter/lifecycle", StringCodec.INSTANCE);
@Override
public void onFirstFrame() {
super.onFirstFrame();
setAlpha(1.0f);
}
@Override
public void onPostResume() {
// Overriding default behavior to avoid dictating system UI via PlatformPlugin.
lifecycleMessages.send("AppLifecycleState.resumed");
}
};
if (initialRoute != null) {
flutterView.setInitialRoute(initialRoute);
}
lifecycle.addObserver(new LifecycleObserver() {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreate() {
final FlutterRunArguments arguments = new FlutterRunArguments();
arguments.bundlePath = FlutterMain.findAppBundlePath(activity.getApplicationContext());
arguments.entrypoint = "main";
flutterView.runFromBundle(arguments);
GeneratedPluginRegistrant.registerWith(flutterView.getPluginRegistry());
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
flutterView.onStart();
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
flutterView.onPostResume();
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
flutterView.onPause();
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() {
flutterView.onStop();
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy() {
flutterView.destroy();
}
});
flutterView.setAlpha(0.0f);
return flutterView;
}
}
package com.ydl.ydl_flutter.flutter.io.flutter.facade;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import io.flutter.view.FlutterView;
/**
* A {@link Fragment} managing a {@link FlutterView}.
*
* <p><strong>Warning:</strong> This file is auto-generated by Flutter tooling.
* DO NOT EDIT.</p>
*/
public class FlutterFragment extends Fragment {
public static final String ARG_ROUTE = "route";
private String mRoute = "/";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mRoute = getArguments().getString(ARG_ROUTE);
}
}
@Override
public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
super.onInflate(context, attrs, savedInstanceState);
}
@Override
public FlutterView onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return Flutter.createView(getActivity(), getLifecycle(), mRoute);
}
}
<resources>
<string name="app_name">ydl_flutter</string>
</resources>
......@@ -40,15 +40,16 @@ dependencies {
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
api 'com.squareup.retrofit2:retrofit:2.6.0'
api 'com.squareup.retrofit2:converter-gson:2.6.0'
api 'com.squareup.retrofit2:adapter-rxjava2:2.6.0'
api "io.reactivex.rxjava2:rxjava:2.2.10"
api 'io.reactivex.rxjava2:rxandroid:2.1.1'
api 'com.squareup.retrofit2:converter-scalars:2.4.0'
api 'com.squareup.okhttp3:logging-interceptor:3.12.2'
api rootProject.ext.dependencies["gson"]
api rootProject.ext.dependencies["rxjava2"]
api(rootProject.ext.dependencies["rxandroid2"]) {
exclude module: 'rxjava'
}
api rootProject.ext.dependencies["retrofit"]
api rootProject.ext.dependencies["okhttp3-logging"]
api rootProject.ext.dependencies["retrofit-converter-gson"]
api rootProject.ext.dependencies["retrofit-converter-scalars"]
api rootProject.ext.dependencies["retrofit-adapter-rxjava2"]
}
......@@ -41,22 +41,6 @@ dependencies {
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
implementation 'com.facebook.stetho:stetho:1.5.0'
implementation 'com.facebook.stetho:stetho-okhttp3:1.4.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
//noinspection GradleCompatible
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'de.greenrobot:eventbus:2.4.0'
api 'com.umeng.sdk:share-wechat:6.9.1'
if (rootProject.ext.dev_mode){
//开发时使用
api project(':ydl-platform')
......
......@@ -75,7 +75,12 @@ dependencies {
api rootProject.ext.dependencies["ydl-pushagent"]
api rootProject.ext.dependencies["ydl-notracepoint"]
api rootProject.ext.dependencies["ydl-hnet"]
api rootProject.ext.dependencies["imagepicker"]
api(rootProject.ext.dependencies["imagepicker"]) {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib'
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
}
api rootProject.ext.dependencies["ydl-utils"]
api rootProject.ext.dependencies["ydl-js"]
api rootProject.ext.dependencies["ydl-net"]
......@@ -83,6 +88,9 @@ dependencies {
api rootProject.ext.dependencies["ptr-lib-release"]
api(rootProject.ext.dependencies["ydl-device"]) {
transitive = true
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib'
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
}
api(rootProject.ext.dependencies["ydl-router"]) {
transitive = true
......
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