Commit 18945a43 by 刘鹏

Merge branch 'feat/diamond_category_zl' into 'd/v4.4.07'

金刚位功能

See merge request app_android_lib/YDL-Component!300
parents baf849fe b6385b63
......@@ -64,15 +64,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
signingConfigs {
release {
storeFile file("keystore.jks")
storePassword "123456"
keyAlias "ydl"
keyPassword "123456"
}
}
productFlavors {
ydl{}
xlzx{}
......
......@@ -4,10 +4,12 @@ import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Typeface
import android.os.Bundle
import android.os.Handler
import android.text.TextUtils
import android.view.View
......@@ -23,6 +25,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.google.android.material.appbar.AppBarLayout
import com.tencent.mmkv.MMKV
import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity
import com.ydl.ydl_image.config.SimpleImageOpConfiger
......@@ -35,24 +38,25 @@ import com.ydl.ydlcommon.ui.LogoLoadingView
import com.ydl.ydlcommon.utils.BuryPointUtils
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.ydl.ydlcommon.utils.remind.ToastHelper
import com.ydl.ydlcommon.view.dialog.CommonDialog
import com.ydl.ydlcommon.view.listener.EndlessRecyclerViewScrollListener
import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.RxImageTool
import com.yidianling.common.tools.ToastUtil
import com.yidianling.consultant.adapter.ExpertSearchAdapter
import com.yidianling.consultant.bean.FunctionWordConsultBean
import com.yidianling.consultant.bean.ConsultantRecentCity
import com.yidianling.consultant.constants.ConsultBIConstants
import com.yidianling.consultant.constants.ConsultBIConstants.ConsultEvent.Companion.POPUP_ICON_CLICK
import com.yidianling.consultant.constants.ConsultBIConstants.ConsultEvent.Companion.YDL_USER_CONSULT_SEARCH_CLICK
import com.yidianling.consultant.listener.OnCategoriesSelectedListener
import com.yidianling.consultant.listener.OnFilterConfirmListener
import com.yidianling.consultant.listener.OnPriceItemSelectedListener
import com.yidianling.consultant.listener.OnSortItemSelectedListener
import com.yidianling.consultant.model.SearchApi
import com.yidianling.consultant.model.bean.*
import com.yidianling.consultant.modular.singlton.ConsultAssistantDialogUtils
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 com.yidianling.consultant.ui.view.*
import com.yidianling.consultant.ui.view.topView.RecommendListView
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
......@@ -66,14 +70,19 @@ import org.json.JSONObject
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
@Route(path = "/consult/list")
class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPresenter>(),
View.OnClickListener, IExpertSearchView,
OnCategoriesSelectedListener, OnSortItemSelectedListener, OnFilterConfirmListener,
SwipeRefreshLayout.OnRefreshListener {
SwipeRefreshLayout.OnRefreshListener, OnPriceItemSelectedListener {
var bottomWordDisposable: Disposable? = null
private lateinit var bottomWordlist: List<FunctionWordBean>
private var searchWord: String? = ""
private var subLocationItem: SubItem? = SubItem()
private var locationRegionItem: RegionItem? = null
private var locationList: ArrayList<SubItem>? = arrayListOf()
private var locationHistoryList: ArrayList<RegionItem>? = arrayListOf()
override fun showImage(url: String?, imgView: ImageView) {
YDLImageCacheManager.showImage(ExpertSearchActivity@ this, url, imgView)
}
......@@ -112,6 +121,7 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
}
companion object {
const val GO_CRITERIA = "go_criteria"
const val EXTRA_CATEGORY = "category"
const val EXTRA_CATEGORY_NAME = "category_name"
const val EXTRA_SHOW_TYPE = "showType"
......@@ -125,6 +135,7 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
private const val FILTER_STATUS_NORMAL = 0 //默认筛选状态
private const val FILTER_STATUS_FILTERED = 1 //非默认筛选状态
private const val FILTER_STATUS_OPEN = 2 //筛选窗打开状态
private const val CONST_CITY = "城市"
const val FROM_ONLINE_EXPERT = 2
fun newIntent(
......@@ -203,6 +214,8 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
private var hasMore = true
private var initCategory = "0"
private var initShowType: Int = 1
var mapFilter: Map<String, Any>? = null
private lateinit var doctorAdapter: ExpertSearchAdapter
private lateinit var onScrollListener: EndlessRecyclerViewScrollListener
private var headData: HeadData? = null //筛选数据
......@@ -346,7 +359,7 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
override fun onLoadMore(page: Int, totalItemsCount: Int, view: RecyclerView?) {
if (hasMore) {
getPresenter().fetchListData(allFilter, getPresenter().mExtras)
getPresenter().fetchListData(allFilter, getPresenter().mExtras, mapFilter)
}
}
}
......@@ -391,8 +404,17 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
private fun initData(mIntent: Intent, isRefresh: Boolean) {
fromPageType = mIntent.getIntExtra(EXTRA_FROM_PAGE, -1)
initCategory = mIntent.getStringExtra(EXTRA_CATEGORY) ?: ""
initCategory = mIntent.getStringExtra(EXTRA_CATEGORY) ?: "0"
initShowType = mIntent.getIntExtra(EXTRA_SHOW_TYPE, 0)
//首页金刚位传递过来的动态Map参数
if (mIntent.getSerializableExtra(GO_CRITERIA) != null) {
mapFilter = mIntent.getSerializableExtra(GO_CRITERIA) as HashMap<String, Any>
}
initCategory = mIntent.getStringExtra("cateId") ?: ""
if (mIntent.getStringExtra("cateTitle") != null) {
cateName = mIntent.getStringExtra("cateTitle")
}
mSign2 = cateName.toString()
val relatedWord = mIntent.getStringExtra(EXTRA_RELATED_WORD) // 搜索内容的联想词
searchWord = mIntent.getStringExtra(EXTRA_SEARCH_WORD)
val isRecommendWords = mIntent.getBooleanExtra(EXTRA_IS_RECCOMMEND_WORD, false)
......@@ -402,7 +424,7 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
allFilter.searchWord = searchWord
}
mSign2 = mIntent.getStringExtra("sign2") ?: ""
getRouterParam()
// getRouterParam()
allFilter.showType.key = initShowType
if (!TextUtils.isEmpty(initCategory) && initCategory != "0") {
......@@ -542,7 +564,7 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
}, {
}, {
})
})
}
}
}
......@@ -1012,7 +1034,29 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
hideSoftInput()
appbar_layout.setExpanded(false)
appbar_layout.postDelayed({
showAreaPopupWindow()
if (MMKV.defaultMMKV()
.decodeBool(ConsultBIConstants.ConsultantLocationAuth.WHETHER_LOCATION_AUTH)
) {
//同意定位授权
showAreaPopupWindow(true)
} else {
val dialog = CommonDialog(mContext)
.setTitle("温馨提示")
.setMessage("建议您授权定位权限,就能轻松获取周边优秀咨询师和其他服务")
.setLeftOnclick("暂不") { v1 ->
//埋点
ActionCountUtils.count(POPUP_ICON_CLICK, "暂不")
showAreaPopupWindow(false)
}.setRightClick("授权") { v12 ->
ActionCountUtils.count(POPUP_ICON_CLICK, "授权")
MMKV.defaultMMKV().encode(
ConsultBIConstants.ConsultantLocationAuth.WHETHER_LOCATION_AUTH,
true
)
showAreaPopupWindow(true)
}
dialog.show()
}
}, 300)
}
......@@ -1021,7 +1065,8 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
hideSoftInput()
appbar_layout.setExpanded(false)
appbar_layout.postDelayed({
showSortPopupWindow()
updateFilterTextViewStatus(tvSort, FILTER_STATUS_OPEN)
showPricePopupWindow()
}, 300)
}
......@@ -1047,7 +1092,10 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
ConsultantIn.startP2PXiaoYi(this)
}
R.id.rl_search -> {
ActionCountUtils.count(YDL_USER_CONSULT_SEARCH_CLICK)
ActionCountUtils.count(
YDL_USER_CONSULT_SEARCH_CLICK,
tv_search_content.hint.toString()
)
ARouter.getInstance()
.build("/consult/hot_search")
.withString(HOT_SEARCH_DOCTOR_NAME, tv_search_content.text.toString())
......@@ -1076,6 +1124,9 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
tempFilter.showType = allFilter.showType
tempFilter.ages.clear()
tempFilter.ages.addAll(allFilter.ages)
//排序
tempFilter.sorStyle.clear()
tempFilter.sorStyle.addAll(allFilter.sorStyle)
//学历
tempFilter.doctorEdu.clear()
tempFilter.doctorEdu.addAll(allFilter.doctorEdu)
......@@ -1090,17 +1141,18 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
tempFilter.priceRangesView = allFilter.priceRangesView
if (headData?.filters != null) {
val filterPopupWindow = FilterPopupWindow(this, headData?.filters!!, tempFilter)
val filterPopupWindow =
FilterPopupWindow(this, headData?.filters!!, tempFilter, headData?.reorder!!)
filterPopupWindow.setOnDismissListener {
viewDim.visibility = View.INVISIBLE
viewDim_filter.visibility = View.GONE
if (allFilter.others.size + allFilter.enquiries.size + allFilter.ages.size + allFilter.doctorEdu.size + allFilter.title.size > 0 || !TextUtils.isEmpty(
if (allFilter.others.size + allFilter.enquiries.size + allFilter.sorStyle.size + allFilter.ages.size + allFilter.doctorEdu.size + allFilter.title.size > 0 || !TextUtils.isEmpty(
allFilter.priceRanges?.min_price
) || !TextUtils.isEmpty(allFilter.priceRanges?.max_price)
) {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_FILTERED)
updateFilterRightTextViewStatus(tvFilter, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_NORMAL)
updateFilterRightTextViewStatus(tvFilter, FILTER_STATUS_NORMAL)
}
ConsultAssistantDialogUtils.INSTANCE.fitRequest(this, "doctor_list", true)
}
......@@ -1108,7 +1160,7 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
filterPopupWindow.showAsDropDown(viewSep2)
ConsultAssistantDialogUtils.INSTANCE.hideAssistantActivity()
filterPopupWindow.onFilterConfirmListener = this
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_OPEN)
updateFilterRightTextViewStatus(tvFilter, FILTER_STATUS_OPEN)
viewDim.visibility = View.VISIBLE
} else {
ToastUtil.toastShort("数据初始化失败,请重试")
......@@ -1154,6 +1206,10 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
allFilter.enquiries.addAll(tempFilter.enquiries)
allFilter.ages.clear()
allFilter.ages.addAll(tempFilter.ages)
//排序
allFilter.sorStyle.clear()
allFilter.sorStyle.addAll(tempFilter.sorStyle)
//学历
allFilter.doctorEdu.clear()
allFilter.doctorEdu.addAll(tempFilter.doctorEdu)
......@@ -1166,7 +1222,7 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
allFilter.title.addAll(tempFilter.title)
allFilter.priceRanges = tempFilter.priceRanges
allFilter.priceRangesView = tempFilter.priceRangesView
allFilter.reorder = tempFilter.reorder
//判断主题选中,判断热门筛选中是否也有该主题
Executors.newCachedThreadPool().execute {
if (headData!!.highlighter.size > 0) {
......@@ -1302,6 +1358,26 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
private var sortPopup: SortPopupWindow? = null
private var pricePopup: PricePopupWindow? = null
//显示价格弹窗
private fun showPricePopupWindow() {
pricePopup = headData?.filters?.let { it1 ->
PricePopupWindow(
this,
it1,
tempFilter, this
)
}
pricePopup!!.setOnDismissListener {
if (tempFilter.priceRanges != null) {
updateFilterTextViewStatus(tvSort, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvSort, FILTER_STATUS_NORMAL)
}
}
pricePopup!!.showAsDropDown(viewSep2)
}
//显示排序弹窗
private fun showSortPopupWindow() {
......@@ -1374,82 +1450,164 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
refresh()
}
//显示地区弹窗
private fun showAreaPopupWindow() {
if (headData?.region != null) {
val regionPopupWindow = AreaPopupWindow(
this, headData?.region
?: ArrayList(), allFilter.region, allFilter.sub
@SuppressLint("CheckResult")
fun getRegionByIp(agreeLocation: Boolean) {
if (agreeLocation) {
SearchApi.getSearchApi().getCityByIp()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
if (it.code == "200") {
locationList?.clear()
subLocationItem?.code = it.data.city_code
subLocationItem?.key = it.data.city_code
subLocationItem?.value = it.data.city_name
subLocationItem?.locationCode = "-1"
subLocationItem?.let { locationList?.add(it) }
locationRegionItem = locationList?.let { it1 ->
RegionItem(
it1,
value = "定位",
key = it.data.province_code,
code = it.data.province_code
)
}
locationRegionItem?.let { locationHistoryList?.add(0, it) }
showAreaPoPup(agreeLocation)
} else {
ErrorLocate(false)
}
}, {
ErrorLocate(false)
})
} else {
ErrorLocate(agreeLocation)
}
}
private fun ErrorLocate(agreeLocation: Boolean) {
locationList?.clear()
subLocationItem?.code = null
subLocationItem?.key = null
subLocationItem?.value = "开启授权,获得定位城市"
subLocationItem?.locationCode = "NotAuth"
subLocationItem?.let { locationList?.add(it) }
locationRegionItem = locationList?.let { it1 ->
RegionItem(
it1,
value = "定位",
key = null,
code = null
)
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)
}
}
locationRegionItem?.let { locationHistoryList?.add(0, it) }
showAreaPoPup(agreeLocation)
}
private fun showAreaPoPup(isAgreeLocation: Boolean) {
locationHistoryList?.addAll(headData?.region ?: ArrayList())
if (allFilter.region.value == null) allFilter.region = locationRegionItem!!
val regionPopupWindow = locationHistoryList?.let {
AreaPopupWindow(
this,
it,
allFilter.region,
allFilter.sub,
isAgreeLocation
)
}
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 (TextUtils.isEmpty(region.code) && TextUtils.isEmpty(sub.code)) {
tvArea.text = "地区"
} else if (!TextUtils.isEmpty(region.code) && !TextUtils.isEmpty(sub.code)) {
if (region.value?.length ?: 0 > 4) {
tvArea.text = region.value?.substring(0, 3) + "..."
} else {
tvArea.text = region.value
}
}
regionPopupWindow?.onRegionSelectedListener =
object : AreaPopupWindow.OnRegionSelectedListener {
override fun onRegionSelected(region: RegionItem, sub: SubItem) {
updateFilterTextViewStatus(tvArea, FILTER_STATUS_OPEN)
allFilter.region = region
allFilter.sub = sub
if (TextUtils.isEmpty(region.code) && TextUtils.isEmpty(sub.code)) {
tvArea.text = "城市"
} else if (!TextUtils.isEmpty(region.code) && !TextUtils.isEmpty(sub.code)) {
if (region.value?.length ?: 0 > 4) {
tvArea.text = region.value?.substring(0, 3) + "..."
} else {
if (sub.value?.length ?: 0 > 4) {
tvArea.text = sub.value?.substring(0, 3) + "..."
} else {
tvArea.text = sub.value
}
tvArea.text = region.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.code)) {
if (TextUtils.equals(sub.code, hot.id)) {
textview.isSelected = true
textview.paint.isFakeBoldText = true
hasSelectedArea = true
} else {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
} else {
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") {
val textview = lin_filter2.getChildAt(index) as TextView
//有选择城市
if (!TextUtils.isEmpty(sub.code)) {
if (TextUtils.equals(sub.code, hot.id)) {
textview.isSelected = true
textview.paint.isFakeBoldText = true
hasSelectedArea = true
} else {
if (TextUtils.equals(region.code, hot.id)) {
textview.isSelected = true
textview.paint.isFakeBoldText = true
hasSelectedArea = true
} else {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
} else {
if (TextUtils.equals(region.code, hot.id)) {
textview.isSelected = true
textview.paint.isFakeBoldText = true
hasSelectedArea = true
} else {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
}
}
}
regionPopupWindow.dismiss()
refresh()
}
regionPopupWindow?.dismiss()
refresh()
}
}
}
//显示地区弹窗
private fun showAreaPopupWindow(isAgreeLocation: Boolean) {
if (headData?.region != null) {
locationHistoryList?.clear()
//添加历史搜索
var recentCityBean =
MMKV.defaultMMKV().decodeParcelable(
ConsultBIConstants.ConsultantLocationAuth.RECENT_CITY,
ConsultantRecentCity::class.java
)
if (recentCityBean == null) recentCityBean = ConsultantRecentCity(arrayListOf())
locationHistoryList?.add(
RegionItem(
recentCityBean!!.recentCity,
value = "历史",
key = "0",
code = "0"
)
)
//添加定位
getRegionByIp(isAgreeLocation)
} else {
ToastUtil.toastShort("数据初始化失败,请重试")
getPresenter().fetchListHead()
......@@ -1513,7 +1671,7 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
srlContainer.isRefreshing = isShowRefresh!!
onScrollListener.resetState()
getPresenter().mExtras = null
getPresenter().fetchListData(allFilter, getPresenter().mExtras)
getPresenter().fetchListData(allFilter, getPresenter().mExtras, mapFilter)
rvExperts.scrollToPosition(0)
}
......@@ -1526,6 +1684,7 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
allFilter.sub = SubItem()
allFilter.enquiries.clear()
allFilter.ages.clear()
allFilter.sorStyle.clear()
allFilter.doctorEdu.clear()
allFilter.others.clear()
updateFilterTextViewStatus(tvSubject, FILTER_STATUS_NORMAL)
......@@ -1541,12 +1700,11 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
}
}
//设置筛选点击按钮状态
private fun updateFilterTextViewStatus(tv: TextView, status: Int) {
when (status) {
FILTER_STATUS_NORMAL -> {
tv.typeface = Typeface.defaultFromStyle(Typeface.NORMAL)
tv.setTextColor(ContextCompat.getColor(this, R.color.platform_colorTextDefault))
tv.setTextColor(ContextCompat.getColor(mContext, R.color.platform_colorTextDefault))
tv.setCompoundDrawablesWithIntrinsicBounds(
0,
0,
......@@ -1556,17 +1714,17 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
}
FILTER_STATUS_FILTERED -> {
tv.typeface = Typeface.DEFAULT_BOLD
tv.setTextColor(ContextCompat.getColor(this, R.color.platform_main_theme))
tv.setTextColor(ContextCompat.getColor(mContext, R.color.platform_main_theme))
tv.setCompoundDrawablesWithIntrinsicBounds(
0,
0,
R.drawable.platform_ic_arrow_drop_down_grey_500_18dp,
R.drawable.platform_arrow_drop_down_en,
0
)
}
FILTER_STATUS_OPEN -> {
tv.typeface = Typeface.DEFAULT_BOLD
tv.setTextColor(ContextCompat.getColor(this, R.color.platform_colorTextDefault))
tv.setTextColor(ContextCompat.getColor(mContext, R.color.platform_main_theme))
tv.setCompoundDrawablesWithIntrinsicBounds(
0,
0,
......@@ -1577,6 +1735,42 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
}
}
//设置筛选点击按钮状态
private fun updateFilterRightTextViewStatus(tv: TextView, status: Int) {
when (status) {
FILTER_STATUS_NORMAL -> {
tv.typeface = Typeface.defaultFromStyle(Typeface.NORMAL)
tv.setTextColor(ContextCompat.getColor(this, R.color.platform_colorTextDefault))
tv.setCompoundDrawablesWithIntrinsicBounds(
0,
0,
R.drawable.filter_up_grey,
0
)
}
FILTER_STATUS_FILTERED -> {
tv.typeface = Typeface.DEFAULT_BOLD
tv.setTextColor(ContextCompat.getColor(this, R.color.platform_main_theme))
tv.setCompoundDrawablesWithIntrinsicBounds(
0,
0,
R.drawable.filter_down_blue,
0
)
}
FILTER_STATUS_OPEN -> {
tv.typeface = Typeface.DEFAULT_BOLD
tv.setTextColor(ContextCompat.getColor(this, R.color.platform_main_theme))
tv.setCompoundDrawablesWithIntrinsicBounds(
0,
0,
R.drawable.filter_down_blue,
0
)
}
}
}
private fun hideSoftInput() {
val view = this.currentFocus
if (view != null) {
......@@ -1598,4 +1792,11 @@ class ExpertSearchActivity : BaseMvpActivity<IExpertSearchView, ExpertSearchPres
bottomWordDisposable?.dispose()
ConsultAssistantDialogUtils.INSTANCE.expertSearchResetStatus()
}
override fun onPriceItemSelected(priceRangesItem: PriceRangesItem) {
//价格筛选回调
updateFilterTextViewStatus(tvSort, FILTER_STATUS_FILTERED)
allFilter.priceRanges = priceRangesItem
refresh(false)
}
}
......@@ -6,7 +6,9 @@ import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.graphics.Typeface
import android.net.Uri
import android.os.Handler
import android.text.TextUtils
import android.view.View
......@@ -22,6 +24,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.google.android.material.appbar.AppBarLayout
import com.tencent.mmkv.MMKV
import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity
import com.ydl.ydl_image.config.SimpleImageOpConfiger
......@@ -39,24 +42,27 @@ import com.ydl.ydlcommon.utils.SharedPreferencesEditor
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.dialog.CommonDialog
import com.ydl.ydlcommon.view.listener.EndlessRecyclerViewScrollListener
import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.RxImageTool
import com.yidianling.common.tools.ToastUtil
import com.yidianling.consultant.adapter.ExpertSearchAdapter
import com.yidianling.consultant.bean.ConsultantRecentCity
import com.yidianling.consultant.constants.ConsultBIConstants
import com.yidianling.consultant.constants.ConsultBIConstants.ConsultantLocationAuth.Companion.REFUSE_ALREADY
import com.yidianling.consultant.constants.ConsultBIConstants.ConsultantLocationAuth.Companion.WHETHER_LOCATION_AUTH
import com.yidianling.consultant.listener.*
import com.yidianling.consultant.dialog.ConsultSubPayDialog
import com.yidianling.consultant.listener.OnCategoriesSelectedListener
import com.yidianling.consultant.listener.OnExpertClickListener
import com.yidianling.consultant.listener.OnFilterConfirmListener
import com.yidianling.consultant.listener.OnSortItemSelectedListener
import com.yidianling.consultant.model.SearchApi
import com.yidianling.consultant.model.bean.*
import com.yidianling.consultant.modular.singlton.ConsultAssistantDialogUtils
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 com.yidianling.consultant.ui.view.*
import com.yidianling.consultant.ui.view.topView.RecommendListView
import com.yidianling.home.api.event.HomeModuleTabEvent
import com.yidianling.user.api.service.IUserService
......@@ -77,7 +83,7 @@ import java.util.concurrent.TimeUnit
class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPresenter>(),
View.OnClickListener, IExpertSearchView,
OnCategoriesSelectedListener, OnSortItemSelectedListener, OnFilterConfirmListener,
SwipeRefreshLayout.OnRefreshListener {
SwipeRefreshLayout.OnRefreshListener, OnPriceItemSelectedListener {
private lateinit var mContext: Context
private lateinit var mActivity: FragmentActivity
var startTime = 0L
......@@ -86,6 +92,11 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
var bottomWordDisposable: Disposable? = null
var isShow: Boolean = false
private lateinit var bottomWordlist: List<FunctionWordBean>
private var subLocationItem: SubItem? = SubItem()
private var locationRegionItem: RegionItem? = null
private var locationList: ArrayList<SubItem>? = arrayListOf()
private var locationHistoryList: ArrayList<RegionItem>? = arrayListOf()
override fun layoutResId(): Int {
return R.layout.consultant_activity_expert_search_list
}
......@@ -312,7 +323,7 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
override fun onLoadMore(page: Int, totalItemsCount: Int, view: RecyclerView?) {
if (hasMore) {
getPresenter().fetchListData(allFilter, getPresenter().mExtras)
getPresenter().fetchListData(allFilter, getPresenter().mExtras, null)
}
}
}
......@@ -583,7 +594,7 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
hasSelectedArea = true
} else {
allFilter.region = RegionItem()
tvArea.text = "地区"
tvArea.text = "城市"
updateFilterTextViewStatus(tvArea, FILTER_STATUS_NORMAL)
hasSelectedArea = false
......@@ -747,7 +758,7 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
allFilter.region = RegionItem()
allFilter.sub = SubItem("不限", null)
tvArea.text = "地区"
tvArea.text = "城市"
updateFilterTextViewStatus(tvArea, FILTER_STATUS_NORMAL)
hasSelectedArea = false
......@@ -905,8 +916,34 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
props1.put("filtrate_first", "地区")
hideSoftInput()
appbar_layout.setExpanded(false)
appbar_layout.postDelayed({
showAreaPopupWindow()
if (MMKV.defaultMMKV().decodeBool(WHETHER_LOCATION_AUTH)) {
//同意定位授权
showAreaPopupWindow(true)
} else if (MMKV.defaultMMKV().decodeBool(REFUSE_ALREADY)) {
showAreaPopupWindow(false)
} else {
val dialog = CommonDialog(mContext)
.setTitle("温馨提示")
.setMessage("建议您授权定位权限,就能轻松获取周边优秀咨询师和其他服务")
.setLeftOnclick("暂不") { v1 ->
ActionCountUtils.count(
ConsultBIConstants.ConsultEvent.POPUP_ICON_CLICK,
"暂不"
)
MMKV.defaultMMKV().encode(REFUSE_ALREADY, true)
showAreaPopupWindow(false)
}.setRightClick("授权") { v12 ->
ActionCountUtils.count(
ConsultBIConstants.ConsultEvent.POPUP_ICON_CLICK,
"授权"
)
MMKV.defaultMMKV().encode(WHETHER_LOCATION_AUTH, true)
showAreaPopupWindow(true)
}
dialog.show()
}
}, 300)
}
......@@ -915,7 +952,8 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
hideSoftInput()
appbar_layout.setExpanded(false)
appbar_layout.postDelayed({
showSortPopupWindow()
updateFilterTextViewStatus(tvSort, FILTER_STATUS_OPEN)
showPricePopupWindow()
}, 300)
}
......@@ -941,6 +979,10 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
ConsultantIn.startP2PXiaoYi(mContext)
}
R.id.rl_search -> {
ActionCountUtils.count(
ConsultBIConstants.ConsultEvent.YDL_USER_CONSULT_SEARCH_CLICK,
tv_search_content.hint.toString()
)
ARouter.getInstance()
.build("/consult/hot_search")
.withString(HOT_SEARCH_DOCTOR_NAME, tv_search_content.text.toString())
......@@ -958,6 +1000,27 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
}
}
private var pricePopup: PricePopupWindow? = null
//显示价格弹窗
private fun showPricePopupWindow() {
pricePopup = headData?.filters?.let { it1 ->
PricePopupWindow(
requireContext(),
it1,
tempFilter, this
)
}
pricePopup!!.setOnDismissListener {
if (tempFilter.priceRanges != null) {
updateFilterTextViewStatus(tvSort, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvSort, FILTER_STATUS_NORMAL)
}
}
pricePopup!!.showAsDropDown(viewSep2)
}
//显示筛选弹窗
private fun showFilterPopupWindow() {
tempFilter.categories.clear()
......@@ -969,6 +1032,9 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
tempFilter.showType = allFilter.showType
tempFilter.ages.clear()
tempFilter.ages.addAll(allFilter.ages)
//排序
tempFilter.sorStyle.clear()
tempFilter.sorStyle.addAll(allFilter.sorStyle)
//学历
tempFilter.doctorEdu.clear()
tempFilter.doctorEdu.addAll(allFilter.doctorEdu)
......@@ -983,17 +1049,18 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
tempFilter.priceRangesView = allFilter.priceRangesView
if (headData?.filters != null) {
val filterPopupWindow = FilterPopupWindow(mContext, headData?.filters!!, tempFilter)
val filterPopupWindow =
FilterPopupWindow(mContext, headData?.filters!!, tempFilter, headData?.reorder!!)
filterPopupWindow.setOnDismissListener {
viewDim.visibility = View.INVISIBLE
viewDim_filter.visibility = View.GONE
if (allFilter.others.size + allFilter.enquiries.size + allFilter.ages.size + allFilter.doctorEdu.size + allFilter.title.size + allFilter.specialityCrowd.size > 0 || !TextUtils.isEmpty(
if (allFilter.others.size + allFilter.enquiries.size + allFilter.sorStyle.size + allFilter.ages.size + allFilter.doctorEdu.size + allFilter.title.size + allFilter.specialityCrowd.size > 0 || !TextUtils.isEmpty(
allFilter.priceRanges?.min_price
) || !TextUtils.isEmpty(allFilter.priceRanges?.max_price)
) {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_FILTERED)
updateFilterRightTextViewStatus(tvFilter, FILTER_STATUS_FILTERED)
} else {
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_NORMAL)
updateFilterRightTextViewStatus(tvFilter, FILTER_STATUS_NORMAL)
}
showConsultAssistantDialog()
}
......@@ -1001,7 +1068,7 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
filterPopupWindow.showAsDropDown(viewSep2)
hideConsultAssistantDialog()
filterPopupWindow.onFilterConfirmListener = this
updateFilterTextViewStatus(tvFilter, FILTER_STATUS_OPEN)
updateFilterRightTextViewStatus(tvFilter, FILTER_STATUS_OPEN)
viewDim.visibility = View.VISIBLE
} else {
ToastUtil.toastShort("数据初始化失败,请重试")
......@@ -1039,6 +1106,10 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
allFilter.showType = tempFilter.showType
allFilter.enquiries.clear()
allFilter.enquiries.addAll(tempFilter.enquiries)
//排序
allFilter.sorStyle.clear()
allFilter.sorStyle.addAll(tempFilter.sorStyle)
allFilter.ages.clear()
allFilter.ages.addAll(tempFilter.ages)
allFilter.doctorEdu.clear()
......@@ -1053,7 +1124,7 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
allFilter.title.addAll(tempFilter.title)
allFilter.priceRanges = tempFilter.priceRanges
allFilter.priceRangesView = tempFilter.priceRangesView
allFilter.reorder = tempFilter.reorder
//判断主题选中,判断热门筛选中是否也有该主题
Executors.newCachedThreadPool().execute {
if (headData!!.highlighter.size > 0) {
......@@ -1260,88 +1331,168 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
refresh()
}
@SuppressLint("CheckResult")
fun getRegionByIp(agreeLocation: Boolean) {
if (agreeLocation) {
SearchApi.getSearchApi().getCityByIp()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
if (it.code == "200") {
locationList?.clear()
subLocationItem?.code = it.data.city_code
subLocationItem?.key = it.data.city_code
subLocationItem?.value = it.data.city_name
subLocationItem?.locationCode = "-1"
subLocationItem?.let { locationList?.add(it) }
locationRegionItem = locationList?.let { it1 ->
RegionItem(
it1,
value = "定位",
key = it.data.province_code,
code = it.data.province_code
)
}
locationRegionItem?.let { locationHistoryList?.add(0, it) }
showAreaPoPup(agreeLocation)
} else {
ErrorLocate(false)
}
}, {
ErrorLocate(false)
})
} else {
ErrorLocate(agreeLocation)
}
}
private fun ErrorLocate(agreeLocation: Boolean) {
locationList?.clear()
subLocationItem?.code = null
subLocationItem?.key = null
subLocationItem?.value = "开启授权,获得定位城市"
subLocationItem?.locationCode = "NotAuth"
subLocationItem?.let { locationList?.add(it) }
locationRegionItem = locationList?.let { it1 ->
RegionItem(
it1,
value = "定位",
key = null,
code = null
)
}
locationRegionItem?.let { locationHistoryList?.add(0, it) }
showAreaPoPup(agreeLocation)
}
//显示地区弹窗
private fun showAreaPopupWindow() {
private fun showAreaPopupWindow(isAgreeLocation: Boolean) {
if (headData?.region != null) {
val regionPopupWindow = AreaPopupWindow(
locationHistoryList?.clear()
//添加历史搜索
var recentCityBean =
MMKV.defaultMMKV().decodeParcelable(
ConsultBIConstants.ConsultantLocationAuth.RECENT_CITY,
ConsultantRecentCity::class.java
)
if (recentCityBean == null) recentCityBean = ConsultantRecentCity(arrayListOf())
locationHistoryList?.add(
RegionItem(
recentCityBean!!.recentCity,
value = "历史",
key = "0",
code = "0"
)
)
//添加定位
getRegionByIp(isAgreeLocation)
} else {
ToastUtil.toastShort("数据初始化失败,请重试")
getPresenter().fetchListHead()
}
}
private fun showAreaPoPup(isAgreeLocation: Boolean) {
locationHistoryList?.addAll(headData?.region ?: ArrayList())
if (allFilter.region.value == null) allFilter.region = locationRegionItem!!
val regionPopupWindow = locationHistoryList?.let {
AreaPopupWindow(
mActivity,
headData?.region ?: ArrayList(),
it,
allFilter.region,
allFilter.sub
allFilter.sub,
isAgreeLocation
)
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?.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 (TextUtils.isEmpty(region.code) && TextUtils.isEmpty(sub.code)) {
tvArea.text = "地区"
} else if (!TextUtils.isEmpty(region.code) && !TextUtils.isEmpty(sub.code)) {
if (region.value?.length ?: 0 > 4) {
tvArea.text = region.value?.substring(0, 3) + "..."
} else {
tvArea.text = region.value
}
}
regionPopupWindow?.onRegionSelectedListener =
object : AreaPopupWindow.OnRegionSelectedListener {
override fun onRegionSelected(region: RegionItem, sub: SubItem) {
updateFilterTextViewStatus(tvArea, FILTER_STATUS_OPEN)
allFilter.region = region
allFilter.sub = sub
if (TextUtils.isEmpty(region.code) && TextUtils.isEmpty(sub.code)) {
tvArea.text = "城市"
} else if (!TextUtils.isEmpty(region.code) && !TextUtils.isEmpty(sub.code)) {
if (region.value?.length ?: 0 > 4) {
tvArea.text = region.value?.substring(0, 3) + "..."
} else {
if (sub.value?.length ?: 0 > 4) {
tvArea.text = sub.value?.substring(0, 3) + "..."
} else {
tvArea.text = sub.value
}
tvArea.text = region.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") {
val textview = lin_filter2.getChildAt(index) as TextView
//有选择城市
if (!TextUtils.isEmpty(sub.code)) {
if (TextUtils.equals(sub.code, hot.id)) {
textview.isSelected = true
textview.paint.isFakeBoldText = true
hasSelectedArea = true
} else {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
} else {
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") {
val textview = lin_filter2.getChildAt(index) as TextView
//有选择城市
if (!TextUtils.isEmpty(sub.code)) {
if (TextUtils.equals(sub.code, hot.id)) {
textview.isSelected = true
textview.paint.isFakeBoldText = true
hasSelectedArea = true
} else {
if (TextUtils.equals(region.code, hot.id)) {
textview.isSelected = true
textview.paint.isFakeBoldText = true
hasSelectedArea = true
} else {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
} else {
if (TextUtils.equals(region.code, hot.id)) {
textview.isSelected = true
textview.paint.isFakeBoldText = true
hasSelectedArea = true
} else {
textview.isSelected = false
textview.paint.isFakeBoldText = false
}
}
}
}
regionPopupWindow.dismiss()
refresh()
}
regionPopupWindow?.dismiss()
refresh()
}
} else {
ToastUtil.toastShort("数据初始化失败,请重试")
getPresenter().fetchListHead()
}
}
}
private var mHandler: Handler? = null
......@@ -1427,11 +1578,10 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
}
onScrollListener.resetState()
getPresenter().mExtras = null
getPresenter().fetchListData(allFilter, getPresenter().mExtras)
getPresenter().fetchListData(allFilter, getPresenter().mExtras, null)
rvExperts.scrollToPosition(0)
}
//设置筛选点击按钮状态
private fun updateFilterTextViewStatus(tv: TextView, status: Int) {
when (status) {
FILTER_STATUS_NORMAL -> {
......@@ -1450,13 +1600,13 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
tv.setCompoundDrawablesWithIntrinsicBounds(
0,
0,
R.drawable.platform_ic_arrow_drop_down_grey_500_18dp,
R.drawable.platform_arrow_drop_down_en,
0
)
}
FILTER_STATUS_OPEN -> {
tv.typeface = Typeface.DEFAULT_BOLD
tv.setTextColor(ContextCompat.getColor(mContext, R.color.platform_colorTextDefault))
tv.setTextColor(ContextCompat.getColor(mContext, R.color.platform_main_theme))
tv.setCompoundDrawablesWithIntrinsicBounds(
0,
0,
......@@ -1467,6 +1617,42 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
}
}
//设置筛选点击按钮状态
private fun updateFilterRightTextViewStatus(tv: TextView, status: Int) {
when (status) {
FILTER_STATUS_NORMAL -> {
tv.typeface = Typeface.defaultFromStyle(Typeface.NORMAL)
tv.setTextColor(ContextCompat.getColor(mContext, R.color.platform_colorTextDefault))
tv.setCompoundDrawablesWithIntrinsicBounds(
0,
0,
R.drawable.filter_up_grey,
0
)
}
FILTER_STATUS_FILTERED -> {
tv.typeface = Typeface.DEFAULT_BOLD
tv.setTextColor(ContextCompat.getColor(mContext, R.color.platform_main_theme))
tv.setCompoundDrawablesWithIntrinsicBounds(
0,
0,
R.drawable.filter_down_blue,
0
)
}
FILTER_STATUS_OPEN -> {
tv.typeface = Typeface.DEFAULT_BOLD
tv.setTextColor(ContextCompat.getColor(mContext, R.color.platform_main_theme))
tv.setCompoundDrawablesWithIntrinsicBounds(
0,
0,
R.drawable.filter_down_blue,
0
)
}
}
}
private fun hideSoftInput() {
val view = mActivity.currentFocus
if (view != null) {
......@@ -1510,4 +1696,11 @@ class ExpertSearchFragment : BaseMvpFragment<IExpertSearchView, ExpertSearchPres
bottomWordDisposable?.dispose()
ConsultAssistantDialogUtils.INSTANCE.resetStatus()
}
override fun onPriceItemSelected(priceRange: PriceRangesItem) {
//价格筛选回调
updateFilterTextViewStatus(tvSort, FILTER_STATUS_FILTERED)
allFilter.priceRanges = priceRange
refresh(false)
}
}
......@@ -8,6 +8,7 @@ import com.ydl.ydlcommon.data.http.RxUtils
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.ydl.ydlcommon.mvp.base.SimplePresenter
import com.ydl.ydlcommon.utils.AnimUtils
import com.ydl.ydlcommon.utils.RxLifecycleUtils
import com.ydl.ydlcommon.utils.remind.HttpErrorUtils
import com.yidianling.common.tools.RxAppTool
......@@ -63,7 +64,7 @@ class ExpertSearchPresenter : SimplePresenter<IExpertSearchView>() {
}
@SuppressLint("CheckResult")
fun fetchListData(allFilter: AllFilter, extras: Extras?) {
fun fetchListData(allFilter: AllFilter, extras: Extras?, mapFilter: Map<String, Any>?) {
//是否亲子教育字段
// ConsultAssistantDialogUtils.REALATION_EDUCATION = allFilter.categories.size == 1 && allFilter.categories[0].cateId == "23"
......@@ -75,8 +76,13 @@ class ExpertSearchPresenter : SimplePresenter<IExpertSearchView>() {
filterMap["__keywords"] = allFilter.searchWord
}
val categoryList = ArrayList<Any>()
//首页金刚位传过来的搜索MAP结果集
if (mapFilter != null) {
filterMap.putAll(mapFilter)
}
map["filter"] = filterMap
// 八大类一级标签
if (allFilter.categoryId2List.size>0){
if (allFilter.categoryId2List.size > 0) {
val categoryMap2 = HashMap<String, Any>()
val categoryIdMap2 = HashMap<String, Any>()
categoryIdMap2["in"] = allFilter.categoryId2List.toSortedSet().toList()
......@@ -84,7 +90,7 @@ class ExpertSearchPresenter : SimplePresenter<IExpertSearchView>() {
categoryList.add(categoryMap2)
}
// 八大类二级标签
if (allFilter.categoryId3List.size>0){
if (allFilter.categoryId3List.size > 0) {
val categoryMap3 = HashMap<String, Any>()
val categoryIdMap3 = HashMap<String, Any>()
categoryIdMap3["in"] = allFilter.categoryId3List.toSortedSet().toList()
......@@ -197,13 +203,13 @@ class ExpertSearchPresenter : SimplePresenter<IExpertSearchView>() {
}
}
}
if (gender.size>0){
if (gender.size > 0) {
val genderMap = HashMap<String, Any>()
genderMap["in"] = gender
filterMap["gender"] = genderMap
}
}
map["filter"] = filterMap
// sorts
if (allFilter.reorder.key != null) {
......
......@@ -33,6 +33,7 @@ import com.yidianling.consultant.api.IConsultantService
import com.yidianling.consultant.bean.*
import com.yidianling.consultant.constants.ConsultBIConstants
import com.yidianling.consultant.constants.ConsultBIConstants.ConsultEvent.Companion.SEARCH_BANNERWORD_CLICK
import com.yidianling.consultant.constants.ConsultBIConstants.ConsultEvent.Companion.YDL_USER_CONSULT_SEARCH_CONFIRM_CLICK
import com.yidianling.consultant.contract.IHotSearchContract
import com.yidianling.consultant.model.bean.FunctionWordBean
import com.yidianling.consultant.modular.utils.ConsultAssistantEntryUtils
......@@ -110,6 +111,12 @@ class HotSearchActivity : BaseMvpActivity<IHotSearchContract.View, IHotSearchCon
}
etSearch.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
//埋点
ActionCountUtils.count(
YDL_USER_CONSULT_SEARCH_CONFIRM_CLICK,
etSearch.text.toString(),
etSearch.hint.toString()
)
// 搜索的关联词
var relatedWords = ""
var isRecommendWords = false
......
......@@ -30,7 +30,6 @@ import com.yidianling.consultant.listener.OnExpertClickListener
import com.yidianling.consultant.model.bean.ExpertServiceItem
import com.yidianling.consultant.modular.utils.TempH5RouteUtils
import com.yidianling.consultant.router.ConsultantIn
import kotlinx.android.synthetic.main.consultant_activity_hot_search.*
import kotlinx.android.synthetic.main.consultant_expert_search_feedbackrate.view.*
import kotlinx.android.synthetic.main.consultant_expert_search_header_view.view.*
import kotlinx.android.synthetic.main.consultant_expert_search_item_view.view.*
......@@ -38,7 +37,6 @@ import kotlinx.android.synthetic.main.consultant_expert_search_products_item.vie
import kotlinx.android.synthetic.main.consultant_item_empty.view.*
import kotlinx.android.synthetic.main.consultant_item_footer.view.*
import kotlinx.android.synthetic.main.consultant_item_tag.view.*
import kotlinx.android.synthetic.main.consultant_layout_search_content.*
import java.math.BigDecimal
/**
......
......@@ -16,7 +16,8 @@ import kotlinx.android.synthetic.main.consultant_item_region.view.*
* 省份列表适配器
* Created by zqk on 17-7-21.
*/
class RegionRecyclerViewAdapter(val context: Context, val regionList: ArrayList<RegionItem>, var selectedRegion: RegionItem
class RegionRecyclerViewAdapter(
val context: Context, var regionList: ArrayList<RegionItem>, var selectedRegion: RegionItem
) : RecyclerView.Adapter<RegionRecyclerViewAdapter.ViewHolder>() {
var onItemClickListener: MyBaseAdapter.OnItemClickListener<RegionItem>? = null
......@@ -29,11 +30,14 @@ class RegionRecyclerViewAdapter(val context: Context, val regionList: ArrayList<
holder.itemView.tvRegionName.setTypeface(Typeface.DEFAULT_BOLD)
holder.itemView.tvRegionName.setTextColor(context.resources.getColor(R.color.platform_main_theme))
holder.itemView.view_select.visibility = View.VISIBLE
holder.itemView.setBackgroundColor(context.resources.getColor(R.color.white))
} else {
//未选中状态
holder.itemView.tvRegionName.setTypeface(Typeface.DEFAULT)
holder.itemView.tvRegionName.setTextColor(context.resources.getColor(R.color.platform_default_text_color))
holder.itemView.view_select.visibility = View.INVISIBLE
holder.itemView.setBackgroundColor(context.resources.getColor(R.color.platform_color_F7F7F7))
}
}
......
......@@ -10,7 +10,8 @@ import com.yidianling.consultant.model.bean.ChildrenBean
/**
* Created by Ykai on 2022/5/18.
*/
class SortAdapter(data: List<ChildrenBean>) : BaseMultiItemQuickAdapter<ChildrenBean, BaseViewHolder>(data) {
class SortAdapter(data: List<ChildrenBean>) :
BaseMultiItemQuickAdapter<ChildrenBean, BaseViewHolder>(data) {
var isVisible = false
init {
......@@ -19,25 +20,37 @@ class SortAdapter(data: List<ChildrenBean>) : BaseMultiItemQuickAdapter<Children
}
override fun convert(holder: BaseViewHolder, item: ChildrenBean) {
when(holder.itemViewType){
1 ->{
holder.setGone(R.id.ll_sort_item,item.isVisible)
when (holder.itemViewType) {
1 -> {
holder.setGone(R.id.ll_sort_item, item.isVisible)
holder.setText(R.id.tv_sort_name, item.cate_name)
holder.getView<TextView>(R.id.tv_sort_name).isSelected = item.isSelected
if (item.isSelected){
holder.setTextColor(R.id.tv_sort_name,ContextCompat.getColor(mContext,R.color.platform_main_theme))
}else{
holder.setTextColor(R.id.tv_sort_name,ContextCompat.getColor(mContext,R.color.platform_color_242424))
if (item.isSelected) {
holder.setTextColor(
R.id.tv_sort_name,
ContextCompat.getColor(mContext, R.color.platform_main_theme)
)
} else {
holder.setTextColor(
R.id.tv_sort_name,
ContextCompat.getColor(mContext, R.color.platform_color_242424)
)
}
}
2->{
holder.setGone(R.id.ll_sort_item,item.isVisible)
2 -> {
holder.setGone(R.id.ll_sort_item, item.isVisible)
holder.setText(R.id.tv_sort_name, item.cate_name)
holder.getView<TextView>(R.id.tv_sort_name).isSelected = item.isSelected
if (item.isSelected){
holder.setTextColor(R.id.tv_sort_name,ContextCompat.getColor(mContext,R.color.platform_main_theme))
}else{
holder.setTextColor(R.id.tv_sort_name,ContextCompat.getColor(mContext,R.color.platform_color_242424))
if (item.isSelected) {
holder.setTextColor(
R.id.tv_sort_name,
ContextCompat.getColor(mContext, R.color.platform_main_theme)
)
} else {
holder.setTextColor(
R.id.tv_sort_name,
ContextCompat.getColor(mContext, R.color.platform_color_242424)
)
}
}
}
......@@ -47,7 +60,7 @@ class SortAdapter(data: List<ChildrenBean>) : BaseMultiItemQuickAdapter<Children
/**
* 设置大于第12个之后的标签全部显示
*/
fun setAllVisible(){
fun setAllVisible() {
mData.forEach { bean ->
bean.isVisible = true
}
......@@ -58,9 +71,9 @@ class SortAdapter(data: List<ChildrenBean>) : BaseMultiItemQuickAdapter<Children
/**
* 设置大于第12个之后的标签全部隐藏
*/
fun setGone(){
fun setGone() {
mData.forEachIndexed { index, bean ->
if (index>12){
if (index > 12) {
bean.isVisible = false
}
}
......
......@@ -16,31 +16,81 @@ import kotlinx.android.synthetic.main.consultant_item_consult_type.view.*
* 城市列表适配器
* Created by zqk on 17-7-21.
*/
class SubRecyclerViewAdapter(val context: Context, val subList: ArrayList<SubItem>, var selectedSub: SubItem) : RecyclerView.Adapter<SubRecyclerViewAdapter.ViewHolder>() {
class SubRecyclerViewAdapter(
val context: Context, val subList: ArrayList<SubItem>,
var selectedSub: SubItem, val locationCode: String
) : RecyclerView.Adapter<SubRecyclerViewAdapter.ViewHolder>() {
var onItemClickListener: MyBaseAdapter.OnItemClickListener<SubItem>? = null
private lateinit var mOnAuthClickLister: OnAuthClickLister
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val subItem = subList[position]
holder.itemView.tvConsultTypeName.text = subItem.value
if (selectedSub.code == subItem.code) {
//选中状态
holder.itemView.tvConsultTypeName.setTypeface(Typeface.DEFAULT_BOLD)
holder.itemView.tvConsultTypeName.setTextColor(ContextCompat.getColor(context,R.color.platform_main_theme))
} else {
if (subItem.locationCode == locationCode) {
holder.itemView.reLocation.visibility = View.GONE
holder.itemView.location_img.visibility = View.VISIBLE
holder.itemView.location_img.drawable.setTint(context.resources.getColor(R.color.platform_color_black_333333))
holder.itemView.isEnabled = true
} else if (subItem.locationCode == "NotAuth") {
//未选中状态
holder.itemView.reLocation.visibility = View.VISIBLE
holder.itemView.reLocation.setOnClickListener {
mOnAuthClickLister.onAuthClick()
}
holder.itemView.location_img.visibility = View.VISIBLE
holder.itemView.tvConsultTypeName.setTypeface(Typeface.DEFAULT)
holder.itemView.tvConsultTypeName.setTextColor(ContextCompat.getColor(context,R.color.platform_default_text_color))
holder.itemView.tvConsultTypeName.setTextColor(
ContextCompat.getColor(
context,
R.color.platform_default_text_color
)
)
holder.itemView.location_img.drawable.setTint(context.resources.getColor(R.color.platform_color_black_333333))
holder.itemView.isEnabled = false
} else {
holder.itemView.reLocation.visibility = View.GONE
holder.itemView.isEnabled = true
holder.itemView.location_img.visibility = View.GONE
if (selectedSub.code == subItem.code) {
//选中状态
holder.itemView.tvConsultTypeName.setTypeface(Typeface.DEFAULT_BOLD)
holder.itemView.tvConsultTypeName.setTextColor(
ContextCompat.getColor(
context,
R.color.platform_main_theme
)
)
} else {
//未选中状态
holder.itemView.tvConsultTypeName.setTypeface(Typeface.DEFAULT)
holder.itemView.tvConsultTypeName.setTextColor(
ContextCompat.getColor(
context,
R.color.platform_default_text_color
)
)
}
}
}
override fun getItemCount(): Int = subList.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.consultant_item_consult_type, parent, false)
val view = LayoutInflater.from(context)
.inflate(R.layout.consultant_item_consult_type, parent, false)
return ViewHolder(view)
}
interface OnAuthClickLister {
fun onAuthClick()
}
fun setOnAuthClickLister(lister: OnAuthClickLister) {
mOnAuthClickLister = lister
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
init {
itemView.setOnClickListener {
......
package com.yidianling.consultant.bean
import android.os.Parcelable
import com.yidianling.consultant.model.bean.SubItem
import kotlinx.android.parcel.Parcelize
@Parcelize
data class ConsultantRecentCity(
var recentCity: MutableList<SubItem> = arrayListOf()
) : Parcelable
\ No newline at end of file
package com.yidianling.consultant.bean
data class ConsultantRegionBean(
val country_code: String?,
val country_name: String?,
val province_code: String?,
val province_name: String?,
val city_code: String?,
val city_name: String?
)
\ No newline at end of file
......@@ -27,6 +27,7 @@ class ConsultBIConstants {
const val POSITION_YDL_USER_ASSOCIATE_WORD_CLICK="ydl_user_associate_word_click" // 联想词点击position
// 咨询师列表页 banner 点击事件
const val POSITION_CONSULT_COUNSELOR_LIST_BANNER_CLICK = "consult_counselor_list_banner_click"
}
//====================APP咨询列表页(app_consult_list_page)====================
......@@ -57,7 +58,8 @@ class ConsultBIConstants {
APP_CONSULT_LIST_PAGE + "ydl_user_consult_search_click"//咨询师页搜索框点击事件
const val YDL_USER_CONSULT_TYPE_CLICK: String =
APP_CONSULT_LIST_PAGE + "ydl_user_consult_type_click"//咨询师顶部ICON 厌学专题、限时特惠、精神心理
const val YDL_USER_CONSULT_SEARCH_CONFIRM_CLICK: String =
APP_CONSULT_LIST_PAGE + "YDL_USER_CONSULT_SEARCH_CONFIRM_CLICK"//搜索词、底纹词点击埋点
const val POSITION_CONSULT_COUNSELOR_CARD_CLICK =
"consult_counselor_card_click" // 咨询师列表点击position
const val POSITION_CHOICE_FILTER_CLICK =
......@@ -68,6 +70,15 @@ class ConsultBIConstants {
"goodat_crowd_click" // 擅长人群埋点
const val SEARCH_BANNERWORD_CLICK =
"$PART_ID_YDL_USER_MAIN_PAGE|search_bannerword_click" //历史搜索、热门搜索、本周热门专家搜索
const val CONSULT_FILTER_CITY_PAGE = "consult_filter_city_page"
const val POPUP_ICON_CLICK = "$CONSULT_FILTER_CITY_PAGE|popup_icon_click"
const val AUTHORIZATION_ICON_CLICK =
"$CONSULT_FILTER_CITY_PAGE|authorization_icon_click"
const val CITY_NAME_CLICK = "$CONSULT_FILTER_CITY_PAGE|city_name_click"
const val CONSULT_FILTER_PRICE_PAGE = "consult_filter_price_page"
const val PRICE_CHOICE_CLICK = "$CONSULT_FILTER_PRICE_PAGE|price_choice_click"
const val PRICE_SLIDE_CLICK = "$CONSULT_FILTER_PRICE_PAGE|price_slide_click"
const val BOTTOM_ICON_CLICK = "$CONSULT_FILTER_PRICE_PAGE|bottom_icon_click"
}
}
class ConsultSearchListEvent {
......@@ -94,4 +105,12 @@ class ConsultBIConstants {
YDL_USER_MAIN_PAGE + "private_chat_click" // 点击私聊按钮
}
}
class ConsultantLocationAuth {
companion object {
const val WHETHER_LOCATION_AUTH = "whether_location_auth"
const val REFUSE_ALREADY = "refuse_already"
const val RECENT_CITY = "recent_city"
}
}
}
\ No newline at end of file
package com.yidianling.consultant.listener
import com.yidianling.consultant.model.bean.PriceRangesItem
/**
* Created by zqk on 17-9-20.
*/
interface OnPriceItemSelectedListener {
fun onPriceItemSelected(priceRangesItem: PriceRangesItem)
}
\ No newline at end of file
......@@ -106,12 +106,17 @@ interface SearchApi {
* 100 有配置接口
* */
@GET("consult/assistant/chat-route-config")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA,"Content-Type:application/json")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA, "Content-Type:application/json")
fun getChatRouteConfig(
@Query("location") location: Int,
@Query("naviType") naviType: String = "1"
): Observable<BaseAPIResponse<Long>>
//根据IP地址获取城市
@GET("region/ip-region")
@Headers(YDL_DOMAIN + YDL_DOMAIN_JAVA, "Content-Type:application/json")
fun getCityByIp(): Observable<BaseAPIResponse<ConsultantRegionBean>>
//搜索条件
@GET("consult/user/order/promptPayment")
......
......@@ -8,45 +8,47 @@ import android.widget.TextView
* Created by zqk on 17-9-20.
*/
data class AllFilter(
var searchWord: String? = null,
val categories: ArrayList<CateItem> = ArrayList(), //主题
var reorder: ReorderItem = ReorderItem(), //排序
var region: RegionItem = RegionItem(), //省
var sub: SubItem = SubItem(), //市
var showType: ShowTypeItem = ShowTypeItem(), //显示方式
val enquiries: ArrayList<EnquiryItem> = ArrayList(), //咨询方式
var priceRanges: PriceRangesItem ?= null, //服务均价
var priceRangesView: TextView ?= null, //服务均价
val ages: ArrayList<AgeItem> = ArrayList(), //年龄
val doctorEdu: ArrayList<DoctorEduItem> = ArrayList(), //学历
val others: ArrayList<OtherItem> = ArrayList(),//其他筛选
val title:ArrayList<ReorderItem> = ArrayList(), //资质
val specialityCrowd:ArrayList<SpecialityCrowdBean> = ArrayList(), // 擅长人群
// 八大类标签集合
val childList:ArrayList<ChildrenBean> = ArrayList(), // 亲子教育
val stressList:ArrayList<ChildrenBean> = ArrayList(), // 情绪压力
val loveEmotionList:ArrayList<ChildrenBean> = ArrayList(), // 恋爱情感
val marriedFamilyList:ArrayList<ChildrenBean> = ArrayList(), // 婚姻家庭
val personalGrowthList:ArrayList<ChildrenBean> = ArrayList(), // 个人成长
val interpersonalRelationshipList:ArrayList<ChildrenBean> = ArrayList(), // 人际关系
val careerDevelopmentList:ArrayList<ChildrenBean> = ArrayList(), // 职场发展
val mentalHealthList:ArrayList<ChildrenBean> = ArrayList(), // 心理健康
var searchWord: String? = null,
val categories: ArrayList<CateItem> = ArrayList(), //主题
var reorder: ReorderItem = ReorderItem(), //排序
var region: RegionItem = RegionItem(), //省
var sub: SubItem = SubItem(), //市
var showType: ShowTypeItem = ShowTypeItem(), //显示方式
val enquiries: ArrayList<EnquiryItem> = ArrayList(), //咨询方式
var priceRanges: PriceRangesItem? = null, //服务均价
var priceRangesView: TextView? = null, //服务均价
var sortRangesView: TextView? = null, //排序均价
val ages: ArrayList<AgeItem> = ArrayList(), //年龄
val sorStyle: ArrayList<ReorderItem> = ArrayList(), //排序方式
val doctorEdu: ArrayList<DoctorEduItem> = ArrayList(), //学历
val others: ArrayList<OtherItem> = ArrayList(),//其他筛选
val title: ArrayList<ReorderItem> = ArrayList(), //资质
val specialityCrowd: ArrayList<SpecialityCrowdBean> = ArrayList(), // 擅长人群
// 八大类标签集合
val childList: ArrayList<ChildrenBean> = ArrayList(), // 亲子教育
val stressList: ArrayList<ChildrenBean> = ArrayList(), // 情绪压力
val loveEmotionList: ArrayList<ChildrenBean> = ArrayList(), // 恋爱情感
val marriedFamilyList:ArrayList<ChildrenBean> = ArrayList(), // 婚姻家庭
val personalGrowthList:ArrayList<ChildrenBean> = ArrayList(), // 个人成长
val interpersonalRelationshipList:ArrayList<ChildrenBean> = ArrayList(), // 人际关系
val careerDevelopmentList:ArrayList<ChildrenBean> = ArrayList(), // 职场发展
val mentalHealthList:ArrayList<ChildrenBean> = ArrayList(), // 心理健康
// 八大类已选中标签id集合
val categoryId2List:ArrayList<String> = ArrayList(), // 一级类目id集合
val categoryId3List:ArrayList<String> = ArrayList(), // 二级类目id集合
val categoryId2List:ArrayList<String> = ArrayList(), // 一级类目id集合
val categoryId3List:ArrayList<String> = ArrayList(), // 二级类目id集合
// 八大类选中下标集合,重置的时候可以减少循坏,提升性能
val chooseChildIndexList:ArrayList<Int> = ArrayList(),
val chooseStressIndexList:ArrayList<Int> = ArrayList(),
val chooseLoveEmotionIndexList:ArrayList<Int> = ArrayList(),
val chooseMarriedFamilyIndexList:ArrayList<Int> = ArrayList(),
val choosePersonalGrowthIndexList:ArrayList<Int> = ArrayList(),
val chooseInterpersonalRelationshipIndexList:ArrayList<Int> = ArrayList(),
val chooseCareerDevelopmentIndexList:ArrayList<Int> = ArrayList(),
val chooseMentalHealthIndexList:ArrayList<Int> = ArrayList()
val chooseChildIndexList:ArrayList<Int> = ArrayList(),
val chooseStressIndexList:ArrayList<Int> = ArrayList(),
val chooseLoveEmotionIndexList:ArrayList<Int> = ArrayList(),
val chooseMarriedFamilyIndexList:ArrayList<Int> = ArrayList(),
val choosePersonalGrowthIndexList:ArrayList<Int> = ArrayList(),
val chooseInterpersonalRelationshipIndexList:ArrayList<Int> = ArrayList(),
val chooseCareerDevelopmentIndexList:ArrayList<Int> = ArrayList(),
val chooseMentalHealthIndexList:ArrayList<Int> = ArrayList()
)
\ No newline at end of file
package com.yidianling.consultant.model.bean
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.android.parcel.Parcelize
@Parcelize
data class SubItem(
@field:SerializedName("value")
var value: String? = null,
@field:SerializedName("value")
var value: String? = null,
@field:SerializedName("key")
var key: String? = null,
@field:SerializedName("key")
var key: String? = null,
@field:SerializedName("code")
var code: String?=null
)
\ No newline at end of file
@field:SerializedName("code")
var code: String? = null,
var locationCode: String? = ""
) : Parcelable
\ No newline at end of file
package com.yidianling.consultant.ui.view
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Region
import android.graphics.drawable.BitmapDrawable
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSnapHelper
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.PopupWindow
import com.tencent.mmkv.MMKV
import com.ydl.ydlcommon.adapter.MyBaseAdapter
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.ydl.ydlcommon.view.dialog.CommonDialog
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.common.tools.RxImageTool
import com.yidianling.common.tools.ToastUtil
import com.yidianling.consultant.R
import com.yidianling.consultant.adapter.RegionRecyclerViewAdapter
import com.yidianling.consultant.adapter.SubRecyclerViewAdapter
import com.yidianling.consultant.bean.ConsultantRecentCity
import com.yidianling.consultant.constants.ConsultBIConstants
import com.yidianling.consultant.constants.ConsultBIConstants.ConsultEvent.Companion.CITY_NAME_CLICK
import com.yidianling.consultant.constants.ConsultBIConstants.ConsultantLocationAuth.Companion.RECENT_CITY
import com.yidianling.consultant.model.SearchApi
import com.yidianling.consultant.model.bean.RegionItem
import com.yidianling.consultant.model.bean.SubItem
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.consultant_ui_region_popup_window.view.*
/**
* 地区选择弹窗
*/
class AreaPopupWindow(val context: Context, regionList: ArrayList<RegionItem>, private var selectedRegion: RegionItem, private var selectedSub: SubItem)
: PopupWindow(null, ViewGroup.LayoutParams.MATCH_PARENT, RxImageTool.dp2px(369f)) {
class AreaPopupWindow(
val context: Context,
regionList: ArrayList<RegionItem>,
private var selectedRegion: RegionItem,
private var selectedSub: SubItem,
private val isAgree: Boolean
) : PopupWindow(null, ViewGroup.LayoutParams.MATCH_PARENT, RxImageTool.dp2px(369f)) {
private val subList = ArrayList<SubItem>()
private val regionAdapter = RegionRecyclerViewAdapter(context, regionList, selectedRegion)
private var subAdapter:SubRecyclerViewAdapter
private var subAdapter: SubRecyclerViewAdapter
private var recentCityBean: ConsultantRecentCity? = ConsultantRecentCity(arrayListOf())
var onRegionSelectedListener: OnRegionSelectedListener? = null
private var subLocationItem: SubItem? = SubItem()
private val locationCode = "-1"
private val recentCityCode = "0"
private var locationRegionItem: RegionItem? = null
private var locationList: ArrayList<SubItem>? = arrayListOf()
private var locationHistoryList = regionList
init {
val view = LayoutInflater.from(context).inflate(R.layout.consultant_ui_region_popup_window, null)
val view =
LayoutInflater.from(context).inflate(R.layout.consultant_ui_region_popup_window, null)
this.contentView = view
this.isFocusable = true
@Suppress("DEPRECATION")
this.setBackgroundDrawable(BitmapDrawable())
this.isOutsideTouchable = true
this.height = ((RxDeviceTool.getScreenHeight(context) - RxImageTool.dp2px(90f)) * 0.618).toInt() //设置高度为屏幕的80%
if (selectedRegion.sub.isNotEmpty()){
this.height =
((RxDeviceTool.getScreenHeight(context) - RxImageTool.dp2px(90f)) * 0.618).toInt() //设置高度为屏幕的80%
regionAdapter.regionList = regionList
if (selectedRegion.sub.isNotEmpty()) {
subList.addAll(selectedRegion.sub)
}else{
} else {
subList.addAll(regionList[0].sub)
}
subAdapter = SubRecyclerViewAdapter(context, subList, selectedSub)
subAdapter = SubRecyclerViewAdapter(context, subList, selectedSub, locationCode)
subAdapter.setOnAuthClickLister(object : SubRecyclerViewAdapter.OnAuthClickLister {
override fun onAuthClick() {
val dialog = CommonDialog(context)
.setTitle("温馨提示")
.setMessage("建议您授权定位权限,就能轻松获取周边优秀咨询师和其他服务")
.setLeftOnclick("暂不") { v1 ->
ActionCountUtils.count(
ConsultBIConstants.ConsultEvent.AUTHORIZATION_ICON_CLICK,
"暂不"
)
}.setRightClick("授权") { v12 ->
ActionCountUtils.count(
ConsultBIConstants.ConsultEvent.AUTHORIZATION_ICON_CLICK,
"授权"
)
MMKV.defaultMMKV().encode(
ConsultBIConstants.ConsultantLocationAuth.WHETHER_LOCATION_AUTH,
true
)
getRegionByIp(true, true)
}
dialog.show()
}
})
view.rvRegion.layoutManager =
LinearLayoutManager(
context,
......@@ -60,8 +112,8 @@ class AreaPopupWindow(val context: Context, regionList: ArrayList<RegionItem>, p
}
view.rvRegion.adapter = regionAdapter
val i = regionList
.takeWhile { it.key != selectedRegion.key }
.count()
.takeWhile { it.key != selectedRegion.key }
.count()
view.rvRegion.scrollToPosition(i)
......@@ -72,13 +124,70 @@ class AreaPopupWindow(val context: Context, regionList: ArrayList<RegionItem>, p
false
)
subAdapter.onItemClickListener = MyBaseAdapter.OnItemClickListener { _, _, data ->
saveCitySearchRecord(data)
selectedSub = data
ActionCountUtils.count(CITY_NAME_CLICK, data.value.toString())
onRegionSelectedListener?.onRegionSelected(selectedRegion, selectedSub)
}
view.rvSub.adapter = subAdapter
view.rvSub.scrollToPosition(subList.indexOf(selectedSub) + 1)
}
//倒序保留最近五次的搜索历史记录并去重
private fun saveCitySearchRecord(data: SubItem) {
if (data.value == "不限") return
recentCityBean?.let {
if (it.recentCity.size < 5) {
it.recentCity.add(0, data)
it.recentCity = it.recentCity.toMutableSet().toMutableList()
MMKV.defaultMMKV().encode(RECENT_CITY, recentCityBean)
} else {
it.recentCity.removeAt(it.recentCity.size - 1)
it.recentCity.add(0, data)
it.recentCity = it.recentCity.toMutableSet().toMutableList()
MMKV.defaultMMKV().encode(RECENT_CITY, recentCityBean)
}
}
}
@SuppressLint("CheckResult")
fun getRegionByIp(agreeLocation: Boolean, refreshAdapter: Boolean) {
if (agreeLocation) {
SearchApi.getSearchApi().getCityByIp()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
if (it.code == "200") {
subLocationItem?.code = it.data.city_code
subLocationItem?.key = it.data.city_code
subLocationItem?.value = it.data.city_name
subLocationItem?.locationCode = locationCode
locationList?.clear()
subLocationItem?.let { locationList?.add(it) }
locationHistoryList.get(0).code = it.data.province_code
locationHistoryList.get(0).key = it.data.province_code
locationHistoryList.get(0).value = "定位"
locationList?.let { locationHistoryList.get(0).sub = it }
subList.clear()
locationList?.let { it1 -> subList.addAll(it1) }
subAdapter.notifyDataSetChanged()
regionAdapter.notifyDataSetChanged()
} else {
ToastUtil.toastShort(it.msg)
}
}, {})
} else {
subLocationItem?.code = null
subLocationItem?.key = null
subLocationItem?.value = "开启授权,获得定位城市"
subLocationItem?.locationCode = "NotAuth"
subAdapter.notifyDataSetChanged()
regionAdapter.notifyDataSetChanged()
}
}
interface OnRegionSelectedListener {
fun onRegionSelected(region: RegionItem, sub: SubItem)
}
......
......@@ -15,7 +15,10 @@ import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.*
import com.bumptech.glide.Glide
import com.google.android.material.slider.LabelFormatter
import com.google.android.material.slider.RangeSlider
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.common.tools.RxImageTool
import com.yidianling.common.tools.RxKeyboardTool
......@@ -25,6 +28,9 @@ import com.yidianling.consultant.listener.OnFilterConfirmListener
import com.yidianling.consultant.model.bean.AllFilter
import com.yidianling.consultant.model.bean.Filters
import com.yidianling.consultant.model.bean.PriceRangesItem
import com.yidianling.consultant.model.bean.ReorderItem
import com.yidianling.consultant.ui.view.rangeseekbar.OnRangeChangedListener
import com.yidianling.consultant.ui.view.rangeseekbar.RangeSeekBar
import kotlinx.android.synthetic.main.consultant_item_filter.view.*
import kotlinx.android.synthetic.main.consultant_item_price_range.view.*
import kotlinx.android.synthetic.main.consultant_ui_filter_popup.view.*
......@@ -38,7 +44,8 @@ import kotlin.math.roundToInt
class FilterPopupWindow(
private val context: Context,
private val filterData: Filters,
private val tempFilter: AllFilter
private val tempFilter: AllFilter,
private val sortItems: ArrayList<ReorderItem>
) : PopupWindow(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) {
......@@ -49,6 +56,7 @@ class FilterPopupWindow(
private val otherViews: ArrayList<View> = ArrayList()
private val ziZhiViews: ArrayList<View> = ArrayList()
private val goodAtViews: ArrayList<TextView> = ArrayList()
private val sortRangeViews: ArrayList<View> = ArrayList() //排序list
var onFilterConfirmListener: OnFilterConfirmListener? = null
/**筛选咨询方式一行数量*/
......@@ -82,12 +90,10 @@ class FilterPopupWindow(
this.isOutsideTouchable = true
// this.animationStyle = R.style.consultant_expert_service_popupwindow_filter_anim_style
initShowSortViews(view)
initShowTypeViews(view)
//咨询方式
initEnquiryViews(view)
//服务均价
initPriceViews(view)
//年龄选择
initAgeViews(view)
//其他选择
......@@ -105,7 +111,6 @@ class FilterPopupWindow(
view.btnReset.setOnClickListener {
reset()
}
view.btnConfirm.setOnClickListener {
if (tempFilter.priceRanges?.key1 == "avg_price" && filterData.priceRanges.isNotEmpty()) {
tempFilter.priceRanges?.key1 = filterData.priceRanges[0].key1
......@@ -116,6 +121,62 @@ class FilterPopupWindow(
}
}
@SuppressLint("UseCompatLoadingForDrawables")
private fun initShowSortViews(view: View) {
val mWidth = (popWidth - RxImageTool.dp2px(52f)) / enquirySize
for ((index, enquiry) in sortItems.withIndex()) {
val llTextView =
View.inflate(context, R.layout.consultant_item_filter, null) as TextView
val params = FrameLayout.LayoutParams(mWidth, RxImageTool.dp2px(36f))
val marginNum = RxImageTool.dp2px(5f)
params.setMargins(
marginNum + (RxImageTool.dp2px(10f) + mWidth) * (index % enquirySize),
RxImageTool.dp2px(46f) * (index / enquirySize),
marginNum,
0
)
llTextView.layoutParams = params
llTextView.text = enquiry.value
sortRangeViews.add(llTextView)
if (enquiry == tempFilter.reorder) {
llTextView.isSelected = true
llTextView.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
llTextView.paint.isFakeBoldText = true
tempFilter.sortRangesView = llTextView
}
llTextView.setOnClickListener {
if (llTextView != tempFilter.sortRangesView) {
tempFilter.sortRangesView?.isSelected = false
tempFilter.sortRangesView?.background =
context.resources.getDrawable(R.drawable.consult_price_expert_unseleted)
tempFilter.sortRangesView?.paint?.isFakeBoldText = false
}
if (llTextView.isSelected) {
tempFilter.sorStyle.remove(enquiry)
tempFilter.priceRanges = null
llTextView.isSelected = false
llTextView.background =
context.resources.getDrawable(R.drawable.consult_price_expert_unseleted)
llTextView.paint.isFakeBoldText = false
tempFilter.sortRangesView = null
} else {
tempFilter.sorStyle.add(enquiry)
llTextView.isSelected = true
llTextView.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
llTextView.paint.isFakeBoldText = true
tempFilter.sortRangesView = llTextView
tempFilter.reorder = sortItems[index]
}
updateCount(ConsultBIConstants.POSITION_CONSULT_TYPE_CLICK)
}
view.flSortType.addView(llTextView)
}
}
@SuppressLint("ClickableViewAccessibility")
private fun initKeyboardListener(view: View) {
val svFilter = view.findViewById<ScrollView>(R.id.sv_filter)
......@@ -147,10 +208,7 @@ class FilterPopupWindow(
tempFilter.specialityCrowd.clear()
tempFilter.others.clear()
tempFilter.title.clear()
tempFilter.priceRangesView = null
tempFilter.priceRanges = null
etMinPrice?.setText("")
etMaxPrice?.setText("")
for (v in showTypeViews) {
v.isSelected = false
......@@ -196,14 +254,6 @@ class FilterPopupWindow(
v.paint.isFakeBoldText = false
}
}
for (v in priceRangeViews) {
v.isSelected = false
if (v is TextView) {
v.paint.isFakeBoldText = false
}
}
updateCount(ConsultBIConstants.POSITION_CONSULT_FILTER_RESET_CLICK)
}
......@@ -357,6 +407,8 @@ class FilterPopupWindow(
if (tempFilter.others.contains(other)) {
textView.isSelected = true
textView.paint.isFakeBoldText = true
textView.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
}
textView.tvFilterName.text = " " + other.value + " "
textView.setOnClickListener {
......@@ -365,10 +417,14 @@ class FilterPopupWindow(
tempFilter.others.remove(other)
textView.isSelected = false
textView.paint.isFakeBoldText = false
textView.background =
context.resources.getDrawable(R.drawable.consult_price_expert_unseleted)
} else {
tempFilter.others.add(other)
textView.isSelected = true
textView.paint.isFakeBoldText = true
textView.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
}
updateCount(ConsultBIConstants.POSITION_OTHER_CHOICE_CLICK)
}
......@@ -392,6 +448,8 @@ class FilterPopupWindow(
if (tempFilter.title.contains(other)) {
textView.isSelected = true
textView.paint.isFakeBoldText = true
textView.background =
context.resources.getDrawable(R.drawable.consultant_filter_expert_two_selected)
}
textView.tvFilterName.text = " " + other.value + " "
textView.setOnClickListener {
......@@ -400,10 +458,14 @@ class FilterPopupWindow(
tempFilter.title.remove(other)
textView.isSelected = false
textView.paint.isFakeBoldText = false
textView.background =
context.resources.getDrawable(R.drawable.consult_price_expert_unseleted)
} else {
tempFilter.title.add(other)
textView.isSelected = true
textView.paint.isFakeBoldText = true
textView.background =
context.resources.getDrawable(R.drawable.consultant_filter_expert_two_selected)
}
updateCount(ConsultBIConstants.POSITION_QUALIFICATION_CHOICE_CLICK)
}
......@@ -447,6 +509,8 @@ class FilterPopupWindow(
if (tempFilter.specialityCrowd.contains(item)) {
textView.isSelected = true
textView.paint.isFakeBoldText = true
textView.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
}
textView.tvFilterName.text = " " + item.value + " "
textView.setOnClickListener {
......@@ -455,10 +519,14 @@ class FilterPopupWindow(
tempFilter.specialityCrowd.remove(item)
textView.isSelected = false
textView.paint.isFakeBoldText = false
textView.background =
context.resources.getDrawable(R.drawable.consult_price_expert_unseleted)
} else {
tempFilter.specialityCrowd.add(item)
textView.isSelected = true
textView.paint.isFakeBoldText = true
textView.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
}
}
......@@ -493,6 +561,8 @@ class FilterPopupWindow(
if (tempFilter.ages.contains(age)) {
textView.isSelected = true
textView.paint.isFakeBoldText = true
textView.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
}
textView.text = " " + age.value + " "
textView.setOnClickListener {
......@@ -501,10 +571,14 @@ class FilterPopupWindow(
tempFilter.ages.remove(age)
textView.isSelected = false
textView.paint.isFakeBoldText = false
textView.background =
context.resources.getDrawable(R.drawable.consult_price_expert_unseleted)
} else {
tempFilter.ages.add(age)
textView.isSelected = true
textView.paint.isFakeBoldText = true
textView.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
}
updateCount(ConsultBIConstants.POSITION_AGE_CHOICE_CLICK)
}
......@@ -534,6 +608,8 @@ class FilterPopupWindow(
if (tempFilter.doctorEdu.contains(edu)) {
textView.isSelected = true
textView.paint.isFakeBoldText = true
textView.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
}
textView.text = " " + edu.value + " "
textView.setOnClickListener {
......@@ -542,10 +618,14 @@ class FilterPopupWindow(
tempFilter.doctorEdu.remove(edu)
textView.isSelected = false
textView.paint.isFakeBoldText = false
textView.background =
context.resources.getDrawable(R.drawable.consult_price_expert_unseleted)
} else {
tempFilter.doctorEdu.add(edu)
textView.isSelected = true
textView.paint.isFakeBoldText = true
textView.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
}
updateCount(ConsultBIConstants.POSITION_EDU_CHOICE_CLICK)
}
......@@ -580,6 +660,8 @@ class FilterPopupWindow(
Glide.with(context)
.load(enquiry.check_url)
.into(ivIcon)
llLayout.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
}
llLayout.setOnClickListener {
if (llLayout.isSelected) {
......@@ -589,6 +671,8 @@ class FilterPopupWindow(
Glide.with(context)
.load(enquiry.un_check_url)
.into(ivIcon)
llLayout.background =
context.resources.getDrawable(R.drawable.consult_price_expert_unseleted)
} else {
tempFilter.enquiries.add(enquiry)
llLayout.isSelected = true
......@@ -596,6 +680,8 @@ class FilterPopupWindow(
Glide.with(context)
.load(enquiry.check_url)
.into(ivIcon)
llLayout.background =
context.resources.getDrawable(R.drawable.consult_filter_four_selected)
}
updateCount(ConsultBIConstants.POSITION_CONSULT_TYPE_CLICK)
}
......@@ -603,131 +689,6 @@ class FilterPopupWindow(
}
}
private fun initPriceViews(view: View) {
val priceRange =
View.inflate(context, R.layout.consultant_item_price_range, null) as LinearLayout
etMinPrice = priceRange.findViewById(R.id.etMinPrice);
etMaxPrice = priceRange.findViewById(R.id.etMaxPrice);
// context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
val listener: TextView.OnEditorActionListener =
TextView.OnEditorActionListener { _, actionId, event ->
if (actionId == EditorInfo.IME_ACTION_DONE || event != null && event.keyCode == KeyEvent.KEYCODE_ENTER) {
updatePriceFilter()
true
} else {
false
}
}
if (tempFilter.priceRanges != null) {
etMinPrice?.setText(tempFilter.priceRanges?.min_price)
etMaxPrice?.setText(tempFilter.priceRanges?.max_price)
}
etMaxPrice?.setOnEditorActionListener(listener)
etMinPrice?.setOnEditorActionListener(listener)
etMaxPrice?.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) {
// 以小数点开头,前面自动加上 "0"
if (s.toString().startsWith(".")) {
etMaxPrice?.setText("0$s");
etMaxPrice?.setSelection(etMaxPrice?.text!!.length);
}
}
})
etMinPrice?.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) {
// 以小数点开头,前面自动加上 "0"
if (s.toString().startsWith(".")) {
etMinPrice?.setText("0$s");
etMinPrice?.setSelection(etMinPrice?.text!!.length);
}
}
})
val mWidth = (popWidth - RxImageTool.dp2px(52f)) / enquirySize
for ((index, priceRangesItem) in filterData.priceRanges.withIndex()) {
val textView = View.inflate(context, R.layout.consultant_item_filter, null) as TextView
val params = FrameLayout.LayoutParams(mWidth, RxImageTool.dp2px(48f))
val marginNum = RxImageTool.dp2px(2f)
params.setMargins(
marginNum + (RxImageTool.dp2px(10f) + mWidth) * (index % enquirySize),
RxImageTool.dp2px(58f) * (index / 3),
marginNum,
0
)
textView.layoutParams = params
val contentStr = String.format(
"%s\n%s",
priceRangesItem.display_range,
priceRangesItem.recommend_percent
)
val msp = SpannableString(contentStr)
msp.setSpan(
AbsoluteSizeSpan(10, true),
contentStr.indexOf("\n"),
contentStr.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = msp
textView.setSingleLine(false)
textView.setLineSpacing(1.0f, 1.2f)
priceRangeViews.add(textView)
if (priceRangesItem == tempFilter.priceRanges) {
textView.isSelected = true
textView.paint.isFakeBoldText = true
tempFilter.priceRangesView = textView
}
textView.setOnClickListener {
if (textView != tempFilter.priceRangesView) {
tempFilter.priceRangesView?.isSelected = false
tempFilter.priceRangesView?.paint?.isFakeBoldText = false
}
if (textView.isSelected) {
tempFilter.priceRanges = null
textView.isSelected = false
textView.paint.isFakeBoldText = false
tempFilter.priceRangesView = null
etMaxPrice?.setText("")
etMinPrice?.setText("")
} else {
tempFilter.priceRanges = priceRangesItem.copy(
min_price = priceRangesItem.min_price,
max_price = priceRangesItem.max_price
)
textView.isSelected = true
textView.paint.isFakeBoldText = true
tempFilter.priceRangesView = textView
etMinPrice?.setText(priceRangesItem.min_price)
etMaxPrice?.setText(priceRangesItem.max_price)
etMinPrice?.setSelection(etMinPrice?.text!!.length)
etMaxPrice?.setSelection(etMaxPrice?.text!!.length)
}
updateCount(ConsultBIConstants.POSITION_AVERAGE_SERVICE_INPUT)
}
priceRange.flPriceRangeContainer.addView(textView)
}
view.flPriceRange.addView(priceRange)
}
private fun updatePriceFilter() {
RxKeyboardTool.hideSoftInput(context, etMaxPrice)
......
package com.yidianling.consultant.ui.view
import android.content.Context
import android.graphics.drawable.BitmapDrawable
import android.text.SpannableString
import android.text.Spanned
import android.text.style.AbsoluteSizeSpan
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.PopupWindow
import android.widget.TextView
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.common.tools.RxImageTool
import com.yidianling.consultant.R
import com.yidianling.consultant.constants.ConsultBIConstants.ConsultEvent.Companion.BOTTOM_ICON_CLICK
import com.yidianling.consultant.constants.ConsultBIConstants.ConsultEvent.Companion.PRICE_CHOICE_CLICK
import com.yidianling.consultant.constants.ConsultBIConstants.ConsultEvent.Companion.PRICE_SLIDE_CLICK
import com.yidianling.consultant.listener.OnPriceItemSelectedListener
import com.yidianling.consultant.model.bean.AllFilter
import com.yidianling.consultant.model.bean.Filters
import com.yidianling.consultant.model.bean.PriceRangesItem
import com.yidianling.consultant.ui.view.rangeseekbar.OnRangeChangedListener
import com.yidianling.consultant.ui.view.rangeseekbar.RangeSeekBar
import kotlinx.android.synthetic.main.consultant_ui_price_popup_window.view.*
/**
* 排序弹窗
* Created by zqk on 17-9-15.
*/
class PricePopupWindow(
val context: Context,
private val filterData: Filters,
private val tempFilter: AllFilter,
var onPriceItemSelectedListener: OnPriceItemSelectedListener
) : PopupWindow(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) {
private val popWidth = (RxDeviceTool.getScreenWidth(context))
//价格筛选一行三个项
private val enquirySize = 3
private val priceRangeViews: ArrayList<View> = ArrayList()
private var min_Price = ""
private var max_Price = ""
private var SeekBarLeftValue = 0f
private var SeekBarRightValue = 0f
private val maxPriceValue = 600
private val infiniteText = "无限"
private var track = false
init {
val view =
LayoutInflater.from(context).inflate(R.layout.consultant_ui_price_popup_window, null)
this.contentView = view
this.isFocusable = true
@Suppress("DEPRECATION")
this.setBackgroundDrawable(BitmapDrawable())
this.isOutsideTouchable = true
initPriceTag()
contentView.price_Confirm.setOnClickListener {
ActionCountUtils.count(BOTTOM_ICON_CLICK, contentView.price_Confirm.text.toString())
if (max_Price == infiniteText) max_Price = ""
var priceRangesItem = PriceRangesItem(min_Price, max_Price)
priceRangesItem.key1 = filterData.priceRanges[0].key1
tempFilter.priceRanges?.key1 = filterData.priceRanges[0].key1
onPriceItemSelectedListener.onPriceItemSelected(priceRangesItem)
dismiss()
}
contentView.price_reset.setOnClickListener {
ActionCountUtils.count(BOTTOM_ICON_CLICK, contentView.price_reset.text.toString())
//重置
contentView.range_price_seekbar.setProgress(0f, 100f)
reset()
}
if (tempFilter.priceRanges != null) {
if (tempFilter.priceRanges?.min_price.isNullOrEmpty()) {
min_Price = "0"
SeekBarLeftValue = 0f
} else {
min_Price = tempFilter.priceRanges?.min_price.toString()
SeekBarLeftValue =
(tempFilter.priceRanges?.min_price.toString().toFloat() / maxPriceValue) * 100f
}
if (tempFilter.priceRanges?.max_price.isNullOrEmpty()) {
max_Price = infiniteText
SeekBarRightValue = 100f
} else {
max_Price = tempFilter.priceRanges?.max_price.toString()
SeekBarRightValue =
(tempFilter.priceRanges?.max_price.toString().toFloat() / maxPriceValue) * 100f
}
if (SeekBarRightValue > 100f) SeekBarRightValue = 100f
if (max_Price == infiniteText) {
contentView.tv_start_end_price.text = "$min_Price-$max_Price"
} else {
contentView.tv_start_end_price.text = "$min_Price-$max_Price" + "元"
}
contentView.range_price_seekbar.setProgress(SeekBarLeftValue, SeekBarRightValue)
} else {
contentView.range_price_seekbar.setProgress(0f, 100f)
}
contentView.range_price_seekbar.setOnRangeChangedListener(object : OnRangeChangedListener {
override fun onRangeChanged(
view: RangeSeekBar?,
leftValue: Float,
rightValue: Float,
isFromUser: Boolean
) {
if (track) {
max_Price = ((rightValue / 100) * maxPriceValue).toInt().toString()
if (rightValue > 93) {
max_Price = infiniteText
}
min_Price = ((leftValue / 100) * maxPriceValue).toInt().toString()
ActionCountUtils.count(PRICE_SLIDE_CLICK, "$min_Price-$max_Price")
contentView.tv_start_end_price.text =
"$min_Price-$max_Price"
}
}
override fun onStartTrackingTouch(view: RangeSeekBar?, isLeft: Boolean) {
track = true
reset()
}
override fun onStopTrackingTouch(view: RangeSeekBar?, isLeft: Boolean) {
track = false
}
})
}
private fun reset() {
tempFilter.priceRangesView = null
tempFilter.priceRanges = null
min_Price = ""
max_Price = ""
contentView?.tv_start_end_price?.text = "0-无限"
for (v in priceRangeViews) {
v.isSelected = false
if (v is TextView) {
v.paint.isFakeBoldText = false
}
}
initPriceTag()
}
fun initPriceTag() {
val mWidth = (popWidth - RxImageTool.dp2px(52f)) / enquirySize
for ((index, priceRangesItem) in filterData.priceRanges.withIndex()) {
val textView = View.inflate(context, R.layout.consultant_item_filter, null) as TextView
val params = FrameLayout.LayoutParams(mWidth, RxImageTool.dp2px(50f))
val marginNum = RxImageTool.dp2px(2f)
params.setMargins(
marginNum + (RxImageTool.dp2px(10f) + mWidth) * (index % enquirySize),
RxImageTool.dp2px(58f) * (index / 3),
marginNum,
0
)
textView.layoutParams = params
val contentStr = String.format(
"%s\n%s",
priceRangesItem.display_range,
priceRangesItem.recommend_percent
)
val msp = SpannableString(contentStr)
msp.setSpan(
AbsoluteSizeSpan(10, true),
contentStr.indexOf("\n"),
contentStr.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = msp
textView.setSingleLine(false)
textView.setLineSpacing(1.0f, 1.2f)
priceRangeViews.add(textView)
if (priceRangesItem == tempFilter.priceRanges) {
textView.isSelected = true
textView.background = context.getDrawable(R.drawable.consult_price_expert_selected)
textView.paint.isFakeBoldText = true
tempFilter.priceRangesView = textView
}
textView.setOnClickListener {
if (textView != tempFilter.priceRangesView) {
tempFilter.priceRangesView?.isSelected = false
tempFilter.priceRangesView?.background =
context.getDrawable(R.drawable.consult_price_expert_unseleted)
tempFilter.priceRangesView?.paint?.isFakeBoldText = false
}
if (textView.isSelected) {
textView.background =
context.getDrawable(R.drawable.consult_price_expert_unseleted)
tempFilter.priceRanges = null
textView.isSelected = false
textView.paint.isFakeBoldText = false
tempFilter.priceRangesView = null
min_Price = ""
max_Price = ""
contentView.range_price_seekbar.setProgress(0f, 100f)
contentView.tv_start_end_price.text = "0-$infiniteText"
} else {
textView.background =
context.getDrawable(R.drawable.consult_price_expert_selected)
tempFilter.priceRanges = priceRangesItem.copy(
min_price = priceRangesItem.min_price,
max_price = priceRangesItem.max_price
)
ActionCountUtils.count(
PRICE_CHOICE_CLICK,
priceRangesItem.min_price + "-" + priceRangesItem.max_price
)
textView.isSelected = true
textView.paint.isFakeBoldText = true
tempFilter.priceRangesView = textView
if (priceRangesItem.min_price.isNullOrEmpty()) {
min_Price = "0"
SeekBarLeftValue = 0f
} else {
min_Price = priceRangesItem.min_price.toString()
SeekBarLeftValue =
(priceRangesItem.min_price.toString().toFloat() / maxPriceValue) * 100f
}
if (priceRangesItem.max_price.isNullOrEmpty()) {
max_Price = infiniteText
SeekBarRightValue = 100f
} else {
max_Price = priceRangesItem.max_price.toString()
SeekBarRightValue =
(priceRangesItem.max_price.toString().toFloat() / maxPriceValue) * 100f
}
if (SeekBarRightValue > 100f) SeekBarRightValue = 100f
contentView.range_price_seekbar.setProgress(SeekBarLeftValue, SeekBarRightValue)
contentView.postDelayed(Runnable { }, 30)
if (max_Price == infiniteText) {
contentView.tv_start_end_price.text = "$min_Price-$max_Price"
} else {
contentView.tv_start_end_price.text = "$min_Price-$max_Price" + "元"
}
}
}
contentView.flPriceRangeView.addView(textView)
}
}
}
\ No newline at end of file
package com.yidianling.consultant.ui.view.rangeseekbar;
/**
* ================================================
* 作 者:JayGoo
* 版 本:
* 创建日期:2018/5/8
* 描 述:
* ================================================
*/
public interface OnRangeChangedListener {
void onRangeChanged(RangeSeekBar view, float leftValue, float rightValue, boolean isFromUser);
void onStartTrackingTouch(RangeSeekBar view, boolean isLeft);
void onStopTrackingTouch(RangeSeekBar view, boolean isLeft);
}
package com.yidianling.consultant.ui.view.rangeseekbar;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.IntDef;
import com.yidianling.consultant.R;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import static com.yidianling.consultant.ui.view.rangeseekbar.SeekBar.INDICATOR_ALWAYS_HIDE;
import static com.yidianling.consultant.ui.view.rangeseekbar.SeekBar.INDICATOR_ALWAYS_SHOW;
public class RangeSeekBar extends View {
//normal seekBar mode
public final static int SEEKBAR_MODE_SINGLE = 1;
//RangeSeekBar
public final static int SEEKBAR_MODE_RANGE = 2;
//number according to the actual proportion of the number of arranged;
public final static int TRICK_MARK_MODE_NUMBER = 0;
//other equally arranged
public final static int TRICK_MARK_MODE_OTHER = 1;
//tick mark text gravity
public final static int TICK_MARK_GRAVITY_LEFT = 0;
public final static int TICK_MARK_GRAVITY_CENTER = 1;
public final static int TICK_MARK_GRAVITY_RIGHT = 2;
private final static int MIN_INTERCEPT_DISTANCE = 100;
float touchDownX, touchDownY;
//剩余最小间隔的进度
float reservePercent;
boolean isScaleThumb = false;
Paint paint = new Paint();
RectF progressDefaultDstRect = new RectF();
RectF progressDstRect = new RectF();
Rect progressSrcRect = new Rect();
RectF stepDivRect = new RectF();
Rect tickMarkTextRect = new Rect();
SeekBar leftSB;
SeekBar rightSB;
SeekBar currTouchSB;
Bitmap progressBitmap;
Bitmap progressDefaultBitmap;
List<Bitmap> stepsBitmaps = new ArrayList<>();
private int progressTop, progressBottom, progressLeft, progressRight;
private int seekBarMode;
//刻度模式:number根据数字实际比例排列;other 均分排列
private int tickMarkMode;
//刻度与进度条间的间距
//The spacing between the tick mark and the progress bar
private int tickMarkTextMargin;
//刻度文字与提示文字的大小
//tick mark text and prompt text size
private int tickMarkTextSize;
private int tickMarkGravity;
private int tickMarkLayoutGravity;
private int tickMarkTextColor;
private int tickMarkInRangeTextColor;
//刻度上显示的文字
//The texts displayed on the scale
private CharSequence[] tickMarkTextArray;
//进度条圆角
//radius of progress bar
private float progressRadius;
//进度中进度条的颜色
//the color of seekBar in progress
private int progressColor;
//默认进度条颜色
//the default color of the progress bar
private int progressDefaultColor;
//the drawable of seekBar in progress
private int progressDrawableId;
//the default Drawable of the progress bar
private int progressDefaultDrawableId;
//the progress height
private int progressHeight;
// the progress width
private int progressWidth;
//the range interval of RangeSeekBar
private float minInterval;
private int gravity;
//****************** the above is attr value ******************//
//enable RangeSeekBar two thumb Overlap
private boolean enableThumbOverlap;
//the color of step divs
private int stepsColor;
//the width of each step
private float stepsWidth;
//the height of each step
private float stepsHeight;
//the radius of step divs
private float stepsRadius;
//steps is 0 will disable StepSeekBar
private int steps;
//the thumb will automatic bonding close to its value
private boolean stepsAutoBonding;
private int stepsDrawableId;
//True values set by the user
private float minProgress, maxProgress;
private boolean isEnable = true;
private int progressPaddingRight;
private OnRangeChangedListener callback;
public RangeSeekBar(Context context) {
this(context, null);
}
public RangeSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
initAttrs(attrs);
initPaint();
initSeekBar(attrs);
initStepsBitmap();
}
private void initProgressBitmap() {
if (progressBitmap == null) {
progressBitmap = Utils.drawableToBitmap(getContext(), progressWidth, progressHeight, progressDrawableId);
}
if (progressDefaultBitmap == null) {
progressDefaultBitmap = Utils.drawableToBitmap(getContext(), progressWidth, progressHeight, progressDefaultDrawableId);
}
}
private boolean verifyStepsMode() {
if (steps < 1 || stepsHeight <= 0 || stepsWidth <= 0) return false;
return true;
}
private void initStepsBitmap() {
if (!verifyStepsMode() || stepsDrawableId == 0) return;
if (stepsBitmaps.isEmpty()) {
Bitmap bitmap = Utils.drawableToBitmap(getContext(), (int) stepsWidth, (int) stepsHeight, stepsDrawableId);
for (int i = 0; i <= steps; i++) {
stepsBitmaps.add(bitmap);
}
}
}
private void initSeekBar(AttributeSet attrs) {
leftSB = new SeekBar(this, attrs, true);
rightSB = new SeekBar(this, attrs, false);
rightSB.setVisible(seekBarMode != SEEKBAR_MODE_SINGLE);
}
private void initAttrs(AttributeSet attrs) {
try {
TypedArray t = getContext().obtainStyledAttributes(attrs, R.styleable.RangeSeekBar);
seekBarMode = t.getInt(R.styleable.RangeSeekBar_rsb_mode, SEEKBAR_MODE_RANGE);
minProgress = t.getFloat(R.styleable.RangeSeekBar_rsb_min, 0);
maxProgress = t.getFloat(R.styleable.RangeSeekBar_rsb_max, 100);
minInterval = t.getFloat(R.styleable.RangeSeekBar_rsb_min_interval, 0);
gravity = t.getInt(R.styleable.RangeSeekBar_rsb_gravity, Gravity.TOP);
progressColor = t.getColor(R.styleable.RangeSeekBar_rsb_progress_color, 0xFF4BD962);
progressRadius = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_progress_radius, -1);
progressDefaultColor = t.getColor(R.styleable.RangeSeekBar_rsb_progress_default_color, 0xFFD7D7D7);
progressDrawableId = t.getResourceId(R.styleable.RangeSeekBar_rsb_progress_drawable, 0);
progressDefaultDrawableId = t.getResourceId(R.styleable.RangeSeekBar_rsb_progress_drawable_default, 0);
progressHeight = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_progress_height, Utils.dp2px(getContext(), 2));
tickMarkMode = t.getInt(R.styleable.RangeSeekBar_rsb_tick_mark_mode, TRICK_MARK_MODE_NUMBER);
tickMarkGravity = t.getInt(R.styleable.RangeSeekBar_rsb_tick_mark_gravity, TICK_MARK_GRAVITY_CENTER);
tickMarkLayoutGravity = t.getInt(R.styleable.RangeSeekBar_rsb_tick_mark_layout_gravity, Gravity.TOP);
tickMarkTextArray = t.getTextArray(R.styleable.RangeSeekBar_rsb_tick_mark_text_array);
tickMarkTextMargin = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_tick_mark_text_margin, Utils.dp2px(getContext(), 7));
tickMarkTextSize = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_tick_mark_text_size, Utils.dp2px(getContext(), 12));
tickMarkTextColor = t.getColor(R.styleable.RangeSeekBar_rsb_tick_mark_text_color, progressDefaultColor);
tickMarkInRangeTextColor = t.getColor(R.styleable.RangeSeekBar_rsb_tick_mark_in_range_text_color, progressColor);
steps = t.getInt(R.styleable.RangeSeekBar_rsb_steps, 0);
stepsColor = t.getColor(R.styleable.RangeSeekBar_rsb_step_color, 0xFF9d9d9d);
stepsRadius = t.getDimension(R.styleable.RangeSeekBar_rsb_step_radius, 0);
stepsWidth = t.getDimension(R.styleable.RangeSeekBar_rsb_step_width, 0);
stepsHeight = t.getDimension(R.styleable.RangeSeekBar_rsb_step_height, 0);
stepsDrawableId = t.getResourceId(R.styleable.RangeSeekBar_rsb_step_drawable, 0);
stepsAutoBonding = t.getBoolean(R.styleable.RangeSeekBar_rsb_step_auto_bonding, true);
t.recycle();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* measure progress bar position
*/
protected void onMeasureProgress(int w, int h) {
int viewHeight = h - getPaddingBottom() - getPaddingTop();
if (h <= 0) return;
if (gravity == Gravity.TOP) {
//calculate the height of indicator and thumb exceeds the part of the progress
float maxIndicatorHeight = 0;
if (leftSB.getIndicatorShowMode() != INDICATOR_ALWAYS_HIDE
|| rightSB.getIndicatorShowMode() != INDICATOR_ALWAYS_HIDE) {
maxIndicatorHeight = Math.max(leftSB.getIndicatorRawHeight(), rightSB.getIndicatorRawHeight());
}
float thumbHeight = Math.max(leftSB.getThumbScaleHeight(), rightSB.getThumbScaleHeight());
thumbHeight -= progressHeight / 2f;
//default height is indicator + thumb exceeds the part of the progress bar
//if tickMark height is greater than (indicator + thumb exceeds the part of the progress)
progressTop = (int) (maxIndicatorHeight + (thumbHeight - progressHeight) / 2f);
if (tickMarkTextArray != null && tickMarkLayoutGravity == Gravity.TOP) {
progressTop = (int) Math.max(getTickMarkRawHeight(), maxIndicatorHeight + (thumbHeight - progressHeight) / 2f);
}
progressBottom = progressTop + progressHeight;
} else if (gravity == Gravity.BOTTOM) {
if (tickMarkTextArray != null && tickMarkLayoutGravity == Gravity.BOTTOM) {
progressBottom = viewHeight - getTickMarkRawHeight();
} else {
progressBottom = (int) (viewHeight - Math.max(leftSB.getThumbScaleHeight(), rightSB.getThumbScaleHeight()) / 2f
+ progressHeight / 2f);
}
progressTop = progressBottom - progressHeight;
} else {
progressTop = (viewHeight - progressHeight) / 2;
progressBottom = progressTop + progressHeight;
}
int maxThumbWidth = (int) Math.max(leftSB.getThumbScaleWidth(), rightSB.getThumbScaleWidth());
progressLeft = maxThumbWidth / 2 + getPaddingLeft();
progressRight = w - maxThumbWidth / 2 - getPaddingRight();
progressWidth = progressRight - progressLeft;
progressDefaultDstRect.set(getProgressLeft(), getProgressTop(), getProgressRight(), getProgressBottom());
progressPaddingRight = w - progressRight;
//default value
if (progressRadius <= 0) {
progressRadius = (int) ((getProgressBottom() - getProgressTop()) * 0.45f);
}
initProgressBitmap();
}
//Android 7.0以后,优化了View的绘制,onMeasure和onSizeChanged调用顺序有所变化
//Android7.0以下:onMeasure--->onSizeChanged--->onMeasure
//Android7.0以上:onMeasure--->onSizeChanged
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
/*
* onMeasure传入的widthMeasureSpec和heightMeasureSpec不是一般的尺寸数值,而是将模式和尺寸组合在一起的数值
* MeasureSpec.EXACTLY 是精确尺寸
* MeasureSpec.AT_MOST 是最大尺寸
* MeasureSpec.UNSPECIFIED 是未指定尺寸
*/
if (heightMode == MeasureSpec.EXACTLY) {
heightSize = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
} else if (heightMode == MeasureSpec.AT_MOST && getParent() instanceof ViewGroup
&& heightSize == ViewGroup.LayoutParams.MATCH_PARENT) {
heightSize = MeasureSpec.makeMeasureSpec(((ViewGroup) getParent()).getMeasuredHeight(), MeasureSpec.AT_MOST);
} else {
int heightNeeded;
if (gravity == Gravity.CENTER) {
if (tickMarkTextArray != null && tickMarkLayoutGravity == Gravity.BOTTOM) {
heightNeeded = (int) (2 * (getRawHeight() - getTickMarkRawHeight()));
} else {
heightNeeded = (int) (2 * (getRawHeight() - Math.max(leftSB.getThumbScaleHeight(), rightSB.getThumbScaleHeight()) / 2));
}
} else {
heightNeeded = (int) getRawHeight();
}
heightSize = MeasureSpec.makeMeasureSpec(heightNeeded, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightSize);
}
protected int getTickMarkRawHeight() {
if (tickMarkTextArray != null && tickMarkTextArray.length > 0) {
return tickMarkTextMargin + Utils.measureText(String.valueOf(tickMarkTextArray[0]), tickMarkTextSize).height() + 3;
}
return 0;
}
protected float getRawHeight() {
float rawHeight;
if (seekBarMode == SEEKBAR_MODE_SINGLE) {
rawHeight = leftSB.getRawHeight();
if (tickMarkLayoutGravity == Gravity.BOTTOM && tickMarkTextArray != null) {
float h = Math.max((leftSB.getThumbScaleHeight() - progressHeight) / 2, getTickMarkRawHeight());
rawHeight = rawHeight - leftSB.getThumbScaleHeight() / 2 + progressHeight / 2f + h;
}
} else {
rawHeight = Math.max(leftSB.getRawHeight(), rightSB.getRawHeight());
if (tickMarkLayoutGravity == Gravity.BOTTOM && tickMarkTextArray != null) {
float thumbHeight = Math.max(leftSB.getThumbScaleHeight(), rightSB.getThumbScaleHeight());
float h = Math.max((thumbHeight - progressHeight) / 2, getTickMarkRawHeight());
rawHeight = rawHeight - thumbHeight / 2 + progressHeight / 2f + h;
}
}
return rawHeight;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
onMeasureProgress(w, h);
//set default value
setRange(minProgress, maxProgress, minInterval);
// initializes the positions of the two thumbs
int lineCenterY = (getProgressBottom() + getProgressTop()) / 2;
leftSB.onSizeChanged(getProgressLeft(), lineCenterY);
if (seekBarMode == SEEKBAR_MODE_RANGE) {
rightSB.onSizeChanged(getProgressLeft(), lineCenterY);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
onDrawTickMark(canvas, paint);
onDrawProgressBar(canvas, paint, true);
onDrawSteps(canvas, paint);
onDrawSeekBar(canvas);
}
//绘制刻度,并且根据当前位置是否在刻度范围内设置不同的颜色显示
// Draw the scales, and according to the current position is set within
// the scale range of different color display
protected void onDrawTickMark(Canvas canvas, Paint paint) {
if (tickMarkTextArray != null) {
int trickPartWidth = progressWidth / (tickMarkTextArray.length - 1);
for (int i = 0; i < tickMarkTextArray.length; i++) {
final String text2Draw = tickMarkTextArray[i].toString();
if (TextUtils.isEmpty(text2Draw)) continue;
paint.getTextBounds(text2Draw, 0, text2Draw.length(), tickMarkTextRect);
paint.setColor(tickMarkTextColor);
//平分显示
float x;
if (tickMarkMode == TRICK_MARK_MODE_OTHER) {
if (tickMarkGravity == TICK_MARK_GRAVITY_RIGHT) {
x = getProgressLeft() + i * trickPartWidth - tickMarkTextRect.width();
} else if (tickMarkGravity == TICK_MARK_GRAVITY_CENTER) {
if (i == tickMarkTextArray.length - 1) {
x = getProgressLeft() + i * trickPartWidth - tickMarkTextRect.width() / 2f - 20;
} else {
x = getProgressLeft() + i * trickPartWidth - tickMarkTextRect.width() / 2f;
}
} else {
x = getProgressLeft() + i * trickPartWidth;
}
} else {
float num = Utils.parseFloat(text2Draw);
SeekBarState[] states = getRangeSeekBarState();
if (Utils.compareFloat(num, states[0].value) != -1 && Utils.compareFloat(num, states[1].value) != 1 && (seekBarMode == SEEKBAR_MODE_RANGE)) {
paint.setColor(tickMarkInRangeTextColor);
}
//按实际比例显示
x = getProgressLeft() + progressWidth * (num - minProgress) / (maxProgress - minProgress)
- tickMarkTextRect.width() / 2f;
}
float y;
if (tickMarkLayoutGravity == Gravity.TOP) {
y = getProgressTop() - tickMarkTextMargin;
} else {
y = getProgressBottom() + tickMarkTextMargin + tickMarkTextRect.height() - 10;
}
canvas.drawText(text2Draw, x, y, paint);
}
}
}
//绘制进度条 另外在收尾两端绘制2个实心点
// draw the progress bar
protected void onDrawProgressBar(Canvas canvas, Paint paint, Boolean isNeedStartEnd) {
//draw default progress
if (Utils.verifyBitmap(progressDefaultBitmap)) {
canvas.drawBitmap(progressDefaultBitmap, null, progressDefaultDstRect, paint);
} else {
paint.setColor(progressDefaultColor);
canvas.drawRoundRect(progressDefaultDstRect, progressRadius, progressRadius, paint);
}
//draw progress
if (seekBarMode == SEEKBAR_MODE_RANGE) {
progressDstRect.top = getProgressTop();
progressDstRect.left = leftSB.left + leftSB.getThumbScaleWidth() / 2f + progressWidth * leftSB.currPercent;
progressDstRect.right = rightSB.left + rightSB.getThumbScaleWidth() / 2f + progressWidth * rightSB.currPercent;
progressDstRect.bottom = getProgressBottom();
} else {
progressDstRect.top = getProgressTop();
progressDstRect.left = leftSB.left + leftSB.getThumbScaleWidth() / 2f;
progressDstRect.right = leftSB.left + leftSB.getThumbScaleWidth() / 2f + progressWidth * leftSB.currPercent;
progressDstRect.bottom = getProgressBottom();
}
if (Utils.verifyBitmap(progressBitmap)) {
progressSrcRect.top = 0;
progressSrcRect.bottom = progressBitmap.getHeight();
int bitmapWidth = progressBitmap.getWidth();
if (seekBarMode == SEEKBAR_MODE_RANGE) {
progressSrcRect.left = (int) (bitmapWidth * leftSB.currPercent);
progressSrcRect.right = (int) (bitmapWidth * rightSB.currPercent);
} else {
progressSrcRect.left = 0;
progressSrcRect.right = (int) (bitmapWidth * leftSB.currPercent);
}
canvas.drawBitmap(progressBitmap, progressSrcRect, progressDstRect, null);
} else {
paint.setColor(progressColor);
canvas.drawRoundRect(progressDstRect, progressRadius, progressRadius, paint);
}
//如果需要绘制start和end的实心圆
if (isNeedStartEnd) {
paint.setColor(progressDefaultColor);
//画左边固定实心圆形
canvas.drawCircle(leftSB.left + leftSB.getThumbScaleWidth() / 2f, leftSB.top +
leftSB.getThumbScaleWidth() / 2f, 10f, paint);
//画右边固定实心圆
canvas.drawCircle(progressWidth + rightSB.getThumbScaleWidth() / 2f, rightSB.top + rightSB
.getThumbScaleWidth() / 2f, 10f, paint);
}
}
//draw steps
//绘制刻度线
protected void onDrawSteps(Canvas canvas, Paint paint) {
if (!verifyStepsMode()) return;
int stepMarks = getProgressWidth() / (steps);
float extHeight = (stepsHeight - getProgressHeight()) / 2f;
//绘制刻度。其他场景要用,需要自己修改这部分代码
for (int k = 1; k <= steps - 1; k++) {
//如果是奇数Setp,则不绘制刻度
// if (k % 2 == 1) continue;
float x = getProgressLeft() + k * stepMarks - stepsWidth / 2f;
stepDivRect.set(x, getProgressTop() + stepsHeight, x + stepsWidth, getProgressBottom() + 3 * stepsHeight);
if (stepsBitmaps.isEmpty() || stepsBitmaps.size() <= k) {
paint.setColor(stepsColor);
canvas.drawRoundRect(stepDivRect, stepsRadius, stepsRadius, paint);
} else {
canvas.drawBitmap(stepsBitmaps.get(k), null, stepDivRect, paint);
}
}
}
//绘制SeekBar相关
protected void onDrawSeekBar(Canvas canvas) {
//draw left SeekBar
if (leftSB.getIndicatorShowMode() == INDICATOR_ALWAYS_SHOW) {
leftSB.setShowIndicatorEnable(true);
}
leftSB.draw(canvas);
//draw right SeekBar
if (seekBarMode == SEEKBAR_MODE_RANGE) {
if (rightSB.getIndicatorShowMode() == INDICATOR_ALWAYS_SHOW) {
rightSB.setShowIndicatorEnable(true);
}
rightSB.draw(canvas);
}
}
//初始化画笔
private void initPaint() {
paint.setStyle(Paint.Style.FILL);
paint.setColor(progressDefaultColor);
paint.setTextSize(tickMarkTextSize);
}
private void changeThumbActivateState(boolean hasActivate) {
if (hasActivate && currTouchSB != null) {
boolean state = currTouchSB == leftSB;
leftSB.setActivate(state);
if (seekBarMode == SEEKBAR_MODE_RANGE)
rightSB.setActivate(!state);
} else {
leftSB.setActivate(false);
if (seekBarMode == SEEKBAR_MODE_RANGE)
rightSB.setActivate(false);
}
}
protected float getEventX(MotionEvent event) {
return event.getX();
}
protected float getEventY(MotionEvent event) {
return event.getY();
}
/**
* scale the touch seekBar thumb
*/
private void scaleCurrentSeekBarThumb() {
if (currTouchSB != null && currTouchSB.getThumbScaleRatio() > 1f && !isScaleThumb) {
isScaleThumb = true;
currTouchSB.scaleThumb();
}
}
/**
* reset the touch seekBar thumb
*/
private void resetCurrentSeekBarThumb() {
if (currTouchSB != null && currTouchSB.getThumbScaleRatio() > 1f && isScaleThumb) {
isScaleThumb = false;
currTouchSB.resetThumb();
}
}
//calculate currTouchSB percent by MotionEvent
protected float calculateCurrentSeekBarPercent(float touchDownX) {
if (currTouchSB == null) return 0;
float percent = (touchDownX - getProgressLeft()) * 1f / (progressWidth);
if (touchDownX < getProgressLeft()) {
percent = 0;
} else if (touchDownX > getProgressRight()) {
percent = 1;
}
//RangeMode minimum interval
if (seekBarMode == SEEKBAR_MODE_RANGE) {
if (currTouchSB == leftSB) {
if (percent > rightSB.currPercent - reservePercent) {
percent = rightSB.currPercent - reservePercent;
}
} else if (currTouchSB == rightSB) {
if (percent < leftSB.currPercent + reservePercent) {
percent = leftSB.currPercent + reservePercent;
}
}
}
return percent;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnable) return true;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDownX = getEventX(event);
touchDownY = getEventY(event);
if (seekBarMode == SEEKBAR_MODE_RANGE) {
if (rightSB.currPercent >= 1 && leftSB.collide(getEventX(event), getEventY(event))) {
currTouchSB = leftSB;
scaleCurrentSeekBarThumb();
} else if (rightSB.collide(getEventX(event), getEventY(event))) {
currTouchSB = rightSB;
scaleCurrentSeekBarThumb();
} else {
float performClick = (touchDownX - getProgressLeft()) * 1f / (progressWidth);
float distanceLeft = Math.abs(leftSB.currPercent - performClick);
float distanceRight = Math.abs(rightSB.currPercent - performClick);
if (distanceLeft < distanceRight) {
currTouchSB = leftSB;
} else {
currTouchSB = rightSB;
}
performClick = calculateCurrentSeekBarPercent(touchDownX);
currTouchSB.slide(performClick);
}
} else {
currTouchSB = leftSB;
scaleCurrentSeekBarThumb();
}
//Intercept parent TouchEvent
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
if (callback != null) {
callback.onStartTrackingTouch(this, currTouchSB == leftSB);
}
changeThumbActivateState(true);
return true;
case MotionEvent.ACTION_MOVE:
float x = getEventX(event);
if ((seekBarMode == SEEKBAR_MODE_RANGE) && leftSB.currPercent == rightSB.currPercent) {
currTouchSB.materialRestore();
if (callback != null) {
callback.onStopTrackingTouch(this, currTouchSB == leftSB);
}
if (x - touchDownX > 0) {
//method to move right
if (currTouchSB != rightSB) {
currTouchSB.setShowIndicatorEnable(false);
resetCurrentSeekBarThumb();
currTouchSB = rightSB;
}
} else {
//method to move left
if (currTouchSB != leftSB) {
currTouchSB.setShowIndicatorEnable(false);
resetCurrentSeekBarThumb();
currTouchSB = leftSB;
}
}
if (callback != null) {
callback.onStartTrackingTouch(this, currTouchSB == leftSB);
}
}
scaleCurrentSeekBarThumb();
currTouchSB.material = currTouchSB.material >= 1 ? 1 : currTouchSB.material + 0.1f;
touchDownX = x;
currTouchSB.slide(calculateCurrentSeekBarPercent(touchDownX));
currTouchSB.setShowIndicatorEnable(true);
if (callback != null) {
SeekBarState[] states = getRangeSeekBarState();
callback.onRangeChanged(this, states[0].value, states[1].value, true);
}
invalidate();
//Intercept parent TouchEvent
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
changeThumbActivateState(true);
break;
case MotionEvent.ACTION_CANCEL:
if (seekBarMode == SEEKBAR_MODE_RANGE) {
rightSB.setShowIndicatorEnable(false);
}
if (currTouchSB == leftSB) {
resetCurrentSeekBarThumb();
} else if (currTouchSB == rightSB) {
resetCurrentSeekBarThumb();
}
leftSB.setShowIndicatorEnable(false);
if (callback != null) {
SeekBarState[] states = getRangeSeekBarState();
callback.onRangeChanged(this, states[0].value, states[1].value, false);
}
//Intercept parent TouchEvent
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
changeThumbActivateState(false);
break;
case MotionEvent.ACTION_UP:
if (verifyStepsMode() && stepsAutoBonding) {
float percent = calculateCurrentSeekBarPercent(getEventX(event));
//步长step 自动滑动到step的一半
float stepPercent = 1.0f / (steps * 2);
int stepSelected = new BigDecimal(percent / stepPercent).setScale(0, RoundingMode.HALF_UP).intValue();
currTouchSB.slide(stepSelected * stepPercent);
}
if (seekBarMode == SEEKBAR_MODE_RANGE) {
rightSB.setShowIndicatorEnable(false);
}
leftSB.setShowIndicatorEnable(false);
currTouchSB.materialRestore();
resetCurrentSeekBarThumb();
if (callback != null) {
SeekBarState[] states = getRangeSeekBarState();
callback.onRangeChanged(this, states[0].value, states[1].value, false);
}
//Intercept parent TouchEvent
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
if (callback != null) {
callback.onStopTrackingTouch(this, currTouchSB == leftSB);
}
changeThumbActivateState(false);
break;
}
return super.onTouchEvent(event);
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.minValue = minProgress;
ss.maxValue = maxProgress;
ss.rangeInterval = minInterval;
SeekBarState[] results = getRangeSeekBarState();
ss.currSelectedMin = results[0].value;
ss.currSelectedMax = results[1].value;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
try {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
float min = ss.minValue;
float max = ss.maxValue;
float rangeInterval = ss.rangeInterval;
setRange(min, max, rangeInterval);
float currSelectedMin = ss.currSelectedMin;
float currSelectedMax = ss.currSelectedMax;
setProgress(currSelectedMin, currSelectedMax);
} catch (Exception e) {
e.printStackTrace();
}
}
public void setOnRangeChangedListener(OnRangeChangedListener listener) {
callback = listener;
}
public void setProgress(float value) {
setProgress(value, maxProgress);
}
public void setProgress(float leftValue, float rightValue) {
leftValue = Math.min(leftValue, rightValue);
rightValue = Math.max(leftValue, rightValue);
if (rightValue - leftValue < minInterval) {
if (leftValue - minProgress > maxProgress - rightValue) {
leftValue = rightValue - minInterval;
} else {
rightValue = leftValue + minInterval;
}
}
if (leftValue < minProgress) {
throw new IllegalArgumentException("setProgress() min < (preset min - offsetValue) . #min:" + leftValue + " #preset min:" + rightValue);
}
if (rightValue > maxProgress) {
throw new IllegalArgumentException("setProgress() max > (preset max - offsetValue) . #max:" + rightValue + " #preset max:" + rightValue);
}
float range = maxProgress - minProgress;
leftSB.currPercent = Math.abs(leftValue - minProgress) / range;
if (seekBarMode == SEEKBAR_MODE_RANGE) {
rightSB.currPercent = Math.abs(rightValue - minProgress) / range;
}
if (callback != null) {
callback.onRangeChanged(this, leftValue, rightValue, false);
}
invalidate();
}
/**
* 设置范围
*
* @param min 最小值
* @param max 最大值
*/
public void setRange(float min, float max) {
setRange(min, max, minInterval);
}
/**
* 设置范围
*
* @param min 最小值
* @param max 最大值
* @param minInterval 最小间隔
*/
public void setRange(float min, float max, float minInterval) {
if (max <= min) {
throw new IllegalArgumentException("setRange() max must be greater than min ! #max:" + max + " #min:" + min);
}
if (minInterval < 0) {
throw new IllegalArgumentException("setRange() interval must be greater than zero ! #minInterval:" + minInterval);
}
if (minInterval >= max - min) {
throw new IllegalArgumentException("setRange() interval must be less than (max - min) ! #minInterval:" + minInterval + " #max - min:" + (max - min));
}
maxProgress = max;
minProgress = min;
this.minInterval = minInterval;
reservePercent = minInterval / (max - min);
//set default value
if (seekBarMode == SEEKBAR_MODE_RANGE) {
if (leftSB.currPercent + reservePercent <= 1 && leftSB.currPercent + reservePercent > rightSB.currPercent) {
rightSB.currPercent = leftSB.currPercent + reservePercent;
} else if (rightSB.currPercent - reservePercent >= 0 && rightSB.currPercent - reservePercent < leftSB.currPercent) {
leftSB.currPercent = rightSB.currPercent - reservePercent;
}
}
invalidate();
}
/**
* @return the two seekBar state , see {@link }
*/
public SeekBarState[] getRangeSeekBarState() {
SeekBarState leftSeekBarState = new SeekBarState();
leftSeekBarState.value = leftSB.getProgress();
leftSeekBarState.indicatorText = String.valueOf(leftSeekBarState.value);
if (Utils.compareFloat(leftSeekBarState.value, minProgress) == 0) {
leftSeekBarState.isMin = true;
} else if (Utils.compareFloat(leftSeekBarState.value, maxProgress) == 0) {
leftSeekBarState.isMax = true;
}
SeekBarState rightSeekBarState = new SeekBarState();
if (seekBarMode == SEEKBAR_MODE_RANGE) {
rightSeekBarState.value = rightSB.getProgress();
rightSeekBarState.indicatorText = String.valueOf(rightSeekBarState.value);
if (Utils.compareFloat(rightSB.currPercent, minProgress) == 0) {
rightSeekBarState.isMin = true;
} else if (Utils.compareFloat(rightSB.currPercent, maxProgress) == 0) {
rightSeekBarState.isMax = true;
}
}
return new SeekBarState[]{leftSeekBarState, rightSeekBarState};
}
//******************* Attributes getter and setter *******************//
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
this.isEnable = enabled;
}
public void setIndicatorText(String progress) {
leftSB.setIndicatorText(progress);
if (seekBarMode == SEEKBAR_MODE_RANGE) {
rightSB.setIndicatorText(progress);
}
}
/**
* format number indicator text
*
* @param formatPattern format rules
*/
public void setIndicatorTextDecimalFormat(String formatPattern) {
leftSB.setIndicatorTextDecimalFormat(formatPattern);
if (seekBarMode == SEEKBAR_MODE_RANGE) {
rightSB.setIndicatorTextDecimalFormat(formatPattern);
}
}
/**
* format string indicator text
*
* @param formatPattern format rules
*/
public void setIndicatorTextStringFormat(String formatPattern) {
leftSB.setIndicatorTextStringFormat(formatPattern);
if (seekBarMode == SEEKBAR_MODE_RANGE) {
rightSB.setIndicatorTextStringFormat(formatPattern);
}
}
/**
* if is single mode, please use it to get the SeekBar
*
* @return left seek bar
*/
public SeekBar getLeftSeekBar() {
return leftSB;
}
public SeekBar getRightSeekBar() {
return rightSB;
}
public int getProgressTop() {
return progressTop;
}
public void setProgressTop(int progressTop) {
this.progressTop = progressTop;
}
public int getProgressBottom() {
return progressBottom;
}
public void setProgressBottom(int progressBottom) {
this.progressBottom = progressBottom;
}
public int getProgressLeft() {
return progressLeft;
}
public void setProgressLeft(int progressLeft) {
this.progressLeft = progressLeft;
}
public int getProgressRight() {
return progressRight;
}
public void setProgressRight(int progressRight) {
this.progressRight = progressRight;
}
public int getProgressPaddingRight() {
return progressPaddingRight;
}
public int getProgressHeight() {
return progressHeight;
}
public void setProgressHeight(int progressHeight) {
this.progressHeight = progressHeight;
}
public float getMinProgress() {
return minProgress;
}
public float getMaxProgress() {
return maxProgress;
}
public void setProgressColor(@ColorInt int progressDefaultColor, @ColorInt int progressColor) {
this.progressDefaultColor = progressDefaultColor;
this.progressColor = progressColor;
}
public int getTickMarkTextColor() {
return tickMarkTextColor;
}
public void setTickMarkTextColor(@ColorInt int tickMarkTextColor) {
this.tickMarkTextColor = tickMarkTextColor;
}
public int getTickMarkInRangeTextColor() {
return tickMarkInRangeTextColor;
}
public void setTickMarkInRangeTextColor(@ColorInt int tickMarkInRangeTextColor) {
this.tickMarkInRangeTextColor = tickMarkInRangeTextColor;
}
public int getSeekBarMode() {
return seekBarMode;
}
/**
* {@link #SEEKBAR_MODE_SINGLE} is single SeekBar
* {@link #SEEKBAR_MODE_RANGE} is range SeekBar
*
* @param seekBarMode
*/
public void setSeekBarMode(@SeekBarModeDef int seekBarMode) {
this.seekBarMode = seekBarMode;
rightSB.setVisible(seekBarMode != SEEKBAR_MODE_SINGLE);
}
public int getTickMarkMode() {
return tickMarkMode;
}
/**
* {@link #TICK_MARK_GRAVITY_LEFT} is number tick mark, it will locate the position according to the value.
* {@link #TICK_MARK_GRAVITY_RIGHT} is text tick mark, it will be equally positioned.
*
* @param tickMarkMode
*/
public void setTickMarkMode(@TickMarkModeDef int tickMarkMode) {
this.tickMarkMode = tickMarkMode;
}
public int getTickMarkTextMargin() {
return tickMarkTextMargin;
}
public void setTickMarkTextMargin(int tickMarkTextMargin) {
this.tickMarkTextMargin = tickMarkTextMargin;
}
public int getTickMarkTextSize() {
return tickMarkTextSize;
}
public void setTickMarkTextSize(int tickMarkTextSize) {
this.tickMarkTextSize = tickMarkTextSize;
}
public int getTickMarkGravity() {
return tickMarkGravity;
}
/**
* the tick mark text gravity
* {@link #TICK_MARK_GRAVITY_LEFT}
* {@link #TICK_MARK_GRAVITY_RIGHT}
* {@link #TICK_MARK_GRAVITY_CENTER}
*
* @param tickMarkGravity
*/
public void setTickMarkGravity(@TickMarkGravityDef int tickMarkGravity) {
this.tickMarkGravity = tickMarkGravity;
}
public CharSequence[] getTickMarkTextArray() {
return tickMarkTextArray;
}
public void setTickMarkTextArray(CharSequence[] tickMarkTextArray) {
this.tickMarkTextArray = tickMarkTextArray;
}
public float getMinInterval() {
return minInterval;
}
public float getProgressRadius() {
return progressRadius;
}
public void setProgressRadius(float progressRadius) {
this.progressRadius = progressRadius;
}
public int getProgressColor() {
return progressColor;
}
public void setProgressColor(@ColorInt int progressColor) {
this.progressColor = progressColor;
}
public int getProgressDefaultColor() {
return progressDefaultColor;
}
public void setProgressDefaultColor(@ColorInt int progressDefaultColor) {
this.progressDefaultColor = progressDefaultColor;
}
public int getProgressDrawableId() {
return progressDrawableId;
}
public void setProgressDrawableId(@DrawableRes int progressDrawableId) {
this.progressDrawableId = progressDrawableId;
progressBitmap = null;
initProgressBitmap();
}
public int getProgressDefaultDrawableId() {
return progressDefaultDrawableId;
}
public void setProgressDefaultDrawableId(@DrawableRes int progressDefaultDrawableId) {
this.progressDefaultDrawableId = progressDefaultDrawableId;
progressDefaultBitmap = null;
initProgressBitmap();
}
public int getProgressWidth() {
return progressWidth;
}
public void setProgressWidth(int progressWidth) {
this.progressWidth = progressWidth;
}
public void setTypeface(Typeface typeFace) {
paint.setTypeface(typeFace);
}
public boolean isEnableThumbOverlap() {
return enableThumbOverlap;
}
public void setEnableThumbOverlap(boolean enableThumbOverlap) {
this.enableThumbOverlap = enableThumbOverlap;
}
public int getSteps() {
return steps;
}
public void setSteps(int steps) {
this.steps = steps;
}
public int getStepsColor() {
return stepsColor;
}
public void setStepsColor(@ColorInt int stepsColor) {
this.stepsColor = stepsColor;
}
public float getStepsWidth() {
return stepsWidth;
}
public void setStepsWidth(float stepsWidth) {
this.stepsWidth = stepsWidth;
}
public float getStepsHeight() {
return stepsHeight;
}
public void setStepsHeight(float stepsHeight) {
this.stepsHeight = stepsHeight;
}
public float getStepsRadius() {
return stepsRadius;
}
public void setStepsRadius(float stepsRadius) {
this.stepsRadius = stepsRadius;
}
public int getTickMarkLayoutGravity() {
return tickMarkLayoutGravity;
}
/**
* the tick mark layout gravity
* Gravity.TOP and Gravity.BOTTOM
*
* @param tickMarkLayoutGravity
*/
public void setTickMarkLayoutGravity(@TickMarkLayoutGravityDef int tickMarkLayoutGravity) {
this.tickMarkLayoutGravity = tickMarkLayoutGravity;
}
public int getGravity() {
return gravity;
}
/**
* the RangeSeekBar gravity
* Gravity.TOP and Gravity.BOTTOM
*
* @param gravity
*/
public void setGravity(@GravityDef int gravity) {
this.gravity = gravity;
}
public boolean isStepsAutoBonding() {
return stepsAutoBonding;
}
public void setStepsAutoBonding(boolean stepsAutoBonding) {
this.stepsAutoBonding = stepsAutoBonding;
}
public int getStepsDrawableId() {
return stepsDrawableId;
}
public void setStepsDrawableId(@DrawableRes int stepsDrawableId) {
this.stepsBitmaps.clear();
this.stepsDrawableId = stepsDrawableId;
initStepsBitmap();
}
public List<Bitmap> getStepsBitmaps() {
return stepsBitmaps;
}
public void setStepsBitmaps(List<Bitmap> stepsBitmaps) {
if (stepsBitmaps == null || stepsBitmaps.isEmpty() || stepsBitmaps.size() <= steps) {
throw new IllegalArgumentException("stepsBitmaps must > steps !");
}
this.stepsBitmaps.clear();
this.stepsBitmaps.addAll(stepsBitmaps);
}
public void setStepsDrawable(List<Integer> stepsDrawableIds) {
if (stepsDrawableIds == null || stepsDrawableIds.isEmpty() || stepsDrawableIds.size() <= steps) {
throw new IllegalArgumentException("stepsDrawableIds must > steps !");
}
if (!verifyStepsMode()) {
throw new IllegalArgumentException("stepsWidth must > 0, stepsHeight must > 0,steps must > 0 First!!");
}
List<Bitmap> stepsBitmaps = new ArrayList<>();
for (int i = 0; i < stepsDrawableIds.size(); i++) {
stepsBitmaps.add(Utils.drawableToBitmap(getContext(), (int) stepsWidth, (int) stepsHeight, stepsDrawableIds.get(i)));
}
setStepsBitmaps(stepsBitmaps);
}
/**
* @hide
*/
@IntDef({SEEKBAR_MODE_SINGLE, SEEKBAR_MODE_RANGE})
@Retention(RetentionPolicy.SOURCE)
public @interface SeekBarModeDef {
}
/**
* @hide
*/
@IntDef({TRICK_MARK_MODE_NUMBER, TRICK_MARK_MODE_OTHER})
@Retention(RetentionPolicy.SOURCE)
public @interface TickMarkModeDef {
}
/**
* @hide
*/
@IntDef({TICK_MARK_GRAVITY_LEFT, TICK_MARK_GRAVITY_CENTER, TICK_MARK_GRAVITY_RIGHT})
@Retention(RetentionPolicy.SOURCE)
public @interface TickMarkGravityDef {
}
/**
* @hide
*/
@IntDef({Gravity.TOP, Gravity.BOTTOM})
@Retention(RetentionPolicy.SOURCE)
public @interface TickMarkLayoutGravityDef {
}
/**
* @hide
*/
@IntDef({Gravity.TOP, Gravity.CENTER, Gravity.BOTTOM})
@Retention(RetentionPolicy.SOURCE)
public @interface GravityDef {
}
public static class Gravity {
public final static int TOP = 0;
public final static int BOTTOM = 1;
public final static int CENTER = 2;
}
}
package com.yidianling.consultant.ui.view.rangeseekbar;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.View;
/**
* ================================================
* 作 者:JayGoo
* 版 本:
* 创建日期:2018/5/8
* 描 述:
* ================================================
*/
public class SavedState extends View.BaseSavedState {
public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
public float minValue;
public float maxValue;
public float rangeInterval;
public int tickNumber;
public float currSelectedMin;
public float currSelectedMax;
public SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
minValue = in.readFloat();
maxValue = in.readFloat();
rangeInterval = in.readFloat();
tickNumber = in.readInt();
currSelectedMin = in.readFloat();
currSelectedMax = in.readFloat();
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeFloat(minValue);
out.writeFloat(maxValue);
out.writeFloat(rangeInterval);
out.writeInt(tickNumber);
out.writeFloat(currSelectedMin);
out.writeFloat(currSelectedMax);
}
}
package com.yidianling.consultant.ui.view.rangeseekbar;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.IntDef;
import androidx.core.content.ContextCompat;
import com.yidianling.consultant.R;
import java.text.DecimalFormat;
/**
* ================================================
* 作 者:JayGoo
* 版 本:
* 创建日期:2018/5/8
* 描 述:
* ================================================
*/
public class SeekBar {
//the indicator show mode
public static final int INDICATOR_SHOW_WHEN_TOUCH = 0;
public static final int INDICATOR_ALWAYS_HIDE = 1;
public static final int INDICATOR_ALWAYS_SHOW_AFTER_TOUCH = 2;
public static final int INDICATOR_ALWAYS_SHOW = 3;
public static final int WRAP_CONTENT = -1;
public static final int MATCH_PARENT = -2;
//when you touch or move, the thumb will scale, default not scale
float thumbScaleRatio;
int left, right, top, bottom;
float currPercent;
float material = 0;
boolean isLeft;
Bitmap thumbBitmap;
Bitmap thumbInactivatedBitmap;
Bitmap indicatorBitmap;
ValueAnimator anim;
String userText2Draw;
boolean isActivate = false;
boolean isVisible = true;
RangeSeekBar rangeSeekBar;
String indicatorTextStringFormat;
Path indicatorArrowPath = new Path();
Rect indicatorTextRect = new Rect();
Rect indicatorRect = new Rect();
//****************** the above is attr value ******************//
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
DecimalFormat indicatorTextDecimalFormat;
int scaleThumbWidth;
int scaleThumbHeight;
private int indicatorShowMode;
//进度提示背景的高度,宽度如果是0的话会自适应调整
//Progress prompted the background height, width,
private int indicatorHeight;
private int indicatorWidth;
//进度提示背景与按钮之间的距离
//The progress indicates the distance between the background and the button
private int indicatorMargin;
private int indicatorDrawableId;
private int indicatorArrowSize;
private int indicatorTextSize;
private int indicatorTextColor;
private float indicatorRadius;
private int indicatorBackgroundColor;
private int indicatorPaddingLeft, indicatorPaddingRight, indicatorPaddingTop, indicatorPaddingBottom;
private int thumbDrawableId;
private int thumbInactivatedDrawableId;
private int thumbWidth;
private int thumbHeight;
private boolean isShowIndicator;
public SeekBar(RangeSeekBar rangeSeekBar, AttributeSet attrs, boolean isLeft) {
this.rangeSeekBar = rangeSeekBar;
this.isLeft = isLeft;
initAttrs(attrs);
initBitmap();
initVariables();
}
private void initAttrs(AttributeSet attrs) {
TypedArray t = getContext().obtainStyledAttributes(attrs, R.styleable.RangeSeekBar);
if (t == null) return;
indicatorMargin = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_indicator_margin, 0);
indicatorDrawableId = t.getResourceId(R.styleable.RangeSeekBar_rsb_indicator_drawable, 0);
indicatorShowMode = t.getInt(R.styleable.RangeSeekBar_rsb_indicator_show_mode, INDICATOR_ALWAYS_HIDE);
indicatorHeight = t.getLayoutDimension(R.styleable.RangeSeekBar_rsb_indicator_height, WRAP_CONTENT);
indicatorWidth = t.getLayoutDimension(R.styleable.RangeSeekBar_rsb_indicator_width, WRAP_CONTENT);
indicatorTextSize = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_indicator_text_size, Utils.dp2px(getContext(), 14));
indicatorTextColor = t.getColor(R.styleable.RangeSeekBar_rsb_indicator_text_color, Color.WHITE);
indicatorBackgroundColor = t.getColor(R.styleable.RangeSeekBar_rsb_indicator_background_color, ContextCompat.getColor(getContext(), R.color.colorAccent));
indicatorPaddingLeft = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_indicator_padding_left, 0);
indicatorPaddingRight = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_indicator_padding_right, 0);
indicatorPaddingTop = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_indicator_padding_top, 0);
indicatorPaddingBottom = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_indicator_padding_bottom, 0);
indicatorArrowSize = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_indicator_arrow_size, 0);
thumbDrawableId = t.getResourceId(R.styleable.RangeSeekBar_rsb_thumb_drawable, R.drawable.rsb_default_thumb);
thumbInactivatedDrawableId = t.getResourceId(R.styleable.RangeSeekBar_rsb_thumb_inactivated_drawable, 0);
thumbWidth = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_thumb_width, Utils.dp2px(getContext(), 26));
thumbHeight = (int) t.getDimension(R.styleable.RangeSeekBar_rsb_thumb_height, Utils.dp2px(getContext(), 26));
thumbScaleRatio = t.getFloat(R.styleable.RangeSeekBar_rsb_thumb_scale_ratio, 1f);
indicatorRadius = t.getDimension(R.styleable.RangeSeekBar_rsb_indicator_radius, 0f);
t.recycle();
}
protected void initVariables() {
scaleThumbWidth = thumbWidth;
scaleThumbHeight = thumbHeight;
if (indicatorHeight == WRAP_CONTENT) {
indicatorHeight = Utils.measureText("8", indicatorTextSize).height() + indicatorPaddingTop + indicatorPaddingBottom;
}
if (indicatorArrowSize <= 0) {
indicatorArrowSize = (int) (thumbWidth / 4);
}
}
public Context getContext() {
return rangeSeekBar.getContext();
}
public Resources getResources() {
if (getContext() != null) return getContext().getResources();
return null;
}
/**
* 初始化进度提示的背景
*/
private void initBitmap() {
setIndicatorDrawableId(indicatorDrawableId);
setThumbDrawableId(thumbDrawableId, thumbWidth, thumbHeight);
setThumbInactivatedDrawableId(thumbInactivatedDrawableId, thumbWidth, thumbHeight);
}
/**
* 计算每个按钮的位置和尺寸
* Calculates the position and size of each button
*
* @param x position x
* @param y position y
*/
protected void onSizeChanged(int x, int y) {
initVariables();
initBitmap();
left = (int) (x - getThumbScaleWidth() / 2);
right = (int) (x + getThumbScaleWidth() / 2);
top = y - getThumbHeight() / 2;
bottom = y + getThumbHeight() / 2;
}
public void scaleThumb() {
scaleThumbWidth = (int) getThumbScaleWidth();
scaleThumbHeight = (int) getThumbScaleHeight();
int y = rangeSeekBar.getProgressBottom();
top = y - scaleThumbHeight / 2;
bottom = y + scaleThumbHeight / 2;
setThumbDrawableId(thumbDrawableId, scaleThumbWidth, scaleThumbHeight);
}
public void resetThumb() {
scaleThumbWidth = getThumbWidth();
scaleThumbHeight = getThumbHeight();
int y = rangeSeekBar.getProgressBottom();
top = y - scaleThumbHeight / 2;
bottom = y + scaleThumbHeight / 2;
setThumbDrawableId(thumbDrawableId, scaleThumbWidth, scaleThumbHeight);
}
public float getRawHeight() {
return getIndicatorHeight() + getIndicatorArrowSize() + getIndicatorMargin() + getThumbScaleHeight();
}
/**
* 绘制按钮和提示背景和文字
* Draw buttons and tips for background and text
*
* @param canvas Canvas
*/
protected void draw(Canvas canvas) {
if (!isVisible) {
return;
}
int offset = (int) (rangeSeekBar.getProgressWidth() * currPercent);
canvas.save();
canvas.translate(offset, 0);
// translate canvas, then don't care left
canvas.translate(left, 0);
if (isShowIndicator) {
onDrawIndicator(canvas, paint, formatCurrentIndicatorText(userText2Draw));
}
onDrawThumb(canvas);
canvas.restore();
}
/**
* 绘制按钮
* 如果没有图片资源,则绘制默认按钮
* <p>
* draw the thumb button
* If there is no image resource, draw the default button
*
* @param canvas canvas
*/
protected void onDrawThumb(Canvas canvas) {
if (thumbInactivatedBitmap != null && !isActivate) {
canvas.drawBitmap(thumbInactivatedBitmap, 0, rangeSeekBar.getProgressTop() + (rangeSeekBar.getProgressHeight() - scaleThumbHeight) / 2f, null);
} else if (thumbBitmap != null) {
canvas.drawBitmap(thumbBitmap, 0, rangeSeekBar.getProgressTop() + (rangeSeekBar.getProgressHeight() - scaleThumbHeight) / 2f, null);
}
}
/**
* 格式化提示文字
* format the indicator text
*
* @param text2Draw
* @return
*/
protected String formatCurrentIndicatorText(String text2Draw) {
SeekBarState[] states = rangeSeekBar.getRangeSeekBarState();
if (TextUtils.isEmpty(text2Draw)) {
if (isLeft) {
if (indicatorTextDecimalFormat != null) {
text2Draw = indicatorTextDecimalFormat.format(states[0].value);
} else {
text2Draw = states[0].indicatorText;
}
} else {
if (indicatorTextDecimalFormat != null) {
text2Draw = indicatorTextDecimalFormat.format(states[1].value);
} else {
text2Draw = states[1].indicatorText;
}
}
}
if (indicatorTextStringFormat != null) {
text2Draw = String.format(indicatorTextStringFormat, text2Draw);
}
return text2Draw;
}
/**
* This method will draw the indicator background dynamically according to the text.
* you can use to set padding
*
* @param canvas Canvas
* @param text2Draw Indicator text
*/
protected void onDrawIndicator(Canvas canvas, Paint paint, String text2Draw) {
if (text2Draw == null) return;
paint.setTextSize(indicatorTextSize);
paint.setStyle(Paint.Style.FILL);
paint.setColor(indicatorBackgroundColor);
paint.getTextBounds(text2Draw, 0, text2Draw.length(), indicatorTextRect);
int realIndicatorWidth = indicatorTextRect.width() + indicatorPaddingLeft + indicatorPaddingRight;
if (indicatorWidth > realIndicatorWidth) {
realIndicatorWidth = indicatorWidth;
}
int realIndicatorHeight = indicatorTextRect.height() + indicatorPaddingTop + indicatorPaddingBottom;
if (indicatorHeight > realIndicatorHeight) {
realIndicatorHeight = indicatorHeight;
}
indicatorRect.left = (int) (scaleThumbWidth / 2f - realIndicatorWidth / 2f);
indicatorRect.top = bottom - realIndicatorHeight - scaleThumbHeight - indicatorMargin;
indicatorRect.right = indicatorRect.left + realIndicatorWidth;
indicatorRect.bottom = indicatorRect.top + realIndicatorHeight;
//draw default indicator arrow
if (indicatorBitmap == null) {
//arrow three point
// b c
// a
int ax = scaleThumbWidth / 2;
int ay = indicatorRect.bottom;
int bx = ax - indicatorArrowSize;
int by = ay - indicatorArrowSize;
int cx = ax + indicatorArrowSize;
indicatorArrowPath.reset();
indicatorArrowPath.moveTo(ax, ay);
indicatorArrowPath.lineTo(bx, by);
indicatorArrowPath.lineTo(cx, by);
indicatorArrowPath.close();
canvas.drawPath(indicatorArrowPath, paint);
indicatorRect.bottom -= indicatorArrowSize;
indicatorRect.top -= indicatorArrowSize;
}
//indicator background edge processing
int defaultPaddingOffset = Utils.dp2px(getContext(), 1);
int leftOffset = indicatorRect.width() / 2 - (int) (rangeSeekBar.getProgressWidth() * currPercent) - rangeSeekBar.getProgressLeft() + defaultPaddingOffset;
int rightOffset = indicatorRect.width() / 2 - (int) (rangeSeekBar.getProgressWidth() * (1 - currPercent)) - rangeSeekBar.getProgressPaddingRight() + defaultPaddingOffset;
if (leftOffset > 0) {
indicatorRect.left += leftOffset;
indicatorRect.right += leftOffset;
} else if (rightOffset > 0) {
indicatorRect.left -= rightOffset;
indicatorRect.right -= rightOffset;
}
//draw indicator background
if (indicatorBitmap != null) {
Utils.drawBitmap(canvas, paint, indicatorBitmap, indicatorRect);
} else if (indicatorRadius > 0f) {
canvas.drawRoundRect(new RectF(indicatorRect), indicatorRadius, indicatorRadius, paint);
} else {
canvas.drawRect(indicatorRect, paint);
}
//draw indicator content text
int tx, ty;
if (indicatorPaddingLeft > 0) {
tx = indicatorRect.left + indicatorPaddingLeft;
} else if (indicatorPaddingRight > 0) {
tx = indicatorRect.right - indicatorPaddingRight - indicatorTextRect.width();
} else {
tx = indicatorRect.left + (realIndicatorWidth - indicatorTextRect.width()) / 2;
}
if (indicatorPaddingTop > 0) {
ty = indicatorRect.top + indicatorTextRect.height() + indicatorPaddingTop;
} else if (indicatorPaddingBottom > 0) {
ty = indicatorRect.bottom - indicatorTextRect.height() - indicatorPaddingBottom;
} else {
ty = indicatorRect.bottom - (realIndicatorHeight - indicatorTextRect.height()) / 2 + 1;
}
//draw indicator text
paint.setColor(indicatorTextColor);
canvas.drawText(text2Draw, tx, ty, paint);
}
/**
* 拖动检测
*
* @return is collide
*/
protected boolean collide(float x, float y) {
int offset = (int) (rangeSeekBar.getProgressWidth() * currPercent);
return x > left + offset && x < right + offset && y > top && y < bottom;
}
protected void slide(float percent) {
if (percent < 0) percent = 0;
else if (percent > 1) percent = 1;
currPercent = percent;
}
protected void setShowIndicatorEnable(boolean isEnable) {
switch (indicatorShowMode) {
case INDICATOR_SHOW_WHEN_TOUCH:
isShowIndicator = isEnable;
break;
case INDICATOR_ALWAYS_SHOW:
case INDICATOR_ALWAYS_SHOW_AFTER_TOUCH:
isShowIndicator = true;
break;
case INDICATOR_ALWAYS_HIDE:
isShowIndicator = false;
break;
}
}
public void materialRestore() {
if (anim != null) anim.cancel();
anim = ValueAnimator.ofFloat(material, 0);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
material = (float) animation.getAnimatedValue();
if (rangeSeekBar != null) rangeSeekBar.invalidate();
}
});
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
material = 0;
if (rangeSeekBar != null) rangeSeekBar.invalidate();
}
});
anim.start();
}
public void setIndicatorText(String text) {
userText2Draw = text;
}
public DecimalFormat getIndicatorTextDecimalFormat() {
return indicatorTextDecimalFormat;
}
public void setIndicatorTextDecimalFormat(String formatPattern) {
indicatorTextDecimalFormat = new DecimalFormat(formatPattern);
}
public void setIndicatorTextStringFormat(String formatPattern) {
indicatorTextStringFormat = formatPattern;
}
public int getIndicatorDrawableId() {
return indicatorDrawableId;
}
public void setIndicatorDrawableId(@DrawableRes int indicatorDrawableId) {
if (indicatorDrawableId != 0) {
this.indicatorDrawableId = indicatorDrawableId;
indicatorBitmap = BitmapFactory.decodeResource(getResources(), indicatorDrawableId);
}
}
public int getIndicatorArrowSize() {
return indicatorArrowSize;
}
public void setIndicatorArrowSize(int indicatorArrowSize) {
this.indicatorArrowSize = indicatorArrowSize;
}
public int getIndicatorPaddingLeft() {
return indicatorPaddingLeft;
}
public void setIndicatorPaddingLeft(int indicatorPaddingLeft) {
this.indicatorPaddingLeft = indicatorPaddingLeft;
}
public int getIndicatorPaddingRight() {
return indicatorPaddingRight;
}
public void setIndicatorPaddingRight(int indicatorPaddingRight) {
this.indicatorPaddingRight = indicatorPaddingRight;
}
public int getIndicatorPaddingTop() {
return indicatorPaddingTop;
}
public void setIndicatorPaddingTop(int indicatorPaddingTop) {
this.indicatorPaddingTop = indicatorPaddingTop;
}
public int getIndicatorPaddingBottom() {
return indicatorPaddingBottom;
}
public void setIndicatorPaddingBottom(int indicatorPaddingBottom) {
this.indicatorPaddingBottom = indicatorPaddingBottom;
}
public int getIndicatorMargin() {
return indicatorMargin;
}
public void setIndicatorMargin(int indicatorMargin) {
this.indicatorMargin = indicatorMargin;
}
public int getIndicatorShowMode() {
return indicatorShowMode;
}
/**
* the indicator show mode
* {@link #INDICATOR_SHOW_WHEN_TOUCH}
* {@link #INDICATOR_ALWAYS_SHOW}
* {@link #INDICATOR_ALWAYS_SHOW_AFTER_TOUCH}
* {@link #INDICATOR_ALWAYS_SHOW}
*
* @param indicatorShowMode
*/
public void setIndicatorShowMode(@IndicatorModeDef int indicatorShowMode) {
this.indicatorShowMode = indicatorShowMode;
}
public void showIndicator(boolean isShown) {
isShowIndicator = isShown;
}
public boolean isShowIndicator() {
return isShowIndicator;
}
/**
* include indicator text Height、padding、margin
*
* @return The actual occupation height of indicator
*/
public int getIndicatorRawHeight() {
if (indicatorHeight > 0) {
if (indicatorBitmap != null) {
return indicatorHeight + indicatorMargin;
} else {
return indicatorHeight + indicatorArrowSize + indicatorMargin;
}
} else {
if (indicatorBitmap != null) {
return Utils.measureText("8", indicatorTextSize).height() + indicatorPaddingTop + indicatorPaddingBottom + indicatorMargin;
} else {
return Utils.measureText("8", indicatorTextSize).height() + indicatorPaddingTop + indicatorPaddingBottom + indicatorMargin + indicatorArrowSize;
}
}
}
public int getIndicatorHeight() {
return indicatorHeight;
}
public void setIndicatorHeight(int indicatorHeight) {
this.indicatorHeight = indicatorHeight;
}
public int getIndicatorWidth() {
return indicatorWidth;
}
public void setIndicatorWidth(int indicatorWidth) {
this.indicatorWidth = indicatorWidth;
}
public int getIndicatorTextSize() {
return indicatorTextSize;
}
public void setIndicatorTextSize(int indicatorTextSize) {
this.indicatorTextSize = indicatorTextSize;
}
public int getIndicatorTextColor() {
return indicatorTextColor;
}
public void setIndicatorTextColor(@ColorInt int indicatorTextColor) {
this.indicatorTextColor = indicatorTextColor;
}
public int getIndicatorBackgroundColor() {
return indicatorBackgroundColor;
}
public void setIndicatorBackgroundColor(@ColorInt int indicatorBackgroundColor) {
this.indicatorBackgroundColor = indicatorBackgroundColor;
}
public int getThumbInactivatedDrawableId() {
return thumbInactivatedDrawableId;
}
public void setThumbInactivatedDrawableId(@DrawableRes int thumbInactivatedDrawableId, int width, int height) {
if (thumbInactivatedDrawableId != 0 && getResources() != null) {
this.thumbInactivatedDrawableId = thumbInactivatedDrawableId;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
thumbInactivatedBitmap = Utils.drawableToBitmap(width, height, getResources().getDrawable(thumbInactivatedDrawableId, null));
} else {
thumbInactivatedBitmap = Utils.drawableToBitmap(width, height, getResources().getDrawable(thumbInactivatedDrawableId));
}
}
}
public int getThumbDrawableId() {
return thumbDrawableId;
}
public void setThumbDrawableId(@DrawableRes int thumbDrawableId) {
if (thumbWidth <= 0 || thumbHeight <= 0) {
throw new IllegalArgumentException("please set thumbWidth and thumbHeight first!");
}
if (thumbDrawableId != 0 && getResources() != null) {
this.thumbDrawableId = thumbDrawableId;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
thumbBitmap = Utils.drawableToBitmap(thumbWidth, thumbHeight, getResources().getDrawable(thumbDrawableId, null));
} else {
thumbBitmap = Utils.drawableToBitmap(thumbWidth, thumbHeight, getResources().getDrawable(thumbDrawableId));
}
}
}
public void setThumbDrawableId(@DrawableRes int thumbDrawableId, int width, int height) {
if (thumbDrawableId != 0 && getResources() != null && width > 0 && height > 0) {
this.thumbDrawableId = thumbDrawableId;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
thumbBitmap = Utils.drawableToBitmap(width, height, getResources().getDrawable(thumbDrawableId, null));
} else {
thumbBitmap = Utils.drawableToBitmap(width, height, getResources().getDrawable(thumbDrawableId));
}
}
}
public int getThumbWidth() {
return thumbWidth;
}
public void setThumbWidth(int thumbWidth) {
this.thumbWidth = thumbWidth;
}
public float getThumbScaleHeight() {
return thumbHeight * thumbScaleRatio;
}
public float getThumbScaleWidth() {
return thumbWidth * thumbScaleRatio;
}
public int getThumbHeight() {
return thumbHeight;
}
public void setThumbHeight(int thumbHeight) {
this.thumbHeight = thumbHeight;
}
public float getIndicatorRadius() {
return indicatorRadius;
}
public void setIndicatorRadius(float indicatorRadius) {
this.indicatorRadius = indicatorRadius;
}
protected boolean getActivate() {
return isActivate;
}
protected void setActivate(boolean activate) {
isActivate = activate;
}
public void setTypeface(Typeface typeFace) {
paint.setTypeface(typeFace);
}
/**
* when you touch or move, the thumb will scale, default not scale
*
* @return default 1.0f
*/
public float getThumbScaleRatio() {
return thumbScaleRatio;
}
public boolean isVisible() {
return isVisible;
}
/**
* if visble is false, will clear the Canvas
*
* @param visible
*/
public void setVisible(boolean visible) {
isVisible = visible;
}
public float getProgress() {
float range = rangeSeekBar.getMaxProgress() - rangeSeekBar.getMinProgress();
return rangeSeekBar.getMinProgress() + range * currPercent;
}
@IntDef({INDICATOR_SHOW_WHEN_TOUCH, INDICATOR_ALWAYS_HIDE, INDICATOR_ALWAYS_SHOW_AFTER_TOUCH, INDICATOR_ALWAYS_SHOW})
public @interface IndicatorModeDef {
}
}
package com.yidianling.consultant.ui.view.rangeseekbar;
/**
* ================================================
* 作 者:JayGoo
* 版 本:
* 创建日期:2018/5/9
* 描 述: it works for draw indicator text
* ================================================
*/
public class SeekBarState {
public String indicatorText;
public float value; //now progress value
public boolean isMin;
public boolean isMax;
@Override
public String toString() {
return "indicatorText: " + indicatorText + " ,isMin: " + isMin + " ,isMax: " + isMax;
}
}
package com.yidianling.consultant.ui.view.rangeseekbar;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.NinePatch;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.Log;
import androidx.annotation.ColorRes;
import androidx.core.content.ContextCompat;
/**
* ================================================
* 作 者:JayGoo
* 版 本:
* 创建日期:2018/5/8
* 描 述:
* ================================================
*/
public class Utils {
private static final String TAG = "RangeSeekBar";
public static void print(String log) {
Log.d(TAG, log);
}
public static void print(Object... logs) {
StringBuilder stringBuilder = new StringBuilder();
for (Object log : logs) {
stringBuilder.append(log);
}
Log.d(TAG, stringBuilder.toString());
}
public static Bitmap drawableToBitmap(Context context, int width, int height, int drawableId) {
if (context == null || width <= 0 || height <= 0 || drawableId == 0) return null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return Utils.drawableToBitmap(width, height, context.getResources().getDrawable(drawableId, null));
} else {
return Utils.drawableToBitmap(width, height, context.getResources().getDrawable(drawableId));
}
}
/**
* make a drawable to a bitmap
*
* @param drawable drawable you want convert
* @return converted bitmap
*/
public static Bitmap drawableToBitmap(int width, int height, Drawable drawable) {
Bitmap bitmap = null;
try {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
bitmap = bitmapDrawable.getBitmap();
if (bitmap != null && bitmap.getHeight() > 0) {
Matrix matrix = new Matrix();
float scaleWidth = width * 1.0f / bitmap.getWidth();
float scaleHeight = height * 1.0f / bitmap.getHeight();
matrix.postScale(scaleWidth, scaleHeight);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return bitmap;
}
}
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
/**
* draw 9Path
*
* @param canvas Canvas
* @param bmp 9path bitmap
* @param rect 9path rect
*/
public static void drawNinePath(Canvas canvas, Bitmap bmp, Rect rect) {
NinePatch.isNinePatchChunk(bmp.getNinePatchChunk());
NinePatch patch = new NinePatch(bmp, bmp.getNinePatchChunk(), null);
patch.draw(canvas, rect);
}
public static void drawBitmap(Canvas canvas, Paint paint, Bitmap bmp, Rect rect) {
try {
if (NinePatch.isNinePatchChunk(bmp.getNinePatchChunk())) {
drawNinePath(canvas, bmp, rect);
return;
}
} catch (Exception e) {
}
canvas.drawBitmap(bmp, rect.left, rect.top, paint);
}
public static int dp2px(Context context, float dpValue) {
if (context == null || compareFloat(0f, dpValue) == 0) return 0;
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* Compare the size of two floating point numbers
*
* @param a
* @param b
* @return 1 is a > b
* -1 is a < b
* 0 is a == b
*/
public static int compareFloat(float a, float b) {
int ta = Math.round(a * 1000000);
int tb = Math.round(b * 1000000);
if (ta > tb) {
return 1;
} else if (ta < tb) {
return -1;
} else {
return 0;
}
}
/**
* Compare the size of two floating point numbers with accuracy
*
* @param a
* @param b
* @return 1 is a > b
* -1 is a < b
* 0 is a == b
*/
public static int compareFloat(float a, float b, int degree) {
if (Math.abs(a - b) < Math.pow(0.1, degree)) {
return 0;
} else {
if (a < b) {
return -1;
} else {
return 1;
}
}
}
public static float parseFloat(String s) {
try {
return Float.parseFloat(s);
} catch (NumberFormatException e) {
return 0f;
}
}
public static Rect measureText(String text, float textSize) {
Paint paint = new Paint();
Rect textRect = new Rect();
paint.setTextSize(textSize);
paint.getTextBounds(text, 0, text.length(), textRect);
paint.reset();
return textRect;
}
public static boolean verifyBitmap(Bitmap bitmap) {
if (bitmap == null || bitmap.isRecycled() || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
return false;
}
return true;
}
public static int getColor(Context context, @ColorRes int colorId) {
if (context != null) {
return ContextCompat.getColor(context.getApplicationContext(), colorId);
}
return Color.WHITE;
}
}
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/platform_color_F7F7F7" />
<corners android:radius="4dp" />
</shape>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#1DA1F2"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="@dimen/dp_4" />
<solid android:color="@color/platform_main_theme_bright" />
<stroke
android:width="0.5dp"
android:color="@color/platform_main_theme" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/platform_gray7" />
<stroke
android:width="1dp"
android:color="@color/platform_gray7" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/white" />
<stroke
android:width="2dp"
android:color="@color/platform_main_theme" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -2,13 +2,22 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="?android:attr/selectableItemBackground"
android:layout_height="wrap_content"
android:background="@color/white"
android:gravity="center_vertical"
android:paddingTop="@dimen/platform_dp_15"
android:paddingBottom="@dimen/platform_dp_15"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<ImageView
android:id="@+id/location_img"
android:layout_width="@dimen/platform_dp_15"
android:layout_height="@dimen/platform_dp_15"
android:src="@drawable/consultant_baseline_location_on_24"
android:visibility="gone" />
<TextView
android:id="@+id/tvConsultTypeName"
android:layout_width="0dp"
......@@ -16,14 +25,24 @@
android:layout_weight="1"
android:textColor="@color/platform_color_black_333333"
android:textSize="14sp"
android:includeFontPadding="false"
tools:text="咨询方式" />
<TextView
android:id="@+id/reLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="授权"
android:textColor="@color/platform_main_theme"
android:textSize="@dimen/platform_sp_14"
android:visibility="gone" />
<ImageView
android:id="@+id/ivCheckCircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/consultant_ic_check"
android:visibility="invisible"/>
android:visibility="invisible" />
</LinearLayout>
......@@ -14,5 +14,5 @@
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:textColor="@color/consultant_color_search_filter_selector"
android:textSize="13dp"
android:textSize="14sp"
tools:text="按专家显示" />
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:background="@color/platform_white">
android:background="@color/platform_color_F7F7F7">
<View
android:id="@+id/view_select"
android:layout_width="4dp"
android:layout_height="21dp"
android:layout_gravity="center_vertical"
android:background="@color/platform_main_theme"
android:visibility="invisible"/>
android:visibility="invisible" />
<TextView
android:id="@+id/tvRegionName"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:paddingTop="@dimen/platform_dp_15"
android:paddingBottom="@dimen/platform_dp_15"
android:gravity="center"
android:text="地区"
android:textColor="@color/platform_default_text_color"
......
......@@ -31,6 +31,8 @@
android:layout_width="0dp"
android:layout_weight="1"
android:width="0dp"
android:ellipsize="end"
android:singleLine="true"
android:drawableEnd="@drawable/platform_ic_arrow_drop_down_grey_500_18dp"
android:drawableRight="@drawable/platform_ic_arrow_drop_down_grey_500_18dp"
android:text="困扰"
......@@ -44,7 +46,7 @@
android:width="0dp"
android:drawableEnd="@drawable/platform_ic_arrow_drop_down_grey_500_18dp"
android:drawableRight="@drawable/platform_ic_arrow_drop_down_grey_500_18dp"
android:text="@string/platform_area"
android:text="城市"
android:textColor="@color/platform_color_242424" />
<com.ydl.ydlcommon.view.DrawableRightTextView
......@@ -55,7 +57,7 @@
android:width="0dp"
android:drawableEnd="@drawable/platform_ic_arrow_drop_down_grey_500_18dp"
android:drawableRight="@drawable/platform_ic_arrow_drop_down_grey_500_18dp"
android:text="@string/platform_sort"
android:text="价格"
android:textColor="@color/platform_color_242424" />
<com.ydl.ydlcommon.view.DrawableRightTextView
......@@ -64,8 +66,8 @@
android:layout_width="0dp"
android:layout_weight="1"
android:width="0dp"
android:drawableEnd="@drawable/platform_ic_arrow_drop_down_grey_500_18dp"
android:drawableRight="@drawable/platform_ic_arrow_drop_down_grey_500_18dp"
android:drawableEnd="@drawable/filter_up_grey"
android:drawableRight="@drawable/filter_up_grey"
android:text="@string/platform_filter"
android:textColor="@color/platform_color_242424" />
</LinearLayout>
......
......@@ -19,7 +19,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginStart="@dimen/platform_dp_10"
android:orientation="vertical">
<TextView
......@@ -44,13 +44,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/platform_dp_28"
android:text="咨询方式"
android:text="排序"
android:layout_marginStart="@dimen/platform_dp_4"
android:textColor="@color/platform_color_242424"
android:textSize="@dimen/platform_dp_16"
android:textStyle="bold" />
<FrameLayout
android:id="@+id/flEnquiryType"
android:id="@+id/flSortType"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp" />
......@@ -59,22 +60,23 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/platform_dp_28"
android:text="价格"
android:text="咨询方式"
android:layout_marginStart="@dimen/platform_dp_4"
android:textColor="@color/platform_color_242424"
android:textSize="@dimen/platform_dp_16"
android:textStyle="bold" />
<FrameLayout
android:id="@+id/flPriceRange"
android:id="@+id/flEnquiryType"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/platform_dp_28"
android:text="年龄选择"
android:layout_marginStart="@dimen/platform_dp_4"
android:textColor="@color/platform_color_242424"
android:textSize="@dimen/platform_dp_16"
android:textStyle="bold" />
......@@ -90,6 +92,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/platform_dp_28"
android:text="资质选择"
android:layout_marginStart="@dimen/platform_dp_4"
android:textColor="@color/platform_color_242424"
android:textSize="@dimen/platform_dp_16"
android:textStyle="bold" />
......@@ -109,6 +112,7 @@
android:text="擅长人群"
android:textColor="@color/platform_color_242424"
android:textSize="16sp"
android:layout_marginStart="@dimen/platform_dp_4"
android:textStyle="bold" />
<cn.lankton.flowlayout.FlowLayout
......@@ -126,6 +130,7 @@
android:text="学历选择"
android:textColor="@color/platform_color_242424"
android:textSize="@dimen/platform_dp_16"
android:layout_marginStart="@dimen/platform_dp_4"
android:textStyle="bold" />
<FrameLayout
......@@ -169,6 +174,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/platform_dp_28"
android:text="其他选择"
android:layout_marginStart="@dimen/platform_dp_4"
android:textColor="@color/platform_color_242424"
android:textSize="@dimen/platform_dp_16"
android:textStyle="bold" />
......@@ -182,6 +188,7 @@
</LinearLayout>
</ScrollView>
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:paddingTop="@dimen/platform_dp_15">
<FrameLayout
android:id="@+id/flPriceRangeView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="50dp"
android:paddingStart="@dimen/platform_dp_12"
android:paddingEnd="@dimen/platform_dp_12"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_start_end_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0-不限"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="@dimen/platform_dp_30"
android:textColor="@color/platform_color_black_333333"
android:textSize="@dimen/platform_sp_14"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/flPriceRangeView" />
<com.yidianling.consultant.ui.view.rangeseekbar.RangeSeekBar
android:id="@+id/range_price_seekbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/platform_dp_12"
android:layout_marginEnd="@dimen/platform_dp_12"
android:layout_marginTop="@dimen/platform_dp_15"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_start_end_price"
app:rsb_gravity="bottom"
app:rsb_mode="range"
app:rsb_progress_color="@color/platform_main_theme"
app:rsb_step_auto_bonding="true"
app:rsb_step_color="@color/platform_gray7"
app:rsb_step_height="5dp"
app:rsb_step_width="0.5dp"
app:rsb_steps="6"
app:rsb_thumb_drawable="@drawable/thumb_yellow_stroke"
app:rsb_thumb_height="15dp"
app:rsb_thumb_width="15dp"
app:rsb_tick_mark_layout_gravity="bottom"
app:rsb_tick_mark_mode="other"
app:rsb_tick_mark_text_array="@array/wordsArray"
app:rsb_tick_mark_text_margin="20dp" />
<View
android:id="@+id/seperate_line"
android:layout_width="wrap_content"
android:layout_height="0.5dp"
android:layout_marginTop="@dimen/platform_dp_30"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/range_price_seekbar"></View>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="68dp"
android:layout_marginTop="@dimen/platform_dp_8"
android:background="@color/white"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:paddingEnd="16dp"
app:layout_constraintTop_toBottomOf="@id/seperate_line">
<TextView
android:id="@+id/price_reset"
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_weight="1"
android:background="@drawable/consultant_stroke_ebebeb_r_8"
android:gravity="center"
android:text="@string/platform_reset"
android:textColor="@color/platform_color_242424"
android:textSize="16sp" />
<TextView
android:id="@+id/price_Confirm"
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_marginStart="13dp"
android:layout_weight="1"
android:background="@drawable/consultant_solid_main_theme_color_r_8"
android:gravity="center"
android:text="@string/platform_confirm"
android:textColor="@color/white"
android:textSize="16sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -8,16 +8,15 @@
android:id="@+id/rvRegion"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@color/platform_white"
android:background="@color/platform_color_F7F7F7"
android:layout_weight="1"
android:paddingTop="10dp"
android:overScrollMode="never"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvSub"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@color/platform_color_F7F7F7"
android:background="@color/white"
android:layout_weight="2"
android:paddingTop="10dp"
android:overScrollMode="never"/>
......
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="wordsArray">
<item>0</item>
<item>100</item>
<item>200</item>
<item>300</item>
<item>400</item>
<item>500</item>
<item>不限</item>
</string-array>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RangeSeekBar">
<!--RangeSeekBar common attrs-->
<!--The maximum-->
<attr name="rsb_max" format="float" />
<!--The minimum-->
<attr name="rsb_min" format="float" />
<!--RangeSeekBar mode, single is normal seekBar, range is RangeSeekBar-->
<attr name="rsb_mode" format="enum">
<enum name="single" value="1" />
<enum name="range" value="2" />
</attr>
<!--RangeSeekBar gravity-->
<attr name="rsb_gravity" format="enum">
<enum name="top" value="0" />
<enum name="bottom" value="1" />
<enum name="center" value="2" />
</attr>
<!--The min interval of the thumbs -->
<attr name="rsb_min_interval" format="float" />
<!-- 0 for the normal mode, greater than 1 to switch to scale mode-->
<attr name="rsb_tick_mark_number" format="integer" />
<!--Scale mode
Number according to the scale of the actual proportion of the distribution of the location (markTextArray must be a number)
Other bisects the current layout (markTextArray can be any character)
-->
<attr name="rsb_tick_mark_mode" format="enum">
<enum name="number" value="0" />
<enum name="other" value="1" />
</attr>
<!--The tick mark text gravity -->
<attr name="rsb_tick_mark_gravity" format="enum">
<enum name="left" value="0" />
<enum name="center" value="1" />
<enum name="right" value="2" />
</attr>
<!--The tick mark text layout gravity -->
<attr name="rsb_tick_mark_layout_gravity" format="enum">
<enum name="top" value="0" />
<enum name="bottom" value="1" />
</attr>
<!--The tick mark text array -->
<attr name="rsb_tick_mark_text_array" format="reference" />
<!--The tick mark text margin bottom to progress -->
<attr name="rsb_tick_mark_text_margin" format="dimension" />
<attr name="rsb_tick_mark_text_size" format="dimension" />
<attr name="rsb_tick_mark_text_color" format="color" />
<!--it just work in range && number mode now-->
<attr name="rsb_tick_mark_in_range_text_color" format="color" />
<attr name="rsb_progress_height" format="dimension" />
<attr name="rsb_progress_radius" format="dimension" />
<!--the color of progress bar when in progress-->
<attr name="rsb_progress_color" format="color" />
<!--the default color of the progress bar-->
<attr name="rsb_progress_default_color" format="color" />
<attr name="rsb_progress_drawable" format="reference" />
<attr name="rsb_progress_drawable_default" format="reference" />
<!--SeekBar attrs-->
<attr name="rsb_indicator_show_mode" format="enum">
<enum name="showWhenTouch" value="0" />
<enum name="alwaysHide" value="1" />
<enum name="alwaysShowAfterTouch" value="2" />
<enum name="alwaysShow" value="3" />
</attr>
<attr name="rsb_indicator_height" format="dimension">
<enum name="wrap_content" value="-1" />
</attr>
<attr name="rsb_indicator_width" format="dimension">
<enum name="wrap_content" value="-1" />
</attr>
<!--indicator margin bottom to progress bar-->
<attr name="rsb_indicator_margin" format="dimension" />
<attr name="rsb_indicator_text_size" format="dimension" />
<attr name="rsb_indicator_text_color" format="color" />
<!--indicator arrow size, it just work when you not use rsb_indicator_drawable -->
<attr name="rsb_indicator_arrow_size" format="dimension" />
<!-- must use 9 path !!!-->
<attr name="rsb_indicator_drawable" format="reference" />
<attr name="rsb_indicator_background_color" format="color" />
<attr name="rsb_indicator_padding_left" format="dimension" />
<attr name="rsb_indicator_padding_right" format="dimension" />
<attr name="rsb_indicator_padding_top" format="dimension" />
<attr name="rsb_indicator_padding_bottom" format="dimension" />
<attr name="rsb_indicator_radius" format="dimension" />
<attr name="rsb_thumb_drawable" format="reference" />
<!--the thumb inactivated is when you don't touch the thumb button-->
<attr name="rsb_thumb_inactivated_drawable" format="reference" />
<attr name="rsb_thumb_width" format="dimension" />
<attr name="rsb_thumb_height" format="dimension" />
<attr name="rsb_thumb_scale_ratio" format="float" />
<!--steps SeekBar-->
<attr name="rsb_steps" format="integer" />
<attr name="rsb_step_color" format="color" />
<attr name="rsb_step_width" format="dimension" />
<attr name="rsb_step_height" format="dimension" />
<attr name="rsb_step_radius" format="dimension" />
<attr name="rsb_step_auto_bonding" format="boolean" />
<attr name="rsb_step_drawable" format="reference" />
</declare-styleable>
<declare-styleable name="VerticalRangeSeekBar">
<!--the vertical RangeSeekBar draw orientation-->
<attr name="rsb_orientation" format="enum">
<enum name="left" value="1" />
<enum name="right" value="2" />
</attr>
<attr name="rsb_tick_mark_orientation" format="enum">
<enum name="vertical" value="1" />
<enum name="horizontal" value="2" />
</attr>
<attr name="rsb_indicator_text_orientation" format="enum">
<enum name="vertical" value="1" />
<enum name="horizontal" value="2" />
</attr>
</declare-styleable>
</resources>
......@@ -80,7 +80,9 @@ open class HomeBaseImpl : IHomeBaseEvent {
?: ""
)
if (!ModularServiceManager.provide(IUserService::class.java).loginByOneKeyLogin(mContext as Context,true)) {
if (!ModularServiceManager.provide(IUserService::class.java)
.loginByOneKeyLogin(mContext as Context, true)
) {
//跳转登录
return
}
......@@ -166,11 +168,18 @@ open class HomeBaseImpl : IHomeBaseEvent {
}
ActionCountUtils.count(HomeBIConstants.YDL_USER_TELEPHONE_CUSTOMER_SERVICE_CLICK)
val tel =
if (PlatformRamImpl.getInstance().getGlobalInfo() == null) "400-765-1010" else PlatformRamImpl.getInstance().getGlobalInfo()!!.info.tel
if (PlatformRamImpl.getInstance()
.getGlobalInfo() == null
) "400-765-1010" else PlatformRamImpl.getInstance().getGlobalInfo()!!.info.tel
var con = "\n400-765-1010\n早8:30-凌晨2:00"
if (PlatformRamImpl.getInstance().getGlobalInfo() != null && PlatformRamImpl.getInstance().getGlobalInfo()!!.info != null) {
if (PlatformRamImpl.getInstance()
.getGlobalInfo() != null && PlatformRamImpl.getInstance()
.getGlobalInfo()!!.info != null
) {
con =
PlatformRamImpl.getInstance().getGlobalInfo()?.info?.tel + "\n" + PlatformRamImpl.getInstance().getGlobalInfo()?.info?.work_time
PlatformRamImpl.getInstance()
.getGlobalInfo()?.info?.tel + "\n" + PlatformRamImpl.getInstance()
.getGlobalInfo()?.info?.work_time
}
val dialog = CommonDialog(mContext)
......@@ -232,7 +241,7 @@ open class HomeBaseImpl : IHomeBaseEvent {
}
override fun categoryClick(data: HomeHeaderBean.AskCategoryDataBean) {
override fun categoryClick(data: HomeHeaderBean.CategoryGoldListDataBean) {
// linkTo(data.url.toString())
if (Utils.isFastClick()) {
//防止连击
......@@ -240,18 +249,16 @@ open class HomeBaseImpl : IHomeBaseEvent {
}
ActionCountUtils.count(
HomeBIConstants.YDL_USER_CONSULT_CLASSIFICATION_CLICK,
data.cateId.toString(),
data.cateTitle
data.id.toString(),
data.title
?: ""
)
goExpertSearch(data)
}
private fun goExpertSearch(data: HomeHeaderBean.AskCategoryDataBean) {
if (!TextUtils.isEmpty(data.url) && data.url!!.endsWith("?")) {
data.url = data.url!!.substring(0, data.url!!.length - 1)
}
if ("全部类别" == data.cateTitle || "全部分类" == data.cateTitle) {
private fun goExpertSearch(data: HomeHeaderBean.CategoryGoldListDataBean) {
if ("全部类别" == data.title || "全部分类" == data.title) {
/*YDLRouterManager.router(
IYDLRouterConstant.ROUTER_H5_H5,
YDLRouterParams().putExtra(
......@@ -261,19 +268,20 @@ open class HomeBaseImpl : IHomeBaseEvent {
)*/
//因心理咨询迁移新系统,跳转咨询列表页
EventBus.getDefault().post(HomeModuleTabEvent(2))
} else if (data.goType.equals("h5")) {
NewH5Activity.start(mContext, H5Params(data.goUrl.toString(), ""))
} else if (data.goType.equals("special_categories")) {
ARouter.getInstance().build("/consult/list")
.withInt(IYDLRouterConstant.EXTRA_SHOWTYPE, 0)
.withString(IYDLRouterConstant.EXTRA_CATETITLE, data.title)
.withSerializable(IYDLRouterConstant.GO_CRITERIA, data.goCriteriaMap)
.navigation()
} else {
//跳转咨询频道页 服务入口
YDLRouterManager.router(
IYDLRouterConstant.ROUTER_CONSULT_LIST,
YDLRouterParams().putExtra(
IYDLRouterConstant.EXTRA_CATEID,
data.cateId.toString()
).putExtra(
IYDLRouterConstant.EXTRA_CATETITLE, data.cateTitle!!
).putExtra(
IYDLRouterConstant.EXTRA_SHOWTYPE, "0"
)
)
ARouter.getInstance().build("/consult/list")
.withInt(IYDLRouterConstant.EXTRA_SHOWTYPE, 0)
.withString(IYDLRouterConstant.EXTRA_CATETITLE, data.title)
.withSerializable(IYDLRouterConstant.GO_CRITERIA, data.goCriteriaMap)
.navigation()
}
}
......@@ -291,7 +299,7 @@ open class HomeBaseImpl : IHomeBaseEvent {
return
}
EventBus.getDefault().post(
HomeModuleTabEvent(2,"11")
HomeModuleTabEvent(2, "11")
)
ActionCountUtils.count(HomeBIConstants.YDL_USER_CONSULT_CLICK)
}
......@@ -304,7 +312,11 @@ open class HomeBaseImpl : IHomeBaseEvent {
ActionCountUtils.count(HomeBIConstants.YDL_USER_TALK_IN_TIME_CLICK)
//倾诉首页 ydl-user://confide/home
ActionCountUtils.record("listen_counselor_list_page", "listen_counselor_list_page_visit", "1")
ActionCountUtils.record(
"listen_counselor_list_page",
"listen_counselor_list_page_visit",
"1"
)
route(mContext, ConfideRoute.R_CONFIDE_HOME)
}
......@@ -347,7 +359,7 @@ open class HomeBaseImpl : IHomeBaseEvent {
* 倾述咨询师点击
* @param linkUrl 跳转地址
*/
override fun confideClick(linkUrl: String?, confideId:String, doctorId: Int, uid:String?) {
override fun confideClick(linkUrl: String?, confideId: String, doctorId: Int, uid: String?) {
if (Utils.isFastClick()) {
//防止连击
return
......@@ -378,7 +390,9 @@ open class HomeBaseImpl : IHomeBaseEvent {
//防止连击
return
}
if (!ModularServiceManager.provide(IUserService::class.java).loginByOneKeyLogin(mContext as Context,true)) {
if (!ModularServiceManager.provide(IUserService::class.java)
.loginByOneKeyLogin(mContext as Context, true)
) {
//判断登录状态内部已完成 跳转登录
return
}
......@@ -452,7 +466,9 @@ open class HomeBaseImpl : IHomeBaseEvent {
}
override fun askItemFocusClick(position: Int, id: String) {
if (!ModularServiceManager.provide(IUserService::class.java).loginByOneKeyLogin(mContext as Context,true)) {
if (!ModularServiceManager.provide(IUserService::class.java)
.loginByOneKeyLogin(mContext as Context, true)
) {
//判断登录状态内部已完成 跳转登录
return
}
......@@ -461,7 +477,9 @@ open class HomeBaseImpl : IHomeBaseEvent {
}
override fun askItemZanClick(position: Int, index: Int, id: String) {
if (!ModularServiceManager.provide(IUserService::class.java).loginByOneKeyLogin(mContext as Context,true)) {
if (!ModularServiceManager.provide(IUserService::class.java)
.loginByOneKeyLogin(mContext as Context, true)
) {
//判断登录状态内部已完成 跳转登录
return
}
......
......@@ -72,7 +72,7 @@ interface IHomeBaseEvent {
/**
* 首页分类跳转
*/
fun categoryClick(category: HomeHeaderBean.AskCategoryDataBean)
fun categoryClick(category: HomeHeaderBean.CategoryGoldListDataBean)
/**
* 心理咨询点击事件
......
package com.yidianling.home.model.bean
import com.google.gson.annotations.SerializedName
import com.yidianling.consultant.bean.Keyworks
import java.io.Serializable
/**
* Created by haorui on 2019/2/14.
* Des:首页头部模块数据 Banner&分类
*/
class HomeHeaderBean : HomeItemBaseBean {
constructor():super(false)
constructor(isRealEmpty:Boolean):super(isRealEmpty)
constructor() : super(false)
constructor(isRealEmpty: Boolean) : super(isRealEmpty)
/**
* 活动弹窗数据
*/
var activityResponse: ActivityResponse? = null
/**
* 分类数据
*/
var askCategoryData: MutableList<AskCategoryDataBean>? = null
/**
* 新版分类数据
*/
var goldList: MutableList<CategoryGoldListDataBean>? = null
/**
* 焦点图数据
*/
var focusList: List<FocusListBean>? = null
/**
* 滚动销售数据
*/
var homeSaleData: List<HomeSaleDataBean>? = null
/**
* 搜索关键词数据
*/
var keywordData: MutableList<Keyworks>? = null
/**
* 倾诉分类
*/
......@@ -39,28 +52,42 @@ class HomeHeaderBean : HomeItemBaseBean {
* 咨询分类
*/
var consultCategoryData: List<ConsultCategoryDateBean>? = null
/**
* 专家名称
*/
var doctorName : String? = null
var doctorName: String? = null
/*
* 倾诉免费标识
* */
var listenFree : Boolean? = null
var listenFree: Boolean? = null
data class CategoryGoldListDataBean(
var id: String? = "",
var title: String? = "",
var icon: String? = "",
var goType: String? = "",
var goUrl: String? = "",
var goCriteriaMap: HashMap<String, Any>? = null
) : Serializable
class AskCategoryDataBean {
/**
* id
*/
var cateId: Int = 0
/**
* 名称
*/
var cateTitle: String? = null //
/**
* 跳转url
*/
var url: String? = null
/**
* 图片icon
*/
......@@ -72,22 +99,27 @@ class HomeHeaderBean : HomeItemBaseBean {
* 标题
*/
var title: String? = null
/**
* 跳转链接
*/
var linkUrl: String? = null
/**
* 图片
*/
var imageUrl: String? = null
/**
* iPhone X图片
*/
var imageIphonex: String? = null
/**
* 焦点图id
*/
var focId: Int = 0
/**
* 分享数据
*/
......@@ -104,26 +136,32 @@ class HomeHeaderBean : HomeItemBaseBean {
* 用户昵称
*/
var nickName: String? = null
/**
* 老师名字
*/
var doctorName: String? = null
/**
* 老师id
*/
var doctorId: Int = 0
/**
* 跳转专家主页
*/
var url: String? = null
/**
* 内容开头
*/
var contentBefore: String? = null
/**
* 内容结尾
*/
var contentAfter: String? = null
/**
* 创建时间
*/
......@@ -135,11 +173,11 @@ class HomeHeaderBean : HomeItemBaseBean {
var name: String? = null
}
class ActivityResponse{
var imageBanner:String? = null// 弹窗图片
var imageUrl: String?=null// 图片
var linkUrl:String?=null // 首页弹窗
var btnLinkurl:String?=null // 首页入口(左上角图标)
var title :String? = null// 标题
class ActivityResponse {
var imageBanner: String? = null// 弹窗图片
var imageUrl: String? = null// 图片
var linkUrl: String? = null // 首页弹窗
var btnLinkurl: String? = null // 首页入口(左上角图标)
var title: String? = null// 标题
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/platform_dp_15"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/category_img"
android:layout_width="@dimen/platform_dp_30"
android:layout_height="@dimen/platform_dp_30" />
<TextView
android:id="@+id/category_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/platform_dp_5"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#1c212d"
android:textSize="@dimen/platform_sp_12" />
</LinearLayout>
\ No newline at end of file
......@@ -161,7 +161,7 @@ class YdlHomeAdapter(
//顶部预约专家,即时倾诉,心理课堂,心理测试按钮模块
is HomeButtonBannerViewHolder -> {
holder.buttonBannerView.initData(
list[position].headerBean?.askCategoryData
list[position].headerBean?.goldList
)
}
//课程*成长模块
......
......@@ -54,7 +54,7 @@ class HomeButtonBannerView(private val mContext: Context, private var homeEvent:
fun initData(
homeCategory: List<HomeHeaderBean.AskCategoryDataBean>?
homeCategory: List<HomeHeaderBean.CategoryGoldListDataBean>?
) {
homeEvent?.let { home_category_view.setEvent(it) }
home_category_view.initData(homeCategory)
......
......@@ -30,7 +30,8 @@ class HomePagerBannerCategoryView(mContext: Context, homeEvent: IHomeBaseEvent)
/**
* 数据缓存
*/
var mDataList: ArrayList<HomeHeaderBean.AskCategoryDataBean>? = null
var mDataList: ArrayList<HomeHeaderBean.CategoryGoldListDataBean>? = null
/**
* 分类view宽度
*/
......@@ -113,7 +114,7 @@ class HomePagerBannerCategoryView(mContext: Context, homeEvent: IHomeBaseEvent)
}
fun initData(
askCategoryDataBean: List<HomeHeaderBean.AskCategoryDataBean>?,
askCategoryDataBean: List<HomeHeaderBean.CategoryGoldListDataBean>?,
homeSaleData: List<HomeHeaderBean.HomeSaleDataBean>?
) {
if (null == askCategoryDataBean || askCategoryDataBean.isEmpty()) {
......@@ -136,17 +137,16 @@ class HomePagerBannerCategoryView(mContext: Context, homeEvent: IHomeBaseEvent)
* 判断数据是否变化
*/
private fun getChange(
bean: List<HomeHeaderBean.AskCategoryDataBean>?,
cacheBean: List<HomeHeaderBean.AskCategoryDataBean>?
bean: List<HomeHeaderBean.CategoryGoldListDataBean>?,
cacheBean: List<HomeHeaderBean.CategoryGoldListDataBean>?
): Boolean {
if (bean?.size != cacheBean?.size) {
return true
}
for (index in 0 until bean?.size!!) {
if (!bean[index].url.equals(cacheBean!![index].url)
|| !bean[index].coverUrl.equals(cacheBean!![index].coverUrl)
|| !bean[index].cateTitle.equals(cacheBean!![index].cateTitle)
|| bean[index].cateId != cacheBean!![index].cateId
if (!bean[index].icon.equals(cacheBean!![index].icon)
|| !bean[index].title.equals(cacheBean!![index].title)
|| bean[index].id != cacheBean!![index].id
) {
return true
}
......@@ -218,9 +218,9 @@ class HomePagerBannerCategoryView(mContext: Context, homeEvent: IHomeBaseEvent)
*/
private fun bindIconData(
imageView: ImageView,
categoryBean: HomeHeaderBean.AskCategoryDataBean
categoryBean: HomeHeaderBean.CategoryGoldListDataBean
) {
GlideApp.with(context).load(categoryBean.coverUrl)
GlideApp.with(context).load(categoryBean.icon)
.centerCrop().into(imageView)
}
......@@ -249,8 +249,11 @@ class HomePagerBannerCategoryView(mContext: Context, homeEvent: IHomeBaseEvent)
/**
* 设置文本
*/
private fun bindTextData(textView: TextView, categoryBean: HomeHeaderBean.AskCategoryDataBean) {
textView.text = categoryBean.cateTitle
private fun bindTextData(
textView: TextView,
categoryBean: HomeHeaderBean.CategoryGoldListDataBean
) {
textView.text = categoryBean.title
}
/**
......
......@@ -30,7 +30,8 @@ class HomeModuleCategoryView : FrameLayout {
/**
* 数据缓存
*/
var mDataList: ArrayList<HomeHeaderBean.AskCategoryDataBean>? = null
var mDataList: ArrayList<HomeHeaderBean.CategoryGoldListDataBean>? = null
/**
* 分类view宽度
*/
......@@ -126,7 +127,7 @@ class HomeModuleCategoryView : FrameLayout {
dp15 = RxImageTool.dip2px(4f)
}
fun initData(askCategoryDataBean: List<HomeHeaderBean.AskCategoryDataBean>?) {
fun initData(askCategoryDataBean: List<HomeHeaderBean.CategoryGoldListDataBean>?) {
if (null == askCategoryDataBean || askCategoryDataBean.isEmpty()) {
visibility = View.GONE
return
......@@ -146,17 +147,16 @@ class HomeModuleCategoryView : FrameLayout {
* 判断数据是否变化
*/
private fun getChange(
bean: List<HomeHeaderBean.AskCategoryDataBean>?,
cacheBean: List<HomeHeaderBean.AskCategoryDataBean>?
bean: List<HomeHeaderBean.CategoryGoldListDataBean>?,
cacheBean: List<HomeHeaderBean.CategoryGoldListDataBean>?
): Boolean {
if (bean?.size != cacheBean?.size) {
return true
}
for (index in 0 until bean?.size!!) {
if (!bean[index].url.equals(cacheBean!![index].url)
|| !bean[index].coverUrl.equals(cacheBean!![index].coverUrl)
|| !bean[index].cateTitle.equals(cacheBean!![index].cateTitle)
|| bean[index].cateId != cacheBean!![index].cateId
if (!bean[index].icon.equals(cacheBean!![index].icon)
|| !bean[index].title.equals(cacheBean!![index].title)
|| bean[index].id != cacheBean!![index].id
) {
return true
}
......@@ -282,8 +282,11 @@ class HomeModuleCategoryView : FrameLayout {
/**
* 设置文本
*/
private fun bindTextData(textView: TextView, categoryBean: HomeHeaderBean.AskCategoryDataBean) {
textView.text = categoryBean.cateTitle
private fun bindTextData(
textView: TextView,
categoryBean: HomeHeaderBean.CategoryGoldListDataBean
) {
textView.text = categoryBean.title
}
/**
......@@ -291,9 +294,9 @@ class HomeModuleCategoryView : FrameLayout {
*/
private fun bindIconData(
imageView: ImageView,
categoryBean: HomeHeaderBean.AskCategoryDataBean
categoryBean: HomeHeaderBean.CategoryGoldListDataBean
) {
GlideApp.with(context).load(categoryBean.coverUrl)
GlideApp.with(context).load(categoryBean.icon)
.centerCrop().into(imageView)
}
}
\ No newline at end of file
package com.yidianling.home.adapter
import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.ydl.ydl_image.module.GlideApp
import com.yidianling.home.R
import com.yidianling.home.event.IHomeBaseEvent
import com.yidianling.home.model.bean.HomeHeaderBean
import kotlinx.android.synthetic.main.home_category_list_item.view.*
/**
* Created by zqk on 17-9-20.
*/
class CategoryAdapter(
private val context: Context,
private val cateList: MutableList<HomeHeaderBean.CategoryGoldListDataBean>,
private val homeEvent: IHomeBaseEvent
) : RecyclerView.Adapter<CategoryAdapter.ViewHolder>() {
override fun getItemCount(): Int = cateList.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val itemView =
LayoutInflater.from(context).inflate(R.layout.home_category_list_item, parent, false)
return ViewHolder(itemView)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
GlideApp.with(context).load(cateList[position].icon)
.centerCrop().into(holder.category_img)
holder.category_text.text = cateList[position].title
holder.itemView.setOnClickListener {
homeEvent.categoryClick(cateList[position])
}
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val category_img = itemView.category_img
val category_text = itemView.category_text
}
}
\ No newline at end of file
......@@ -24,9 +24,10 @@ class HomeCategoryAdapter : PagerAdapter {
private var mContext : Context? = null
private var mHomeEvent : IHomeBaseEvent? = null
//源数据
private var mOriginList : MutableList<HomeHeaderBean.AskCategoryDataBean>? = null
private var mOriginList: MutableList<HomeHeaderBean.AskCategoryDataBean>? = null
//数据
private var list : MutableList<MutableList<HomeHeaderBean.AskCategoryDataBean>>? = null
private var list: MutableList<MutableList<HomeHeaderBean.CategoryGoldListDataBean>>? = null
init {
list = ArrayList()
......@@ -40,13 +41,15 @@ class HomeCategoryAdapter : PagerAdapter {
/**
* 更新数据
*/
fun updateItems(data : MutableList<HomeHeaderBean.AskCategoryDataBean>?){
if (null == data || data.isEmpty()){
fun updateItems(data: MutableList<HomeHeaderBean.CategoryGoldListDataBean>?) {
if (null == data || data.isEmpty()) {
return
}
Log.e("http","--------------data.size="+data!!.size)
list = this.averageAssign(data, HomeCategoryContainer.PAGE_ITEM_SIZE)
Log.e("http","--------------list.size="+list!!.size)
Log.e("http", "--------------data.size=" + data!!.size)
list?.clear()
list?.add(data)
// list = this.averageAssign(data, HomeCategoryContainer.PAGE_ITEM_SIZE)
Log.e("http", "--------------list.size=" + list!!.size)
notifyDataSetChanged()
}
......
......@@ -136,7 +136,10 @@ class YdlHomeAdapter(private val mContext: Context,
if (viewType == -1){
//空布局
val view = View(mContext)
val layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,1)
val layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
view.layoutParams = layoutParams
view.visibility = View.GONE
return HomePagerBannerViewHolder(view,viewType)
......
......@@ -5,10 +5,13 @@ import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.yidianling.common.tools.RxDeviceTool
import com.yidianling.common.tools.RxImageTool
import com.yidianling.home.R
import com.yidianling.home.event.IHomeBaseEvent
import kotlinx.android.synthetic.ydl.home_button_banner_view.view.*
......@@ -20,7 +23,11 @@ import kotlinx.android.synthetic.ydl.home_button_banner_view.view.*
* @Company 壹点灵
* @date 2019/02/13
*/
class HomeButtonBannerView(private val mContext: Context, private var homeEvent: IHomeBaseEvent?,var listenFree:Boolean) : LinearLayout(mContext) {
class HomeButtonBannerView(
private val mContext: Context,
private var homeEvent: IHomeBaseEvent?,
var listenFree: Boolean
) : LinearLayout(mContext) {
private var buttonParams: LinearLayout.LayoutParams? = null
private var buttonParamsFrame: FrameLayout.LayoutParams? = null
......@@ -29,24 +36,29 @@ class HomeButtonBannerView(private val mContext: Context, private var homeEvent:
init {
initView()
}
fun setVisibilityFree(boolean: Boolean){
if (boolean){
qingsuGif.visibility=View.VISIBLE
fun setVisibilityFree(boolean: Boolean) {
if (boolean) {
qingsuGif.visibility = View.VISIBLE
homeModuleButtonBannerSecondTitle.text = "免费热线"
}else{
qingsuGif.visibility=View.GONE
} else {
qingsuGif.visibility = View.GONE
homeModuleButtonBannerSecondTitle.text = "倾诉热线"
}
}
private fun initView() {
val params = RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
val params = RecyclerView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
layoutParams = params
View.inflate(mContext, R.layout.home_button_banner_view, this)
setVisibilityFree(listenFree)
Glide.with(context)
.load(R.drawable.qingsu_new_free_dynamic)
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.into(qingsuGif)
Glide.with(context)
.load(R.drawable.qingsu_new_free_dynamic)
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.into(qingsuGif)
initButtonView()
homeModuleButtonBannerFirst.setOnClickListener {
......@@ -69,19 +81,21 @@ class HomeButtonBannerView(private val mContext: Context, private var homeEvent:
private fun initButtonView() {
if (null == buttonParams) {
val screenWidth = RxDeviceTool.getScreenWidth(mContext)
val viewWidth = ((screenWidth - 2 * 9 * RxDeviceTool.getScreenDensity(mContext)) / 4).toInt()
val viewHeight = viewWidth * 78 / 80
// val viewWidth = ((screenWidth - 2 * 9 * RxDeviceTool.getScreenDensity(mContext)) / 4).toInt()
val viewWidth = screenWidth / 4 - 40
val viewHeight = viewWidth
buttonParams = LinearLayout.LayoutParams(viewWidth, viewHeight)
buttonParams!!.setMargins(0, 0, 15, 0)
buttonParamsFrame = FrameLayout.LayoutParams(viewWidth, viewHeight)
buttonParamsFrame2= FrameLayout.LayoutParams((viewWidth/2.0).toInt(), (viewHeight/2.3).toInt())
buttonParamsFrame2!!.setMargins((((viewWidth/12f).toInt())),0,0,0)
qingsuGif.layoutParams=buttonParamsFrame2
buttonParamsFrame2 =
FrameLayout.LayoutParams((viewWidth / 2.0).toInt(), (viewHeight / 2.3).toInt())
buttonParamsFrame2!!.setMargins((((viewWidth / 12f).toInt())), 0, 0, 0)
// qingsuGif.layoutParams=buttonParamsFrame2
homeModuleButtonBannerFirst.layoutParams = buttonParams
homeModuleButtonBannerFourth.layoutParams = buttonParams
homeModuleButtonBannerSecond.layoutParams = buttonParams
homeModuleButtonBannerThird.layoutParams = buttonParams
homeModuleButtonBannerFourth.layoutParams = buttonParams
homeModuleButtonBannerSecondFrame.layoutParams=buttonParamsFrame
homeModuleButtonBannerSecondFrame.layoutParams = buttonParamsFrame
}
}
}
\ No newline at end of file
......@@ -29,7 +29,7 @@ class HomeCategoryContainer(private val mContext: Context, private var homeEvent
private var lastPosition = 0
private var count = 0
private var mIndicatorWidth: Int = RxImageTool.dip2px(9f)
private var mIndicatorWidth: Int = RxImageTool.dip2px(15f)
private var mIndicatorHeight: Int = RxImageTool.dip2px(5f)
private var dp2 : Int = 0
......@@ -39,7 +39,7 @@ class HomeCategoryContainer(private val mContext: Context, private var homeEvent
init {
initView()
dp2 = RxImageTool.dip2px(4f)
dp2 = RxImageTool.dip2px(2f)
}
private fun initView() {
......@@ -51,17 +51,18 @@ class HomeCategoryContainer(private val mContext: Context, private var homeEvent
* 填充数据
*/
fun initData(bean: HomeHeaderBean?) {
mHomeCategoryAdapter?.updateItems(bean?.askCategoryData)
if (bean?.askCategoryData?.size!! > PAGE_ITEM_SIZE){
count = Math.ceil(Math.ceil(bean.askCategoryData?.size?.toFloat()?.div(PAGE_ITEM_SIZE.toFloat())?.toDouble()!!)).toInt()
createIndicator()
val params = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,RxImageTool.dip2px(153f))
vp_category.layoutParams = params
}else{
val params = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,RxImageTool.dip2px(143f))
vp_category.layoutParams = params
ll_Indicator.visibility = View.GONE
}
if (bean?.goldList == null) return
mHomeCategoryAdapter?.updateItems(bean?.goldList)
//向上取整
count = bean.goldList?.size?.toDouble()?.div(5)?.let { Math.ceil(it).toInt() }!!
val params = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
RxImageTool.dip2px(65f * count)
)
vp_category.layoutParams = params
ll_Indicator.visibility = View.GONE
}
private fun initViewPager() {
......
......@@ -9,17 +9,21 @@ import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.ydl.ydl_image.module.GlideApp
import com.ydl.ydlcommon.utils.ScreenUtil
import com.yidianling.common.tools.RxImageTool
import com.yidianling.home.R
import com.yidianling.home.adapter.CategoryAdapter
import com.yidianling.home.event.IHomeBaseEvent
import com.yidianling.home.model.bean.HomeHeaderBean
import kotlinx.android.synthetic.ydl.home_pager_banner_category_view.view.*
/**
* @author <a href="https://www.jianshu.com/u/c1e5310dd724">xujian</a>
* @描述: 首页顶部模块-分类模块
* @描述: 首页顶部模块-分类模块 金刚位跳转H5或咨询列表页面
* @Copyright Copyright (c) 2019
* @Company 壹点灵
* @date 2019/02/16
......@@ -28,7 +32,8 @@ class HomePagerBannerCategoryItemView(mContext: Context, homeEvent: IHomeBaseEve
/**
* 数据缓存
*/
var mDataList: ArrayList<HomeHeaderBean.AskCategoryDataBean>? = null
var mDataList: ArrayList<HomeHeaderBean.CategoryGoldListDataBean>? = null
/**
* 分类view宽度
*/
......@@ -66,10 +71,12 @@ class HomePagerBannerCategoryItemView(mContext: Context, homeEvent: IHomeBaseEve
* 倍数
*/
private var multiple: Int = 0
/**
* 测评首页事件处理类
*/
private var homeEvent: IHomeBaseEvent? = null
private lateinit var categoryAdapter: CategoryAdapter
init {
initView()
......@@ -84,7 +91,7 @@ class HomePagerBannerCategoryItemView(mContext: Context, homeEvent: IHomeBaseEve
val params = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)
// params.topMargin = ScreenUtil.screenHeight * (356f / 750f).toInt()
layoutParams = params
initArgs()
// initArgs()
}
/**
......@@ -102,7 +109,7 @@ class HomePagerBannerCategoryItemView(mContext: Context, homeEvent: IHomeBaseEve
}
//, homeSaleData: List<HomeHeaderBean.HomeSaleDataBean>?
fun initData(askCategoryDataBean: MutableList<HomeHeaderBean.AskCategoryDataBean>?) {
fun initData(askCategoryDataBean: MutableList<HomeHeaderBean.CategoryGoldListDataBean>?) {
if (null == askCategoryDataBean || askCategoryDataBean.isEmpty()) {
visibility = View.GONE
return
......@@ -115,22 +122,36 @@ class HomePagerBannerCategoryItemView(mContext: Context, homeEvent: IHomeBaseEve
mDataList!!.clear()
mDataList!!.addAll(askCategoryDataBean)
}
refreshView()
homeEvent?.let {
categoryAdapter = CategoryAdapter(context, mDataList!!, it)
}
homeModulePagerBannerFlRoot.adapter = categoryAdapter
homeModulePagerBannerFlRoot.layoutManager = GridLayoutManager(
context,
5,
LinearLayoutManager.VERTICAL,
false
)
// refreshView()
// setRealTextView(homeSaleData)
}
/**
* 判断数据是否变化
*/
private fun getChange(bean: MutableList<HomeHeaderBean.AskCategoryDataBean>?, cacheBean: MutableList<HomeHeaderBean.AskCategoryDataBean>?): Boolean {
private fun getChange(
bean: MutableList<HomeHeaderBean.CategoryGoldListDataBean>?,
cacheBean: MutableList<HomeHeaderBean.CategoryGoldListDataBean>?
): Boolean {
if (bean?.size != cacheBean?.size) {
return true
}
for (index in 0 until bean?.size!!) {
if (!bean[index].url.equals(cacheBean!![index].url)
|| !bean[index].coverUrl.equals(cacheBean!![index].coverUrl)
|| !bean[index].cateTitle.equals(cacheBean!![index].cateTitle)
|| bean[index].cateId != cacheBean!![index].cateId) {
if (!bean[index].icon.equals(cacheBean!![index].icon)
|| !bean[index].title.equals(cacheBean!![index].title)
|| bean[index].id != cacheBean!![index].id
) {
return true
}
}
......@@ -144,9 +165,6 @@ class HomePagerBannerCategoryItemView(mContext: Context, homeEvent: IHomeBaseEve
homeModulePagerBannerFlRoot.removeAllViews()
var i = 0
for (item in mDataList!!) {
if (i > 9) {
break
}
val imageView = createIcon(i)
val textView = createText(i)
......@@ -189,9 +207,12 @@ class HomePagerBannerCategoryItemView(mContext: Context, homeEvent: IHomeBaseEve
/**
* 加载图片
*/
private fun bindIconData(imageView: ImageView, categoryBean: HomeHeaderBean.AskCategoryDataBean) {
GlideApp.with(context).load(categoryBean.coverUrl)
.centerCrop().into(imageView)
private fun bindIconData(
imageView: ImageView,
categoryBean: HomeHeaderBean.CategoryGoldListDataBean
) {
GlideApp.with(context).load(categoryBean.icon)
.centerCrop().into(imageView)
}
/**
......@@ -219,8 +240,11 @@ class HomePagerBannerCategoryItemView(mContext: Context, homeEvent: IHomeBaseEve
/**
* 设置文本
*/
private fun bindTextData(textView: TextView, categoryBean: HomeHeaderBean.AskCategoryDataBean) {
textView.text = categoryBean.cateTitle
private fun bindTextData(
textView: TextView,
categoryBean: HomeHeaderBean.CategoryGoldListDataBean
) {
textView.text = categoryBean.title
}
/**
......
......@@ -105,11 +105,7 @@ class HomePagerBannerView(private val mContext: Context, private var homeEvent:
if (null != focusListBean && focusListBean.isNotEmpty()) {
mImageViews.clear()
//产品说取前8个
if (focusListBean.size > 8){
cacheList.addAll(focusListBean.subList(0,8))
}else{
cacheList.addAll(focusListBean)
}
cacheList.addAll(focusListBean)
for (item in cacheList) {
mImageViews.add(item.imageUrl!!)
}
......
......@@ -7,7 +7,7 @@
android:color="#E0E0E0"/>
<size
android:width="22dp"
android:width="5dp"
android:height="5dp"/>
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/four_button_constrain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:paddingLeft="@dimen/platform_dp_8"
android:paddingRight="@dimen/platform_dp_8"
android:layout_marginTop="@dimen/platform_dp_12"
>
android:paddingTop="@dimen/platform_dp_8"
android:paddingRight="@dimen/platform_dp_8">
<RelativeLayout
android:id="@+id/homeModuleButtonBannerFirst"
android:layout_width="80dp"
android:layout_width="0dp"
android:layout_height="78dp"
android:layout_weight="1"
android:background="@drawable/home_button_banner_first_img_new"
android:gravity="center">
android:gravity="center"
android:paddingRight="@dimen/platform_dp_10">
<TextView
android:id="@+id/homeModuleButtonBannerFirstTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="@color/platform_color_FFFFFF"
android:text="心理咨询"
android:textColor="@color/black"
android:textSize="@dimen/platform_dp_16"
android:text="心理咨询"/>
android:textStyle="bold" />
<TextView
android:layout_below="@+id/homeModuleButtonBannerFirstTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/platform_color_FFFFFF"
android:textSize="@dimen/platform_dp_12"
android:text="3W+师资"/>
android:layout_below="@+id/homeModuleButtonBannerFirstTitle"
android:text="3W+师资"
android:textColor="@color/black"
android:textSize="@dimen/platform_dp_12" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/homeModuleButtonBannerFourth"
android:layout_width="80dp"
android:layout_width="0dp"
android:layout_height="78dp"
android:layout_weight="1"
android:background="@drawable/home_confide_free_icon"
android:gravity="center">
android:gravity="center"
android:paddingRight="@dimen/platform_dp_10">
<TextView
android:id="@+id/homeModuleButtonBannerFourthTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="@color/platform_color_FFFFFF"
android:text="心理测试"
android:textColor="@color/black"
android:textSize="@dimen/platform_dp_16"
android:text="心理测试"/>
android:textStyle="bold" />
<TextView
android:layout_below="@+id/homeModuleButtonBannerFourthTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/platform_color_FFFFFF"
android:textSize="@dimen/platform_dp_12"
android:text="抑郁测量"/>
android:layout_below="@+id/homeModuleButtonBannerFourthTitle"
android:text="抑郁测量"
android:textColor="@color/black"
android:textSize="@dimen/platform_dp_12" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/homeModuleButtonBannerThird"
android:layout_width="80dp"
android:layout_width="0dp"
android:layout_height="78dp"
android:orientation="vertical"
android:layout_weight="1"
android:background="@drawable/home_button_banner_third_img_new"
android:gravity="center">
android:gravity="center"
android:orientation="vertical"
android:paddingRight="@dimen/platform_dp_10">
<TextView
android:id="@+id/homeModuleButtonBannerThirdTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="@color/platform_color_FFFFFF"
android:text="心理课堂"
android:textColor="@color/black"
android:textSize="@dimen/platform_dp_16"
android:text="心理课堂"/>
android:textStyle="bold" />
<TextView
android:layout_below="@+id/homeModuleButtonBannerThirdTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/platform_color_FFFFFF"
android:textSize="@dimen/platform_dp_12"
android:text="学习与成长"/>
android:layout_below="@+id/homeModuleButtonBannerThirdTitle"
android:text="学习与成长"
android:textColor="@color/black"
android:textSize="@dimen/platform_dp_12" />
</RelativeLayout>
<FrameLayout
android:id="@+id/homeModuleButtonBannerSecond"
android:layout_width="80dp"
<FrameLayout
android:id="@+id/homeModuleButtonBannerSecond"
android:layout_width="0dp"
android:layout_height="78dp"
android:layout_weight="1"
android:background="@drawable/home_button_banner_fourth_img_new"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toRightOf="@id/homeModuleButtonBannerThird"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:id="@+id/homeModuleButtonBannerSecondFrame"
android:layout_width="78dp"
android:layout_height="78dp"
android:background="@drawable/home_button_banner_fourth_img_new"
>
<RelativeLayout
android:id="@+id/homeModuleButtonBannerSecondFrame"
android:layout_width="80dp"
android:layout_height="78dp"
android:gravity="center">
<TextView
android:id="@+id/homeModuleButtonBannerSecondTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="@color/platform_color_FFFFFF"
android:textSize="@dimen/platform_dp_16"
android:text="倾诉热线"/>
android:gravity="center"
android:paddingRight="@dimen/platform_dp_10">
<TextView
android:id="@+id/homeModuleButtonBannerSecondTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="倾诉热线"
android:textColor="@color/black"
android:textSize="@dimen/platform_dp_16"
android:textStyle="bold" />
<TextView
android:layout_below="@+id/homeModuleButtonBannerSecondTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/platform_color_FFFFFF"
android:textSize="@dimen/platform_dp_12"
android:text="温暖守护您"/>
</RelativeLayout>
<ImageView
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/qingsuGif"
android:visibility="gone"
>
</ImageView>
</FrameLayout>
android:layout_below="@+id/homeModuleButtonBannerSecondTitle"
android:text="温暖守护您"
android:textColor="@color/black"
android:textSize="@dimen/platform_dp_12" />
</RelativeLayout>
<ImageView
android:id="@+id/qingsuGif"
android:layout_width="@dimen/platform_dp_48"
android:layout_height="@dimen/platform_dp_22"
android:visibility="visible" />
</FrameLayout>
</LinearLayout>
......@@ -9,7 +9,7 @@
<androidx.viewpager.widget.ViewPager
android:id="@+id/vp_category"
android:layout_width="match_parent"
android:layout_height="153dp"
android:layout_height="wrap_content"
android:background="@color/platform_white"/>
<LinearLayout
......@@ -23,7 +23,7 @@
android:orientation="horizontal"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:visibility="gone"
android:visibility="visible"
tools:visibility="visible"/>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/homeModulePagerBannerFlRoot"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/platform_dp_8"
android:layout_marginEnd="@dimen/platform_dp_8"
android:paddingBottom="1dp" />
</merge>
\ No newline at end of file
......@@ -21,7 +21,6 @@
android:id="@+id/homeModulePagerBannerViewAddLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="175dp"
android:background="@drawable/home_home_category_bg"
android:orientation="vertical"
android:paddingTop="20dp">
......
......@@ -82,6 +82,7 @@ interface IYDLRouterConstant{
const val EXTRA_RED_PACKET = "by_red_packet"
const val EXTRA_CONFIDEDID = "confidedId"
const val EXTRA_DOCTORID = "doctorId"
const val GO_CRITERIA = "go_criteria"
/**
* 冥想模块额外参数
......
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