feat(home): 新增健康资讯模块(健康知识 + 健康咨询)
采用 HMAC-SHA256 签名认证获取 Token,通过栏目/文章 API 获取数据, 详情/更多/搜索均跳转 H5 页面。同时新增带下划线指示器的 Tab 样式。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
4ff52c0465
commit
f5be575491
@@ -0,0 +1,27 @@
|
||||
package com.xjjk.healthyclients.adapter
|
||||
|
||||
import android.widget.ImageView
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter
|
||||
import com.chad.library.adapter.base.viewholder.BaseViewHolder
|
||||
import com.xjjk.healthyclients.R
|
||||
import com.xjjk.healthyclients.bean.home.ArticleBean
|
||||
import com.xjjk.healthyclients.superfuntion.loadRoundedImage
|
||||
import com.xjjk.healthyclients.superfuntion.orEmptyDefault
|
||||
|
||||
/**
|
||||
* 健康咨询列表 Adapter
|
||||
*/
|
||||
class HealthConsultationAdapter :
|
||||
BaseQuickAdapter<ArticleBean, BaseViewHolder>(R.layout.item_health_consultation) {
|
||||
|
||||
override fun convert(holder: BaseViewHolder, item: ArticleBean) {
|
||||
// 标题
|
||||
holder.setText(R.id.tv_title, item.articleTitle.orEmptyDefault())
|
||||
// 收藏和分享数
|
||||
holder.setText(R.id.tv_meta, "收藏 ${item.favoriteCount} 分享 ${item.likeCount}")
|
||||
// 封面图片 80x60 圆角8
|
||||
holder.getView<ImageView>(R.id.iv_cover)?.loadRoundedImage(
|
||||
item.articleHeaderimage, 8f,R.mipmap.ic_placeholder_rectangle
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.xjjk.healthyclients.adapter
|
||||
|
||||
import android.widget.ImageView
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter
|
||||
import com.chad.library.adapter.base.viewholder.BaseViewHolder
|
||||
import com.sw.healthyclients.utils.DateUtil
|
||||
import com.xjjk.healthyclients.R
|
||||
import com.xjjk.healthyclients.bean.home.ArticleBean
|
||||
import com.xjjk.healthyclients.superfuntion.loadRoundedImage
|
||||
import com.xjjk.healthyclients.superfuntion.orEmptyDefault
|
||||
|
||||
/**
|
||||
* 健康知识列表 Adapter
|
||||
*/
|
||||
class HealthKnowledgeAdapter :
|
||||
BaseQuickAdapter<ArticleBean, BaseViewHolder>(R.layout.item_health_knowledge) {
|
||||
|
||||
override fun convert(holder: BaseViewHolder, item: ArticleBean) {
|
||||
// 封面图片 100x100 圆角15
|
||||
holder.getView<ImageView>(R.id.iv_cover)?.loadRoundedImage(
|
||||
item.articleHeaderimage, 15f, R.mipmap.ic_placeholder_square,
|
||||
)
|
||||
// 标题
|
||||
holder.setText(R.id.tv_title, item.articleTitle.orEmptyDefault())
|
||||
// 摘要
|
||||
holder.setText(R.id.tv_detail, item.articleSubtitle.orEmptyDefault(""))
|
||||
// 标签文本
|
||||
holder.setText(R.id.tv_tag, item.articleTag.orEmptyDefault())
|
||||
// 日期
|
||||
holder.setText(R.id.tv_date, DateUtil.long2ShortDateStr(item.createTime))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package com.xjjk.healthyclients.bankRequest
|
||||
|
||||
import com.sw.healthyclients.data.local.DataStoreManager
|
||||
import com.xjjk.healthyclients.bean.home.ArticleBean
|
||||
import com.xjjk.healthyclients.bean.home.ArticleListBean
|
||||
import com.xjjk.healthyclients.bean.home.CategoryBean
|
||||
import com.xjjk.healthyclients.data.api.CategoryListResponse
|
||||
import com.xjjk.healthyclients.data.api.HealthInfoApi
|
||||
import com.xjjk.healthyclients.data.api.TokenResponse
|
||||
import com.xjjk.healthyclients.retrofit.UrlConfig
|
||||
import com.xjjk.healthyclients.retrofit.getBankRetrofit
|
||||
import com.xjjk.healthyclients.superfuntion.toJson
|
||||
import com.xjjk.healthyclients.utils.SignatureUtils
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
/**
|
||||
* 健康资讯网络请求封装类
|
||||
* 负责 Token 获取(签名认证)、栏目列表、文章列表的 API 调用
|
||||
*/
|
||||
class HealthInfoRequest {
|
||||
|
||||
private val api: HealthInfoApi = getBankRetrofit()
|
||||
.create(HealthInfoApi::class.java)
|
||||
|
||||
companion object {
|
||||
/** 缓存的 Token,避免重复请求 */
|
||||
private var cachedToken: String? = null
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Token(带 HMAC-SHA256 签名)
|
||||
*/
|
||||
fun fetchToken(
|
||||
onSuccess: (String) -> Unit,
|
||||
onFailure: (Throwable) -> Unit
|
||||
) {
|
||||
// 如果已有缓存 Token,直接返回
|
||||
cachedToken?.let {
|
||||
onSuccess(it)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
val timestamp = System.currentTimeMillis() / 1000
|
||||
val userId = DataStoreManager.getUserId() ?: ""
|
||||
val workNo = DataStoreManager.getUserInfo()?.workNo ?: ""
|
||||
val bodyString = """{"userId":"$userId","workNo":"$workNo"}"""
|
||||
val sign = SignatureUtils.generateSignature(timestamp, bodyString, UrlConfig.SECRET_KEY)
|
||||
|
||||
val headers = mapOf(
|
||||
"Content-Type" to "application/json; charset=utf-8",
|
||||
"X-Timestamp" to timestamp.toString(),
|
||||
"X-Sign" to sign
|
||||
)
|
||||
|
||||
val body = mapOf("userId" to userId, "workNo" to workNo)
|
||||
|
||||
api.getToken(headers, body.toJson().toRequestBody())
|
||||
.enqueue(object : Callback<TokenResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<TokenResponse>,
|
||||
response: Response<TokenResponse>
|
||||
) {
|
||||
if (response.code() == 200) {
|
||||
val token = response.body()?.data?.token
|
||||
if (!token.isNullOrEmpty()) {
|
||||
cachedToken = token
|
||||
onSuccess(token)
|
||||
} else {
|
||||
onFailure(Exception("Token 为空"))
|
||||
}
|
||||
} else {
|
||||
onFailure(Exception("HTTP ${response.code()}: ${response.message()}"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
call: Call<TokenResponse>,
|
||||
t: Throwable
|
||||
) {
|
||||
onFailure(t)
|
||||
}
|
||||
})
|
||||
} catch (e: Exception) {
|
||||
onFailure(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取栏目列表
|
||||
*/
|
||||
fun fetchCategoryList(
|
||||
token: String,
|
||||
onSuccess: (MutableList<CategoryBean>) -> Unit,
|
||||
onFailure: (Throwable) -> Unit
|
||||
) {
|
||||
try {
|
||||
val headers = mapOf("token" to token)
|
||||
|
||||
api.getCategoryList(headers)
|
||||
.enqueue(object : Callback<CategoryListResponse> {
|
||||
override fun onResponse(
|
||||
call: Call<CategoryListResponse>,
|
||||
response: Response<CategoryListResponse>
|
||||
) {
|
||||
if (response.code() == 200) {
|
||||
val data = response.body()?.data ?: mutableListOf()
|
||||
onSuccess(data)
|
||||
} else {
|
||||
onFailure(Exception("HTTP ${response.code()}: ${response.message()}"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
call: Call<CategoryListResponse>,
|
||||
t: Throwable
|
||||
) {
|
||||
onFailure(t)
|
||||
}
|
||||
})
|
||||
} catch (e: Exception) {
|
||||
onFailure(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询文章列表
|
||||
*
|
||||
* @param token 认证 Token
|
||||
* @param categoryId 栏目 ID
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页数量
|
||||
* @param articleType 文章类型,"0"-图文,"1"-视频,不传则全部
|
||||
*/
|
||||
fun fetchArticleList(
|
||||
token: String,
|
||||
categoryId: Int,
|
||||
pageNum: Int = 1,
|
||||
pageSize: Int = 3,
|
||||
onSuccess: (MutableList<ArticleBean>?) -> Unit,
|
||||
onFailure: (Throwable) -> Unit
|
||||
) {
|
||||
try {
|
||||
val headers = mapOf("token" to token)
|
||||
val params = mapOf(
|
||||
"categoryId" to categoryId.toString(),
|
||||
"pageNum" to pageNum.toString(),
|
||||
"pageSize" to pageSize.toString(),
|
||||
"showAppHomepage" to "Y"
|
||||
)
|
||||
|
||||
api.getArticleList(headers, params)
|
||||
.enqueue(object : Callback<ArticleListBean> {
|
||||
override fun onResponse(
|
||||
call: Call<ArticleListBean>,
|
||||
response: Response<ArticleListBean>
|
||||
) {
|
||||
if (response.code() == 200) {
|
||||
val body = response.body()
|
||||
onSuccess(body?.rows)
|
||||
} else {
|
||||
onFailure(Exception("HTTP ${response.code()}: ${response.message()}"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<ArticleListBean>, t: Throwable) {
|
||||
onFailure(t)
|
||||
}
|
||||
})
|
||||
} catch (e: Exception) {
|
||||
onFailure(e)
|
||||
}
|
||||
}
|
||||
|
||||
/** 清除缓存的 Token(登录态变化时调用) */
|
||||
fun clearToken() {
|
||||
cachedToken = null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.xjjk.healthyclients.bean.home
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
/**
|
||||
* 获取 token 响应
|
||||
*/
|
||||
data class TokenBean(
|
||||
@SerializedName("token") val token: String? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* 栏目分类
|
||||
*/
|
||||
data class CategoryBean(
|
||||
@SerializedName("categoryId") val categoryId: Int = 0,
|
||||
@SerializedName("categoryName") val categoryName: String? = null,
|
||||
@SerializedName("categoryStatus") val categoryStatus: String? = null,
|
||||
@SerializedName("children") val children: MutableList<CategoryBean>? = null,
|
||||
@SerializedName("parentId") val parentId: Int = 0,
|
||||
@SerializedName("sortOrder") val sortOrder: Int = 0
|
||||
)
|
||||
|
||||
/**
|
||||
* 文章
|
||||
*/
|
||||
data class ArticleBean(
|
||||
@SerializedName("articleId") val articleId: Int = 0,
|
||||
@SerializedName("articleTitle") val articleTitle: String? = null,
|
||||
@SerializedName("articleSubtitle") val articleSubtitle: String? = null,
|
||||
@SerializedName("articleTag") val articleTag: String? = null,
|
||||
@SerializedName("articleHeaderimage") val articleHeaderimage: String? = null,
|
||||
@SerializedName("articleType") val articleType: String? = null,
|
||||
@SerializedName("articleExcerpt") val articleExcerpt: String? = null,
|
||||
@SerializedName("articleContent") val articleContent: String? = null,
|
||||
@SerializedName("articleVideo") val articleVideo: String? = null,
|
||||
@SerializedName("favoriteCount") val favoriteCount: Int = 0,
|
||||
@SerializedName("likeCount") val likeCount: Int = 0,
|
||||
@SerializedName("viewCount") val viewCount: Int = 0,
|
||||
@SerializedName("createTime") val createTime: String? = null,
|
||||
@SerializedName("categoryId") val categoryId: Int = 0,
|
||||
@SerializedName("articleScore") val articleScore: Double = 0.0,
|
||||
@SerializedName("articleStatus") val articleStatus: String? = null,
|
||||
@SerializedName("showAppHomepage") val showAppHomepage: String? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* 文章列表分页响应
|
||||
*/
|
||||
data class ArticleListBean(
|
||||
@SerializedName("rows") val rows: MutableList<ArticleBean>? = null,
|
||||
@SerializedName("total") val total: Int = 0
|
||||
)
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.xjjk.healthyclients.data.api
|
||||
|
||||
import com.xjjk.healthyclients.bean.home.ArticleListBean
|
||||
import com.xjjk.healthyclients.bean.home.CategoryBean
|
||||
import com.xjjk.healthyclients.bean.home.TokenBean
|
||||
import com.xjjk.healthyclients.retrofit.UrlConfig
|
||||
import okhttp3.RequestBody
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.HeaderMap
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.QueryMap
|
||||
|
||||
/**
|
||||
* 健康资讯 API 接口(使用银行 Retrofit 实例,baseUrl 为 getDefaultBankBaseUrl())
|
||||
*/
|
||||
interface HealthInfoApi {
|
||||
|
||||
/**
|
||||
* 获取 Token(带签名认证)
|
||||
*/
|
||||
@POST("${UrlConfig.middleCheck}pe/frontend/init")
|
||||
fun getToken(
|
||||
@HeaderMap headers: Map<String, String>,
|
||||
@Body requestBody: RequestBody
|
||||
): Call<TokenResponse>
|
||||
|
||||
/**
|
||||
* 获取栏目列表
|
||||
*/
|
||||
@GET("${UrlConfig.middleCheck}cms/frontend/category/list")
|
||||
fun getCategoryList(
|
||||
@HeaderMap headers: Map<String, String>
|
||||
): Call<CategoryListResponse>
|
||||
|
||||
/**
|
||||
* 分页查询文章列表
|
||||
*/
|
||||
@GET("${UrlConfig.middleCheck}cms/frontend/articleList")
|
||||
fun getArticleList(
|
||||
@HeaderMap headers: Map<String, String>,
|
||||
@QueryMap params: Map<String, String>
|
||||
): Call<ArticleListBean>
|
||||
}
|
||||
|
||||
/**
|
||||
* Token 接口响应外层
|
||||
*/
|
||||
data class TokenResponse(
|
||||
val msg: String? = null,
|
||||
val code: Int = 0,
|
||||
val data: TokenBean? = null
|
||||
)
|
||||
|
||||
/**
|
||||
* 栏目列表接口响应外层
|
||||
*/
|
||||
data class CategoryListResponse(
|
||||
val msg: String? = null,
|
||||
val code: Int = 0,
|
||||
val data: MutableList<CategoryBean>? = null
|
||||
)
|
||||
@@ -15,8 +15,10 @@ import com.tencent.qcloud.tuikit.tuichat.bean.WorkBean
|
||||
import com.xjjk.healthyclients.R
|
||||
import com.xjjk.healthyclients.adapter.common.MultiItemTypeAdapter
|
||||
import com.xjjk.healthyclients.bankRequest.BankPointRequest
|
||||
import com.xjjk.healthyclients.bankRequest.HealthInfoRequest
|
||||
import com.xjjk.healthyclients.base.BaseVMBFragment
|
||||
import com.xjjk.healthyclients.bean.guidance.GuidanceListBean
|
||||
import com.xjjk.healthyclients.bean.home.CategoryBean
|
||||
import com.xjjk.healthyclients.bean.home.WatchInfoBean
|
||||
import com.xjjk.healthyclients.data.api.HomeApi
|
||||
import com.xjjk.healthyclients.databinding.FragmentHomeBinding
|
||||
@@ -67,6 +69,13 @@ class HomeFragment :
|
||||
var noticeTime = REQUEST_DURATION
|
||||
var watchInfo: WatchInfoBean? = null
|
||||
|
||||
/** 健康资讯请求 */
|
||||
private var mHealthInfoRequest: HealthInfoRequest? = null
|
||||
/** 健康资讯 Token */
|
||||
private var mHealthToken: String? = null
|
||||
/** 健康知识子栏目列表 */
|
||||
private var mKnowledgeCategories: MutableList<CategoryBean> = mutableListOf()
|
||||
|
||||
/** 通知轮播协程 Job,重新启动前先取消旧任务,防止多协程并发叠加 */
|
||||
private var noticeJob: Job? = null
|
||||
|
||||
@@ -140,6 +149,7 @@ class HomeFragment :
|
||||
})
|
||||
mBinding.layoutItem3.fragmentGuidanceRvDoctor.adapter = mGuidanceFragmentDoctorAdapter
|
||||
mBinding.watchView.init(this@HomeFragment)
|
||||
setupHealthViews()
|
||||
}
|
||||
|
||||
override fun bindEvent() {
|
||||
@@ -169,9 +179,9 @@ class HomeFragment :
|
||||
}
|
||||
mBinding.watchView.mBinding.watchName.setOnClickListener {
|
||||
if (DataStoreManager.isLogin()) {
|
||||
if (watchInfo?.hasWatch==true){
|
||||
showWatchBindDialog(watchInfo?.watchNo)
|
||||
}
|
||||
// if (watchInfo?.hasWatch==true){
|
||||
// showWatchBindDialog(watchInfo?.watchNo)
|
||||
// }
|
||||
} else {
|
||||
toActivity(LoginActivity::class.java)
|
||||
}
|
||||
@@ -457,6 +467,7 @@ class HomeFragment :
|
||||
mViewModel.getHomeWatchInfo(DataStoreManager.getUserId())
|
||||
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
|
||||
getBankPointDetail()
|
||||
loadHealthInfoData()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,8 +495,151 @@ class HomeFragment :
|
||||
mViewModel.getHomeWatchInfo(DataStoreManager.getUserId())
|
||||
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
|
||||
getBankPointDetail()
|
||||
loadHealthInfoData()
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 健康资讯相关 ====================
|
||||
|
||||
/** 初始化健康资讯两个 View 的事件回调 */
|
||||
private fun setupHealthViews() {
|
||||
mHealthInfoRequest = HealthInfoRequest()
|
||||
|
||||
// 健康知识 - Tab 切换加载对应栏目文章
|
||||
mBinding.healthKnowledgeView.setOnTabSelectedListener { category ->
|
||||
loadKnowledgeArticles(category.categoryId)
|
||||
}
|
||||
|
||||
// 健康知识 - 列表项点击 → 跳转文章详情 H5
|
||||
mBinding.healthKnowledgeView.setOnItemClickListener { article ->
|
||||
navigateToArticleDetail(article.articleId)
|
||||
}
|
||||
|
||||
// 健康知识 - 更多按钮 → 跳转健康知识 H5 页面
|
||||
mBinding.healthKnowledgeView.setOnMoreClickListener {
|
||||
navigateToHealthKnowledgeMore()
|
||||
}
|
||||
|
||||
// 健康知识 - 搜索
|
||||
mBinding.healthKnowledgeView.setOnSearchClickListener {
|
||||
navigateToHealthKnowledgeSearch()
|
||||
}
|
||||
|
||||
|
||||
// 健康咨询 - 列表项点击 → 跳转文章详情 H5
|
||||
mBinding.healthConsultationView.setOnItemClickListener { article ->
|
||||
navigateToArticleDetail(article.articleId)
|
||||
}
|
||||
|
||||
// 健康咨询 - 更多按钮 → 跳转健康咨询 H5 页面
|
||||
mBinding.healthConsultationView.setOnMoreClickListener {
|
||||
navigateToHealthConsultationMore()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/** 加载健康资讯数据(Token → 栏目 → 文章) */
|
||||
private fun loadHealthInfoData() {
|
||||
mHealthInfoRequest?.fetchToken(
|
||||
onSuccess = { token ->
|
||||
mHealthToken = token
|
||||
loadCategories(token)
|
||||
loadConsultationArticles(token)
|
||||
},
|
||||
onFailure = { /* Token 获取失败,静默处理 */ }
|
||||
)
|
||||
}
|
||||
|
||||
/** 加载栏目列表并设置健康知识 Tab */
|
||||
private fun loadCategories(token: String) {
|
||||
mHealthInfoRequest?.fetchCategoryList(
|
||||
token,
|
||||
onSuccess = { categories ->
|
||||
// 查找健康知识栏目(categoryId=1)的子栏目
|
||||
val knowledgeCategory = categories.find { it.categoryId == 1 }
|
||||
mKnowledgeCategories.clear()
|
||||
knowledgeCategory?.children?.let { mKnowledgeCategories.addAll(it) }
|
||||
mBinding.healthKnowledgeView.setupTabs(mKnowledgeCategories)
|
||||
|
||||
// 默认加载第一个子栏目文章
|
||||
if (mKnowledgeCategories.isNotEmpty()) {
|
||||
loadKnowledgeArticles(mKnowledgeCategories[0].categoryId)
|
||||
}
|
||||
},
|
||||
onFailure = { /* 栏目加载失败,静默处理 */ }
|
||||
)
|
||||
}
|
||||
|
||||
/** 加载健康知识指定栏目下的文章列表 */
|
||||
private fun loadKnowledgeArticles(categoryId: Int) {
|
||||
mHealthToken?.let { token ->
|
||||
mHealthInfoRequest?.fetchArticleList(
|
||||
token, categoryId,
|
||||
onSuccess = { articles ->
|
||||
mBinding.healthKnowledgeView.setArticles(articles)
|
||||
},
|
||||
onFailure = { /* 文章加载失败,静默处理 */ }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** 加载健康咨询文章列表(categoryId=2) */
|
||||
private fun loadConsultationArticles(token: String) {
|
||||
mHealthInfoRequest?.fetchArticleList(
|
||||
token, 2,
|
||||
onSuccess = { articles->
|
||||
mBinding.healthConsultationView.setArticles(articles)
|
||||
},
|
||||
onFailure = { /* 文章加载失败,静默处理 */ }
|
||||
)
|
||||
}
|
||||
|
||||
/** 跳转文章详情 H5 */
|
||||
private fun navigateToArticleDetail(articleId: Int) {
|
||||
val param = mViewModel.enCryptInfoUrl.value
|
||||
if (param.isNullOrEmpty()) {
|
||||
showToast("网络错误")
|
||||
return
|
||||
}
|
||||
val url = "${UrlConfig.getHealthNewsDetailH5Url()}?param=$param&articleId=$articleId"
|
||||
requireContext().startWebActivity(url, isFull = true, myTitle = "文章详情", hideStatus = true)
|
||||
}
|
||||
|
||||
/** 跳转健康知识更多 H5 */
|
||||
private fun navigateToHealthKnowledgeMore() {
|
||||
val param = mViewModel.enCryptInfoUrl.value
|
||||
if (param.isNullOrEmpty()) {
|
||||
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
|
||||
showToast("网络错误")
|
||||
return
|
||||
}
|
||||
val url = "${UrlConfig.getHealthKnowledgeH5Url()}?param=$param"
|
||||
requireContext().startWebActivity(url, isFull = true, myTitle = "健康知识", hideStatus = true)
|
||||
}
|
||||
/** 跳转健康知识 搜索 */
|
||||
private fun navigateToHealthKnowledgeSearch() {
|
||||
val param = mViewModel.enCryptInfoUrl.value
|
||||
if (param.isNullOrEmpty()) {
|
||||
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
|
||||
showToast("网络错误")
|
||||
return
|
||||
}
|
||||
val url = "${UrlConfig.getHealthNewsSearchH5Url()}?param=$param"
|
||||
requireContext().startWebActivity(url, isFull = true, myTitle = "搜索", hideStatus = true)
|
||||
}
|
||||
|
||||
/** 跳转健康咨询更多 H5 */
|
||||
private fun navigateToHealthConsultationMore() {
|
||||
val param = mViewModel.enCryptInfoUrl.value
|
||||
if (param.isNullOrEmpty()) {
|
||||
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
|
||||
showToast("网络错误")
|
||||
return
|
||||
}
|
||||
val url = "${UrlConfig.getHealthConsultationH5Url()}?param=$param"
|
||||
requireContext().startWebActivity(url, isFull = true, myTitle = "健康咨询", hideStatus = true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,10 @@ object UrlConfig {
|
||||
val baseUrlType: BaseUrlType = BaseUrlType.PRODUCT
|
||||
|
||||
// const val middle = "xj_health/" //test
|
||||
// const val middleCheck = "healthcheck/" //test
|
||||
const val middle = "hb/" //product
|
||||
|
||||
const val middleCheck = "hb/" //product
|
||||
//
|
||||
var isOpenIm: Boolean = true
|
||||
|
||||
enum class BaseUrlType(val type: Int) {
|
||||
@@ -122,6 +124,42 @@ object UrlConfig {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 健康资讯 H5 页面基础地址
|
||||
*/
|
||||
fun getHealthNewsH5BaseUrl(): String {
|
||||
return getDefaultBankBaseUrl() + "healthnewsweb/"
|
||||
}
|
||||
|
||||
/**
|
||||
* 健康知识 H5 页面地址
|
||||
*/
|
||||
fun getHealthKnowledgeH5Url(): String {
|
||||
return getHealthNewsH5BaseUrl() + "healthKnow.html"
|
||||
}
|
||||
|
||||
/**
|
||||
* 健康咨询 H5 页面地址
|
||||
*/
|
||||
fun getHealthConsultationH5Url(): String {
|
||||
return getHealthNewsH5BaseUrl() + "healthNews.html"
|
||||
}
|
||||
|
||||
/**
|
||||
* 健康资讯详情 H5 页面地址
|
||||
*/
|
||||
fun getHealthNewsDetailH5Url(): String {
|
||||
return getHealthNewsH5BaseUrl() + "healthNewsDetail.html"
|
||||
}
|
||||
|
||||
/**
|
||||
* 健康资讯搜索 H5 页面地址
|
||||
*/
|
||||
fun getHealthNewsSearchH5Url(): String {
|
||||
return getHealthNewsH5BaseUrl() + "healthSecrch.html"
|
||||
}
|
||||
|
||||
/**
|
||||
* 方便后续加一些其他逻辑
|
||||
*/
|
||||
|
||||
@@ -590,6 +590,7 @@ fun TabLayout.attachViewPager(
|
||||
fun getTabStyle(i: Int): Int {
|
||||
return when (i) {
|
||||
1 -> R.layout.item_tablayout_group_title
|
||||
2 -> R.layout.item_tablayout_group_index_theme//有下标线的绿色
|
||||
else -> R.layout.item_tablayout_group_title
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.xjjk.healthyclients.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.xjjk.healthyclients.R
|
||||
import com.xjjk.healthyclients.adapter.HealthConsultationAdapter
|
||||
import com.xjjk.healthyclients.bean.home.ArticleBean
|
||||
import com.xjjk.healthyclients.databinding.LayoutHealthConsultationBinding
|
||||
|
||||
/**
|
||||
* 健康咨询 View 组件
|
||||
* 头部标题 + 列表(左侧标题+收藏分享信息 / 右侧图片)
|
||||
*/
|
||||
class HealthConsultationView(context: Context?, attrs: AttributeSet?) :
|
||||
RelativeLayout(context, attrs, 0) {
|
||||
|
||||
var mContext: Context? = context
|
||||
var mBinding: LayoutHealthConsultationBinding = DataBindingUtil.inflate(
|
||||
LayoutInflater.from(context),
|
||||
R.layout.layout_health_consultation, this, true
|
||||
)
|
||||
|
||||
private val mAdapter = HealthConsultationAdapter()
|
||||
private var mOnItemClickListener: ((ArticleBean) -> Unit)? = null
|
||||
private var mOnMoreClickListener: (() -> Unit)? = null
|
||||
|
||||
init {
|
||||
mBinding.rvList.layoutManager = LinearLayoutManager(mContext)
|
||||
mBinding.rvList.adapter = mAdapter
|
||||
|
||||
// 列表项点击
|
||||
mAdapter.setOnItemClickListener { _, _, position ->
|
||||
mAdapter.getItem(position)?.let { mOnItemClickListener?.invoke(it) }
|
||||
}
|
||||
|
||||
// 头部更多按钮点击
|
||||
mBinding.ivMore.setOnClickListener {
|
||||
mOnMoreClickListener?.invoke()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** 设置文章列表数据(替换),最多取前 2 条 */
|
||||
fun setArticles(articles: List<ArticleBean>?) {
|
||||
if (articles.isNullOrEmpty()) {
|
||||
mBinding.rvList.visibility = GONE
|
||||
mBinding.tvEmpty.visibility = VISIBLE
|
||||
return
|
||||
} else {
|
||||
mBinding.rvList.visibility = VISIBLE
|
||||
mBinding.tvEmpty.visibility = GONE
|
||||
}
|
||||
val topTwo = articles.take(2).toMutableList()
|
||||
mAdapter.setNewInstance(topTwo)
|
||||
}
|
||||
|
||||
/** 追加文章列表数据(分页加载) */
|
||||
fun addArticles(articles: List<ArticleBean>) {
|
||||
mAdapter.addData(articles)
|
||||
}
|
||||
|
||||
fun setOnItemClickListener(listener: (ArticleBean) -> Unit) {
|
||||
mOnItemClickListener = listener
|
||||
}
|
||||
|
||||
fun setOnMoreClickListener(listener: () -> Unit) {
|
||||
mOnMoreClickListener = listener
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.xjjk.healthyclients.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.xjjk.healthyclients.R
|
||||
import com.xjjk.healthyclients.adapter.HealthKnowledgeAdapter
|
||||
import com.xjjk.healthyclients.bean.home.ArticleBean
|
||||
import com.xjjk.healthyclients.bean.home.CategoryBean
|
||||
import com.xjjk.healthyclients.databinding.LayoutHealthKnowledgeBinding
|
||||
import com.xjjk.healthyclients.superfuntion.onCreateTab
|
||||
|
||||
/**
|
||||
* 健康知识 View 组件
|
||||
* 头部标题 + 搜索栏 + TabLayout(医生说/体检/保健/药品/疾病) + 列表
|
||||
*/
|
||||
class HealthKnowledgeView(context: Context?, attrs: AttributeSet?) :
|
||||
RelativeLayout(context, attrs, 0) {
|
||||
|
||||
var mContext: Context? = context
|
||||
var mBinding: LayoutHealthKnowledgeBinding = DataBindingUtil.inflate(
|
||||
LayoutInflater.from(context),
|
||||
R.layout.layout_health_knowledge, this, true
|
||||
)
|
||||
|
||||
private val mAdapter = HealthKnowledgeAdapter()
|
||||
private var mCategoryList: MutableList<CategoryBean> = mutableListOf()
|
||||
private var mOnTabSelectedListener: ((CategoryBean) -> Unit)? = null
|
||||
private var mOnItemClickListener: ((ArticleBean) -> Unit)? = null
|
||||
private var mOnMoreClickListener: (() -> Unit)? = null
|
||||
private var mOnSearchClickListener: (() -> Unit)? = null
|
||||
|
||||
init {
|
||||
mBinding.rvList.layoutManager = LinearLayoutManager(mContext)
|
||||
mBinding.rvList.adapter = mAdapter
|
||||
|
||||
// 列表项点击
|
||||
mAdapter.setOnItemClickListener { _, _, position ->
|
||||
mAdapter.getItem(position)?.let { mOnItemClickListener?.invoke(it) }
|
||||
}
|
||||
|
||||
// 头部更多按钮点击
|
||||
mBinding.ivMore.setOnClickListener {
|
||||
mOnMoreClickListener?.invoke()
|
||||
}
|
||||
|
||||
// 健康知识 - 搜索
|
||||
mBinding.searchView.root.setOnClickListener {
|
||||
mOnSearchClickListener?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据栏目列表设置 TabLayout
|
||||
* @param categories 子栏目列表(健康知识 categoryId=1 的 children)
|
||||
*/
|
||||
fun setupTabs(categories: MutableList<CategoryBean>) {
|
||||
mCategoryList.clear()
|
||||
mCategoryList.addAll(categories)
|
||||
|
||||
mBinding.tabLayout.removeAllTabs()
|
||||
val array = Array<String>(categories.size) {
|
||||
categories[it].categoryName?:""
|
||||
}
|
||||
mBinding.tabLayout.onCreateTab(array,2){index->
|
||||
mOnTabSelectedListener?.invoke(categories[index!!.position]) ?: return@onCreateTab
|
||||
}
|
||||
}
|
||||
|
||||
/** 设置文章列表数据(替换) */
|
||||
fun setArticles(articles: MutableList<ArticleBean>?) {
|
||||
if (articles.isNullOrEmpty()) {
|
||||
mBinding.rvList.visibility = GONE
|
||||
mBinding.tvEmpty.visibility = VISIBLE
|
||||
return
|
||||
}
|
||||
|
||||
mBinding.rvList.visibility = VISIBLE
|
||||
mBinding.tvEmpty.visibility = GONE
|
||||
|
||||
articles.take(3).let {
|
||||
mAdapter.setNewInstance(it.toMutableList()) }
|
||||
}
|
||||
|
||||
/** 追加文章列表数据(分页加载) */
|
||||
fun addArticles(articles: List<ArticleBean>) {
|
||||
mAdapter.addData(articles)
|
||||
}
|
||||
|
||||
|
||||
fun setOnTabSelectedListener(listener: (CategoryBean) -> Unit) {
|
||||
mOnTabSelectedListener = listener
|
||||
}
|
||||
|
||||
fun setOnItemClickListener(listener: (ArticleBean) -> Unit) {
|
||||
mOnItemClickListener = listener
|
||||
}
|
||||
|
||||
fun setOnMoreClickListener(listener: () -> Unit) {
|
||||
mOnMoreClickListener = listener
|
||||
}
|
||||
|
||||
fun setOnSearchClickListener(listener: () -> Unit) {
|
||||
mOnSearchClickListener = listener
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ class WatchBindDialog(context: Context, var listener: (String,Int) -> Unit) : Al
|
||||
if (TextUtils.isEmpty(watchId)) {
|
||||
binding.etWatchid.isEnabled = true
|
||||
binding.confirm.setText("绑定")
|
||||
type = 0
|
||||
// type = 0
|
||||
} else {
|
||||
binding.etWatchid.isEnabled = false
|
||||
binding.confirm.isEnabled = false
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/theme_color" android:state_selected="true" />
|
||||
<item android:color="@color/text_black_60" />
|
||||
</selector>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- 选中状态-->
|
||||
<item android:drawable="@drawable/bg_theme_background_shape3" android:state_checked="true"/>
|
||||
<item android:drawable="@drawable/bg_theme_background_shape3" android:state_selected="true"/>
|
||||
<!-- 默认状态-->
|
||||
<item android:drawable="@color/colorWhite"/>
|
||||
</selector>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="?attr/colorPrimary" />
|
||||
<corners android:radius="3dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_50"
|
||||
android:background="@color/white">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_marginRight="10dp"
|
||||
android:id="@+id/custom_ll_search"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_35"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="@dimen/dp_18"
|
||||
android:layout_toLeftOf="@+id/custom_search_tv"
|
||||
android:background="@drawable/bg_search_shap_radius23">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/dp_15"
|
||||
android:layout_height="@dimen/dp_15"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="@dimen/dp_17"
|
||||
android:src="@mipmap/ic_search" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/custom_search_et"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="@dimen/dp_12"
|
||||
android:background="@null"
|
||||
android:longClickable="false"
|
||||
android:gravity="center_vertical"
|
||||
android:hint="@string/search_hint"
|
||||
android:maxLines="1"
|
||||
android:imeOptions="actionSearch"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/text_black_66"
|
||||
android:textColorHint="@color/text_black_99"
|
||||
android:textSize="@dimen/txt13" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/custom_search_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginRight="@dimen/dp_22"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/dp_10"
|
||||
android:text="@string/search_submit"
|
||||
android:textColor="@color/text_black_99"
|
||||
android:textSize="@dimen/txt13" />
|
||||
</RelativeLayout>
|
||||
</layout>
|
||||
@@ -169,7 +169,22 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.xjjk.healthyclients.view.HealthKnowledgeView
|
||||
android:id="@+id/health_knowledge_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:layout_marginTop="10dp" />
|
||||
|
||||
<com.xjjk.healthyclients.view.HealthConsultationView
|
||||
android:id="@+id/health_consultation_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:layout_marginTop="10dp" />
|
||||
|
||||
<com.youth.banner.Banner
|
||||
android:layout_marginTop="10dp"
|
||||
android:id="@+id/banner4"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/dp_15"
|
||||
android:paddingTop="@dimen/dp_12"
|
||||
android:paddingRight="@dimen/dp_15">
|
||||
|
||||
<!-- 左侧文字区域 -->
|
||||
|
||||
<!-- 标题 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="90dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="#111225"
|
||||
android:textSize="@dimen/txt15"
|
||||
tools:text="高血压患者日常生活注意事项与饮食指南" />
|
||||
|
||||
|
||||
<!-- 右侧图片 80x60 圆角8 -->
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_cover"
|
||||
android:layout_width="@dimen/dp_80"
|
||||
android:layout_height="@dimen/dp_60"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginLeft="@dimen/dp_12"
|
||||
tools:src="@mipmap/ic_placeholder_rectangle" />
|
||||
<!-- 收藏和分享信息 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_meta"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginTop="@dimen/dp_8"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:textColor="@color/text_tab_color"
|
||||
android:textSize="@dimen/txt12"
|
||||
tools:text="收藏 128 分享 36" />
|
||||
|
||||
<View
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="1dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="#EAECF1" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="130dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/dp_15"
|
||||
android:paddingTop="@dimen/dp_12"
|
||||
android:paddingRight="@dimen/dp_15">
|
||||
|
||||
<!-- 左侧图片 100x100 圆角15 -->
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_cover"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@mipmap/ic_home_item_head_bg" />
|
||||
|
||||
<!-- 右侧文字区域 -->
|
||||
<RelativeLayout
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/dp_120"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 标题 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="#252535"
|
||||
android:textSize="@dimen/txt15"
|
||||
tools:text="高血压患者日常生活注意事项" />
|
||||
|
||||
<!-- 详情 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/tv_title"
|
||||
android:layout_marginTop="@dimen/dp_8"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="@color/text_tab_color"
|
||||
android:textSize="@dimen/txt13"
|
||||
tools:text="高血压是一种常见的慢性疾病,需要长期坚持治疗和管理..." />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- 底部:标签 + 日期 -->
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginLeft="@dimen/dp_120"
|
||||
android:layout_marginBottom="20dp">
|
||||
|
||||
<!-- 标签图标 -->
|
||||
<ImageView
|
||||
android:id="@+id/iv_tag_icon"
|
||||
android:layout_width="@dimen/dp_20"
|
||||
android:layout_height="@dimen/dp_20"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@mipmap/ic_home_know_tag" />
|
||||
|
||||
<!-- 标签文本 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_tag"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="@dimen/dp_4"
|
||||
android:layout_toRightOf="@+id/iv_tag_icon"
|
||||
android:textColor="#14BEBE"
|
||||
android:textSize="@dimen/txt11"
|
||||
tools:text="心血管" />
|
||||
|
||||
<!-- 日期 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:textColor="@color/text_tab_color"
|
||||
android:textSize="@dimen/txt11"
|
||||
tools:text="2024-06-29" />
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="1dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginLeft="120dp"
|
||||
android:background="#EAECF1" />
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/tv_tab_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingVertical="7dp"
|
||||
android:textColor="@color/color_tab_layout_text_theme"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<View
|
||||
android:id="@+id/tv_line"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="3dp"
|
||||
android:layout_below="@+id/tv_text"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:background="@drawable/bg_child_tab_layout_item_line" />
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<data>
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/dp_10"
|
||||
android:background="@drawable/bg_white_background_shap_radius12"
|
||||
>
|
||||
|
||||
<!-- 头部:标题 + 更多箭头 -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/rl_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:background="@mipmap/ic_home_item_head_bg"
|
||||
android:scaleType="fitXY">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:ellipsize="end"
|
||||
android:text="健康咨询"
|
||||
android:textColor="@color/text_black_33"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_more"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:background="@drawable/arrow_right"
|
||||
android:padding="10dp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- 列表 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:nestedScrollingEnabled="false"
|
||||
android:paddingTop="@dimen/dp_10" />
|
||||
|
||||
<!-- 空状态提示 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:gravity="center"
|
||||
android:text="暂无健康咨询"
|
||||
android:textColor="#14BEBE"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<data></data>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="@dimen/dp_10"
|
||||
android:background="@drawable/bg_white_background_shap_radius12"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 头部:标题 + 更多箭头 -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/rl_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:background="@mipmap/ic_home_item_head_bg"
|
||||
android:scaleType="fitXY">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:ellipsize="end"
|
||||
android:text="健康知识"
|
||||
android:textColor="@color/text_black_33"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_more"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:background="@drawable/arrow_right"
|
||||
android:padding="10dp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<include
|
||||
android:id="@+id/search_view"
|
||||
layout="@layout/custom_search_view_home" />
|
||||
<!-- Tab 标签栏 -->
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tab_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@color/white"
|
||||
app:tabIndicatorFullWidth="false"
|
||||
app:tabIndicatorHeight="@dimen/dp_0"
|
||||
app:tabMinWidth="@dimen/dp_0"
|
||||
app:tabMode="fixed"
|
||||
app:tabPaddingEnd="@dimen/dp_0"
|
||||
app:tabPaddingStart="@dimen/dp_0"
|
||||
app:tabRippleColor="@null" />
|
||||
|
||||
<!-- 分隔线 -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dp_1"
|
||||
android:background="@color/line" />
|
||||
|
||||
<!-- 列表 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:nestedScrollingEnabled="false"
|
||||
android:paddingTop="@dimen/dp_10" />
|
||||
|
||||
<!-- 空状态提示 -->
|
||||
<TextView
|
||||
android:id="@+id/tv_empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:gravity="center"
|
||||
android:text="暂无健康知识"
|
||||
android:textColor="#14BEBE"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
Reference in New Issue
Block a user