Commit 878ea97f by konghaorui

补充 PlayerFloatView

parent 6566127c
......@@ -12,10 +12,12 @@ import android.provider.Settings
import android.util.Log
import com.alibaba.android.arouter.launcher.ARouter
import com.tbruyelle.rxpermissions2.RxPermissions
import com.umeng.analytics.MobclickAgent
import com.ydl.component.music.MusicPlayActivity
import com.ydl.component.mvp.DemoContract
import com.ydl.component.mvp.DemoPresenter
import com.ydl.media.music.PlayService
import com.ydl.media.audio.PlayService
import com.ydl.media.view.PlayerFloatHelper
import com.ydl.ydlcommon.mvp.lce.BaseLceActivity
import com.yidianling.common.tools.ToastUtil
import com.yidianling.consultant.ExpertSearchActivity.Companion.HOT_SEARCH_DOCTOR_NAME
......@@ -110,6 +112,12 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
}
override fun onResume() {
super.onResume()
MobclickAgent.onResume(this)
}
override fun onDestroy() {
if (serviceConnection != null) {
unbindService(serviceConnection)
......
......@@ -5,7 +5,7 @@ import android.app.Application;
import android.content.Context;
import android.content.Intent;
import com.ydl.media.music.PlayService;
import com.ydl.media.audio.PlayService;
import com.ydl.ydlcommon.base.delegate.IAppLifecycles;
import com.ydl.ydlcommon.utils.YdlBuryPointUtil;
......
......@@ -13,13 +13,16 @@ import android.widget.SeekBar;
import android.widget.TextView;
import com.ydl.component.R;
import com.ydl.media.music.AudioPlayer;
import com.ydl.media.music.OnPlayerEventListener;
import com.ydl.media.music.enums.PlayModeEnum;
import com.ydl.media.music.model.Music;
import com.ydl.media.music.utils.CoverImageUtils;
import com.ydl.media.audio.AudioPlayer;
import com.ydl.media.audio.OnPlayerEventListener;
import com.ydl.media.audio.enums.PlayModeEnum;
import com.ydl.media.audio.model.Music;
import com.ydl.media.audio.utils.CoverImageUtils;
import com.ydl.media.view.PlayTypeEnum;
import com.ydl.media.view.PlayerFloatHelper;
import com.yidianling.common.tools.ToastUtil;
import java.util.HashMap;
import java.util.Locale;
import java.util.Objects;
......@@ -151,6 +154,11 @@ public class PlayFragment extends Fragment implements View.OnClickListener,
break;
case R.id.iv_play:
play();
if(PlayerFloatHelper.Companion.isShow(getActivity())) {
PlayerFloatHelper.Companion.show(getActivity(), PlayTypeEnum.PLAY_TYPE_FM,new HashMap<>());
}else {
PlayerFloatHelper.Companion.showIfPlaying(getActivity());
}
break;
case R.id.iv_next:
next();
......@@ -271,6 +279,7 @@ public class PlayFragment extends Fragment implements View.OnClickListener,
@Override
public void onDestroy() {
AudioPlayer.Companion.get().removeOnPlayEventListener(this);
PlayerFloatHelper.Companion.onDestroy();
super.onDestroy();
}
......@@ -279,4 +288,9 @@ public class PlayFragment extends Fragment implements View.OnClickListener,
sbProgress.setMax((int) duration);
tvTotalTime.setText(formatTime(duration));
}
@Override
public void onComplete() {
}
}
......@@ -3,11 +3,10 @@ package com.ydl.component.mvp
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.ydl.component.model.HomeFMBean
import com.ydl.media.music.AudioPlayer
import com.ydl.media.music.model.Music
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.audio.model.Music
import com.ydl.ydlcommon.data.http.RxUtils
import com.ydl.ydlcommon.mvp.base.BasePresenter
import com.ydl.ydlcommon.utils.RxLifecycleUtils
import com.ydl.ydlnet.builder.interceptor.YDLTransformer
import com.ydl.ydlnet.client.observer.CommonObserver
/**
......@@ -16,10 +15,10 @@ import com.ydl.ydlnet.client.observer.CommonObserver
*/
class DemoPresenter : BasePresenter<DemoContract.View,DemoContract.Model>(),
DemoContract.Presenter {
override fun loadFmMusic() {
mModel.getFmMusic()
.compose(YDLTransformer.switchSchedulers(mView))
.compose(RxLifecycleUtils.bindToLifecycle(mView))//使用 Rxlifecycle,使 Disposable 和 Activity 一起销毁
.compose(RxUtils.applySchedulers(mView))
.subscribe(object : CommonObserver<HomeFMBean>() {
override fun onError(errorMsg: String) {
}
......@@ -37,8 +36,7 @@ class DemoPresenter : BasePresenter<DemoContract.View,DemoContract.Model>(),
}
override fun loadHome() = mModel!!.getHome()
.compose(YDLTransformer.switchSchedulers(mView))
.compose(RxLifecycleUtils.bindToLifecycle(mView!!))//使用 Rxlifecycle,使 Disposable 和 Activity 一起销毁
.compose(RxUtils.applySchedulers(mView))
.subscribe(object : CommonObserver<JsonObject>() {
override fun onError(errorMsg: String) {
}
......@@ -50,8 +48,7 @@ class DemoPresenter : BasePresenter<DemoContract.View,DemoContract.Model>(),
})
override fun loadUsers() = mModel!!.getUser()
.compose(YDLTransformer.switchSchedulers(mView))
.compose(RxLifecycleUtils.bindToLifecycle(mView!!))//使用 Rxlifecycle,使 Disposable 和 Activity 一起销毁
.compose(RxUtils.applySchedulers(mView))//使用 Rxlifecycle,使 Disposable 和 Activity 一起销毁
.subscribe(object : CommonObserver<JsonArray>() {
override fun onError(errorMsg: String) {
}
......
......@@ -56,6 +56,7 @@ buildscript {
classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.16'
classpath 'com.ydl.plugins:modular:1.0.0'
classpath 'com.ydl:notracepoint-gradle-plugin:0.0.3'
classpath 'com.github.better.restools:ResTools:1.0.1'
}
}
......
modular {
//模块包名
packageName "com.yidianling.consultant"
// 模块发布需要的参数
publish {
modules {
xlzx {
//发布信息 module/api 通用
groupId = "com.ydl"
artifactId = "m-consultant-module-xlzx"
// 上报的业务模块 aar 包的版本号
// 上报的 心理咨询 业务模块 aar 包的版本号
version = "0.0.11"
}
ydl{
//发布信息 module/api 通用
groupId = "com.ydl"
artifactId = "m-consultant-module-ydl"
// 上报的业务模块 aar 包的版本号
// 上报的 壹点灵 业务模块 aar 包的版本号
version = "0.0.11"
}
}
api {
//发布信息 module/api 通用
// 壹点灵/心理咨询 业务模块 API层 jar包的发布信息
groupId = "com.ydl"
artifactId = "m-consultant-api"
// version = "0.0.1"
//开发时注释掉版本号,发布api时打开
//version = "0.0.1"
// API 层打包时需要引入的依赖
apiDependencies {
implementation "com.google.code.gson:gson:2.8.2"
......
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
//apply plugin: 'plugin.resTools' // 资源重命名插件
// 配置插件dsl
//resConfig {
// new_prefix = 'tests_' // 资源前缀
// old_prefix = '' // 老前缀,可为''空字符串
// // === below use default
// // resFolderPath 资源目录
// // srcFolderPath 源代码目录
// // manifestFilePath 清单文件目录
//}
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
}
android {
compileSdkVersion rootProject.ext.android["compileSdkVersion"]
buildToolsVersion rootProject.ext.android["buildToolsVersion"]
defaultConfig {
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
versionCode 1
versionName "1.0"
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
flavorDimensions "versionCode"
}
lintOptions {
abortOnError false
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//前缀的名字
resourcePrefix "tests_"
//Flavor 信息
publishNonDefault true
productFlavors {
ydl {}
xlzx {}
}
sourceSets {
main {
res.srcDirs = [
'src/main/res/layouts/testhome',
'src/main/res/layouts',
'src/main/res'
]
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation 'com.google.code.gson:gson:2.8.2'
implementation "com.alibaba:arouter-api:$arouter_api"
// 注意此处的依赖方式:kotlin中使用和java中使用方式有不同
kapt "com.alibaba:arouter-compiler:$arouter_compiler"
api rootProject.ext.dependencies["ydl-user-router"]
if (rootProject.ext.dev_mode){
//开发时使用
api project(':ydl-webview')
api project(':ydl-platform')
implementation modularPublication('com.ydl:m-test-api')
}else {
//发布时使用
compileOnly rootProject.ext.dependencies["ydl-m-test-api"]
api rootProject.ext.dependencies["ydl-webview"]
api(rootProject.ext.dependencies["ydl-platform"]) {
transitive = true
}
}
}
\ No newline at end of file
modular {
//模块包名
packageName "com.yidianling.tests"
// 模块发布需要的参数
publish {
modules {
xlzx {
groupId = "com.ydl"
artifactId = "m-tests-module-xlzx"
// 上报的 心理咨询 业务模块 aar 包的版本号
version = "0.0.1"
}
ydl{
groupId = "com.ydl"
artifactId = "m-tests-module-ydl"
// 上报的 壹点灵 业务模块 aar 包的版本号
version = "0.0.1"
}
}
api {
//壹点灵/心理咨询 业务模块 API层 jar包的发布信息
groupId = "com.ydl"
artifactId = "m-tests-api"
//开发时注释掉版本号,发布api时打开
//version = "0.0.1"
// API 层打包时需要引入的依赖
apiDependencies {
implementation "com.google.code.gson:gson:2.8.2"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.alibaba:arouter-api:1.4.1'
implementation 'de.greenrobot:eventbus:2.4.0'
}
}
}
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
package com.yidianling.tests;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.yidianling.tests.test", appContext.getPackageName());
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yidianling.tests">
<application>
<activity
android:name=".list.view.TestListActivity"
android:screenOrientation="portrait" />
<activity
android:name=".list.view.TestCategoryListActivity"
android:screenOrientation="portrait"
android:theme="@style/NoTitleTheme"
/>
<activity
android:name=".answer.TestAnswerActivity"
android:screenOrientation="portrait" />
<activity
android:name=".detail.TestDetailActivity"
android:screenOrientation="portrait" />
<!-- 跳转测评详情 中间页面-->
<activity
android:name=".detail.jump.JumpTestDetailActivity"
android:screenOrientation="portrait"
android:theme="@style/Transparent" />
<activity
android:name=".SelectConversationActivity"
android:screenOrientation="portrait" />
<activity
android:name=".result.TestResultActivity"
android:screenOrientation="portrait" />
<activity
android:name=".search.TestSearchActivity"
android:screenOrientation="portrait"
android:theme="@style/NoTitleTheme"
/>
<!--测评首页-->
<activity
android:name=".home.TestHomeActivity"
android:screenOrientation="portrait" />
<!--跳转测试结果 中间页-->
<activity
android:name=".result.jump.JumpTestResultActivity"
android:screenOrientation="portrait"
android:theme="@style/Transparent" />
</application>
</manifest>
package com.yidianling.tests;
import android.support.annotation.Keep;
/**
* Created by hgw on 2018/3/8.
*/
//最近聊天专家
@Keep
public class Recent {
public int uid;
public String name;
public String head;
}
\ No newline at end of file
package com.yidianling.tests;
import android.support.annotation.Keep;
/**
* 聊过天的专家列表
* Created by hgw on 2018/3/8.
*/
@Keep
public class RecentExpert {
private String uid;//专家id
private String head;//专家头像
private String name;//专家名
public RecentExpert(String uid, String head, String name) {
this.uid = uid;
this.head = head;
this.name = name;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getHead() {
return head;
}
public void setHead(String head) {
this.head = head;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
\ No newline at end of file
package com.yidianling.tests
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import com.alibaba.android.arouter.facade.annotation.Route
import com.ydl.ydl_image.module.GlideApp
import com.ydl.ydl_image.transform.GlideCircleTransform
import com.yidianling.router.im.IMRequestCallback
import com.yidianling.tests.router.TestsIn
import com.yidianling.ydlcommon.base.BaseActivity
import com.yidianling.ydlcommon.dialog.NormalDialog
import com.yidianling.ydlcommon.http.YdlRetrofitUtils
import com.yidianling.ydlcommon.http.api.Command
import com.yidianling.ydlcommon.router.YdlCommonOut
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_select_conversation.*
import java.util.*
/**
* Created by Wi1ls on 2016/11/10;
*/
@Route(path = "/test/select_conversation")
class SelectConversationActivity : BaseActivity() {
override fun layoutResId(): Int {
return R.layout.activity_select_conversation
}
override fun initDataAndEvent() {
url = getIntent().getStringExtra("url")
head = getIntent().getStringExtra("head")
title = getIntent().getStringExtra("title")
share_url = getIntent().getStringExtra("share_url")
id = getIntent().getIntExtra("id", 0)
flag = getIntent().getIntExtra("flag", 0)
init()
}
// internal var text_empty: TextView? = null
internal var url: String? = null
internal var head: String? = null
internal var title: String? = null
internal var share_url: String? = null
internal var id: Int = 0
internal var flag: Int = 0
private var myData: MutableList<RecentExpert> = ArrayList<RecentExpert>()
internal fun init() {
getData()
}
@SuppressLint("WrongConstant")
private fun handleData() {
text_empty.visibility = View.INVISIBLE
select_lv.visibility = View.VISIBLE
val conversationAdapter = object : BaseAdapter() {
override fun getCount(): Int {
return myData.size
}
override fun getItem(position: Int): Any {
return myData[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view = LayoutInflater.from(mContext).inflate(R.layout.ui_select_conversation_item, null, false)
val s = view.findViewById<ImageView>(R.id.sdv_head) as ImageView
val n = view.findViewById<TextView>(R.id.name) as TextView
GlideApp.with(mContext)
.load(myData[position].getHead())
.transform(GlideCircleTransform(mContext))
.centerCrop()
.into(s)
n.text = myData[position].name
view.setOnClickListener {
val builder = NormalDialog.Builder(mContext)
builder.setTitle("")
builder.setMessage("确定将测试结果发送给:" + myData[position].name + "?")
builder.setPositiveButton("确定"
) { dialog, which ->
TestsIn.sendTestResultMessage(myData[position].uid, "测试结果", title, head, url, id, share_url,
object : IMRequestCallback<Void> {
override fun onSuccess(t: Void?) {
YdlCommonOut.showToast("发送成功")
finish()
}
override fun onFailed(i: Int) {
YdlCommonOut.showToast("发送失败")
finish()
}
override fun onException(throwable: Throwable?) {
YdlCommonOut.showToast("发送失败")
finish()
}
})
dialog.dismiss()
}
builder.setNegativeButton("取消"
) { dialog, _ -> dialog.dismiss() }
builder.create().show()
}
return view
}
}
select_lv.adapter = conversationAdapter
}
private fun getData() {
val cmd = Command.RecentCmd()
TestRetrofitApi.getTestRetrofitApi().getRecentExpertList(YdlRetrofitUtils.getMaps(cmd))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe({showProgressDialog("")})
.doAfterTerminate({dismissProgressDialog()})
.subscribe(
{
if (it.code == 0) {
for (recent in it.data) {
val recentExpert = RecentExpert(""+recent.uid, recent.head, recent.name)
myData.add(recentExpert)
}
handleData()
} else {
Toast.makeText(this@SelectConversationActivity, it.msg, Toast.LENGTH_SHORT).show()
}
},{
YdlRetrofitUtils.handleError(mContext,it)
})
}
companion object {
val FLAG_SEND_TESTRESULT = 1
}
}
package com.yidianling.tests
import com.ydl.ydlcommon.base.config.YDL_DOMAIN
import com.ydl.ydlcommon.base.config.YDL_DOMAIN_JAVA
import com.ydl.ydlcommon.data.http.BaseAPIResponse
import com.ydl.ydlcommon.data.http.BaseResponse
import com.ydl.ydlnet.YDLHttpUtils
import com.yidianling.tests.answer.HandleResultData
import com.yidianling.tests.detail.model.bean.TestAddOrder
import com.yidianling.tests.detail.model.bean.TestDetail
import com.yidianling.tests.list.model.bean.RecommendSearchItemBean
import com.yidianling.tests.list.model.bean.TestCategory
import com.yidianling.tests.list.model.bean.TestListData
import com.yidianling.tests.result.model.TestResult
import io.reactivex.Observable
import retrofit2.http.*
/**
* 测试相关网络接口
* Created by zqk on 17-11-24.
*/
interface TestRetrofitApi {
companion object {
var instance: TestRetrofitApi? = null
fun getTestRetrofitApi(): TestRetrofitApi {
if (instance == null) {
instance = YDLHttpUtils.obtainApi(TestRetrofitApi::class.java)
}
return instance!!
}
fun clearTestRetrofitApi() {
instance = null
}
}
//获取测试分类
@GET("test-tag/cat_all")
@Headers( YDL_DOMAIN+ YDL_DOMAIN_JAVA)
fun fetchTestCategory(): Observable<BaseAPIResponse<MutableList<TestCategory>>>
/**
* 获取测评红包
*/
@GET("auth/test-coupon/max-coupon-money")
@Headers( YDL_DOMAIN + YDL_DOMAIN_JAVA)
fun fetchMaxCoupon(@Query("uid") uid: String = ""): Observable<BaseAPIResponse<String>>
//获取测试列表
@FormUrlEncoded
@POST("ceshi/list")
fun fetchTestList(@FieldMap params: Map<String, String>): Observable<BaseResponse<TestListData>>
@GET("test-item/top-search")
@Headers( YDL_DOMAIN+ YDL_DOMAIN_JAVA)
fun fetchTopSearch(): Observable<BaseAPIResponse<MutableList<RecommendSearchItemBean>>>
//获取测试列表 - NEW
@GET("test-item/list-by-newTag")
@Headers( YDL_DOMAIN+ YDL_DOMAIN_JAVA)
fun fetchTestListByTag(
//测试标签ID
@Query("testTagId") testTagId:String,
//筛选条件免费付费 2免费 3付费
@Query("testPrice") testPrice:String = "",
//筛选条件测试人数 条件4
@Query("testVisitNum") testVisitNum:String = "",
//筛选条件创建时间 条件5
@Query("testCreateTime") testCreateTime:String = "",
//是否仅付费题 0全部 1仅付费
@Query("onlyFee") onlyFee:String = "0",
@Query("page") page: String,
@Query("uid") uid: String = ""
): Observable<BaseAPIResponse<TestListData>>
//获取测试详情
@FormUrlEncoded
@POST("ceshi/detail")
fun fetchTestDetail(@FieldMap params: Map<String, String>): Observable<BaseResponse<TestDetail>>
//测试详情页面跳转
@FormUrlEncoded
@POST("ceshi/is-answer-h5")
fun getTestDetailJumpType(@FieldMap params: Map<String, String>): Observable<BaseResponse<String>>
//测试详情页 下订单接口
@FormUrlEncoded
@POST("ceshi/add-order")
fun fetchTestAddOrder(@FieldMap params: Map<String, String>): Observable<BaseResponse<TestAddOrder>>
//上传测试答案
@FormUrlEncoded
@POST("ceshi/handle-result")
fun handleResult(@FieldMap params: Map<String, String>): Observable<BaseResponse<HandleResultData>>
//获取测试结果
@FormUrlEncoded
@POST("ceshi/result")
fun fetchResult(@FieldMap params: Map<String, String>): Observable<BaseResponse<TestResult>>
//用户最近聊天专家
@FormUrlEncoded
@POST("sms/recent")
fun getRecentExpertList(@FieldMap params: Map<String, String>): Observable<BaseResponse<List<Recent>>>
}
\ No newline at end of file
package com.yidianling.tests
/**
* Created by haorui on 2019-10-30.
* Des:
*/
class TestsBIConstants{
companion object {
val EVENT_TEST_HOME_SEARCH_CLICK = "测评主页搜索"
val EVENT_TEST_HOME_MINE_CLICK = "测评主页个人中心图标点击"
val EVENT_TEST_HOME_BANNER_CLICK = "测评主页banner点击"
val EVENT_TEST_HOME_CATEGORY_CLICK = "测评主页测评分类点击"
val EVENT_TEST_HOME_LOOP_CLICK = "测评主页轮播点击"
val EVENT_TEST_HOME_DAILY_CLICK = "测评主页每日精选点击"
val EVENT_TEST_HOME_DAILY_CHANGE_CLICK = "测评主页每日精选换一换点击"
val EVENT_TEST_HOME_HOT_CLICK = "测评主页热门推荐点击"
val EVENT_TEST_LIST_SEARCH_CLICK = "测评列表页搜索"
val EVENT_TEST_LIST_MORE_CLICK = "测评列表页更多点击"
val EVENT_TEST_LIST_CATEGORY_CLICK = "测评列表页分类点击"
val EVENT_TEST_LIST_TEST_TITLE_CLICK = "测评列表页测评题点击"
val EVENT_TEST_DETAIL_SHARE_CLICK = "测评详情页顶部分享点击"
val EVENT_TEST_DETAIL_START_CLICK = "测评详情页立即测试点击"
val EVENT_TEST_DETAIL_MORE_CLICK = "测评详情页更多点击"
val EVENT_PAY_CLICK = "支付页面底部按钮点击"
val EVENT_TEST_RESULT_BOTTOM_CLICK = "测评结果页底部点击"
val EVENT_TEST_RESULT_MORE_CLICK = "测评结果页更多点击"
val EVENT_TEST_RESULT_SHARE_CLICK = "测评结果页顶部分享点击"
val PROPERTY_TEST_HOME_BANNER_URL = "banner链接"
val PROPERTY_TEST_HOME_BANNER_NAME = "banner标题"
}
}
package com.yidianling.tests.home.adapter
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import com.yidianling.tests.R
import com.yidianling.tests.home.config.ITestHomeConfig
import kotlinx.android.synthetic.main.testhome_item_load_more.view.*
/**
* @author yuanwai
* @描述:上拉加载更多适配器
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
class AdapterWrapper(private val mAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() ,View.OnClickListener{
private var mShowLoadItem = true
private var mWrapperHolder: WrapperHolder? = null
private var mAdapterType = ADAPTER_TYPE_LINEAR
private var mSpanCount: Int = 0
private var STATUS_FOOTER : Int = 1
/**
* footer回调
*/
private var mFooterCallBack: FooterCallBack? = null
/** 设置Wrapper的类型, 默认是线性的 */
fun setAdapterType(type: Int) {
if (mAdapterType != type) {
mAdapterType = type
}
}
/** 网格布局的网格数量 */
fun setSpanCount(count: Int) {
if (count != mSpanCount) {
mSpanCount = count
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
if (viewType == ITEM_TYPE_LOAD) {
if (mWrapperHolder == null) {
var view = View.inflate(parent.context, R.layout.testhome_item_load_more, null)
view.setOnClickListener(this)
mWrapperHolder = WrapperHolder(view)
}
return mWrapperHolder as WrapperHolder
} else {
return mAdapter.onCreateViewHolder(parent, viewType)
}
}
// 允许显示"加载更多"item, 并且position为末尾时,拦截
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (mShowLoadItem && position == itemCount - 1) {
// 最后一项 不需要做什么额外的事
} else if (position < mAdapter.itemCount) {
// 正常情况
holder.itemView.visibility = View.VISIBLE
mAdapter.onBindViewHolder(holder, position)
} else {
// 网格的补空的情况
holder.itemView.visibility = View.INVISIBLE
}
}
override fun getItemCount(): Int {
if (mAdapterType == ADAPTER_TYPE_LINEAR) {
// 线性布局
return if (mShowLoadItem) mAdapter.itemCount + 1 else mAdapter.itemCount
} else {
// 网格布局
if (!mShowLoadItem)
return mAdapter.itemCount// 不显示load more时直接返回真实数量
val remain = mAdapter.itemCount % mSpanCount // 余数
return if (remain == 0) {
mAdapter.itemCount + 1
} else mAdapter.itemCount + 1 + (mSpanCount - remain)
// 余数不为0时,先凑满再加1
}
}
override fun getItemViewType(position: Int): Int {
// 当显示"加载更多"条目, 并且位置是最后一个时, wrapper进行拦截
return if (mShowLoadItem && position == itemCount - 1) {
ITEM_TYPE_LOAD// 注意要避免和原生adapter返回值重复
} else mAdapter.getItemViewType(position)
// 其他情况交给原生adapter处理
}
fun setLoadItemVisibility(isShow: Boolean) {
if (mShowLoadItem != isShow) {
mShowLoadItem = isShow
notifyDataSetChanged()
}
}
fun setLoadItemState(status: Int) {
STATUS_FOOTER = status
when(status){
ITestHomeConfig.STATUS_UP_LOAD -> {
mWrapperHolder!!.setLoadText("上拉加载更多")
mWrapperHolder!!.setNullDrawable()
mWrapperHolder!!.setLoadPbVisibility(false)
}
ITestHomeConfig.STATUS_LOADING -> {
mWrapperHolder!!.setLoadText("正在加载...")
mWrapperHolder!!.setNullDrawable()
mWrapperHolder!!.setLoadPbVisibility(true)
}
ITestHomeConfig.STATUS_SELECT_ALL -> {
mWrapperHolder!!.setLoadText("查看全部测评")
mWrapperHolder!!.setMoreDrawable()
mWrapperHolder!!.setLoadPbVisibility(false)
}
}
}
internal inner class WrapperHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun setLoadText(text: CharSequence) {
itemView.item_load_tv!!.text = text
}
fun setMoreDrawable(){
val drawable = itemView.context.resources.getDrawable(R.drawable.testhome_more)
/// 这一步必须要做,否则不会显示.
drawable.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
itemView.item_load_tv.setCompoundDrawablesWithIntrinsicBounds(null, null, drawable, null)
}
fun setNullDrawable(){
itemView.item_load_tv.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
}
fun setLoadPbVisibility(show: Boolean) {
itemView.item_load_pb!!.visibility = if (show) View.VISIBLE else View.GONE
}
}
companion object {
/** 线性 */
val ADAPTER_TYPE_LINEAR = 0x01
/** 网格 */
val ADAPTER_TYPE_GRID = 0x02
/** view type : "上拉加载更多" */
private val ITEM_TYPE_LOAD = Integer.MAX_VALUE / 2
}
override fun onClick(v: View?) {
if (ITestHomeConfig.STATUS_SELECT_ALL == STATUS_FOOTER){
mFooterCallBack!!.selectAll()
}
}
/**
* 设置底部footer点击回调
*/
fun setFooterCallBack(footerCallBack: FooterCallBack){
mFooterCallBack = footerCallBack
}
/**
* 底部footer点击回调
*/
interface FooterCallBack{
/**
* 查看全部测评点击事件
*/
fun selectAll()
}
}
\ No newline at end of file
package com.yidianling.tests.home.adapter
import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import com.yidianling.tests.R
import com.yidianling.tests.home.bean.TestHomeDataBean
import com.yidianling.tests.home.config.ITestHomeConfig
import com.yidianling.tests.home.contract.ITestHomeContract
import com.yidianling.tests.home.event.ITestHomeEvent
import com.yidianling.tests.home.widget.*
import java.util.*
/**
* @author yuanwai
* @描述:测评首页列表适配器
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/27
*/
class TestHomeAdapter(private val mContext: Context,
private var mListData: List<TestHomeDataBean>,
private var testHomeEvent: ITestHomeEvent,
private var testHomeView: ITestHomeContract.View) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var categoryViewHolder: CategoryViewHolder? = null
private var bannerViewHolder: BannerViewHolder? = null
var couponMoney = ""
override fun getItemViewType(position: Int): Int {
if (ITestHomeConfig.TYPE_RECOMMENDED == mListData[position].type!!) {
if (mListData[position].body!![0].recommendIsFirst!!) {
return ITestHomeConfig.TYPE_RECOMMENDED_FIRST
}
}
return mListData[position].type!!
}
fun updataItems(list: List<TestHomeDataBean>) {
if (null == mListData || mListData.isEmpty()) {
mListData = ArrayList()
} else {
(mListData as ArrayList).clear()
}
(mListData as ArrayList).addAll(list)
}
fun setBannerRefresh(){
if (null != bannerViewHolder && null != bannerViewHolder!!.bannerView!!) {
bannerViewHolder!!.bannerView!!.setRefresh(false)
}
}
fun addItems(list: List<TestHomeDataBean>) {
if (null == mListData || mListData.isEmpty()) {
mListData = ArrayList()
}
(mListData as ArrayList).addAll(list)
}
fun getList(): List<TestHomeDataBean> {
return mListData
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
when (viewType) {
//banner
ITestHomeConfig.TYPE_BANNER -> {
return BannerViewHolder(TestHomeBannerView(parent.context, testHomeEvent))
}
//分类测评+实时测试状态
ITestHomeConfig.TYPE_CATEGORY -> {
return CategoryViewHolder(TestHomeCategoryView(parent.context, testHomeEvent))
}
//每日精选
ITestHomeConfig.TYPE_DAILY -> {
return DailyViewViewHolder(TestHomeDailyView(parent.context, testHomeEvent, testHomeView))
}
//推荐测评列表
ITestHomeConfig.TYPE_RECOMMENDED -> {
return RecommendedViewHolder(TestHomeRecommendedView(parent.context, testHomeEvent))
}
ITestHomeConfig.TYPE_RECOMMENDED_FIRST -> {
return RecommendedFirstViewHolder(TestHomeRecommendedFirstView(parent.context, testHomeEvent))
}
else -> {
return EmptyViewHolder(View.inflate(parent.context, R.layout.testhome_empty, null))
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) =
if (holder is BannerViewHolder && null != holder.bannerView) {
bannerViewHolder = holder
holder.bannerView!!.initData(mListData[position])
} else if (holder is CategoryViewHolder && null != holder.categoryView) {
categoryViewHolder = holder
holder.categoryView!!.initData(mListData[position])
} else if (holder is DailyViewViewHolder && null != holder.dailyView) {
holder.dailyView!!.couponMoney = couponMoney
holder.dailyView!!.initData(mListData[position])
} else if (holder is RecommendedFirstViewHolder) {
holder.recommendedFirstView!!.couponMoney = couponMoney
holder.recommendedFirstView!!.initData(mListData[position], position)
} else if (holder is RecommendedViewHolder && null != holder.recommendedView) {
holder.recommendedView!!.couponMoney = couponMoney
holder.recommendedView!!.initData(mListData[position], position)
} else if (holder is EmptyViewHolder) {
} else {
}
override fun getItemCount(): Int {
return mListData.size
}
/**
* Banner viewHolder
*/
inner class BannerViewHolder(itemView: TestHomeBannerView) : RecyclerView.ViewHolder(itemView) {
var bannerView: TestHomeBannerView? = null
init {
bannerView = itemView
}
}
/**
* 测评分类+实时测试状态viewHolder
*/
inner class CategoryViewHolder(itemView: TestHomeCategoryView) : RecyclerView.ViewHolder(itemView) {
var categoryView: TestHomeCategoryView? = null
init {
categoryView = itemView
}
}
/**
* 每日精选 viewHolder
*/
inner class DailyViewViewHolder(itemView: TestHomeDailyView) : RecyclerView.ViewHolder(itemView) {
var dailyView: TestHomeDailyView? = null
init {
dailyView = itemView
}
}
/**
* 热门推荐 第一个view的 viewHolder
*/
inner class RecommendedFirstViewHolder(itemView: TestHomeRecommendedFirstView) : RecyclerView.ViewHolder(itemView) {
var recommendedFirstView: TestHomeRecommendedFirstView? = null
init {
recommendedFirstView = itemView
}
}
/**
* 热门推荐viewHolder
*/
inner class RecommendedViewHolder(itemView: TestHomeRecommendedView) : RecyclerView.ViewHolder(itemView) {
var recommendedView: TestHomeRecommendedView? = null
init {
recommendedView = itemView
}
}
/**
* 空ViewHolder
*/
inner class EmptyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var view: View? = null
init {
view = itemView
}
}
fun starBanner() {
if (null != bannerViewHolder && null != bannerViewHolder!!.bannerView) {
bannerViewHolder!!.bannerView!!.startBanner()
}
}
fun stopBanner() {
if (null != bannerViewHolder && null != bannerViewHolder!!.bannerView) {
bannerViewHolder!!.bannerView!!.stopBanner()
}
}
fun onDestory() {
//暂停 实施测评状态轮播
if (null != categoryViewHolder && null != categoryViewHolder!!.categoryView) {
categoryViewHolder!!.categoryView!!.onDestory()
}
//暂停 banner轮播
if (null != bannerViewHolder && null != bannerViewHolder!!.bannerView) {
bannerViewHolder!!.bannerView!!.stopBanner()
}
}
}
\ No newline at end of file
package com.yidianling.tests.home.bean
/**
* @author yuanwai
* @描述: 测评首页数据--body节点
* @Copyright Copyright (c) 2016
* @Company 壹点灵
* @date 2018/7/26
*/
data class TestHomeBodyBean(
/**
* banner
*/
//banner ID
val bannerId : String?,
//banner图片地址
val bannerImageUrl : String?,
//banner 名称
val bannerName : String?,
//跳转地址
val bannerLinkUrl : String?,
/**
* 实时测试状态
*/
//实时测试状态Id
val realTestId : String?,
//实时测试状态用户名+测试了文案
val realTestName : String?,
//实时测试状态测试题标题
val realTestTitle : String?,
//实时测试状态用户头像
val realTestIcon : String?,
//c
val realTestLinkUrl : String?,
/**
* 每日精选
*/
//每日精选Id
val dailyId : String?,
//每日精选标题
val dailyTitle : String?,
//每日精选图片地址
val dailyImageUrl : String?,
//每日精选多人测过的文案
val dailyContent : String?,
//跳转地址
val dailyLinkUrl : String?,
//每日精选价格
val price : String?,
/**
* 推荐测评列表数据
*/
//是否为推荐测评第一个View
var recommendIsFirst : Boolean?,
//推荐测评Id
val recommendedId : String?,
//推荐测评标题
val recommendedTitle : String?,
//推荐测评副标题
val recommendedContent : String?,
//推荐测评图片地址
val recommendedUrl : String?,
//推荐测评费用
val recommendedPrice : String?,
//推荐测评测试人次文案
val recommendedNum : String?,
//跳转地址
val recommendedLinkUrl : String?,
//人气
val recommendedHits : String?)
\ No newline at end of file
package com.yidianling.tests.home.bean
/**
* @author yuanwai
* @描述:测评首页--测评分类数据节点
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
data class TestHomeCategoryBean(
//测评分类Id
val categoryId : String?,
//测评分类名称
val categoryName : String?,
//测评分类图片地址
val categoryUrl : String?,
//测评分类拼音
val categoryTab : String?)
\ No newline at end of file
package com.yidianling.tests.home.bean
/**
* @author yuanwai
* @描述:测评首页数据bean
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
data class TestHomeDataBean(
/**
* 数据分类 8.banner+测评分类 9.实时测试状态 10.每日精选 11.推荐测评
*/
val type: Int?,
/**
* 数据集合节点(数据都会放在这个节点,除测评分类数据为单独节点)
*/
val body : List<TestHomeBodyBean>?,
/**
* 测评分类数据节点( 仅type=8时才需要这个字段 )
*/
val category : List<TestHomeCategoryBean>?,
/**
* 头部数据节点
*/
val head : TestHomeHeadBean?,
/**
* 底部数据节点
*/
val footer : TestHomeFooterBean?,
/**
* 是否显示分割线 0.不显示 1.显示( 当type=11时,diviLine对所有推荐测评数据生效,最后一条会不显示 )
*/
val diviLine : Int?)
\ No newline at end of file
package com.yidianling.tests.home.bean
/**
* @author yuanwai
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/28
*/
data class TestHomeFooterBean(
/**
* 标题
*/
val title : String,
/**
* 1.http开头的 跳转 H5 2.app开头的 跳转原生界面
*/
val linkUrl : String)
\ No newline at end of file
package com.yidianling.tests.home.bean
import java.io.Serializable
/**
* @author yuanwai
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/28
*/
data class TestHomeHeadBean(val title : String?) : Serializable
\ No newline at end of file
package com.yidianling.tests.home.config
/**
* @author yuanwai
* @描述:测评首页配置
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/27
*/
interface ITestHomeConfig{
companion object {
/**
* banner
*/
const val TYPE_BANNER = 8
/**
* 测评分类+实时测试状态
*/
const val TYPE_CATEGORY = 9
/**
* 每日精选
*/
const val TYPE_DAILY = 10
/**
* 推荐测评列表
*/
const val TYPE_RECOMMENDED = 11
/**
* 推荐测评列表 第一个View 类型
*/
const val TYPE_RECOMMENDED_FIRST = 999
/**
* 底部view加载类型
* 1.上拉加载 2.加载中 3.查看全部测评
*/
const val STATUS_UP_LOAD = 1
const val STATUS_LOADING = 2
const val STATUS_SELECT_ALL = 3
}
}
\ No newline at end of file
package com.yidianling.tests.home.contract
import com.ydl.ydlcommon.mvp.base.IModel
import com.ydl.ydlcommon.mvp.base.IPresenter
import com.ydl.ydlcommon.mvp.base.IView
import com.yidianling.tests.home.bean.TestHomeDataBean
import io.reactivex.Observable
/**
* @author yuanwai
* @描述:测试首页约束类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
interface ITestHomeContract{
//View接口
interface View : IView {
/**
* 测评首页数据请求
*/
fun newHomeRequest()
/**
* 测评首页数据请求结果
*/
fun newHomeResponse(datalist : List<TestHomeDataBean>)
/**
* 测评首页数据请求失败
*/
fun newHomeRequestFail()
/**
* 每日精选 换一批
*/
fun dailyChange()
/**
* 测评首页换一批请求结果
*/
fun dailyChangeResponse(dataBean : TestHomeDataBean)
/**
* 加载更多
*/
fun loadMoreResponse(datalist : List<TestHomeDataBean>)
/**
* 显示错误信息
*/
fun showError(msg : String?)
}
interface Presenter : IPresenter<View> {
/**
* 测评首页数据请求
*/
fun newHomeRequest()
/**
* 上拉加载更多
*/
fun onLoadMore(page : Int)
/**
* 每日精选 换一批
*/
fun dailyChange()
}
interface Model: IModel {
/**
* 测评首页数据请求
*/
fun newHomeRequest() : Observable<List<TestHomeDataBean>>
/**
* 每日精选 换一批
*/
fun dailyChange() : Observable<TestHomeDataBean>
}
}
\ No newline at end of file
package com.yidianling.tests.home.event
/**
* @author yuanwai
* @描述:测评首页点击事件接口类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/8/3
*/
interface ITestHomeEvent {
/**
* 跳转我的界面
*/
fun jumpMine()
/**
* 跳转搜索界面
*/
fun jumpSearch()
/**
* banner点击事件
*/
fun bannerClick(linkUrl: String?, position: Int, title: String?)
/**
* 测评分类点击事件
* @param tabName 标签名称
*/
fun categoryClick(tabName: String?, position: Int, title: String?,id: String?)
/**
* 实时测评状态点击事件
*/
fun realTestClick(linkUrl: String?, title: String?)
/**
* 每日精选点击事件
*/
fun dailyClick(linkUrl: String?, position: Int, title: String?)
/**
* 热门推荐点击事件
*/
fun recommendedClick(linkUrl: String?, position: Int, title: String?)
/**
* 查看全部测评
*/
fun selectAll()
}
\ No newline at end of file
package com.yidianling.tests.home.event
import android.app.Activity
import android.content.Context
import android.net.Uri
import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity
import com.ydl.ydl_router.manager.YDLRouterManager
import com.ydl.ydl_router.manager.YDLRouterParams
import com.ydl.ydlcommon.router.IYDLRouterConstant
import com.ydl.ydlcommon.utils.BuryPointUtils
import com.ydl.ydlcommon.utils.UMEventUtils
import com.yidianling.router.RouterManager
import com.yidianling.tests.TestsBIConstants
import com.yidianling.tests.list.view.TestCategoryListActivity
import com.yidianling.tests.router.TestsIn
import com.yidianling.tests.search.TestSearchActivity
import com.yidianling.ydlcommon.constant.UMConstants
import com.yidianling.ydlcommon.h5.H5Params
import com.yidianling.ydlcommon.h5.NewH5Activity
import com.yidianling.ydlcommon.http.YdlRetrofitUtils
import com.yidianling.ydlcommon.router.IYDLRouterConstant
import com.yidianling.ydlcommon.tool.BuryPointUtils
import com.yidianling.ydlcommon.utils.UMEventUtils
/**
* @author yuanwai
* @描述:测评首页点击事件实现类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/8/3
*/
class TestHomeEventImpl(mContext: Context) : ITestHomeEvent {
var context: Context? = null
init {
context = mContext
}
/**
* 跳转我的界面
*/
override fun jumpMine() {
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_HOME_MINE_CLICK, "", "")
// TestHomeUtils.buildJumpMine(context!!)
if (!TestsIn.isLogin()) {
//如果未登录 走登录逻辑
context!!.startActivity(TestsIn.loginWayIntent(context as Activity))
return
}
val testParam = H5Params(YdlRetrofitUtils.MH5_URL + "ceshi/my-test", "测试记录")
NewH5Activity.start(context, testParam)
}
/**
* 跳转搜索界面
*/
override fun jumpSearch() {
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_HOME_SEARCH_CLICK, "", "")
TestSearchActivity.start(context!!)
}
/**
* banner点击事件
*/
override fun bannerClick(linkUrl: String?, position: Int, title: String?) {
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_HOME_BANNER_CLICK, TestsBIConstants.PROPERTY_TEST_HOME_BANNER_URL, linkUrl)
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_HOME_BANNER_CLICK, TestsBIConstants.PROPERTY_TEST_HOME_BANNER_NAME, title)
//埋点
BuryPointUtils.getInstance().createMap()
.put("position", position)
.put("title", title)
.burryPoint("ceping_banner")
link(linkUrl)
}
/**
* 测评分类点击事件
*/
override fun categoryClick(tabName: String?, position: Int, title: String?, id: String?) {
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_HOME_CATEGORY_CLICK, TestsBIConstants.PROPERTY_TEST_HOME_CATEGORY_NAME, title)
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_HOME_CATEGORY_CLICK, TestsBIConstants.PROPERTY_TEST_HOME_CATEGORY_ID, id)
//埋点
BuryPointUtils.getInstance().createMap()
.put("position", position)
.put("title", title)
.burryPoint("ceping_icon")
// TestListActivity.start(context!!, tabName)
TestCategoryListActivity.start(context!!, tabName)
}
/**
* 实时测试状态点击事件
*/
override fun realTestClick(linkUrl: String?, title: String?) {
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_HOME_LOOP_CLICK, TestsBIConstants.PROPERTY_TEST_HOME_LOOP_NAME, title)
//埋点
BuryPointUtils.getInstance().createMap()
.put("title", title)
.burryPoint("ceping_current")
link(linkUrl)
}
/**
* 每日精选点击事件
*/
override fun dailyClick(linkUrl: String?, position: Int, title: String?) {
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_HOME_DAILY_CLICK, TestsBIConstants.PROPERTY_TEST_HOME_DAILY_NAME, title)
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_HOME_DAILY_CLICK, TestsBIConstants.PROPERTY_TEST_HOME_DAILY_URL, title)
//埋点
BuryPointUtils.getInstance().createMap()
.put("position", position)
.put("title", title)
.burryPoint("ceping_Featured")
link(linkUrl)
}
/**
* 热门推荐点击事件
*/
override fun recommendedClick(linkUrl: String?, position: Int, title: String?) {
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_HOME_HOT_CLICK, TestsBIConstants.PROPERTY_TEST_HOME_HOT_URL, linkUrl)
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_HOME_HOT_CLICK, TestsBIConstants.PROPERTY_TEST_HOME_HOT_NAME, title)
//埋点
BuryPointUtils.getInstance().createMap()
.put("position", position)
.put("title", title)
.burryPoint("ceping_recommend")
link(linkUrl)
}
private fun link(linkUrl: String?) {
if (null == linkUrl || linkUrl.isEmpty()) {
return
}
if (linkUrl.startsWith("app")) {
val uri = Uri.parse(linkUrl)
if ("ceshi" == uri.host) {
val id = uri.getQueryParameter("id")
// YDLRouterManager.router(IYDLRouterConstant.ROUTER_TEST_DETAIL, YDLRouterParams().putExtra(IYDLRouterConstant.EXTRA_ID, id))
RouterManager.getTestsRouter()?.testDetailH5(id)
}
} else if (linkUrl.startsWith("http")) {
YDLRouterManager.router(
IYDLRouterConstant.ROUTER_H5_H5,
YDLRouterParams().putExtra(IYDLRouterConstant.EXTRA_URL, linkUrl), "")
} else {
YDLRouterManager.router(linkUrl)
}
}
/**
* 查看全部测评点击事件
*/
override fun selectAll() {
// TestListActivity.start(context!!)
TestCategoryListActivity.start(context!!)
}
}
\ No newline at end of file
package com.yidianling.tests.home.event
/**
* 更新优惠券金额
*/
class UpdateCouponMoneyEvent(val money: String)
package com.yidianling.tests.home.http
import com.yidianling.tests.home.bean.TestHomeDataBean
import com.yidianling.tests.home.param.TestHomeParam
import com.yidianling.ydlcommon.http.BaseResponse
import io.reactivex.Observable
/**
* @author yuanwai
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
interface ITestHomeHttp{
/**
* 测评首页请求
*/
fun newHomeRequest(testHomeParam: TestHomeParam): Observable<BaseResponse<List<TestHomeDataBean>>>
/**
* 每日精选--换一批
*/
fun dailyChange(testHomeParam: TestHomeParam): Observable<BaseResponse<TestHomeDataBean>>
}
\ No newline at end of file
package com.yidianling.tests.home.http
import com.yidianling.tests.home.bean.TestHomeDataBean
import com.yidianling.ydlcommon.http.BaseResponse
import io.reactivex.Observable
import retrofit2.http.FieldMap
import retrofit2.http.FormUrlEncoded
import retrofit2.http.POST
/**
* @author yuanwai
* @描述:测评首页API
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
interface TestHomeApi{
//测评首页
@FormUrlEncoded
@POST("ceshi/new-home")
fun newHome(@FieldMap params: Map<String, String>): Observable<BaseResponse<List<TestHomeDataBean>>>
//每日精选 换一批
@FormUrlEncoded
@POST("ceshi/flush-daily-selection")
fun dailySelection(@FieldMap params: Map<String, String>): Observable<BaseResponse<TestHomeDataBean>>
}
\ No newline at end of file
package com.yidianling.tests.home.http
/**
* @author yuanwai
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
object TestHomeDataManager{
fun getHttp(): ITestHomeHttp = TestHomeHttpImpl.getInstance()
}
\ No newline at end of file
package com.yidianling.tests.home.http
import com.yidianling.tests.home.bean.TestHomeDataBean
import com.yidianling.tests.home.param.TestHomeParam
import com.yidianling.ydlcommon.http.BaseResponse
import com.yidianling.ydlcommon.http.RetrofitProvider
import com.yidianling.ydlcommon.http.RxUtils
import io.reactivex.Observable
/**
* @author yuanwai
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
class TestHomeHttpImpl private constructor() : ITestHomeHttp {
companion object {
fun getInstance(): TestHomeHttpImpl {
return Holder.INSTANCE
}
fun clearTestHomeApi() {
Holder.INSTANCE.testHomeApi = null
}
}
object Holder {
val INSTANCE = TestHomeHttpImpl()
}
private var testHomeApi: TestHomeApi? = null
private fun getTestHomeApi(): TestHomeApi {
if (testHomeApi == null){
testHomeApi=RetrofitProvider.getRetrofit().create(TestHomeApi::class.java)
}
return testHomeApi!!
}
// private val testHomeApi: TestHomeApi by lazy {
// RetrofitProvider.getRetrofit().create(TestHomeApi::class.java)
// }
override fun newHomeRequest(testHomeParam: TestHomeParam): Observable<BaseResponse<List<TestHomeDataBean>>> {
return RxUtils.mapObservable(testHomeParam)
.flatMap {
getTestHomeApi().newHome(it)
}
}
override fun dailyChange(testHomeParam: TestHomeParam): Observable<BaseResponse<TestHomeDataBean>> {
return RxUtils.mapObservable(testHomeParam)
.flatMap {
getTestHomeApi().dailySelection(it)
}
}
fun fetchMaxCoupon(){
}
}
\ No newline at end of file
package com.yidianling.tests.home.model
import com.ydl.ydlcommon.data.http.RxUtils
import com.yidianling.tests.home.bean.TestHomeDataBean
import com.yidianling.tests.home.contract.ITestHomeContract
import com.yidianling.tests.home.http.TestHomeDataManager
import com.yidianling.tests.home.param.TestHomeParam
import io.reactivex.Observable
/**
* @author yuanwai
* @描述:测评首页数据模型实现类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
class TestHomeModelImpl : ITestHomeContract.Model{
/**
* 测评首页
*/
override fun newHomeRequest() : Observable<List<TestHomeDataBean>> {
return TestHomeDataManager.getHttp().newHomeRequest(TestHomeParam( 0))
.compose(RxUtils.resultData())
}
/**
* 每日精选--换一批
*/
override fun dailyChange() : Observable<TestHomeDataBean>{
return TestHomeDataManager.getHttp().dailyChange(TestHomeParam( 1))
.compose(RxUtils.resultData())
}
}
\ No newline at end of file
package com.yidianling.tests.home.param
/**
* @author yuanwai
* @描述:测评首页请求参数bean
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
data class TestHomeParam(val type : Int)
\ No newline at end of file
package com.yidianling.tests.home.presenter
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.ydl.ydlcommon.mvp.base.BasePresenter
import com.ydl.ydlcommon.utils.RxLifecycleUtils
import com.yidianling.tests.home.contract.ITestHomeContract
import com.yidianling.tests.home.model.TestHomeModelImpl
import com.yidianling.tests.home.utils.TestHomeUtils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
/**
* @author yuanwai
* @描述:测评首页逻辑实现类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
class TestHomePresenterImpl:
BasePresenter<ITestHomeContract.View, ITestHomeContract.Model>(), ITestHomeContract.Presenter{
/**
* 实例化数据模型
*/
override fun createModel(): ITestHomeContract.Model {
return TestHomeModelImpl()
}
/**
* 测评首页数据请求
*/
override fun newHomeRequest() {
val disposable = mModel.newHomeRequest()
.map { it }
.filter { it != null }
.observeOn(AndroidSchedulers.mainThread())
.compose(RxLifecycleUtils.bindToLifecycle(mView))//使用 Rxlifecycle,使 Disposable 和 Activity 一起销毁
.subscribe(Consumer {
mView.newHomeResponse(it)
}, object : ThrowableConsumer() {
override fun accept(msg: String) {
mView.showError(msg)
}
})
}
/**
* 加载更多
*/
override fun onLoadMore(page : Int) {
mView.loadMoreResponse(TestHomeUtils.getRecommedDataByPage(page))
}
/**
* 每日精选 换一批
*/
override fun dailyChange() {
val disposable = mModel.dailyChange()
.map { it }
.filter { it != null }
.observeOn(AndroidSchedulers.mainThread())
.compose(RxLifecycleUtils.bindToLifecycle(mView))
.subscribe(Consumer {
mView.dailyChangeResponse(it)
}, object : ThrowableConsumer() {
override fun accept(msg: String) {
mView.showError(msg)
}
})
}
}
\ No newline at end of file
package com.yidianling.tests.home.widget
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.GridLayoutManager
import android.widget.AbsListView.OnScrollListener.SCROLL_STATE_IDLE
import com.yidianling.tests.home.adapter.AdapterWrapper
import com.yidianling.tests.home.config.ITestHomeConfig
/**
* @author yuanwai
* @描述:上拉加载更多帮助类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/26
*/
class SwipeToLoadHelper(recyclerView: RecyclerView, private val mAdapterWrapper: AdapterWrapper) : RecyclerView.OnScrollListener() ,AdapterWrapper.FooterCallBack{
private val mRecyclerView: RecyclerView? = null
private val mLayoutManager: RecyclerView.LayoutManager
private var mListener: LoadMoreListener? = null
/** 是否正在加载中 */
private var mLoading = false
/** 上拉刷新功能是否开启 */
private var mIsSwipeToLoadEnabled = true
init {
mLayoutManager = recyclerView.layoutManager
if (mLayoutManager is GridLayoutManager) {
mAdapterWrapper.setAdapterType(AdapterWrapper.ADAPTER_TYPE_GRID)
mAdapterWrapper.setSpanCount(mLayoutManager.spanCount)
} else if (mLayoutManager is LinearLayoutManager) {
mAdapterWrapper.setAdapterType(AdapterWrapper.ADAPTER_TYPE_LINEAR)
}
mAdapterWrapper.setFooterCallBack(this)
// 将OnScrollListener设置RecyclerView
recyclerView.addOnScrollListener(this)
}
override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
if (mIsSwipeToLoadEnabled && SCROLL_STATE_IDLE === newState && !mLoading) {
if (mLayoutManager is GridLayoutManager) {
val gridLayoutManager = mLayoutManager
gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (mIsSwipeToLoadEnabled) {
// 功能开启, 根据位置判断, 最后一个item时返回整个宽度, 其他位置返回1
// AdapterWrapper会保证最后一个item会从新的一行开始
if (position == mLayoutManager.getItemCount() - 1) {
gridLayoutManager.spanCount
} else {
1
}
} else {
1
}
}
}
}
if (mLayoutManager is LinearLayoutManager) {
val linearLayoutManager = mLayoutManager
val lastCompletePosition = linearLayoutManager.findLastCompletelyVisibleItemPosition()
// only when the complete visible item is second last
if (lastCompletePosition == mLayoutManager.getItemCount() - 2) {
val firstCompletePosition = linearLayoutManager.findFirstCompletelyVisibleItemPosition()
val child = linearLayoutManager.findViewByPosition(lastCompletePosition)
?: return
val deltaY = recyclerView!!.bottom - recyclerView.paddingBottom - child.bottom
if (deltaY > 0 && firstCompletePosition != 0) {
recyclerView.smoothScrollBy(0, -deltaY)
}
} else if (lastCompletePosition == mLayoutManager.getItemCount() - 1) {
// 最后一项完全显示, 触发操作, 执行加载更多操作 禁用回弹判断
mLoading = true
mAdapterWrapper.setLoadItemState(ITestHomeConfig.STATUS_LOADING)
if (mListener != null) {
mListener!!.onLoad()
}
}
}
}
}
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
}
/** 设置下拉刷新功能是否开启 */
fun setSwipeToLoadEnabled(isSwipeToLoadEnabled: Boolean) {
if (mIsSwipeToLoadEnabled != isSwipeToLoadEnabled) {
mIsSwipeToLoadEnabled = isSwipeToLoadEnabled
mAdapterWrapper.setLoadItemVisibility(isSwipeToLoadEnabled)
}
}
/** 设置LoadMore Item为加载完成状态, 上拉加载更多完成时调用 */
fun setLoadMoreFinish() {
mLoading = false
mAdapterWrapper.setLoadItemState(ITestHomeConfig.STATUS_UP_LOAD)
}
/**
* 设置LoadMore Item为没有更多数据状态 显示查看全部测评
*/
fun setNoMoreData(){
mLoading = false
mAdapterWrapper.setLoadItemState(ITestHomeConfig.STATUS_SELECT_ALL)
}
override fun selectAll() {
mListener!!.selectAll()
}
/** 上拉操作触发时调用的接口 */
fun setLoadMoreListener(loadMoreListener: LoadMoreListener) {
mListener = loadMoreListener
}
interface LoadMoreListener {
/**
* 加载更多
*/
fun onLoad()
/**
* 查看全部测评
*/
fun selectAll()
}
}
\ No newline at end of file
package com.yidianling.tests.home.widget
import android.content.Context
import android.support.v4.view.PagerAdapter
import android.support.v4.view.ViewPager
import android.view.View
import android.widget.ImageView
import com.ydl.ydl_image.module.GlideApp
import com.yidianling.tests.R
import com.yidianling.tests.home.bean.TestHomeBodyBean
import com.yidianling.tests.home.event.ITestHomeEvent
import java.util.*
/**
* @author yuanwai
* @描述:测评首页banner viewpager适配器
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/27
*/
class TestHomeBannerAdapter(
/**
* 数据集合
*/
var mDataList: List<TestHomeBodyBean>,
var mContext: Context,
var testHomeEvent: ITestHomeEvent) : PagerAdapter() {
private var mImageViews: List<ImageView>? = null
/**
* 初始化
*/
init {
updataImage()
}
/**
* 更新图片集合 todo 待优化 yuanwai 2018/07/27
*/
private fun updataImage() {
if (null == mImageViews || mImageViews!!.isEmpty()) {
mImageViews = ArrayList()
} else {
(mImageViews as ArrayList).clear()
}
var count = mDataList.size - 1
for (index in 0..count) {
var item = mDataList[index]
val imageView = ImageView(mContext)
imageView.scaleType = ImageView.ScaleType.FIT_XY
GlideApp.with(mContext)
.load(item.bannerImageUrl)
.placeholder(R.drawable.testhome_banner_nor)
.centerCrop()
.into(imageView)
(mImageViews as ArrayList<ImageView>).add(imageView)
imageView.setOnClickListener {
testHomeEvent.bannerClick(item.bannerLinkUrl, index, item.bannerName)
}
}
}
override fun getCount(): Int {
return mDataList.size
}
/**
* 数据更新
*/
fun updataItems(items: List<TestHomeBodyBean>) {
if (items.isEmpty()) {
return
}
if (null == mDataList) {
mDataList = ArrayList()
} else {
(mDataList as ArrayList).clear()
}
(mDataList as ArrayList<TestHomeBodyBean>).addAll(items)
updataImage()
notifyDataSetChanged()
}
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view === `object`
}
override fun destroyItem(container: View?, position: Int, `object`: Any?) {
}
override fun instantiateItem(container: View?, position: Int): Any {
try {
(container as ViewPager).addView(mImageViews!!.get(position % mDataList.size), 0)
} catch (e: Exception) {
}
return mImageViews!!.get(position % mDataList.size)
}
}
\ No newline at end of file
package com.yidianling.tests.home.widget
import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import com.yidianling.common.tools.RxImageTool
import com.yidianling.tests.R
import com.yidianling.tests.home.bean.TestHomeBodyBean
import com.yidianling.tests.home.bean.TestHomeDataBean
import com.yidianling.tests.home.event.ITestHomeEvent
import com.yidianling.ydlcommon.view.banner.GlideImageLoader
import kotlinx.android.synthetic.main.testhome_banner_view.view.*
/**
* @author yuanwai
* @描述:测评首页banner
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/27
*/
class TestHomeBannerView(context: Context?, testHomeEvent: ITestHomeEvent) : FrameLayout(context) {
/**
* banner数据缓存
*/
private var mDataList: List<TestHomeBodyBean>? = null
/**
* 数据缓存
*/
private var mDataBean: TestHomeDataBean? = null
private var testHomeEvent: ITestHomeEvent? = null
private var dp14 = 0
private var dp4 = 0
private var margin = 0
private var isRefresh: Boolean? = false
init {
this.testHomeEvent = testHomeEvent
initView()
}
private fun initView() {
val params = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
View.inflate(context, R.layout.testhome_banner_view, this)
layoutParams = params
dp14 = RxImageTool.dip2px(14f)
dp4 = RxImageTool.dip2px(4f)
margin = RxImageTool.dip2px(2.5f)
}
fun setRefresh(isRefresh: Boolean) {
this.isRefresh = isRefresh
}
fun initData(dataBean: TestHomeDataBean) {
if (isRefresh!!) {
return
}
isRefresh = true
if (null == dataBean ||
(dataBean.body == null && null == dataBean.category) ||
(dataBean.body!!.isEmpty() && dataBean.category!!.isEmpty())) {
visibility = View.GONE
return
}
mDataBean = dataBean
visibility = View.VISIBLE
if (null == mDataList) {
mDataList = ArrayList()
} else {
(mDataList as ArrayList).clear()
}
(mDataList as ArrayList<TestHomeBodyBean>).addAll(mDataBean!!.body!!)
var urlLists = ArrayList<String>()
var count = (mDataList as ArrayList<TestHomeBodyBean>).size - 1
for (index in 0..count) {
urlLists.add((mDataList as ArrayList<TestHomeBodyBean>)[index].bannerImageUrl!!)
}
banner.setImageLoader(GlideImageLoader(R.drawable.testhome_banner_nor)).setImages(urlLists).start()
banner.setOnBannerListener {
testHomeEvent!!.bannerClick((mDataList as ArrayList<TestHomeBodyBean>)[it].bannerLinkUrl, it, (mDataList as ArrayList<TestHomeBodyBean>)[it].bannerName)
}
// initAdapter()
// initTimer()
}
// /**
// * 更新适配器
// */
// private fun initAdapter() {
// isInitFinish = false
//
// if (null == bannerAdapter) {
// bannerAdapter = TestHomeBannerAdapter(mDataList as ArrayList<TestHomeBodyBean>, context, testHomeEvent!!)
// viewPager.adapter = bannerAdapter
// } else {
// bannerAdapter!!.updataItems(mDataList as ArrayList<TestHomeBodyBean>)
// }
// viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
// override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
// }
//
// override fun onPageSelected(position: Int) {
// countImg = position
// setImageBackground(position % tips!!.size)
// }
//
// override fun onPageScrollStateChanged(state: Int) {
// }
//
// })
// updataPoint()
// isInitFinish = true
// countImg = 0
// }
//
// /**
// * 更新viewpager 指示器原点
// */
// private fun updataPoint() {
// if (null == tips) {
// tips = ArrayList()
// } else {
// (tips as ArrayList).clear()
// }
// ll_tips!!.removeAllViews()
// var index = 0
// var imageWidth = 0
// for (item in mDataList!!) {
// val imageView = ImageView(context)
//
// if (index == 0) {
// imageWidth = dp14
// imageView.setBackgroundResource(R.drawable.testhome_tip_select)
// } else {
// imageWidth = dp4
// imageView.setBackgroundResource(R.drawable.testhome_tip_unselect)
// }
// var layoutParams = LinearLayout.LayoutParams(imageWidth, dp4)
// imageView.scaleType = ImageView.ScaleType.FIT_XY
// layoutParams.leftMargin = margin
// layoutParams.rightMargin = margin
// imageView.layoutParams = layoutParams
// index++
// (tips as ArrayList<ImageView>).add(imageView)
// ll_tips!!.addView(imageView)
// }
// }
//
// /**
// * 改变图片
// */
// private fun setImageBackground(selectItems: Int) {
// var count = tips!!.size
// var imageWidth = 0
// for (i in 0..count) {
// var imageView = ll_tips!!.getChildAt(i)
// if (null == imageView) {
// return
// }
// if (imageView !is ImageView) {
// return
// }
// if (i == selectItems) {
// imageWidth = dp14
// imageView.setBackgroundResource(R.drawable.testhome_tip_select)
// } else {
// imageWidth = dp4
// imageView.setBackgroundResource(R.drawable.testhome_tip_unselect)
// }
// var params = LinearLayout.LayoutParams(imageWidth, dp4)
// params.leftMargin = margin
// params.rightMargin = margin
// imageView.layoutParams = params
// }
// }
//
// override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
// val action = ev.action
// if (action == MotionEvent.ACTION_DOWN) {
// timeDown = System.currentTimeMillis()
// viewPager.isClick = true
// } else if (action == MotionEvent.ACTION_UP) {
// timeUp = System.currentTimeMillis()
// viewPager.isClick = false
// }
// return super.dispatchTouchEvent(ev)
// }
// private var dcTime = 0
//
// private fun initTimer() {
// //计时,如果没有用户干预,每5秒进行vp操作,
// if (null != mTimer) {
// dcTime = 0
// mTimer!!.cancel()
// }
// mTimer = Timer(true)
// mTimer!!.schedule(object : TimerTask() {
// override fun run() {
// if (isNeedStop) {
// return
// }
// dcTime++
// if (dcTime % 5 == 0) {
// updateUI()
// }
// }
// }, 0, 1000)
// }
// internal fun updateUI() {
// if (!isInitFinish)
// return
//
// Observable.just(0)
// .observeOn(AndroidSchedulers.mainThread())
// .subscribe { integer ->
//
// countImg++
// countImg %= if (bannerAdapter!!.count == 0) 1 else bannerAdapter!!.count
// viewPager.currentItem = countImg
// }
// }
fun startBanner() {
if (banner != null) {
banner.startAutoPlay()
}
}
fun stopBanner() {
if (banner != null) {
banner.stopAutoPlay()
}
}
}
\ No newline at end of file
package com.yidianling.tests.home.widget
import android.content.Context
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.ydl.ydl_image.module.GlideApp
import com.yidianling.common.tools.RxImageTool
import com.yidianling.tests.R
import com.yidianling.tests.home.bean.TestHomeBodyBean
import com.yidianling.tests.home.bean.TestHomeCategoryBean
import com.yidianling.tests.home.bean.TestHomeDataBean
import com.yidianling.tests.home.event.ITestHomeEvent
import com.yidianling.ydlcommon.utils.ScreenUtil
import kotlinx.android.synthetic.main.testhome_category_view.view.*
import java.util.*
/**
* @author yuanwai
* @描述:测评首页测评分类View
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/27
*/
class TestHomeCategoryView(mContext: Context, testHomeEvent: ITestHomeEvent) : LinearLayout(mContext) {
/**
* 数据缓存
*/
var mDataList: List<TestHomeCategoryBean>? = null
/**
* 分类view宽度
*/
var categoryWidth: Int = 0
/**
* 图片宽高
*/
var imageViewWidth: Int = 0
/**
* 文本宽度
*/
var textViewWidth: Int = 0
/**
* 文本高度
*/
var textViewHeight: Int = 0
/**
* 间隔
*/
var margin: Int = 0
var dp8: Int = 0
/**
* 是否添加了实时测试状态View
*/
var hasRealTestView: Boolean = false
private var realTestView: TestHomeRealTestView? = null
/**
* 线
*/
private var lineView: View? = null
/**
* 图片View缓存
*/
private var imageViewCache: List<ImageView>? = null
/**
* 文本View缓存
*/
private var textViewCache: List<TextView>? = null
/**
* 倍数
*/
private var multiple: Int = 0
/**
* 测评首页事件处理类
*/
private var testHomeEvent: ITestHomeEvent? = null
init {
initView()
this.testHomeEvent = testHomeEvent
}
/**
* 界面初始化
*/
private fun initView() {
orientation = VERTICAL
View.inflate(context, R.layout.testhome_category_view, this)
val params = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
layoutParams = params
initArgs()
}
/**
* 初始化变量
*/
private fun initArgs() {
categoryWidth = ScreenUtil.screenWidth - RxImageTool.dp2px(30f)
textViewWidth = categoryWidth / 4
imageViewWidth = RxImageTool.dip2px(38f)
margin = (categoryWidth - 4 * imageViewWidth) / 8
dp8 = RxImageTool.dip2px(8f)
//高度=文字12dp+16dp间距
textViewHeight = RxImageTool.dip2px(28f)
}
fun initData(bean: TestHomeDataBean) {
if (null == bean ||
(bean.body == null && bean.category == null) ||
(bean.body!!.isEmpty() && bean.category!!.isEmpty())) {
visibility = View.GONE
return
}
visibility = View.VISIBLE
if (null == mDataList) {
mDataList = ArrayList<TestHomeCategoryBean>()
} else {
(mDataList as ArrayList).clear()
}
(mDataList as ArrayList<TestHomeCategoryBean>).addAll(bean.category!!)
refreshView()
setRealTextView(bean.body)
}
/**
* 刷新View
*/
private fun refreshView() {
var i = 0
if (null == imageViewCache) {
imageViewCache = ArrayList()
}
if (null == textViewCache) {
textViewCache = ArrayList()
}
var imageCount = imageViewCache!!.size
for (item in this!!.mDataList!!) {
if (i > 7) {
break
}
if (i >= imageCount) {
val imageView = createIcon(i)
val textView = createText(i)
(imageViewCache as ArrayList).add(imageView)
(textViewCache as ArrayList).add(textView)
fl_root.addView(imageView)
fl_root.addView(textView)
imageView.setOnClickListener {
testHomeEvent!!.categoryClick(item.categoryTab, i, item.categoryName, item.categoryId)
}
textView.setOnClickListener {
testHomeEvent!!.categoryClick(item.categoryTab, i, item.categoryName, item.categoryId)
}
}
bindIconData(imageViewCache!!.get(i), item)
bindTextData(textViewCache!!.get(i), item)
i++
}
}
/**
* 创建图标
*/
private fun createIcon(i: Int): ImageView {
val imageParams = FrameLayout.LayoutParams(imageViewWidth, imageViewWidth)
val imageView = ImageView(context)
imageView.scaleType = ImageView.ScaleType.CENTER_CROP
if (i > 3) {
multiple = 2
imageParams.topMargin = imageViewWidth + dp8 + textViewHeight
imageParams.leftMargin = margin * (i - 3) + (i - 4) * (imageViewWidth + margin)
} else {
multiple = 1
imageParams.leftMargin = margin * (i + 1) + i * (imageViewWidth + margin)
}
imageView.layoutParams = imageParams
return imageView
}
/**
* 加载图片
*/
private fun bindIconData(imageView: ImageView, categoryBean: TestHomeCategoryBean) {
GlideApp.with(context).load(categoryBean.categoryUrl).placeholder(R.drawable.testhome_type_nor)
.centerCrop().into(imageView)
}
/**
* 创建文本
*/
private fun createText(index: Int): TextView {
val textParams = FrameLayout.LayoutParams(textViewWidth, textViewHeight)
val textView = TextView(context)
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f)
textView.gravity = Gravity.CENTER_HORIZONTAL
if (index > 3) {
textParams.topMargin = 2 * (imageViewWidth + dp8) + textViewHeight
textParams.leftMargin = textViewWidth * (index - 4)
} else {
textParams.topMargin = imageViewWidth + dp8
textParams.leftMargin = textViewWidth * (index)
}
textView.layoutParams = textParams
return textView
}
/**
* 设置文本
*/
private fun bindTextData(textView: TextView, categoryBean: TestHomeCategoryBean) {
textView.text = categoryBean.categoryName
}
/**
* 初始化实时测评状态View
*/
private fun initRealTextView() {
var realTestParam = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
realTestParam.topMargin = multiple * (imageViewWidth + dp8 + textViewHeight) + dp8 + RxImageTool.dip2px(10f)
realTestView = TestHomeRealTestView(context, testHomeEvent!!)
realTestView!!.layoutParams = realTestParam
}
private fun initLineView() {
var lineParam = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, RxImageTool.dip2px(0.5f))
var dp15 = RxImageTool.dip2px(15f)
lineParam.leftMargin = dp15
lineParam.rightMargin = dp15
lineParam.topMargin = multiple * (imageViewWidth + dp8 + textViewHeight) + dp8
lineView = View(context)
lineView!!.setBackgroundColor(resources.getColor(R.color.testhome_line))
lineView!!.layoutParams = lineParam
}
/**
* 实时测评状态赋值
*/
private fun setRealTextView(list: List<TestHomeBodyBean>) {
if (!hasRealTestView) {
initLineView()
fl_root.addView(lineView)
initRealTextView()
fl_root.addView(realTestView)
hasRealTestView = true
}
realTestView!!.initData(list)
}
fun onDestory() {
if (null == realTestView) {
return
}
realTestView!!.onDestory()
}
}
\ No newline at end of file
package com.yidianling.tests.home.widget
import android.content.Context
import android.graphics.Color
import android.support.v7.widget.CardView
import android.text.TextUtils
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import com.ydl.ydl_image.module.GlideApp
import com.yidianling.common.tools.RxImageTool
import com.yidianling.tests.R
import com.yidianling.tests.home.bean.TestHomeBodyBean
import com.yidianling.tests.home.event.ITestHomeEvent
import com.yidianling.tests.home.utils.TestHomeUtils
import kotlinx.android.synthetic.main.testhome_dailyitem_view.view.*
/**
* @author yuanwai
* @描述:每日精选itemView
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/8/1
*/
class TestHomeDailyHorizoItemView(mContext: Context, testHomeEvent: ITestHomeEvent, isRight: Boolean) : CardView(mContext) {
/**
* 测评首页事件处理类
*/
private var testHomeEvent: ITestHomeEvent? = null
private var isRight: Boolean? = false
var couponMoney = ""
init {
this.testHomeEvent = testHomeEvent
this.isRight = isRight
initView()
}
/**
* 界面初始化
*/
private fun initView() {
var params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
View.inflate(context, R.layout.testhome_dailyitem_view, this)
var dp6 = RxImageTool.dip2px(6f)
if (isRight!!) {
params.setMargins(dp6, RxImageTool.dip2px(5f), RxImageTool.dip2px(15f), RxImageTool.dip2px(5f))
} else {
params.setMargins(dp6, RxImageTool.dip2px(5f), dp6, RxImageTool.dip2px(5f))
}
layoutParams = params
radius = RxImageTool.dip2px(6f).toFloat()
cardElevation = RxImageTool.dip2px(2f).toFloat()
}
/**
* 设置数据
*/
fun initData(bodyBean: TestHomeBodyBean, position: Int) {
GlideApp.with(context).load(bodyBean.dailyImageUrl)
.placeholder(R.drawable.testhome_list_nor)
.centerCrop().into(img_icon)
tv_title.text = bodyBean.dailyTitle
tv_content.text = TestHomeUtils.getNum(context, bodyBean.dailyContent)
setPrice(bodyBean.price)
setOnClickListener {
testHomeEvent!!.dailyClick(bodyBean.dailyLinkUrl, position, bodyBean.dailyTitle)
}
}
private fun setPrice(price : String?){
if (TextUtils.isEmpty(price)){
tv_price.visibility = View.INVISIBLE
return
}
tv_price.visibility = View.VISIBLE
if (price.equals("免费")
||TextUtils.isEmpty(price)
|| "0" == price
|| "0.0" == price
|| "0.00" == price){
tv_price.text = "免费"
tv_price.setBackgroundResource(R.drawable.testhome_recom_price_bg)
tv_price.setTextColor(Color.parseColor("#34CD65"))
} else {
var newPrice = TestHomeUtils.getOriginalPrice(tv_coupon_money,price,couponMoney)
var priceContent = "¥$newPrice"
TestHomeUtils.priceStyleNew(context, tv_price, priceContent, 1, priceContent.length)
tv_price.setBackgroundResource(R.drawable.testhome_null)
}
}
}
\ No newline at end of file
package com.yidianling.tests.home.widget
import android.content.Context
import android.view.View
import android.widget.HorizontalScrollView
import com.yidianling.tests.R
import com.yidianling.tests.home.bean.TestHomeBodyBean
import com.yidianling.tests.home.event.ITestHomeEvent
import kotlinx.android.synthetic.main.testhome_dailyhorizo_view.view.*
/**
* @author yuanwai
* @描述:测评首页--每日精选横向滚动父View
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/8/1
*/
class TestHomeDailyHorizoView(mContext: Context, testHomeEvent: ITestHomeEvent) : HorizontalScrollView(mContext) {
private var testHomeEvent: ITestHomeEvent? = null
var couponMoney = ""
init {
this.testHomeEvent = testHomeEvent
initView()
}
/**
* 界面初始化
*/
private fun initView() {
View.inflate(context, R.layout.testhome_dailyhorizo_view, this)
isVerticalScrollBarEnabled = false
isHorizontalScrollBarEnabled = false
}
/**
* 设置数据
*/
fun initData(list: List<TestHomeBodyBean>) {
var index = 0
for (item in list) {
if (index >= ll_root.childCount) {
if (index == list.size - 1) {
//如果没创建 就创建view并赋值
ll_root.addView(TestHomeDailyHorizoItemView(context, testHomeEvent!!, true))
} else {
//如果没创建 就创建view并赋值
ll_root.addView(TestHomeDailyHorizoItemView(context, testHomeEvent!!, false))
}
}
//如果view已创建 那就重新赋值
var childView = ll_root.getChildAt(index)
if (childView is TestHomeDailyHorizoItemView) {
childView.couponMoney = this.couponMoney
childView.initData(item, index)
}
index++
}
//如果本次数据小于上一次的数据 那就将多余的View 隐藏掉
if (index < childCount) {
for (i in index..childCount) {
getChildAt(i).visibility = View.GONE
}
}
}
}
\ No newline at end of file
package com.yidianling.tests.home.widget
import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import com.yidianling.common.tools.RxImageTool
import com.yidianling.tests.R
import com.yidianling.tests.home.bean.TestHomeDataBean
import com.yidianling.tests.home.contract.ITestHomeContract
import com.yidianling.tests.home.event.ITestHomeEvent
import kotlinx.android.synthetic.main.testhome_daily_view.view.*
/**
* @author yuanwai
* @描述:测评首页--每日精选View
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/27
*/
class TestHomeDailyView(mContext: Context,
testHomeEvent: ITestHomeEvent,
testHomeView: ITestHomeContract.View
)
: RelativeLayout(mContext) {
/**
* 数据缓存
*/
private var mDataBean: TestHomeDataBean? = null
private var mView: View? = null
private var testHomeEvent: ITestHomeEvent? = null
private var testHomeView: ITestHomeContract.View? = null
/**
* 底部线是否添加
*/
private var hasLine: Boolean = false
var couponMoney = ""
init {
this.testHomeView = testHomeView
this.testHomeEvent = testHomeEvent
initView()
}
/**
* 界面初始化
*/
private fun initView() {
var params = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
layoutParams = params
mView = View.inflate(context, R.layout.testhome_daily_view, this)
testhome_dailyRight.setOnClickListener {
testHomeView!!.dailyChange()
}
}
/**
* 设置数据
*/
fun initData(dataBean: TestHomeDataBean) {
//如果数据为空 隐藏当前View
if (null == dataBean || null == dataBean.body || dataBean.body.isEmpty()) {
visibility = View.GONE
return
}
visibility = View.VISIBLE
mDataBean = dataBean
refreshView()
}
/**
* 界面刷新
*/
fun refreshView() {
//标题赋值
createTitle()
//列表赋值
createDailyHorizo()
addBottomLine()
}
/**
* 创建标题
*/
private fun createTitle() {
if (null == mDataBean) {
tv_title.text = ""
return
}
tv_title.text = mDataBean!!.head!!.title
}
/**
* 创建每日精选横向滚动View
*/
private fun createDailyHorizo() {
var dailyHorizoView = getChildAt(childCount - 2)
if (dailyHorizoView is TestHomeDailyHorizoView) {
dailyHorizoView.couponMoney = this.couponMoney
dailyHorizoView.initData(mDataBean!!.body!!)
} else {
var params = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
dailyHorizoView = TestHomeDailyHorizoView(context, testHomeEvent!!)
dailyHorizoView.id = R.id.testhome_daily
dailyHorizoView.couponMoney = this.couponMoney
dailyHorizoView.initData(mDataBean!!.body!!)
params.addRule(BELOW, R.id.tv_title)
params.leftMargin = RxImageTool.dip2px(9f)
dailyHorizoView.layoutParams = params
addView(dailyHorizoView)
}
}
/**
* 添加底部灰色线
*/
private fun addBottomLine() {
if (!hasLine) {
hasLine = true
var param = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, RxImageTool.dip2px(9f))
var bottomLine = View(context)
bottomLine.setBackgroundColor(resources.getColor(R.color.testhome_line))
param.addRule(BELOW, R.id.testhome_daily)
bottomLine.layoutParams = param
addView(bottomLine)
}
}
}
\ No newline at end of file
package com.yidianling.tests.home.widget
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.DecelerateInterpolator
import android.view.animation.TranslateAnimation
import android.widget.FrameLayout
import com.yidianling.tests.R
import com.yidianling.tests.home.bean.TestHomeBodyBean
import com.yidianling.tests.home.event.ITestHomeEvent
import kotlinx.android.synthetic.main.testhome_realtest_view_in.view.*
import kotlinx.android.synthetic.main.testhome_realtest_view_out.view.*
/**
* @author yuanwai
* @描述:测评首页--实时测试状态View
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/28
*/
class TestHomeRealTestView(mContext : Context,testHomeEvent : ITestHomeEvent) : FrameLayout(mContext){
private val STATUS_IN = 0
private val STATUS_OUT = 1
private var curTipIndex = 0
private var lastTimeMillis: Long = 0
private val ANIM_DELAYED_MILLIONS = 2 * 1000
/**
* 动画持续时长
*/
private val ANIM_DURATION = 500
/**
* 进、出 两个view (主要用于做动画,其实是两个相同的布局文件)
*/
private var view_out: View? = null
private var view_in:View? = null
/**
* 进、出 两个View 的动画
*/
private var anim_out: Animation? = null
private var anim_in:Animation? = null
/**
* 数据缓存
*/
private var mDataList : List<TestHomeBodyBean>? = null
private var testHomeEvent : ITestHomeEvent? = null
private val mHandler: Handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message?) {
super.handleMessage(msg)
updateTipAndPlayAnimation()
sendMessageDelayed(Message(), ANIM_DELAYED_MILLIONS.toLong())
}
}
init {
this.testHomeEvent = testHomeEvent
initView()
initAnimation()
}
/**
* 界面初始化
*/
private fun initView() {
var params = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT)
view_out = View.inflate(context, R.layout.testhome_realtest_view_out,null)
view_in = View.inflate(context, R.layout.testhome_realtest_view_in,null)
addView(view_out)
addView(view_in)
layoutParams = params
}
private fun initAnimation() {
anim_out = newAnimation(0f, -1f)
anim_in = newAnimation(1f, 0f)
anim_in!!.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
}
override fun onAnimationRepeat(animation: Animation) {
}
override fun onAnimationEnd(animation: Animation) {
updateViewVisibility()
}
})
}
/**
* 设置数据
*/
fun initData(list: List<TestHomeBodyBean>){
mHandler.removeCallbacksAndMessages(null)
if (null == list || list.isEmpty()){
visibility = View.GONE
return
}
visibility = View.VISIBLE
if (null == mDataList){
mDataList = ArrayList()
}else{
(mDataList as ArrayList).clear()
}
(mDataList as ArrayList).addAll(list)
curTipIndex = 0
updateTip(STATUS_OUT)
updateTipAndPlayAnimation()
mHandler.sendMessageDelayed(Message(), ANIM_DELAYED_MILLIONS.toLong())
}
private fun updateViewVisibility() {
if (curTipIndex % 2 == 0) {
view_out!!.visibility = View.INVISIBLE
} else {
view_in!!.visibility = View.INVISIBLE
}
}
private fun newAnimation(fromYValue: Float, toYValue: Float): Animation {
val anim = TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f,
Animation.RELATIVE_TO_SELF, fromYValue, Animation.RELATIVE_TO_SELF, toYValue)
anim.duration = ANIM_DURATION.toLong()
anim.interpolator = DecelerateInterpolator()
return anim
}
private fun updateTipAndPlayAnimation() {
view_in!!.visibility = View.VISIBLE
view_out!!.visibility = View.VISIBLE
if (curTipIndex % 2 == 0) {
updateTip(STATUS_OUT)
view_in!!.startAnimation(anim_out)
view_out!!.startAnimation(anim_in)
this.bringChildToFront(view_in)
} else {
updateTip(STATUS_IN)
view_out!!.startAnimation(anim_out)
view_in!!.startAnimation(anim_in)
this.bringChildToFront(view_out)
}
}
private fun updateTip(status : Int){
val bodyBean = getNextTip() ?: return
when(status){
STATUS_IN -> {
tv_title_in.text = bodyBean.realTestTitle
tv_name_in.text = getName(bodyBean.realTestName)
view_in!!.setOnClickListener{
testHomeEvent!!.realTestClick(bodyBean.realTestLinkUrl,bodyBean.realTestTitle)
}
}
STATUS_OUT -> {
tv_title_out.text = bodyBean.realTestTitle
tv_name_out.text = getName(bodyBean.realTestName)
view_out!!.setOnClickListener{
testHomeEvent!!.realTestClick(bodyBean.realTestLinkUrl,bodyBean.realTestTitle)
}
}
}
}
private fun getName(name : String?) : String{
var nameBuffer = StringBuffer()
nameBuffer.append(resources.getString(R.string.testhome_just))
nameBuffer.append(" ")
nameBuffer.append(name)
nameBuffer.append(" ")
nameBuffer.append(resources.getString(R.string.testhome_test))
return nameBuffer.toString()
}
private fun getNextTip() : TestHomeBodyBean? {
if (null == mDataList || mDataList!!.isEmpty()){
return null
}
return mDataList!!.get(curTipIndex++ % mDataList!!.size)
}
fun onDestory(){
mHandler.removeCallbacksAndMessages(null)
}
}
\ No newline at end of file
package com.yidianling.tests.home.widget
import android.content.Context
import android.graphics.Color
import android.text.TextUtils
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.TextView
import com.ydl.ydl_image.module.GlideApp
import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.RxImageTool
import com.yidianling.tests.R
import com.yidianling.tests.home.bean.TestHomeBodyBean
import com.yidianling.tests.home.bean.TestHomeDataBean
import com.yidianling.tests.home.event.ITestHomeEvent
import com.yidianling.tests.home.utils.TestHomeUtils
import com.yidianling.ydlcommon.utils.ScreenUtil
import kotlinx.android.synthetic.main.testhome_recommend_first_view.view.*
/**
* @author yuanwai
* @描述:热门推荐列表第一个显示的View
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/8/3
*/
class TestHomeRecommendedFirstView(mContext: Context, testHomeEvent: ITestHomeEvent) : FrameLayout(mContext) {
/**
* 图片宽度
*/
private var imgWidth = 0
private var isAddTitle = false
private var testHomeEvent: ITestHomeEvent? = null
var couponMoney = ""
init {
this.testHomeEvent = testHomeEvent
initView()
}
/**
* 界面初始化
*/
private fun initView() {
View.inflate(context, R.layout.testhome_recommend_first_view, this)
imgWidth = ScreenUtil.screenWidth - RxImageTool.dip2px(30f)
initImageParam()
addTitle()
}
private fun addTitle() {
if (isAddTitle) {
return
}
isAddTitle = true
val params = FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
params.leftMargin = RxImageTool.dip2px(15f)
params.topMargin = RxImageTool.dip2px(30f)
val titleView = TextView(context)
titleView.id = R.id.testhome_recommenTitle
titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18f)
titleView.setTextColor(resources.getColor(R.color.testhome_title))
val drawable = resources.getDrawable(R.drawable.testhome_hot)
/// 这一步必须要做,否则不会显示.
drawable.setBounds(0, 0, drawable.minimumWidth, drawable.minimumHeight)
titleView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
titleView.compoundDrawablePadding = RxImageTool.dip2px(5f)
titleView.layoutParams = params
addView(titleView)
}
fun initData(dataBean: TestHomeDataBean, position: Int) {
if (null == dataBean || null == dataBean.body || dataBean.body.isEmpty()) {
visibility = View.GONE
return
}
//设置标题
findViewById<TextView>(R.id.testhome_recommenTitle).text = dataBean.head!!.title
//设置推荐列表数据
initRecommeded(dataBean.body!![0], position)
}
private fun initImageParam() {
val params = LinearLayout.LayoutParams(imgWidth, imgWidth/2)
img_recom.layoutParams = params
}
/**
* 设置推荐列表数据
*/
private fun initRecommeded(bodyBean: TestHomeBodyBean, position: Int) {
tv_recomTitle.text = bodyBean.recommendedTitle
tv_recomContent.text = bodyBean.recommendedContent
setPrice(bodyBean.recommendedPrice)
tv_recomNum.text = TestHomeUtils.getNum(context, bodyBean.recommendedNum)
GlideApp.with(context).load(bodyBean.recommendedUrl).placeholder(R.drawable.testhome_banner_nor)
.into(img_recom)
LogUtil.e("宽:${img_recom.measuredWidth};高${img_recom.measuredHeight}")
tv_Hits.text = TestHomeUtils.getHits(context, bodyBean.recommendedHits)
setOnClickListener {
testHomeEvent!!.recommendedClick(bodyBean.recommendedLinkUrl, position, bodyBean.recommendedTitle)
}
}
private fun setPrice(price: String?) {
if (TextUtils.isEmpty(price)) {
tv_recomPrice.visibility = View.INVISIBLE
return
}
tv_recomPrice.visibility = View.VISIBLE
if ("免费" == price) {
tv_recomPrice.text = price
tv_recomPrice.setBackgroundResource(R.drawable.testhome_recom_price_bg)
tv_recomPrice.setTextColor(Color.parseColor("#34CD65"))
} else {
var newPrice = TestHomeUtils.getOriginalPrice(tv_coupon_money,price,couponMoney)
var priceContent = "¥$newPrice"
TestHomeUtils.priceStyleNew(context, tv_recomPrice, priceContent, 1, priceContent.length)
tv_recomPrice.setBackgroundResource(R.drawable.testhome_null)
}
}
/**
* 释放
*/
fun onDestory() {
isAddTitle = false
}
}
\ No newline at end of file
package com.yidianling.tests.home.widget
import android.content.Context
import android.graphics.Color
import android.text.Html
import android.text.TextUtils
import android.view.View
import android.widget.RelativeLayout
import com.ydl.ydl_image.module.GlideApp
import com.yidianling.common.tools.RxImageTool
import com.yidianling.tests.R
import com.yidianling.tests.home.bean.TestHomeBodyBean
import com.yidianling.tests.home.bean.TestHomeDataBean
import com.yidianling.tests.home.event.ITestHomeEvent
import com.yidianling.tests.home.utils.TestHomeUtils
import kotlinx.android.synthetic.main.testhome_recommended_view.view.*
/**
* @author yuanwai
* @描述:测评首页--热门推荐View
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/7/28
*/
class TestHomeRecommendedView(mContext: Context, testHomeEvent: ITestHomeEvent) : RelativeLayout(mContext) {
private var testHomeEvent: ITestHomeEvent? = null
var couponMoney = ""
private var dp2 : Int? = 0
private var dp5 : Int? = 0
init {
this.testHomeEvent = testHomeEvent
initView()
}
/**
* 界面初始化
*/
private fun initView() {
View.inflate(context, R.layout.testhome_recommended_view, this)
dp2 = RxImageTool.dip2px(2f)
dp5 = RxImageTool.dip2px(5f)
}
/**
* 设置数据
*/
fun initData(dataBean: TestHomeDataBean, position: Int) {
if (null == dataBean || null == dataBean.body || dataBean.body.isEmpty()) {
visibility = View.GONE
return
}
//设置推荐列表数据
initRecommeded(dataBean.body!!.get(0), position)
}
/**
* 设置推荐列表数据
*/
private fun initRecommeded(bodyBean: TestHomeBodyBean, position: Int) {
tv_recomTitle.text = bodyBean.recommendedTitle
tv_recomContent.text = Html.fromHtml(bodyBean.recommendedContent)
setPrice(bodyBean.recommendedPrice)
tv_recomNum.text = TestHomeUtils.getNum(context, bodyBean.recommendedNum)
GlideApp.with(context).load(bodyBean.recommendedUrl)
.placeholder(R.drawable.testhome_list_nor)
.centerCrop().into(img_recom)
tv_Hits.text = TestHomeUtils.getHits(context, bodyBean.recommendedHits)
setOnClickListener {
testHomeEvent!!.recommendedClick(bodyBean.recommendedLinkUrl, position, bodyBean.recommendedTitle)
}
}
private fun setPrice(price : String?){
if (TextUtils.isEmpty(price)){
tv_recomPrice.visibility = View.INVISIBLE
return
}
tv_recomPrice.visibility = View.VISIBLE
if ("免费" == price){
tv_recomPrice.setPadding(dp5!!,dp2!!,dp5!!,dp2!!)
tv_recomPrice.text = price
tv_recomPrice.setBackgroundResource(R.drawable.testhome_recom_price_bg)
tv_recomPrice.setTextColor(Color.parseColor("#34CD65"))
tv_coupon_money.visibility = View.GONE
}else{
var newPrice = TestHomeUtils.getOriginalPrice(tv_coupon_money,price,couponMoney)
tv_recomPrice.setPadding(0,dp2!!,dp5!!,dp2!!)
var priceContent = "¥$newPrice"
TestHomeUtils.priceStyleNew(context,tv_recomPrice,priceContent, 1, priceContent.length)
tv_recomPrice.setBackgroundResource(R.drawable.testhome_null)
}
}
}
\ No newline at end of file
package com.yidianling.tests.list.model
import com.yidianling.ydlcommon.http.BaseCommand
/**
* 测试列表接口参数
* Created by zqk on 17-11-25.
*/
class TestListCommand : BaseCommand() {
@JvmField
var page: Int = 1
@JvmField
var tab: String? = null
@JvmField
var keyword: String? = null
}
\ No newline at end of file
package com.yidianling.tests.list.model.bean
import com.google.gson.annotations.SerializedName
data class CategotyPopItem(
@field:SerializedName("value")
val value: String? = null,
@field:SerializedName("key")
val key: String? = null
)
\ No newline at end of file
package com.yidianling.tests.list.model.bean
/**
* 测试列表数据
* Created by zqk on 17-11-24.
*/
data class RecommendSearchItemBean(
val id:Int,
val keyWord:String
)
package com.yidianling.tests.list.model.bean
import com.google.gson.annotations.SerializedName
/**
* 测试Model
* Created by zqk on 17-11-22.
*/
data class Test(
//测试项目id
@SerializedName(value = "id", alternate = ["recommendedId"])
val id: Int,
//封面url
@SerializedName(value = "cover", alternate = ["recommendedUrl","shareImage"])
val cover: String?,
//测试标题
@SerializedName(value = "name", alternate = ["recommendedTitle"])
val name: String?,
//测试数量
@SerializedName(value = "test_num", alternate = ["recommendedNum","visitNum"])
val count: String,
@SerializedName("test_result_id")
val testResultId: Int,
//价格
@SerializedName(value = "price", alternate = ["recommendedPrice"])
val price : String,
//人气(点击数)
@SerializedName(value = "hits", alternate = ["recommendedHits"])
val hits : String,
//是否免费 1.付费 2.免费
val isFree : Int,
//内容
@SerializedName(value = "desc", alternate = ["recommendedContent"])
val desc : String,
//支付ID
val pay_id : String?,
//红包金额
@SerializedName(value = "coupon_money", alternate = ["couponMoney"])
val coupon_money : Float?)
\ No newline at end of file
package com.yidianling.tests.list.model.bean
import com.google.gson.annotations.SerializedName
/**
* 测试类型Model
* Created by zqk on 17-11-22.
*/
data class TestCategory(
@SerializedName(value = "tab", alternate = ["pinyin"])
val tab: String?,
@SerializedName(value = "name", alternate = ["alias"])
val name: String?,
val icon: String?,
val sort: Int?,
val catName: String?,
val id: String?
)
\ No newline at end of file
package com.yidianling.tests.list.model.bean
/**
* Created by haorui on 2019/4/11.
* Des:
*/
class TestListContainer {
/**
* pageNum : 1
* pageSize : 10
* size : 10
* startRow : 1
* endRow : 10
* pages : 3
* prePage : 0
* nextPage : 2
* isFirstPage : true
* isLastPage : false
* hasPreviousPage : false
* hasNextPage : true
* navigatePages : 8
* navigatepageNums : [1,2,3]
* navigateFirstPage : 1
* navigateLastPage : 3
* total : 23
* list : [{"id":948,"testCatId":1,"name":"幼儿基础智力测验","price":1,"visitNum":124,"shareImage":"http://img.diggme.cn/2017/09/14/cbecb4544190dabe06e13f12152727be.png@150x150","commentNum":0,"desc":"智力发展是幼儿发展最重要的领域,也是其他领域发展的重要基础。有些孩子的发展可能会落后于他们的年龄阶段,而有些孩子可能会超前。你想知道你孩子的发展水平吗?可以通过这个专业的评估具体了解。这个评估是一个纯图片的测评,3-10岁的孩子都适用。报告以幼儿的智能发展阶段来表示,从辨别能力、类比能力、推理能力三个角度出发,可以用来判断幼儿的智力发展水平是否与生理发展阶段相符。从而判断幼儿智力发展水平属于滞后、正常还是超前,然后针对智力发展滞后的儿童提供相应的参考建议。家长还需要注意孩子的智力发展是一个动态的过程,本次测评结果无法预测孩子将来的成功或失败。① 综合评估孩子的智力水平② 分析孩子在三项能力的表现③ 为孩子提供发展建议▲ 报告部分截图 ▲◆ 温馨提示 ◆1. 本测试评估的是3-10岁儿童的一般智能,请尽量让儿童独立完成。2. 本测评为付费测试,体验价9.9元。3. 测试可重复购买,每次付费仅允许测试一次。4. 如在测试过程中遇到任何问题,欢迎来敲宠物喵(ID:digger1618)","tipsTitle":"","couponNumb":0,"testTagName":"亲子","couponMoney":0,"hits":878},{"id":781,"testCatId":6,"name":"分手挽回:挽回姿态评估","price":0,"visitNum":12,"shareImage":"https://img.ydlcdn.com/file/2018/04/18/kbg8mf4mq8w9c0qk.png","commentNum":0,"desc":"评估你的挽回姿态类型。你在求助专业婚恋情感师之前,在挽回TA的过程之中,曾有过哪些行为?根据自己的实际情况进行选择。","tipsTitle":"","couponNumb":0,"testTagName":"亲子","couponMoney":0,"hits":12},{"id":720,"testCatId":6,"name":"学生学校适应自评量表","price":0,"visitNum":2,"shareImage":"https://img.ydlcdn.com/file/2017/12/12/ms9fc6x64g0d2hci.jpg","commentNum":0,"desc":"亲爱的同学,你好! 此问卷的主要目的是想了解你对学校适应情况。请逐条阅读问卷中的句子,看懂后根据你自己真实的情况或看法填写。这不是考试,只要你依据自己的真实情况,诚实地回答,就是正确的答案","tipsTitle":"","couponNumb":0,"testTagName":"亲子","couponMoney":0,"hits":17},{"id":954,"testCatId":11,"name":"1","price":0,"visitNum":0,"shareImage":"http://img.diggme.cn/2017/09/14/cbecb4544190dabe06e13f12152727be.png@150x150","commentNum":0,"desc":"测试测试","tipsTitle":"1","couponNumb":0,"testTagName":"亲子","couponMoney":0,"hits":27},{"id":955,"testCatId":11,"name":"跳转题","price":0,"visitNum":2,"shareImage":"http://img.diggme.cn/2017/09/14/cbecb4544190dabe06e13f12152727be.png@150x150","commentNum":0,"desc":"测试","tipsTitle":"跳转题","couponNumb":0,"testTagName":"亲子","couponMoney":0,"hits":24},{"id":1023,"testCatId":4,"name":"测测你\u201c中年油腻\u201d了吗?","price":1,"visitNum":3,"shareImage":"","commentNum":0,"desc":"","tipsTitle":"","couponNumb":0,"testTagName":"亲子","couponMoney":0,"hits":21},{"id":1005,"testCatId":4,"name":"抑郁风险评估","price":1,"visitNum":1,"shareImage":"http://img.diggme.cn/2017/09/13/06ac4ad1374c1baba9327ae7c8a0bf43.jpg?x-oss-process=image/auto-orient,1/resize,m_lfit,w_300/quality,q_90","commentNum":0,"desc":"写在最前:本测评并非诊断评估,即使被检出是高风险的状态,也不能依此说明该个体当下已是抑郁障碍人群,进一步的确诊需要前往医院由医生进行诊断。▸ 研究背景 (Theoretical Background)抑郁(Depression),是精神世界的感冒。一种虚无、迟滞、想哭又哭不出来的绝望的状态、带着能量被掏空的疲惫感。全世界大概1/3到一半的人会在一生的某个时刻遭遇抑郁的袭击,而罹患抑郁症的患者人数至少达到了3.2亿。在美国,抑郁障碍的发生率大约在12.5%-14.2%之间。但鉴于医生的漏诊和误诊,这个数字还比较乐观。在我国,抑郁障碍的患病率据报道在5%左右,但近数十年来报告的患病率一直在上升。作为世界第四大疾病,抑郁症的影响还在上升,但我国对于抑郁症的防治还处在识别率较低的局面。因此,我们必须及早重视起来对抑郁风险的预防。那么,一个人究竟为什么患上抑郁障碍?当下的心理研究多认为,抑郁障碍的形成是多个因素综合作用的结果。一部分因素,让有些人存在发生抑郁障碍的风险性;另一部分因素,则让这部分的风险人群更易真正陷入抑郁障碍。▸ 测评内容 (Assessment Content)本次测评,我们针对心理认知方面的易感因素,基于大量的国内外相关文献,以及对抑郁障碍发生的心理机制进行研究,构建了抑郁障碍发生的风险思维模型。&nbsp;大家可以通过该测评,评估自己近期的情绪状态,以及日常思维习惯,依此判断自己是否存在抑郁障碍发生的风险。▸ 你将获得 (What You&#39;ll Gain)✎ 了解你的抑郁风险水平。✎ 了解当前生理情绪方面的抑郁状态程度。✎ 掌握对自身三种主要抑郁思维的分析与评价。 ✎ 得到抗击抑郁的针对性建议。","tipsTitle":"","couponNumb":0,"testTagName":"亲子","couponMoney":0,"hits":52},{"id":990,"testCatId":4,"name":"基础智力测验(图片版)","price":0.01,"visitNum":26,"shareImage":"http://img.diggme.cn/2017/09/14/cbecb4544190dabe06e13f12152727be.png@150x150","commentNum":0,"desc":"智力发展是幼儿发展最重要的领域,也是其他领域发展的重要基础。有些孩子的发展可能会落后于他们的年龄阶段,而有些孩子可能会超前。你想知道你孩子的发展水平吗?可以通过这个专业的评估具体了解。这个评估是一个纯图片的测评,3-10岁的孩子都适用。报告以幼儿的智能发展阶段来表示,从辨别能力、类比能力、推理能力三个角度出发,可以用来判断幼儿的智力发展水平是否与生理发展阶段相符。从而判断幼儿智力发展水平属于滞后、正常还是超前,然后针对智力发展滞后的儿童提供相应的参考建议。家长还需要注意孩子的智力发展是一个动态的过程,本次测评结果无法预测孩子将来的成功或失败。① 综合评估孩子的智力水平② 分析孩子在三项能力的表现③ 为孩子提供发展建议▲ 报告部分截图 ▲◆ 温馨提示 ◆1. 本测试评估的是3-10岁儿童的一般智能,请尽量让儿童独立完成。2. 本测评为付费测试,体验价9.9元。3. 测试可重复购买,每次付费仅允许测试一次。4. 如在测试过程中遇到任何问题,欢迎来敲宠物喵(ID:digger1618)","tipsTitle":"","couponNumb":0,"testTagName":"亲子","couponMoney":0,"hits":53},{"id":935,"testCatId":9,"name":"高级题测试2","price":0.1,"visitNum":116,"shareImage":"http://img.diggme.cn/2017/11/09/65120e66ade331a166d8d8b55bd9a713.png@150x150","commentNum":0,"desc":"财商(Finacial Quotient),全称为财富商数,指认识、创造和管理财富的能力。对于财产的认识、创造和管理能力是能够伴随我们一生的能力。高财商的人能够凭借其管理财富的能力比低财商的人更早一步实现经济自由。在本测评中,我们将会探讨你的财商指数和财商影响因素,评估你在管理财产过程中的风险承受能力和风险偏好,分析你的财富价值观和财富情绪体验。① 综合评估你的财商水平② 剖析影响你的财商因素③ 你的风险能力&amp;财富态度▲ 报告部分截图 ▲◆ 温馨提示 ◆1. 本测评为付费测试,体验价9.9元。2. 测试可重复购买,每次付费仅允许测试一次。3. 如在测试过程中遇到任何问题,欢迎来敲宠物喵(ID:digger1618)","tipsTitle":"","couponNumb":0,"testTagName":"亲子","couponMoney":0,"hits":707},{"id":933,"testCatId":12,"name":"测试啦啦啦","price":0,"visitNum":16,"shareImage":"https://img.yidianling.com/file/2018/09/06/2wtmng827njanj0n.jpg","commentNum":0,"desc":"啦啦啦啦啦","tipsTitle":"啦啦啦啦","couponNumb":0,"testTagName":"亲子","couponMoney":0,"hits":18}]
*/
var pageNum: Int = 0
var pageSize: Int = 0
var size: Int = 0
var startRow: Int = 0
var endRow: Int = 0
var pages: Int = 0
var prePage: Int = 0
var nextPage: Int = 0
var isIsFirstPage: Boolean = false
var isIsLastPage: Boolean = false
var isHasPreviousPage: Boolean = false
var isHasNextPage: Boolean = false
var navigatePages: Int = 0
var navigateFirstPage: Int = 0
var navigateLastPage: Int = 0
var total: Int = 0
var navigatepageNums: List<Int>? = null
var list: MutableList<Test>? = null
}
package com.yidianling.tests.list.model.bean
import com.google.gson.annotations.SerializedName
import com.yidianling.ydlcommon.data.ShareData
/**
* 测试列表数据
* Created by zqk on 17-11-24.
*/
data class TestListData(
@SerializedName("test_items")
val testList: MutableList<Test>?,
//兼容php老接口和java新接口
@SerializedName("testItemListList")
val testListContainer: TestListContainer,
@SerializedName("list_type")
val listType: Int,//列表类型 1测试项目类型,2测试结果类型
val share: ShareData,
val couponMoney: String
)
package com.yidianling.tests.list.presenter
import com.hannesdorfmann.mosby3.mvp.MvpNullObjectBasePresenter
import com.ydl.ydlcommon.data.http.RxUtils
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.yidianling.tests.TestRetrofitApi
import com.yidianling.tests.list.view.TestListActivityView
import com.yidianling.ydlcommon.data.YdlDataManager
import com.yidianling.ydlcommon.http.RxUtils
import com.yidianling.ydlcommon.http.ThrowableConsumer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
/**
* TestListActivityPresenter
* Created by zqk on 17-11-22.
*/
class TestListActivityPresenter : MvpNullObjectBasePresenter<TestListActivityView>() {
fun fetchTestTypeList() {
TestRetrofitApi.getTestRetrofitApi().fetchTestCategory()
.compose(RxUtils.resultJavaData())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ resp ->
view.onTestCategoryListFetched(resp)
}, { t ->
view.onFailed(t.message)
})
}
/**
* 请求红包列表
*/
fun requestCoupon() {
YdlDataManager.getHttp().getCoupon()
.subscribeOn(Schedulers.io())
.compose(RxUtils.resultData())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer {
view.couponResponse(it)
}, object : ThrowableConsumer() {
override fun accept(msg: String) {
view.onFailed(msg)
}
})
}
}
\ No newline at end of file
package com.yidianling.tests.list.presenter
import com.yidianling.tests.list.model.TestListCommand
import com.yidianling.tests.TestRetrofitApi
import com.yidianling.tests.list.view.TestListFragmentView
import com.hannesdorfmann.mosby3.mvp.MvpNullObjectBasePresenter
import com.yidianling.ydlcommon.http.YdlRetrofitUtils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
/**
* TestListFragmentPresenter
* Created by zqk on 17-11-22.
*/
class TestListFragmentPresenter : MvpNullObjectBasePresenter<TestListFragmentView>() {
fun fetchTestList(type: String?, currentPage: Int) {
val cmd = TestListCommand()
cmd.tab = type
cmd.page = currentPage
TestRetrofitApi.getTestRetrofitApi()
.fetchTestList(YdlRetrofitUtils.getMaps(cmd))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ resp ->
view.dismissLoading()
if (resp.code == 0) {
view.onTestListFetched(resp.data, currentPage)
} else {
view.onFailed(resp.msg)
}
}, { t ->
view.onError(t)
})
}
}
\ No newline at end of file
package com.yidianling.tests.list.view
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.support.v4.view.ViewPager
import android.view.View
import android.widget.PopupWindow
import com.alibaba.android.arouter.facade.annotation.Route
import com.yidianling.common.tools.LogUtil
import com.yidianling.common.tools.ToastUtil
import com.yidianling.tests.R
import com.yidianling.tests.base.BaseMvpActivity
import com.yidianling.tests.list.model.bean.TestCategory
import com.yidianling.tests.list.presenter.TestListActivityPresenter
import com.yidianling.tests.list.view.adapter.TestListPagerAdapter
import com.yidianling.tests.router.TestsIn
import com.yidianling.tests.search.TestSearchActivity
import com.yidianling.ydlcommon.constant.UMConstants
import com.yidianling.ydlcommon.http.YdlRetrofitUtils
import com.yidianling.ydlcommon.log.LogHelper
import com.yidianling.ydlcommon.pay.redpacket.RedPacketBean
import com.yidianling.ydlcommon.tool.BuryPointUtils
import com.yidianling.ydlcommon.tool.PopUtils
import com.yidianling.ydlcommon.utils.UMEventUtils
import kotlinx.android.synthetic.main.activity_test_list.*
@Route(path = "/ceshi/list")
class TestListActivity : BaseMvpActivity<TestListActivityView, TestListActivityPresenter>(), TestListActivityView {
override fun layoutResId(): Int {
return R.layout.activity_test_list
}
override fun initDataAndEvent() {
if (null != intent && intent.hasExtra(EXTRA_IS_MINE)) {
isMine = intent.getBooleanExtra(EXTRA_IS_MINE, false)
}
if (null != intent && intent.hasExtra(EXTRA_TABNAME)) {
tabName = intent.getStringExtra(EXTRA_TABNAME)
}
titleBar.setOnRightTextClick { _, _ ->
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_LIST_SEARCH_CLICK, "", "")
TestSearchActivity.start(this)
}
titleBar.setRightImageListener {
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_LIST_MORE_CLICK, "", "")
popupWindow = PopUtils.showMoreItem(mContext,
titleBar.rootView,
0,
0)
}
presenter.fetchTestTypeList()
viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {
UMEventUtils.umEvent(TestsBIConstants.EVENT_TEST_LIST_CATEGORY_CLICK, TestsBIConstants.PROPERTY_TEST_LIST_CATEGORY_NAME, testCategorys?.get(position)?.name)
click_category()
LogUtil.d("page selected: " + testCategorys?.get(position)?.name)
BuryPointUtils.getInstance().createMap()
.put("test_type_click", testCategorys?.get(position)?.name + "")
.burryPoint("Testtype_click")
if (("my" == testCategorys?.get(position)?.tab || "unpay" == testCategorys?.get(position)?.tab) && !TestsIn.isLogin()) {
// RouterManager.startActivity(this@TestListActivity,RouterEnum.USER,null,ClassNameEnum.ChooseLoginWayActivity)
startActivity(TestsIn.loginWayIntent(this@TestListActivity))
}
}
})
}
private fun click_category() {
}
override fun onResume() {
super.onResume()
//获取红包列表
if (TestsIn.isLogin()){
presenter.requestCoupon()
}
}
companion object {
private const val EXTRA_IS_MINE = "is_mine"
private const val EXTRA_TABNAME = "tab"
private const val payRequestCode = 33
fun start(context: Context) {
LogHelper.getInstance().writeLogSync("跳转到测试题")
val intent = Intent(context, TestListActivity::class.java)
context.startActivity(intent)
}
fun start(context: Context, isMine: Boolean) {
LogHelper.getInstance().writeLogSync("跳转到测试题")
val intent = Intent(context, TestListActivity::class.java)
intent.putExtra(EXTRA_IS_MINE, isMine)
context.startActivity(intent)
}
/**
* 根据所传的tab标签 定位到指定标签下
*/
fun start(context: Context, tab: String?) {
LogHelper.getInstance().writeLogSync("跳转到测试题")
val intent = Intent(context, TestListActivity::class.java)
intent.putExtra(EXTRA_TABNAME, tab)
context.startActivity(intent)
}
}
override fun onError(t: Throwable) {
YdlRetrofitUtils.handleError(mContext, t)
}
private var isMine: Boolean = false
private var tabName: String? = null
private var testCategorys: MutableList<TestCategory>? = null
override fun couponResponse(list: ArrayList<RedPacketBean>) {
if (null == list || list.isEmpty()){
llTestRedPacketTips.visibility = View.GONE
}else{
llTestRedPacketTips.visibility = View.VISIBLE
val sb = StringBuffer()
sb.append("还有").append(list.size).append("个心理测试红包等你使用")
tvTestRedPacketTips.text = sb.toString()
llTestRedPacketTips.setOnClickListener {
TestsIn.myRedPockIntent(TestListActivity@this)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == payRequestCode && resultCode == Activity.RESULT_OK) {
//如果 是待付款列表 则需要刷新界面
if (null != presenter){
presenter.fetchTestTypeList()
}
}
}
override fun onTestCategoryListFetched(testCategoryList: MutableList<TestCategory>) {
testCategorys = testCategoryList
viewPager.adapter = TestListPagerAdapter(supportFragmentManager,this, testCategoryList)
tabLayout.setupWithViewPager(viewPager)
if (isMine) {
var myTab = 0
for ((index, cat) in testCategoryList.withIndex()) {
if (cat.tab == "my") {
myTab = index
break
}
}
viewPager.currentItem = myTab
} else if (null != tabName && !tabName!!.isEmpty()) {
var myTab = 0
for ((index, cat) in testCategoryList.withIndex()) {
if (cat.tab == tabName) {
myTab = index
break
}
}
viewPager.currentItem = myTab
}
}
override fun onFailed(msg: String?) {
ToastUtil.toastShort(msg ?: "")
}
override fun createPresenter(): TestListActivityPresenter = TestListActivityPresenter()
private var popupWindow: PopupWindow? = null
override fun onBackPressed() {
if (popupWindow != null && popupWindow!!.isShowing) {
popupWindow!!.dismiss()
} else {
super.onBackPressed()
}
}
}
package com.yidianling.tests.list.view
import com.hannesdorfmann.mosby3.mvp.MvpView
import com.yidianling.tests.list.model.bean.TestCategory
import com.yidianling.ydlcommon.pay.redpacket.RedPacketBean
/**
* TestListActivityView
* Created by zqk on 17-11-22.
*/
interface TestListActivityView : MvpView {
fun onTestCategoryListFetched(testCategoryList: MutableList<TestCategory>)
fun couponResponse(list : ArrayList<RedPacketBean>)
fun onFailed(msg: String?)
fun onError(t: Throwable)
}
\ No newline at end of file
package com.yidianling.tests.list.view
import com.yidianling.tests.list.model.bean.TestListData
import com.hannesdorfmann.mosby3.mvp.MvpView
/**
* TestListFragmentView
* Created by zqk on 17-11-22.
*/
interface TestListFragmentView : MvpView {
fun onTestListFetched(testListData: TestListData, page: Int)
fun onFailed(msg: String?)
fun dismissLoading()
fun onError(t: Throwable)
}
\ No newline at end of file
package com.yidianling.tests.list.view.adapter
import android.content.Context
import android.support.v4.content.ContextCompat
import android.support.v7.widget.RecyclerView
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.yidianling.tests.R
import com.yidianling.tests.list.model.bean.CategotyPopItem
import kotlinx.android.synthetic.main.item_tab_pop_sort.view.*
/**
* Created by zqk on 17-9-20.
*/
class CategoryConditionRecyclerViewAdapter(private val context: Context,
private val sortItems: ArrayList<CategotyPopItem>,
private val onItemSelectedListener: OnItemSelectedListener) : RecyclerView.Adapter<CategoryConditionRecyclerViewAdapter.ViewHolder>() {
override fun getItemCount(): Int = sortItems.size
var lastSelectView : TextView ?= null
var lastSelectText : String ?= null
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
val itemView = LayoutInflater.from(context).inflate(R.layout.item_tab_pop_sort, parent, false)
return ViewHolder(itemView)
}
override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
val item = sortItems[position]
if (holder != null) {
holder.tvSort.text = item.value
holder.tvSort.setTextColor(ContextCompat.getColor(context, R.color.color_242424))
if (!TextUtils.isEmpty(lastSelectText) && item.value.equals(lastSelectText) && position!=0){
holder.tvSort.setTextColor(ContextCompat.getColor(context, R.color.google_green))
lastSelectView = holder.tvSort
}
}
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvSort = itemView.tvSort!!
init {
itemView.setOnClickListener {
lastSelectView?.setTextColor(ContextCompat.getColor(context, R.color.color_242424))
if (adapterPosition != 0){
tvSort.setTextColor(ContextCompat.getColor(context, R.color.google_green))
}
if (adapterPosition != RecyclerView.NO_POSITION){
onItemSelectedListener.onSortItemSelected(sortItems[adapterPosition])
}
lastSelectView = tvSort
}
}
}
interface OnItemSelectedListener {
fun onSortItemSelected(sortItem: CategotyPopItem)
}
}
\ No newline at end of file
package com.yidianling.tests.list.view.adapter
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentPagerAdapter
import com.yidianling.tests.list.model.bean.TestCategory
import com.yidianling.tests.list.view.TestListFragment
import com.yidianling.ydlcommon.view.verticaltablayout.TabAdapter
import com.yidianling.ydlcommon.view.verticaltablayout.TabView
/**
* 测试列表ViewPager适配器
* Created by zqk on 17-11-22.
*/
class TestListPagerAdapter(fm: FragmentManager,
private val context: Context ,
private val testCategoryList: MutableList<TestCategory>
) : FragmentPagerAdapter(fm), TabAdapter {
private var fragments:HashMap<Int,TestListFragment> = HashMap();
override fun getIcon(position: Int): TabView.TabIcon? {
return null
}
override fun getTitle(position: Int): TabView.TabTitle {
return TabView.TabTitle.Builder()
.setContent(testCategoryList[position].name)
.setTextColor(Color.parseColor("#333333"), Color.parseColor("#666666"))
.setBgColor(Color.parseColor("#FFFFFF"), Color.parseColor("#F7F7F7"))
.setFontFamily(Typeface.defaultFromStyle(Typeface.BOLD), Typeface.defaultFromStyle(Typeface.NORMAL))
.setTextSize(14)
.build();
}
override fun getBackground(position: Int): Int {
return 0
}
override fun getPageTitle(position: Int): CharSequence = testCategoryList[position].name ?: ""
override fun getItem(position: Int): TestListFragment {
var fragment = TestListFragment.newInstance(testCategoryList[position].tab, testCategoryList[position].id,testCategoryList[position].name);
fragments[position] = fragment
return fragment
}
fun getFragmentByPosition(position: Int): TestListFragment? {
return fragments[position]
}
override fun getCount(): Int = testCategoryList.size
}
\ No newline at end of file
package com.yidianling.tests.list.view.adapter
import android.content.Context
import android.graphics.Color
import android.support.v7.widget.RecyclerView
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.ydl.ydl_image.module.GlideApp
import com.yidianling.common.tools.RxImageTool
import com.yidianling.tests.R
import com.yidianling.tests.base.MyBaseAdapter
import com.yidianling.tests.home.utils.TestHomeUtils
import com.yidianling.tests.list.model.bean.Test
import kotlinx.android.synthetic.main.testlist_item_view.view.*
import kotlinx.android.synthetic.main.view_footview_loadmore.view.*
/**
* 测试列表适配器
* Created by zqk on 17-11-22.
*/
class TestListRecyclerAdapter(private val context: Context,
private val testList: MutableList<Test>,
private val pageType : Int
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
companion object {
private val TYPE_HEADER= 1
private val TYPE_FOOTER = 2
private val TYPE_NORMAL = 0
const val PAGE_TYPE_CATEGORY = 1
const val PAGE_TYPE_SEARCH = 2
}
var onItemClickListener: MyBaseAdapter.OnItemClickListener<Test>? = null
var hasMore = true
var couponMoney =""
private var dp2 : Int? = 0
private var dp5 : Int? = 0
private var headerView: View? = null
init {
dp2 = RxImageTool.dip2px(2f)
dp5 = RxImageTool.dip2px(5f)
}
fun setHeaderView(view: View) {
headerView = view
notifyDataSetChanged()
}
fun removeHeaderView() {
headerView = null
notifyDataSetChanged()
}
private fun hasHeader(): Boolean {
return headerView != null
}
override fun getItemCount(): Int = if (testList.size > 0) testList.size + 1 + (if (hasHeader()) 1 else 0) else 0
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
if (holder is NormalViewHolder) {
var newPosition = position - if (hasHeader()) 1 else 0
val test = testList[newPosition]
GlideApp.with(context)
.load(test.cover)
.dontAnimate()
.dontTransform()
// .diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(R.drawable.default_img)
.into(holder.ivCover)
holder.tvTitle.text = test.name
holder.tvTestCount.text =TestHomeUtils.getNumNew(context, test.count)
holder.tvTestContent.text = test.desc
holder.tvHit.text = TestHomeUtils.getHitsNew(context, test.hits)
setPrice(holder.tvPrice,holder.tvCoupon,test.price,test.isFree)
} else if (holder is FootViewHolder) {
if (hasMore) {
holder.pbLoading.visibility = View.VISIBLE
holder.ivNoMoreLeft.visibility = View.GONE
holder.ivNoMoreRight.visibility = View.GONE
holder.tvContent.text = context.getString(R.string.loading)
} else {
holder.pbLoading.visibility = View.GONE
holder.tvContent.text = context.getString(R.string.load_end)
holder.ivNoMoreLeft.visibility = View.VISIBLE
holder.ivNoMoreRight.visibility = View.VISIBLE
}
}
}
private fun setPrice(textView : TextView,tvCoupon : TextView,price : String?,isFree : Int){
if (TextUtils.isEmpty(price)){
textView.visibility = View.INVISIBLE
return
}
textView.visibility = View.VISIBLE
if (isFree == 2
||price.equals("免费")
||TextUtils.isEmpty(price)
||"0".equals(price)
||"0.0".equals(price)
||"0.00".equals(price)){
tvCoupon.visibility = View.GONE
textView.setPadding(dp5!!,dp2!!,dp5!!,dp2!!)
textView.text = "免费"
textView.setBackgroundResource(R.drawable.testhome_recom_price_bg)
textView.setTextColor(Color.parseColor("#34CD65"))
}else{
var newPrice = TestHomeUtils.getOriginalPrice(tvCoupon,price,couponMoney)
textView.setPadding(0,dp5!!,dp5!!,0)
var priceContent = "¥$newPrice"
TestHomeUtils.priceStyleNew(context,textView,priceContent, 1, priceContent.length)
textView.setBackgroundResource(R.drawable.testhome_null)
}
}
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder {
return if (viewType == TYPE_HEADER) {
object : RecyclerView.ViewHolder(headerView) {}
} else if (viewType == TYPE_NORMAL) {
var view :View ?=null
if (pageType== PAGE_TYPE_CATEGORY){
view = LayoutInflater.from(parent?.context).inflate(R.layout.item_category_testlist_view, parent, false)
}else {
view = LayoutInflater.from(parent?.context).inflate(R.layout.testlist_item_view, parent, false)
}
NormalViewHolder(view!!)
} else {
val view = LayoutInflater.from(parent?.context).inflate(R.layout.view_footview_loadmore, parent, false)
FootViewHolder(view)
}
}
override fun getItemViewType(position: Int): Int {
return if (hasHeader() && position == 0) {
return TYPE_HEADER
}else if (position == testList.size + (if (hasHeader()) 1 else 0)) {
TYPE_FOOTER
} else {
TYPE_NORMAL
}
}
inner class NormalViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
var ivCover = view.ivCover
var tvTitle = view.tv_title
var tvTestCount = view.tv_num
var tvTestContent = view.tvContent
var tvHit = view.tv_hits
var tvPrice = view.tv_price
var tvCoupon = view.tv_coupon_money
init {
view.setOnClickListener {
if (adapterPosition != RecyclerView.NO_POSITION) {
onItemClickListener?.onItemClickListener(view, adapterPosition- (if (hasHeader()) 1 else 0), testList[adapterPosition- (if (hasHeader()) 1 else 0)])
}
}
}
}
inner class FootViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
var pbLoading = view.circle_progress
var tvContent = view.tv_content
var ivNoMoreLeft = view.iv_no_more_left
var ivNoMoreRight = view.iv_no_more_right
}
}
\ No newline at end of file
package com.yidianling.tests.list.view.widget
import android.content.Context
import android.graphics.drawable.BitmapDrawable
import android.support.v7.widget.LinearLayoutManager
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.PopupWindow
import com.yidianling.tests.R
import com.yidianling.tests.list.model.bean.CategotyPopItem
import com.yidianling.tests.list.view.adapter.CategoryConditionRecyclerViewAdapter
import kotlinx.android.synthetic.main.ui_category_sort_popup_window.view.*
/**
* 排序弹窗
* Created by zqk on 17-9-15.
*/
class CategoryPopupWindow(val context: Context,
private val items: ArrayList<CategotyPopItem>,
private val onItemSelectedListener: CategoryConditionRecyclerViewAdapter.OnItemSelectedListener)
: PopupWindow(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) {
var adapter: CategoryConditionRecyclerViewAdapter
init {
val view = LayoutInflater.from(context).inflate(R.layout.ui_category_sort_popup_window, null)
this.contentView = view
this.isFocusable = true
@Suppress("DEPRECATION")
this.setBackgroundDrawable(BitmapDrawable())
this.isOutsideTouchable = true
val rvSortItem = view.rvSortItem
adapter = CategoryConditionRecyclerViewAdapter(context, items, onItemSelectedListener)
rvSortItem.adapter = adapter
rvSortItem.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
}
fun notifyDataSetChanged() {
adapter.notifyDataSetChanged()
}
}
\ No newline at end of file
package com.yidianling.tests.router
import android.app.Activity
import android.content.Intent
import com.yidianling.router.RouterManager
import com.yidianling.router.im.IMRequestCallback
/**
* author : Zhangwenchao
* e-mail : zhangwch@yidianling.com
* time : 2018/04/25
*/
object TestsIn {
fun isLogin(): Boolean {
return RouterManager.getUserRouter()?.isLogin()?:false
}
fun loginWayIntent(activity: Activity): Intent? {
return RouterManager.getUserRouter()?.loginWayIntent(activity)
}
fun publishTrendIntent(activity: Activity, url: String, cover: String, title: String): Intent? {
return RouterManager.getDynamicRouter()?.publishTrendIntent(activity, url, cover, title)
}
fun sendTestResultMessage(uid : String,content : String,title: String?,head : String?,url : String?,id : Int,share_url : String?, callback: IMRequestCallback<Void>) {
RouterManager.getImRouter().sendTestResultMessage(uid, content, title, head, url, id, share_url, callback)
}
/**
* 跳转红包
*/
fun myRedPockIntent(activity: Activity){
activity.startActivity(RouterManager.getAppRouter()?.myRedPockIntent(activity))
}
}
\ No newline at end of file
package com.yidianling.tests.router
import android.app.Activity
import android.content.Intent
import com.ydl.ydl_router.manager.YDLRouterManager
import com.ydl.ydl_router.manager.YDLRouterParams
import com.yidianling.router.tests.ITestsRouter
import com.yidianling.tests.answer.TestAnswerActivity
import com.yidianling.tests.detail.TestDetailActivity
import com.yidianling.tests.result.jump.JumpTestResultActivity
import com.yidianling.ydlcommon.BuildConfig
import com.yidianling.ydlcommon.router.IYDLRouterConstant
class TestsRouterImp : ITestsRouter {
override fun testH5Result(testResultId: String) {
YDLRouterManager.router(IYDLRouterConstant.ROUTER_H5_H5,
YDLRouterParams().putExtra(IYDLRouterConstant.EXTRA_URL, BuildConfig.MH5_URL+"ceshi/result/"+testResultId),"")
}
override fun testDetailH5(testId: String) {
YDLRouterManager.router(IYDLRouterConstant.ROUTER_H5_H5,
YDLRouterParams().putExtra(IYDLRouterConstant.EXTRA_URL, BuildConfig.MH5_URL+"ceshi/"+testId),"")
}
override fun testDetailIntent(activity: Activity, testId: Int): Intent {
return TestDetailActivity.newIntent(activity, testId.toString())
}
override fun testResultIntent(activity: Activity, testResultId: Int): Intent {
return JumpTestResultActivity.newIntent(activity, testResultId.toString())
}
override fun testAnswerIntent(activity: Activity): Intent {
return TestAnswerActivity.newIntent(activity)
}
}
\ No newline at end of file
package com.yidianling.tests.search
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.yidianling.tests.list.model.bean.Test
import com.yidianling.tests.R
import com.yidianling.tests.base.MyBaseAdapter
import kotlinx.android.synthetic.main.item_hot_test.view.*
/**
* HotTestListAdapter
* Created by zqk on 17-12-5.
*/
class HotTestListAdapter(val hotTestList: MutableList<Test>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
companion object {
private val TYPE_NORMAL = 0
private val TYPE_HEADER = 1
}
var onItemClickListener: MyBaseAdapter.OnItemClickListener<Test>? = null
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
if (holder is NormalViewHolder) {
holder.tvTestName.text = hotTestList[position - 1].name
}
}
override fun getItemViewType(position: Int): Int {
return if (position == 0) {
TYPE_HEADER
} else {
TYPE_NORMAL
}
}
override fun getItemCount(): Int = hotTestList.size + 1
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder {
return if (viewType == TYPE_NORMAL) {
val view = LayoutInflater.from(parent!!.context).inflate(R.layout.item_hot_test, parent, false)
NormalViewHolder(view)
} else {
val view = LayoutInflater.from(parent!!.context).inflate(R.layout.item_hot_test_header, parent, false)
object : RecyclerView.ViewHolder(view) {}
}
}
inner class NormalViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvTestName = itemView.tvTestName!!
init {
itemView.setOnClickListener {
if (adapterPosition != RecyclerView.NO_POSITION) {
onItemClickListener?.onItemClickListener(itemView, adapterPosition, hotTestList[adapterPosition - 1])
}
}
}
}
}
\ No newline at end of file
package com.yidianling.tests.search
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.hannesdorfmann.mosby3.mvp.MvpNullObjectBasePresenter
import com.ydl.ydlcommon.data.http.RxUtils
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.yidianling.common.tools.ToastUtil
import com.yidianling.tests.TestRetrofitApi
import com.yidianling.tests.home.http.TestHomeDataManager
import com.yidianling.tests.home.param.TestHomeParam
import com.yidianling.tests.list.model.TestListCommand
import com.yidianling.tests.list.model.bean.Test
import com.yidianling.ydlcommon.app.YdlCommonApp
import com.yidianling.ydlcommon.http.RxUtils
import com.yidianling.ydlcommon.http.ThrowableConsumer
import com.yidianling.ydlcommon.http.YdlRetrofitUtils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
/**
* TestSearchPresenter
* Created by zqk on 17-12-5.
*/
class TestSearchPresenter : MvpNullObjectBasePresenter<TestSearchView>() {
fun fetchHotTests() {
view.showLoadingView()
val cmd = TestListCommand()
cmd.tab = "hot_test"
cmd.page = 1
TestRetrofitApi.getTestRetrofitApi()
.fetchTopSearch()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ resp ->
if (resp.code == "200") {
view.hideNoResultView()
view.onRecommendSearchListResponse(resp.data)
} else {
ToastUtil.toastShort(resp.msg)
view.hideLoadingView()
}
}, { throwble ->
YdlRetrofitUtils.handleError(YdlCommonApp.getApp(), throwble)
})
}
/**
* 测评热门推荐
*/
fun hotRecommendRequest() {
view.showLoadingView()
TestHomeDataManager
.getHttp()
.newHomeRequest(TestHomeParam( 0))
.compose(RxUtils.resultData())
.map { it }
.filter { it != null }
.observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer {
if (it[3].body!=null){
var jsonStr = Gson().toJson(it[3].body)
val list = Gson().fromJson<MutableList<Test>>(jsonStr, object : TypeToken<MutableList<Test>>() {
}.type)
view.hideNoResultView()
view.onHotRecommendResponse(list)
}else{
view.hideLoadingView()
}
}, object : ThrowableConsumer() {
override fun accept(msg: String) {
view.showError(msg)
}
})
}
fun searchTests(keyword: String?, page: Int) {
if (page == 1) {
view.showLoadingView()
}
val cmd = TestListCommand()
cmd.tab = "search"
cmd.page = page
cmd.keyword = keyword
TestRetrofitApi.getTestRetrofitApi()
.fetchTestList(YdlRetrofitUtils.getMaps(cmd))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ resp ->
if (resp.code == 0) {
view.hideLoadingView()
if (page == 1 && (resp.data.testList == null || resp.data.testList?.size == 0)) {
view.showNoResultView()
view.showSearchResultView(resp.data.testList, page)
} else {
view.hideNoResultView()
view.showSearchResultView(resp.data.testList, page)
}
} else {
view.hideLoadingView()
ToastUtil.toastShort(resp.msg)
}
}, { throwble ->
YdlRetrofitUtils.handleError(YdlCommonApp.getApp(), throwble)
})
}
}
\ No newline at end of file
package com.yidianling.tests.search
import com.hannesdorfmann.mosby3.mvp.MvpView
import com.yidianling.tests.list.model.bean.RecommendSearchItemBean
import com.yidianling.tests.list.model.bean.Test
/**
* TestSearchView
* Created by zqk on 17-12-5.
*/
interface TestSearchView : MvpView {
fun showLoadingView()
fun hideLoadingView()
fun showError(msg: String)
fun showNoResultView()
fun hideNoResultView()
fun showSearchResultView(testList: List<Test>?, page: Int)
fun onRecommendSearchListResponse(testList: List<RecommendSearchItemBean>)
fun onHotRecommendResponse(datalist : List<Test>)
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment